Add bill action pipeline, admin health panel, and LLM provider fixes

- Fetch bill actions from Congress.gov and populate the action timeline
- Add nightly batch task and beat schedule for active bill actions
- Add admin reprocess endpoint for per-bill debugging
- Add BriefPanel with "What Changed" view and version history
- Add External API Health section with per-source latency testing
- Redesign Manual Controls as health panel with status dots and descriptions
- Add Resume Analysis task for stalled LLM jobs
- Add Backfill Dates & Links task for bills with null metadata
- Fix LLM provider/model DB overrides being ignored (env vars used instead)
- Fix Gemini 404: gemini-1.5-pro deprecated → gemini-2.0-flash
- Fix Anthropic models list: use REST API directly (SDK too old for .models)
- Replace test-LLM full analysis with lightweight ping (max_tokens=20)
- Add has_document field to BillDetail; show "No bill text published" state
- Fix "Introduced: —" showing for bills with null introduced_date
- Add bills_missing_sponsor and bills_missing_metadata to admin stats
- Add GovInfo health check using /collections endpoint (fixes 500 from /packages)

Authored-By: Jack Levy
This commit is contained in:
Jack Levy
2026-03-01 11:06:14 -05:00
parent defc2c116d
commit 5eebc2f196
10 changed files with 586 additions and 74 deletions

View File

@@ -137,6 +137,19 @@ export interface AdminUser {
created_at: string;
}
export interface ApiHealthResult {
status: "ok" | "error" | "skipped";
detail: string;
latency_ms?: number;
}
export interface ApiHealth {
congress_gov: ApiHealthResult;
govinfo: ApiHealthResult;
newsapi: ApiHealthResult;
google_news: ApiHealthResult;
}
export interface AnalysisStats {
total_bills: number;
docs_fetched: number;
@@ -144,6 +157,10 @@ export interface AnalysisStats {
full_briefs: number;
amendment_briefs: number;
uncited_briefs: number;
no_text_bills: number;
pending_llm: number;
bills_missing_sponsor: number;
bills_missing_metadata: number;
remaining: number;
}
@@ -182,6 +199,12 @@ export const adminAPI = {
apiClient.post("/api/admin/backfill-citations").then((r) => r.data),
triggerFetchActions: () =>
apiClient.post("/api/admin/trigger-fetch-actions").then((r) => r.data),
backfillMetadata: () =>
apiClient.post("/api/admin/backfill-metadata").then((r) => r.data),
resumeAnalysis: () =>
apiClient.post("/api/admin/resume-analysis").then((r) => r.data),
getApiHealth: () =>
apiClient.get<ApiHealth>("/api/admin/api-health").then((r) => r.data),
getTaskStatus: (taskId: string) =>
apiClient.get(`/api/admin/task-status/${taskId}`).then((r) => r.data),
};