Files
xianren_studio/ui/src/api.ts
T

266 lines
6.8 KiB
TypeScript

import { invoke as rawInvoke } from "@tauri-apps/api/core";
import { listen } from "@tauri-apps/api/event";
/** 统一命令包装:失败时自动上报错误到本地日志,再抛出给界面。 */
async function invoke<T>(command: string, args?: Record<string, unknown>): Promise<T> {
try {
return await rawInvoke<T>(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<string, unknown>;
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<AppInfo>("app_info"),
listModels: () => invoke<ModelInfo[]>("list_models"),
importModel: (path: string) => invoke<ModelInfo>("import_model", { path }),
removeModel: (id: string) => invoke<void>("remove_model", { id }),
scanModels: () => invoke<ModelInfo[]>("scan_models"),
addRemoteModel: (name: string, baseUrl: string, apiKey: string, apiModel: string) =>
invoke<ModelInfo>("add_remote_model", { name, baseUrl, apiKey, apiModel }),
searchModels: (query: string, source: string) =>
invoke<RepoSummary[]>("search_models", { query, source }),
listModelFiles: (repoId: string, source: string) =>
invoke<ModelFile[]>("list_model_files", { repoId, source }),
settingsGet: () => invoke<Record<string, string>>("settings_get"),
settingsSet: (key: string, value: string) =>
invoke<void>("settings_set", { key, value }),
listConversations: () => invoke<Conversation[]>("list_conversations"),
createConversation: (title: string, modelId?: string) =>
invoke<Conversation>("create_conversation", { title, modelId: modelId ?? null }),
deleteConversation: (id: string) =>
invoke<void>("delete_conversation", { id }),
getMessages: (conversationId: string) =>
invoke<Message[]>("get_messages", { conversationId }),
engineStart: (modelId: string, params: ChatParams) =>
invoke<EngineStatus>("engine_start", { modelId, params }),
deployModel: (modelId: string, params: ChatParams) =>
invoke<void>("deploy_model", { modelId, params }),
engineStop: () => invoke<void>("engine_stop"),
engineStatus: () => invoke<EngineStatus>("engine_status"),
chatSend: (payload: ChatSendPayload) =>
invoke<{ conversation_id: string; message_id: string }>("chat_send", { payload }),
regenerateMessage: (
conversationId: string,
messageId: string,
params: ChatParams,
) =>
invoke<void>("regenerate_message", {
payload: { conversation_id: conversationId, message_id: messageId, params },
}),
editMessage: (
conversationId: string,
messageId: string,
content: string,
params: ChatParams,
) =>
invoke<void>("edit_message", {
payload: {
conversation_id: conversationId,
message_id: messageId,
content,
params,
},
}),
listMessageVersions: (messageId: string) =>
invoke<MessageVersion[]>("list_message_versions", { messageId }),
applyMessageVersion: (
conversationId: string,
messageId: string,
versionId: string,
) => invoke<void>("apply_message_version", { conversationId, messageId, versionId }),
downloadEnqueue: (
url: string,
fileName: string,
sha256?: string,
repoId?: string,
source?: string,
) =>
invoke<string>("download_enqueue", {
payload: {
url,
file_name: fileName,
sha256: sha256 ?? null,
repo_id: repoId ?? null,
source: source ?? null,
},
}),
serverStart: (port: number, apiKey: string) =>
invoke<ServerStatus>("server_start", { port, apiKey }),
serverStop: () => invoke<void>("server_stop"),
serverStatus: () => invoke<ServerStatus>("server_status"),
openPath: (path: string) => invoke<void>("open_path", { path }),
};
export function onEvent<T>(channel: string, handler: (payload: T) => void) {
return listen<T>(channel, (event) => handler(event.payload));
}