v0.7.0: 过程/答案分离 + 流式时序 + 自定义 API + 虚拟列表 + 打包
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { BrowserWindow, dialog, ipcMain } from 'electron'
|
||||
import { BrowserWindow, dialog, ipcMain, shell } from 'electron'
|
||||
import { mkdirSync } from 'node:fs'
|
||||
import { userInfo } from 'node:os'
|
||||
import { AgentService } from './pi/agent-service'
|
||||
|
||||
@@ -90,6 +91,37 @@ export function registerIpc(): AgentService {
|
||||
|
||||
ipcMain.handle('models:catalog', () => pass(() => service.getModelCatalog()))
|
||||
|
||||
// ---- 自定义 API 提供商(models.json)----
|
||||
ipcMain.handle('models:custom:list', () => service.listCustomProviders())
|
||||
|
||||
ipcMain.handle('models:custom:save', (_event, config: unknown) => {
|
||||
if (typeof config !== 'object' || config === null) throw new Error('invalid custom provider')
|
||||
const c = config as Record<string, unknown>
|
||||
if (
|
||||
typeof c.id !== 'string' ||
|
||||
typeof c.baseUrl !== 'string' ||
|
||||
typeof c.apiKey !== 'string' ||
|
||||
typeof c.api !== 'string' ||
|
||||
!Array.isArray(c.models)
|
||||
) {
|
||||
throw new Error('invalid custom provider')
|
||||
}
|
||||
const normalized = {
|
||||
id: c.id,
|
||||
name: typeof c.name === 'string' ? c.name : c.id,
|
||||
baseUrl: c.baseUrl,
|
||||
apiKey: c.apiKey,
|
||||
api: c.api,
|
||||
models: c.models.filter((m): m is string => typeof m === 'string')
|
||||
}
|
||||
return pass(() => service.saveCustomProvider(normalized))
|
||||
})
|
||||
|
||||
ipcMain.handle('models:custom:delete', (_event, id: unknown) => {
|
||||
if (typeof id !== 'string' || !id.trim()) throw new Error('invalid provider id')
|
||||
return pass(() => service.deleteCustomProvider(id))
|
||||
})
|
||||
|
||||
ipcMain.handle('models:set', (_event, providerId: unknown, modelId: unknown) => {
|
||||
if (typeof providerId !== 'string' || typeof modelId !== 'string') throw new Error('invalid model')
|
||||
return pass(() => service.setModel(providerId, modelId))
|
||||
@@ -178,9 +210,35 @@ export function registerIpc(): AgentService {
|
||||
})
|
||||
|
||||
ipcMain.handle('permissions:set', (_event, mode: unknown) => {
|
||||
const valid: ReadonlySet<string> = new Set(['confirm', 'autoEdit', 'plan', 'full'])
|
||||
if (typeof mode !== 'string' || !valid.has(mode)) throw new Error('invalid permission mode')
|
||||
service.setPermissionMode(mode as never)
|
||||
if (mode !== 'confirm' && mode !== 'full') throw new Error('invalid permission mode')
|
||||
service.setPermissionMode(mode)
|
||||
})
|
||||
|
||||
// ---- 设置页:技能 / 命令详情 ----
|
||||
ipcMain.handle('resources:details', () =>
|
||||
service.listResourceDetails().catch((err: unknown) => {
|
||||
throw new Error(err instanceof Error ? err.message : String(err))
|
||||
})
|
||||
)
|
||||
|
||||
// 在系统文件管理器中打开(技能/命令来源文件所在目录)
|
||||
ipcMain.handle('shell:openPath', (_event, target: unknown) => {
|
||||
if (typeof target !== 'string' || !target.trim()) throw new Error('invalid path')
|
||||
return shell.openPath(target)
|
||||
})
|
||||
|
||||
// 打开资源目录:不存在时先创建(skills/prompts 目录通常尚未建立)
|
||||
ipcMain.handle('shell:openDirectory', (_event, target: unknown) => {
|
||||
if (typeof target !== 'string' || !target.trim()) throw new Error('invalid path')
|
||||
try {
|
||||
mkdirSync(target, { recursive: true })
|
||||
} catch {
|
||||
// 已存在等情况忽略,交给 openPath 反馈
|
||||
}
|
||||
return shell.openPath(target).then((result) => {
|
||||
// shell.openPath 失败时以字符串返回错误信息,成功返回空串
|
||||
if (result) throw new Error(result)
|
||||
})
|
||||
})
|
||||
|
||||
ipcMain.handle('files:list', () =>
|
||||
|
||||
Reference in New Issue
Block a user