import { invoke as rawInvoke } from "@tauri-apps/api/core"; import { listen } from "@tauri-apps/api/event"; /** 统一命令包装:失败时自动上报错误到本地日志,再抛出给界面。 */ async function invoke(command: string, args?: Record): Promise { try { return await rawInvoke(command, args); } catch (error) { try { await rawInvoke("report_error", { source: command, message: String(error), }); } catch { // 上报失败不影响主流程 } throw error; } } export interface AppInfo { version: string; platform: string; models_dir: string; logs_dir: string; engine_bin: string | null; engine_exists: boolean; db_path: string; } export interface ModelInfo { id: string; repo_id: string; source: string; kind: string; file_name: string; file_path: string; file_size: number; quant: string | null; family: string | null; status: string; sha256: string | null; base_url: string | null; api_key: string | null; api_model: string | null; meta: Record; created_at: string; } export interface RepoSummary { repo_id: string; author: string; name: string; downloads: number | null; likes: number | null; tags: string[]; } export interface ModelFile { path: string; size: number; sha256: string | null; } export interface EngineStatus { running: boolean; port: number | null; pid: number | null; model: string | null; backend: string | null; ctx_size: number | null; ngl: number | null; uptime_secs: number | null; } export interface Conversation { id: string; title: string; model_id: string | null; system_prompt: string | null; created_at: string; updated_at: string; } export interface Message { id: string; conversation_id: string; role: string; content: string; tokens_in: number | null; tokens_out: number | null; elapsed_ms: number | null; first_token_ms: number | null; images: string[]; created_at: string; } export interface ChatParams { temperature: number; top_p: number; max_tokens: number; ctx_size: number; ngl: number; } export interface ChatSendPayload { conversation_id: string; model_id: string; content: string; params: ChatParams; images: string[]; } export interface ChatTokenEvent { conversation_id: string; text: string; } export interface ChatDoneEvent { conversation_id: string; message_id: string; content: string; tokens_in: number | null; tokens_out: number | null; tokens_estimated: boolean; elapsed_ms: number; first_token_ms: number | null; } export interface ChatErrorEvent { conversation_id: string; message: string; } export interface ChatMessageUpdatedEvent { conversation_id: string; message: Message; } export interface MessageVersion { id: string; message_id: string; content: string; tokens_out: number | null; elapsed_ms: number | null; first_token_ms: number | null; seq: number; created_at: string; } export interface EngineDeployEvent { model_id: string; file_name: string; state: string; message: string | null; } export interface EngineDeployProgressEvent { model_id: string; file_name: string; percent: number; stage: string; } export interface DownloadProgressEvent { id: string; url: string; file_name: string; downloaded: number; total: number | null; percent: number | null; speed_bps: number; status: string; } export interface ServerStatus { running: boolean; port: number | null; } export const api = { appInfo: () => invoke("app_info"), listModels: () => invoke("list_models"), importModel: (path: string) => invoke("import_model", { path }), removeModel: (id: string) => invoke("remove_model", { id }), scanModels: () => invoke("scan_models"), addRemoteModel: (name: string, baseUrl: string, apiKey: string, apiModel: string) => invoke("add_remote_model", { name, baseUrl, apiKey, apiModel }), searchModels: (query: string, source: string) => invoke("search_models", { query, source }), listModelFiles: (repoId: string, source: string) => invoke("list_model_files", { repoId, source }), settingsGet: () => invoke>("settings_get"), settingsSet: (key: string, value: string) => invoke("settings_set", { key, value }), listConversations: () => invoke("list_conversations"), createConversation: (title: string, modelId?: string) => invoke("create_conversation", { title, modelId: modelId ?? null }), deleteConversation: (id: string) => invoke("delete_conversation", { id }), getMessages: (conversationId: string) => invoke("get_messages", { conversationId }), engineStart: (modelId: string, params: ChatParams) => invoke("engine_start", { modelId, params }), deployModel: (modelId: string, params: ChatParams) => invoke("deploy_model", { modelId, params }), engineStop: () => invoke("engine_stop"), engineStatus: () => invoke("engine_status"), chatSend: (payload: ChatSendPayload) => invoke<{ conversation_id: string; message_id: string }>("chat_send", { payload }), regenerateMessage: ( conversationId: string, messageId: string, params: ChatParams, ) => invoke("regenerate_message", { payload: { conversation_id: conversationId, message_id: messageId, params }, }), editMessage: ( conversationId: string, messageId: string, content: string, params: ChatParams, ) => invoke("edit_message", { payload: { conversation_id: conversationId, message_id: messageId, content, params, }, }), listMessageVersions: (messageId: string) => invoke("list_message_versions", { messageId }), applyMessageVersion: ( conversationId: string, messageId: string, versionId: string, ) => invoke("apply_message_version", { conversationId, messageId, versionId }), downloadEnqueue: ( url: string, fileName: string, sha256?: string, repoId?: string, source?: string, ) => invoke("download_enqueue", { payload: { url, file_name: fileName, sha256: sha256 ?? null, repo_id: repoId ?? null, source: source ?? null, }, }), serverStart: (port: number, apiKey: string) => invoke("server_start", { port, apiKey }), serverStop: () => invoke("server_stop"), serverStatus: () => invoke("server_status"), openPath: (path: string) => invoke("open_path", { path }), }; export function onEvent(channel: string, handler: (payload: T) => void) { return listen(channel, (event) => handler(event.payload)); }