feat: auto-narasi LLM (OmniRoute sonnet-5) — hero briefing + narasi_awam report, migrasi 0006
This commit is contained in:
+2
-2
@@ -21,7 +21,7 @@ export interface FlowSummary { date: string; foreign_net_total: number; top_accu
|
||||
export interface ScreenRow { symbol: string; name: string; composite: number; breakdown: Record<string, unknown>; citations: Citation[] }
|
||||
export interface Routine { id: number; user_key: string; type: string; schedule_cron: string; channels_json?: string; channels?: string[]; enabled: boolean; last_run?: unknown }
|
||||
export interface AlertItem { id: number; user_key: string; name: string; rule_json: string; channels_json: string; last_fired: string }
|
||||
export interface ReportPayload { ticker: string; generated_at: string; sections: { name: string; body: string; citations: Citation[] }[]; synthesis: { recommendation: string; conviction: number; thesis: string; position_pct: number; conflict: boolean; conflict_note?: string }; agent_scores: unknown[]; citations: Citation[] }
|
||||
export interface ReportPayload { ticker: string; generated_at: string; sections: { name: string; body: string; citations: Citation[] }[]; synthesis: { recommendation: string; conviction: number; thesis: string; position_pct: number; conflict: boolean; conflict_note?: string }; agent_scores: unknown[]; citations: Citation[]; narasi_awam?: string }
|
||||
export interface AuthUser { id: number; email: string; name: string; avatar_url: string; user_key: string; google_configured: boolean }
|
||||
export const api = {
|
||||
health: (force = false) => req<Health>(`/api/health${force ? "?force=1" : ""}`),
|
||||
@@ -33,7 +33,7 @@ export const api = {
|
||||
createRoutine: (body: Record<string, unknown>) => req<{ id: number }>("/api/routines", { method: "POST", body: JSON.stringify(body) }),
|
||||
updateRoutine: (id: number, body: Record<string, unknown>) => req<unknown>(`/api/routines/${id}`, { method: "PATCH", body: JSON.stringify(body) }),
|
||||
runs: (routine_id?: number) => req<{ runs: Record<string, unknown>[] }>(`/api/routine-runs${routine_id ? `?routine_id=${routine_id}` : ""}`),
|
||||
briefing: () => req<{ date: string; payload: string; citations: string }>("/api/briefing/today"),
|
||||
briefing: () => req<{ date: string; payload: string; citations: string; narasi?: string }>("/api/briefing/today"),
|
||||
destinations: () => req<{ destinations: { id: number; kind: string; label: string; enabled: boolean; configured: boolean }[] }>("/api/destinations"),
|
||||
createDestination: (body: Record<string, unknown>) => req<{ id: number }>("/api/destinations", { method: "POST", body: JSON.stringify(body) }),
|
||||
updateDestination: (id: number, body: Record<string, unknown>) => req<unknown>(`/api/destinations/${id}`, { method: "PATCH", body: JSON.stringify(body) }),
|
||||
|
||||
@@ -21,7 +21,9 @@ export default function Dashboard() {
|
||||
const [foreign] = createResource(chartTiker, (t) => api.flowForeign(t).catch(() => null));
|
||||
|
||||
const ringkasan = () => {
|
||||
const p = (briefing() as { payload: string } | null)?.payload;
|
||||
const n = briefing()?.narasi?.trim();
|
||||
if (n) return n.split("\n").map((s) => s.replace(/^[-•\d.]+\s*/, "")).filter(Boolean).slice(0, 3);
|
||||
const p = briefing()?.payload;
|
||||
return p ? heroSummary(p) : [];
|
||||
};
|
||||
const sorotan = () => (screen()?.rows || []).map((r) => ({ row: r, ...verdictFor(r) }));
|
||||
|
||||
@@ -48,6 +48,12 @@ export default function Report() {
|
||||
<Show when={err()}><p class="text-sm text-destructive">{err()}</p></Show>
|
||||
<Show when={busy()}><div class="space-y-2"><Skeleton class="h-32 w-full" /><Skeleton class="h-24 w-full" /></div></Show>
|
||||
<Show when={rep()}>
|
||||
<Show when={rep()!.narasi_awam}>
|
||||
<Card class="border-primary/30 bg-gradient-to-br from-primary/10 to-transparent">
|
||||
<CardHeader><CardTitle class="text-xl">Kesimpulan buat kamu 🤝</CardTitle></CardHeader>
|
||||
<CardContent><p class="whitespace-pre-wrap text-base leading-relaxed">{rep()!.narasi_awam}</p></CardContent>
|
||||
</Card>
|
||||
</Show>
|
||||
<Card class="border-l-4 border-l-primary">
|
||||
<CardContent class="flex flex-wrap items-center gap-2 pt-6">
|
||||
<RecBadge rec={rep()!.synthesis.recommendation} />
|
||||
|
||||
Reference in New Issue
Block a user