feat: 完成助手模式初版

This commit is contained in:
digua
2026-03-02 01:19:54 +08:00
parent c6aaa733ae
commit f36623d72e
24 changed files with 2086 additions and 64 deletions
+77 -4
View File
@@ -22,6 +22,7 @@ export interface AIConversation {
id: string
sessionId: string
title: string | null
assistantId: string
createdAt: number
updatedAt: number
}
@@ -416,8 +417,8 @@ export const aiApi = {
/**
* 创建 AI 对话
*/
createConversation: (sessionId: string, title?: string): Promise<AIConversation> => {
return ipcRenderer.invoke('ai:createConversation', sessionId, title)
createConversation: (sessionId: string, title?: string, assistantId?: string): Promise<AIConversation> => {
return ipcRenderer.invoke('ai:createConversation', sessionId, title, assistantId)
},
/**
@@ -661,6 +662,76 @@ export const llmApi = {
},
}
// ==================== Assistant API ====================
export interface AssistantSummary {
id: string
name: string
description: string
presetQuestions: string[]
order?: number
builtinId?: string
isUserModified?: boolean
applicableChatTypes?: ('group' | 'private')[]
supportedLocales?: string[]
}
export interface AssistantConfigFull {
id: string
name: string
description: string
systemPrompt: string
responseRules?: string
presetQuestions: string[]
allowedBuiltinTools?: string[]
customSkills?: unknown[]
version: number
builtinId?: string
isUserModified?: boolean
order?: number
applicableChatTypes?: ('group' | 'private')[]
supportedLocales?: string[]
}
export const assistantApi = {
getAll: (): Promise<AssistantSummary[]> => {
return ipcRenderer.invoke('assistant:getAll')
},
getConfig: (id: string): Promise<AssistantConfigFull | null> => {
return ipcRenderer.invoke('assistant:getConfig', id)
},
update: (
id: string,
updates: Partial<AssistantConfigFull>
): Promise<{ success: boolean; error?: string }> => {
return ipcRenderer.invoke('assistant:update', id, updates)
},
create: (
config: Omit<AssistantConfigFull, 'id' | 'version'>
): Promise<{ success: boolean; id?: string; error?: string }> => {
return ipcRenderer.invoke('assistant:create', config)
},
delete: (id: string): Promise<{ success: boolean; error?: string }> => {
return ipcRenderer.invoke('assistant:delete', id)
},
reset: (id: string): Promise<{ success: boolean; error?: string }> => {
return ipcRenderer.invoke('assistant:reset', id)
},
backupOldPresets: (data: {
customPresets?: unknown[]
builtinOverrides?: Record<string, unknown>
remotePresetIds?: string[]
}): Promise<{ success: boolean; filePath?: string; error?: string }> => {
return ipcRenderer.invoke('assistant:backupOldPresets', data)
},
}
// ==================== Agent API ====================
export const agentApi = {
@@ -680,7 +751,8 @@ export const agentApi = {
chatType?: 'group' | 'private',
promptConfig?: PromptConfig,
locale?: string,
maxHistoryRounds?: number
maxHistoryRounds?: number,
assistantId?: string
): { requestId: string; promise: Promise<{ success: boolean; result?: AgentResult; error?: string }> } => {
// 防御性处理:确保传给 IPC 的 context 是“可结构化克隆”的纯对象
// 避免调用方误传入响应式 Proxy(例如 Pinia/Vue state)导致 invoke 失败
@@ -759,7 +831,8 @@ export const agentApi = {
chatType,
promptConfig,
locale,
maxHistoryRounds
maxHistoryRounds,
assistantId
)
.then((result) => {
console.log('[preload] Agent invoke 返回:', result)
+53 -2
View File
@@ -281,6 +281,7 @@ interface AIConversation {
id: string
sessionId: string
title: string | null
assistantId: string
createdAt: number
updatedAt: number
}
@@ -356,7 +357,7 @@ interface AiApi {
senderId?: number,
keywords?: string[]
) => Promise<{ messages: SearchMessageResult[]; hasMore: boolean }>
createConversation: (sessionId: string, title?: string) => Promise<AIConversation>
createConversation: (sessionId: string, title?: string, assistantId?: string) => Promise<AIConversation>
getConversations: (sessionId: string) => Promise<AIConversation[]>
getConversation: (conversationId: string) => Promise<AIConversation | null>
updateConversationTitle: (conversationId: string, title: string) => Promise<boolean>
@@ -670,11 +671,57 @@ interface AgentApi {
chatType?: 'group' | 'private',
promptConfig?: PromptConfig,
locale?: string,
maxHistoryRounds?: number
maxHistoryRounds?: number,
assistantId?: string
) => { requestId: string; promise: Promise<{ success: boolean; result?: AgentResult; error?: string }> }
abort: (requestId: string) => Promise<{ success: boolean; error?: string }>
}
// ==================== 助手管理 ====================
interface AssistantSummary {
id: string
name: string
description: string
presetQuestions: string[]
order?: number
builtinId?: string
isUserModified?: boolean
applicableChatTypes?: ('group' | 'private')[]
supportedLocales?: string[]
}
interface AssistantConfigFull {
id: string
name: string
description: string
systemPrompt: string
responseRules?: string
presetQuestions: string[]
allowedBuiltinTools?: string[]
customSkills?: unknown[]
version: number
builtinId?: string
isUserModified?: boolean
order?: number
applicableChatTypes?: ('group' | 'private')[]
supportedLocales?: string[]
}
interface AssistantApi {
getAll: () => Promise<AssistantSummary[]>
getConfig: (id: string) => Promise<AssistantConfigFull | null>
update: (id: string, updates: Partial<AssistantConfigFull>) => Promise<{ success: boolean; error?: string }>
create: (config: Omit<AssistantConfigFull, 'id' | 'version'>) => Promise<{ success: boolean; id?: string; error?: string }>
delete: (id: string) => Promise<{ success: boolean; error?: string }>
reset: (id: string) => Promise<{ success: boolean; error?: string }>
backupOldPresets: (data: {
customPresets?: unknown[]
builtinOverrides?: Record<string, unknown>
remotePresetIds?: string[]
}) => Promise<{ success: boolean; filePath?: string; error?: string }>
}
// Cache API 类型
interface CacheDirectoryInfo {
id: string
@@ -867,6 +914,7 @@ declare global {
llmApi: LlmApi
embeddingApi: EmbeddingApi
agentApi: AgentApi
assistantApi: AssistantApi
cacheApi: CacheApi
networkApi: NetworkApi
sessionApi: SessionApi
@@ -884,6 +932,9 @@ export {
EmbeddingServiceConfig,
EmbeddingServiceConfigDisplay,
AgentApi,
AssistantApi,
AssistantSummary,
AssistantConfigFull,
CacheApi,
NetworkApi,
NlpApi,
+4 -1
View File
@@ -8,7 +8,7 @@ import { electronAPI } from '@electron-toolkit/preload'
// 从拆分的模块导入 API
import { extendedApi } from './apis/core'
import { chatApi, mergeApi } from './apis/chat'
import { aiApi, llmApi, agentApi, embeddingApi } from './apis/ai'
import { aiApi, llmApi, agentApi, embeddingApi, assistantApi } from './apis/ai'
import { nlpApi, networkApi, cacheApi, sessionApi } from './apis/utils'
// Use `contextBridge` APIs to expose Electron APIs to
@@ -24,6 +24,7 @@ if (process.contextIsolated) {
contextBridge.exposeInMainWorld('llmApi', llmApi)
contextBridge.exposeInMainWorld('agentApi', agentApi)
contextBridge.exposeInMainWorld('embeddingApi', embeddingApi)
contextBridge.exposeInMainWorld('assistantApi', assistantApi)
contextBridge.exposeInMainWorld('cacheApi', cacheApi)
contextBridge.exposeInMainWorld('networkApi', networkApi)
contextBridge.exposeInMainWorld('sessionApi', sessionApi)
@@ -49,6 +50,8 @@ if (process.contextIsolated) {
// @ts-ignore (define in dts)
window.embeddingApi = embeddingApi
// @ts-ignore (define in dts)
window.assistantApi = assistantApi
// @ts-ignore (define in dts)
window.cacheApi = cacheApi
// @ts-ignore (define in dts)
window.networkApi = networkApi