feat(ui): add summary/action-item types + errorMessage() helper (T7.1, FR-LLM-2/3/4)
Types for SummaryFile/ActionItem/LlmStatus and a confirmActionItems
wrapper + onLlmDone listener, so the frontend can consume what
generate_summary/confirm_action_items already produce on the backend.
Also adds errorMessage(): every backend command rejects with
{ kind, message } (see src-tauri/src/error.rs), not a native Error, so
`e instanceof Error` is always false for it and `String(e)` renders as
the literal text "[object Object]" — found by actually clicking
"Generate summary" against an unreachable Ollama endpoint.
This commit is contained in:
1 parent
b2d423e3ec
commit
075eec6a95
1 file changed
+51
-1
+51
-1
@@ -8,6 +8,22 @@ import { listen, type UnlistenFn } from "@tauri-apps/api/event";
|
||||
export type MeetingId = string;
|
||||
export type BackendId = "npu" | "nvidia" | "amd" | "intel" | "cpu";
|
||||
|
||||
// Every backend command rejects an `Err` as this shape, not a native Error
|
||||
// (see src-tauri/src/error.rs) — `e instanceof Error` is always false for it.
|
||||
export interface WaError {
|
||||
kind: string;
|
||||
message: string;
|
||||
}
|
||||
|
||||
export function errorMessage(e: unknown): string {
|
||||
if (typeof e === "string") return e;
|
||||
if (e instanceof Error) return e.message;
|
||||
if (e && typeof e === "object" && typeof (e as WaError).message === "string") {
|
||||
return (e as WaError).message;
|
||||
}
|
||||
return String(e);
|
||||
}
|
||||
|
||||
export interface BackendInfo {
|
||||
id: BackendId;
|
||||
name: string;
|
||||
@@ -23,6 +39,13 @@ export interface HardwareStatus {
|
||||
estRtf: number;
|
||||
}
|
||||
|
||||
export interface LlmStatus {
|
||||
provider: string; // ollama|custom|off (Phase 10a adds anthropic|openai)
|
||||
reachable: boolean;
|
||||
isLocal: boolean;
|
||||
models: string[];
|
||||
}
|
||||
|
||||
export interface ModelInfo {
|
||||
id: string;
|
||||
label: string;
|
||||
@@ -57,6 +80,28 @@ export interface SpeakerInfo {
|
||||
participant_id: string | null;
|
||||
}
|
||||
|
||||
// Drafted action item from a summary (Phase 5, FR-LLM-3). `id` is only set
|
||||
// once `confirmActionItems` has persisted it as a row.
|
||||
export interface ActionItem {
|
||||
id: string | null;
|
||||
text: string;
|
||||
owner: string | null;
|
||||
due_at: number | null;
|
||||
confirmed: boolean;
|
||||
}
|
||||
|
||||
// On-disk shape of summary.json (FR-LLM-2/4) — `null` until generate_summary
|
||||
// has run at least once for a meeting.
|
||||
export interface SummaryFile {
|
||||
schema: number;
|
||||
generated_at: number;
|
||||
provider: string;
|
||||
model: string;
|
||||
summary_md: string;
|
||||
decisions: string[];
|
||||
action_items: ActionItem[];
|
||||
}
|
||||
|
||||
// Full meeting detail (get_meeting) — DB row + transcript + speakers + notes.
|
||||
export interface Meeting {
|
||||
id: MeetingId;
|
||||
@@ -72,6 +117,7 @@ export interface Meeting {
|
||||
segments: TranscriptSegment[];
|
||||
speakers: SpeakerInfo[];
|
||||
notes_markdown: string;
|
||||
summary: SummaryFile | null;
|
||||
calendar_event_id: string | null;
|
||||
}
|
||||
|
||||
@@ -227,7 +273,7 @@ export const api = {
|
||||
exportMeeting: (meetingId: MeetingId, dest: string, format: "md" | "bundle") =>
|
||||
invoke<string>("export_meeting", { meetingId, dest, format }),
|
||||
|
||||
llmStatus: () => invoke("llm_status"),
|
||||
llmStatus: () => invoke<LlmStatus>("llm_status"),
|
||||
// provider ∈ ollama|custom|anthropic|openai|off; apiKey (hosted) → OS credential store (ADR-0011).
|
||||
setLlmProvider: (config: {
|
||||
provider: string;
|
||||
@@ -237,6 +283,8 @@ export const api = {
|
||||
}) => invoke<void>("set_llm_provider", { config }),
|
||||
generateSummary: (meetingId: MeetingId, templateId?: string) =>
|
||||
invoke<void>("generate_summary", { meetingId, templateId }),
|
||||
confirmActionItems: (meetingId: MeetingId, items: ActionItem[]) =>
|
||||
invoke<void>("confirm_action_items", { meetingId, items }),
|
||||
|
||||
importPst: (path: string, password?: string) => invoke<number>("import_pst", { path, password }),
|
||||
listCalendarEvents: (from?: number, to?: number) =>
|
||||
@@ -316,6 +364,8 @@ export const events = {
|
||||
): Promise<UnlistenFn> => listen("transcript://finalized", (e) => cb(e.payload as never)),
|
||||
onLlmToken: (cb: (p: { meetingId: string; text: string }) => void): Promise<UnlistenFn> =>
|
||||
listen("llm://token", (e) => cb(e.payload as never)),
|
||||
onLlmDone: (cb: (p: { meetingId: string; summary: SummaryFile }) => void): Promise<UnlistenFn> =>
|
||||
listen("llm://done", (e) => cb(e.payload as never)),
|
||||
onModelProgress: (
|
||||
cb: (p: { id: string; receivedBytes: number; totalBytes: number | null }) => void,
|
||||
): Promise<UnlistenFn> => listen("model://progress", (e) => cb(e.payload as never)),
|
||||
|
||||
Reference in new issue
Block a user