Skip to content

Commit 86ef3d7

Browse files
jetyuJet
andauthored
Feature/v2.2.0 (#259)
## Summary / 概述 - ## Type of Change / 改动类型 - [ ] Bug fix / 问题修复 - [ ] Feature / 新功能 - [ ] Documentation / 文档 - [ ] Refactor / 重构 - [ ] Build, CI, or release / 构建、CI 或发布 - [ ] Other / 其他: ## Related Issues / 关联 Issue Closes # ## Changes / 主要改动 - ## Screenshots or Recordings / 截图或录屏 If this changes the UI, add screenshots or recordings here. 如涉及 UI 改动,请在此添加截图或录屏。 ## Testing / 测试 - [ ] `npm run build:main` - [ ] `npm run build:preload` - [ ] `npm run typecheck` - [ ] `npm run lint` - [ ] `npm run test:unit` - [ ] Not run / 未运行,原因: ## Checklist / 检查清单 - [ ] I kept this pull request focused and avoided unrelated refactors. - [ ] I followed the Electron layer boundary: Renderer → Preload/Bridge → Main. - [ ] I validated IPC input at the boundary when applicable. - [ ] I avoided `any`, `@ts-ignore`, and unnecessary `@ts-expect-error`. - [ ] I updated Simplified Chinese locale files for new or changed user-visible UI text. - [ ] I updated documentation when behavior, setup, or user-facing functionality changed. - [ ] I considered privacy, security, and user-data impact. - [ ] 我保持了 PR 聚焦,避免无关重构。 - [ ] 我遵循了 Electron 分层边界:Renderer → Preload/Bridge → Main。 - [ ] 如涉及 IPC,我已在边界完成输入校验。 - [ ] 我没有使用 `any`、`@ts-ignore` 或不必要的 `@ts-expect-error`。 - [ ] 如新增或修改用户可见 UI 文案,我已同步更新简体中文 locale 文件。 - [ ] 如行为、配置或用户可见功能变化,我已更新文档。 - [ ] 我已考虑隐私、安全和用户数据影响。 --------- Co-authored-by: Jet <jetyu91@163.com>
1 parent 1033db8 commit 86ef3d7

1 file changed

Lines changed: 30 additions & 14 deletions

File tree

‎electron/shared/ai-provider.constants.ts‎

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -52,25 +52,41 @@ export const AI_PROVIDER_CAPABILITIES = {
5252

5353
const AI_PROVIDER_SET = new Set<string>(Object.values(AI_PROVIDERS));
5454

55+
const AI_PROVIDER_BY_HOSTNAME = new Map<string, AiProvider>([
56+
['api.snaptium.com', AI_PROVIDERS.SNAPTIUM],
57+
['api.siliconflow.cn', AI_PROVIDERS.SILICONFLOW],
58+
['api.openai.com', AI_PROVIDERS.OPENAI],
59+
['generativelanguage.googleapis.com', AI_PROVIDERS.GOOGLE_GEMINI],
60+
['openrouter.ai', AI_PROVIDERS.OPENROUTER],
61+
['api.deepseek.com', AI_PROVIDERS.DEEPSEEK],
62+
['dashscope.aliyuncs.com', AI_PROVIDERS.QWEN],
63+
['maas.aliyuncs.com', AI_PROVIDERS.QWEN],
64+
['ark.cn-beijing.volces.com', AI_PROVIDERS.DOUBAO],
65+
['api.moonshot.ai', AI_PROVIDERS.KIMI],
66+
['open.bigmodel.cn', AI_PROVIDERS.ZHIPU],
67+
['api.x.ai', AI_PROVIDERS.GROK],
68+
]);
69+
5570
export function isAiProvider(value: unknown): value is AiProvider {
5671
return typeof value === 'string' && AI_PROVIDER_SET.has(value);
5772
}
5873

5974
export function inferAiProvider(baseUrl: string): AiProvider {
60-
const normalized = baseUrl.trim().toLowerCase();
61-
if (normalized.includes('api.snaptium.com')) return AI_PROVIDERS.SNAPTIUM;
62-
if (normalized.includes('api.siliconflow.cn')) return AI_PROVIDERS.SILICONFLOW;
63-
if (normalized.includes('api.openai.com')) return AI_PROVIDERS.OPENAI;
64-
if (normalized.includes('generativelanguage.googleapis.com')) return AI_PROVIDERS.GOOGLE_GEMINI;
65-
if (normalized.includes('openrouter.ai')) return AI_PROVIDERS.OPENROUTER;
66-
if (normalized.includes('api.deepseek.com')) return AI_PROVIDERS.DEEPSEEK;
67-
if (normalized.includes('dashscope.aliyuncs.com') || normalized.includes('maas.aliyuncs.com')) return AI_PROVIDERS.QWEN;
68-
if (normalized.includes('ark.cn-beijing.volces.com')) return AI_PROVIDERS.DOUBAO;
69-
if (normalized.includes('api.moonshot.ai')) return AI_PROVIDERS.KIMI;
70-
if (normalized.includes('open.bigmodel.cn')) return AI_PROVIDERS.ZHIPU;
71-
if (normalized.includes('api.x.ai')) return AI_PROVIDERS.GROK;
72-
if (normalized.includes('localhost:11434') || normalized.includes('127.0.0.1:11434')) return AI_PROVIDERS.OLLAMA;
73-
return AI_PROVIDERS.OPENAI_COMPATIBLE;
75+
try {
76+
const parsedUrl = new URL(baseUrl.trim());
77+
if (parsedUrl.protocol !== 'http:' && parsedUrl.protocol !== 'https:') {
78+
return AI_PROVIDERS.OPENAI_COMPATIBLE;
79+
}
80+
81+
const hostname = parsedUrl.hostname.toLowerCase();
82+
if ((hostname === 'localhost' || hostname === '127.0.0.1') && parsedUrl.port === '11434') {
83+
return AI_PROVIDERS.OLLAMA;
84+
}
85+
86+
return AI_PROVIDER_BY_HOSTNAME.get(hostname) ?? AI_PROVIDERS.OPENAI_COMPATIBLE;
87+
} catch {
88+
return AI_PROVIDERS.OPENAI_COMPATIBLE;
89+
}
7490
}
7591

7692
export function getAiProviderCapabilities(provider: AiProvider): AiCapability[] {

0 commit comments

Comments
 (0)