Add AI news risk analysis and dashboard

Analyze news revisions with independent model settings, evidence-backed risk ratings, event grouping, and rolling market outlooks. Add a default homepage, archival history, pending-result refresh, and isolated regression coverage.

Keep analysis disabled until explicitly enabled. Require a separately authorized schema migration before deployment and preserve compatibility with the previous six-service instance.
This commit is contained in:
eezd committed 2026-10-30 18:35:49 +08:00
1 parent 549b818e95
commit 4f43ca8b57
31 files changed
+1521 -18

No files matched your search

+11
View File
@@ -0,0 +1,11 @@
import type * as Risk from "./type"
import { request } from "@/http/axios"
export const getRiskSettingsApi = () => request<Risk.Settings>({ url: "/risk/settings", method: "get" })
export const saveRiskSettingsApi = (data: Risk.Settings) => request<null>({ url: "/risk/settings", method: "put", data })
export const enableRiskApi = (data: Risk.Settings) => request<null>({ url: "/risk/enable", method: "post", timeout: 650000, data })
export const getRiskOverviewApi = (hours: number) => request<Risk.Overview>({ url: "/risk/overview", method: "get", params: { hours } })
export const listRiskEventsApi = (params: Risk.EventQuery) => request<{ items: Risk.RiskEvent[], total: number }>({ url: "/risk/events", method: "get", params })
export const getRiskEventApi = (id: number) => request<{ event: Risk.RiskEvent, history: Risk.Analysis[] }>({ url: `/risk/events/${id}`, method: "get" })
export const listRiskAnalysesApi = (params: { news_id?: number, revision_no?: number, failed?: boolean }, notify = true) => request<Risk.Analysis[]>({ url: "/risk/analyses", method: "get", params, notify })
export const retryRiskAnalysisApi = (id: number) => request<null>({ url: `/risk/analyses/${id}/retry`, method: "post" })
+45
View File
@@ -0,0 +1,45 @@
export interface RiskResult {
summary: string
reasoning: string
uncertainty: string
evidence: string
direction: string
verification: string
confidence: string
stars: number
}
export interface RiskEvent {
id: number
title: string
category: string
entities: string[]
stars: number
peak_stars: number
result: RiskResult
published_at: string
updated_at: string
}
export interface Settings { enabled: boolean, provider_id: number | null, model: string, start_at: string }
export interface Analysis {
id: number
news_id: number
state: string
result: RiskResult | null
input: { title: string, source: string, url: string, published_at: string, progress_at: string, revision_no: number }
model: string | null
error: string | null
analyzed_at: string | null
historical: boolean
}
export interface Overview {
as_of: string
counts: Record<string, number>
coverage: { total: number, done: number, failed: number, pending: number, processing: number }
scenario: { direction: string, summary: string, conditions: string, counter_factors: string, uncertainty: string, event_ids: number[] } | null
snapshot_at: string | null
quotes: { at: string, BTCUSDT?: { lastPrice: string, priceChangePercent: string }, ETHUSDT?: { lastPrice: string, priceChangePercent: string } } | null
stale: boolean
error: string | null
heartbeat: string | null
}
export interface EventQuery { hours?: number, stars?: number, q?: string, start?: string, end?: string, page?: number }