ProviderManager 内部机制
ProviderManager 负责 LLM 提供商的生命周期管理,包括创建、读取、更新、删除操作,以及预设模板系统和持久化存储。
文件位置
| 文件 | 路径 |
|---|---|
| ProviderManager | packages/desktop/app/main/services/capabilities/llm/config-service/ProviderManager.ts |
| LLMConfigService | packages/desktop/app/main/services/capabilities/llm/config-service/LLMConfigService.ts |
| Provider 模板 | packages/desktop/app/shared/llm-config.ts (PROVIDER_TEMPLATES) |
| Provider 预设 | packages/desktop/app/shared/provider-presets.ts |
| Schemas | packages/desktop/app/main/services/capabilities/llm/config-service/schemas.ts |
| IPC Router | packages/desktop/app/main/services/routers/llm/ProviderRouter.ts |
架构上下文
委托模式
LLMConfigService 采用委托模式(Delegate Pattern),将职责分散到四个专职管理器。ProviderManager 通过 ProviderManagerDelegate 接口与宿主通信,避免循环依赖。
graph TB
subgraph LLMConfigService
direction TB
PM[ProviderManager]
MDM[ModelDiscoveryManager]
CIOM[ConfigIOManager]
AMM[AgentModelsManager]
end
PM -->|Delegate| LLMConfigService
MDM -->|Delegate| LLMConfigService
CIOM -->|Delegate| LLMConfigService
AMM -->|Delegate| LLMConfigService
subgraph 存储
SQLite[(SQLite 主存储)]
JSON[(JSON 回退)]
end
PM --> SQLite
PM --> JSON
subgraph 缓存
PI[Provider Index<br/>Map 索引]
end
PM --> PI
Delegate 接口
interface ProviderManagerDelegate {
loadConfig(): Promise<LLMsConfig>; // 加载 JSON 配置
saveConfig(): Promise<void>; // 保存 JSON 配置
getDb(): DbClient | null; // 获取数据库实例
waitForMigration(): Promise<void>; // 等待数据迁移完成
useSQLite(): boolean; // 是否使用 SQLite
isMigrated(): Promise<boolean>; // 是否已迁移
invalidateProviderIndex(): void; // 使 Provider 索引失效
invalidateConfig(): void; // 使配置缓存失效
buildProviderIndex(providers: LLMProvider[]): void; // 构建索引
getProviderFromIndex(id: string): LLMProvider | undefined; // 索引查询
hasProviderIndex(): boolean; // 索引是否存在
}
数据结构
LLMProvider 完整定义
interface LLMProvider {
id: string; // UUID 或预设 ID(如 'openai', 'anthropic')
name: string; // 显示名称
apiFormat?: ApiFormat; // 首选 API 格式字段
chatApiFormat?: ApiFormat; // 遗留格式字段(向后兼容)
apiType?: string; // 遗留类型字段
api_base_url?: string; // API Base URL
api_key: string; // 单密钥值(遗留,新系统使用 ApiKeyPool)
models: string[]; // 支持的模型 ID 列表
modelConfigs?: ModelConfig[]; // 每模型详细配置
modelGroups?: ModelGroup[]; // 模型分组(带分类信息)
modelsEndpoint?: string; // 模型发现 API 端点
enabled: boolean; // 是否启用
transformer?: TransformerConfig; // 请求/响应转换链
icon?: string; // 图标路径或 emoji
website?: string; // 官网链接
docsUrl?: string; // API 文档链接
defaultSettings?: CompletionSettings; // 默认补全设置
codingPlan?: CodingPlanConfig; // Coding Plan 专用配置
isSystem?: boolean; // 系统内置标记(不可删除)
presetId?: string; // 来源预设模板 ID
headers?: Record<string, string>; // 自定义 HTTP 头
createdAt: string; // ISO 时间戳
updatedAt: string; // ISO 时间戳
}
interface ModelConfig {
id: string;
name: string;
enabled: boolean;
category?: 'chat' | 'reasoning' | 'image' | 'video' | 'embedding' | 'code';
group?: string;
contextLength?: number;
maxTokens?: number;
completionSettings?: CompletionSettings;
vision?: boolean; // 视觉能力
functionCall?: boolean; // 函数调用能力
reasoning?: boolean; // 推理能力
webSearch?: boolean; // 搜索能力
}
算法/逻辑说明
Provider CRUD 操作流程
添加提供商(SQLite 路径)
1. 接收 LLMProviderInput
2. 生成 UUID 作为 provider.id
3. 填充默认值(enabled=false, defaultSettings=DEFAULT_COMPLETION_SETTINGS)
4. Zod Schema 验证(LLMProviderSchema.parse)
5. 唯一性检查:查询 SQLite 确认 ID 不存在
6. 写入 SQLite: db.llmProvidersInsert(provider)
7. 同步模型列表到 llm_models 表
8. 同步模型分组到 llm_model_groups 表
9. 使 Provider Index 失效: invalidateProviderIndex()
10. 返回 { success: true, provider }
更新提供商
1. 接收 { id, ...updates }
2. 从 SQLite 读取现有 provider
3. 合并更新字段(浅合并)
4. 更新 updatedAt 时间戳
5. 写入 SQLite: db.llmProvidersUpdate(id, updates)
6. 如果 models 或 modelConfigs 变更 → 同步模型表
7. 使 Provider Index 失效
8. 返回 { success: true, provider }
删除提供商
1. 检查 isSystem 标记 → 系统内置不可删除
2. 从 SQLite 删除: db.llmProvidersDelete(id)
3. 级联删除关联模型和分组
4. 使 Provider Index 失效
5. 返回 { success: true }
Provider Index(O(1) 查找)
graph LR
subgraph 首次查询
Load[loadConfig 或 SQLite 查询] --> Build[构建 Map]
Build --> Cache[providerIndex: Map<id, Provider>]
end
subgraph 后续查询
Cache --> Lookup[O(1) Map.get]
end
subgraph 变更操作
CRUD[add/update/delete] --> Invalidate[providerIndex = null]
Invalidate --> Load
end
行为规则:
| 操作 | 对索引的影响 |
|---|---|
getProvider(id) | 命中索引 → 返回;未命中 → 重建索引后查找 |
getProviders() | 返回完整列表并重建索引 |
addProvider | 使索引失效 |
updateProvider | 使索引失效 |
deleteProvider | 使索引失效 |
toggleProvider | 使索引失效 |
双存储机制(SQLite + JSON 回退)
flowchart TD
Start[启动] --> CheckDB{DbClient 可用?}
CheckDB -->|是| Migrate[ensureMigrated]
CheckDB -->|否| JSONMode[JSON 模式]
Migrate --> CheckMigrated{已迁移?}
CheckMigrated -->|是| SQLiteMode[SQLite 模式]
CheckMigrated -->|否| DoMigrate[JSON → SQLite 迁移]
DoMigrate --> SQLiteMode
subgraph SQLite模式
SQLiteMode --> SQLiteRead[db.llmProvidersGetAll]
SQLiteMode --> SQLiteWrite[db.llmProvidersInsert/Update/Delete]
end
subgraph JSON模式
JSONMode --> JSONRead[fs.readFile + JSON.parse]
JSONMode --> JSONWrite[JSON.stringify + fs.writeFile]
end
迁移过程:
- 启动时检查 SQLite 中
llm_config_migrated标记 - 如果未迁移,读取
llms-config.json - 逐条将 Provider 数据写入 SQLite
- 同步 models、modelGroups 到对应表
- 设置迁移完成标记
- JSON 文件保留作为备份(不再作为主存储)
预设/模板系统
默认提供商列表
系统内置以下提供商模板(按 getDefaultProviders() 中的顺序):
| 序号 | ID | 名称 | API Format |
|---|---|---|---|
| 1 | deepseek | DeepSeek | openai |
| 2 | openrouter | OpenRouter | openai |
| 3 | silicon | SiliconFlow | openai |
| 4 | openai | OpenAI | openai |
| 5 | anthropic | Anthropic | anthropic |
| 6 | gemini | Google Gemini | |
| 7 | zhipu | 智谱 AI | openai |
| 8 | moonshot | Moonshot | openai |
| 9 | dashscope | 通义千问 | openai |
| 10 | ollama | Ollama | openai |
| 11 | groq | Groq | openai |
| 12 | claude-code | Claude Code | anthropic |
从模板创建提供商
createProviderFromTemplate(template):
1. 复制 template 的所有配置字段
2. 设置 api_key = ''(用户需要自行配置)
3. 设置 enabled = false
4. 填充 defaultSettings(使用 template.defaultSettings 或 DEFAULT_COMPLETION_SETTINGS)
5. 生成 createdAt / updatedAt 时间戳
6. 返回 LLMProvider 实例
预设模板(Provider Presets)
预设模板来自 provider-presets.ts,是比内置模板更丰富的配置,通常针对中国云厂商。预设模板包含:
interface PresetProviderTemplate {
id: string; // 预设 ID
name: string; // 显示名称
apiFormat: ApiFormat; // API 格式
baseUrl: string; // Base URL
models: string[]; // 模型列表
modelConfigs: ModelConfig[]; // 模型详细配置
features: string[]; // 特性标签
// ... 更多字段
}
从预设添加提供商:
addFromPreset(presetId, apiKey?):
1. 通过 getPresetById(presetId) 查找预设
2. 将预设转为 ProviderTemplate
3. 调用 createProviderFromTemplate(template)
4. 如果提供 apiKey → 设置密钥
5. 调用 addProvider() 持久化
6. 返回新提供商
IPC 集成表
| IPC 通道 | 方向 | 参数 | 返回值 | Zod 验证 |
|---|---|---|---|---|
llmConfig:getProviders | R → M | 无 | LLMProvider[] | 无 |
llmConfig:getProvider | R → M | { id: string } | LLMProvider | null | llmProviderIdSchema |
llmConfig:addProvider | R → M | LLMProviderInput | LLMProviderResult | llmProviderCreateSchema |
llmConfig:updateProvider | R → M | { id, ...fields } | LLMProviderResult | llmProviderUpdateSchema |
llmConfig:deleteProvider | R → M | { id: string } | { success, message? } | llmProviderIdSchema |
llmConfig:toggleProvider | R → M | { id, enabled } | LLMProviderResult | id + boolean |
llmConfig:discoverModels | R → M | { id, options? } | ProviderModelDiscoveryResult | modelDiscoverOptionsSchema |
llmConfig:getProviderPresets | R → M | 无 | PresetProviderTemplate[] | 无 |
llmConfig:addFromPreset | R → M | { presetId, apiKey? } | LLMProviderResult | string + string? |
llmConfig:exportConfig | R → M | 无 | LLMsConfig | 无 |
llmConfig:importConfig | R → M | 配置对象 | { success, message? } | Zod object |
扩展点
如何添加新的内置提供商
- 在
packages/desktop/app/shared/llm-config.ts的PROVIDER_TEMPLATES数组中添加ProviderTemplate - 在
ProviderManager.getDefaultProviders()的defaultTemplateIds数组中添加新 ID - 如果需要特殊 URL 构建逻辑,在
url-builder.ts中添加处理 - 如果需要搜索支持,在
provider-presets.ts的PROVIDER_SEARCH_CONFIGS中添加条目 - 如果需要 Coding Plan 支持,在
CODING_PLAN_URL_PRESETS中添加条目 - 如果需要 Follow-Provider 支持,在
PROVIDER_MODEL_MAPPINGS中添加条目
如何添加新的预设模板
- 在
provider-presets.ts的PROVIDER_PRESETS数组中添加PresetProviderTemplate - 填充完整的模型配置(modelConfigs、contextLength、maxTokens、capabilities)
- 前端会自动在预设列表中显示新模板
关联文件表
| 文件 | 关联方式 |
|---|---|
capabilities/llm/config-service/LLMConfigService.ts | 宿主服务,初始化 ProviderManager 并提供 Delegate |
capabilities/llm/config-service/schemas.ts | Zod 验证 Schema(LLMProviderSchema 等) |
routers/llm/ProviderRouter.ts | IPC 层,接收前端请求并调用 LLMConfigService |
routers/llm/schemas.ts | IPC 参数验证 Schema |
shared/llm-config.ts | 共享类型定义和内置模板 |
shared/provider-presets.ts | 预设模板、搜索配置、Coding Plan URL |
workers/DbClient.ts | SQLite 数据库操作 |
workers/db/apiKeys.ts | API 密钥表 CRUD |
capabilities/llm/completion/CompletionService.ts | 消费 Provider 配置进行 API 调用 |