From 972650377d65beec51837823cb6d681cad14f24f Mon Sep 17 00:00:00 2001 From: Jason Date: Sun, 2 Nov 2025 22:22:45 +0800 Subject: [PATCH] feat(codex): add AiHubMix provider and enhance configuration UX - Add new AiHubMix provider preset with dual endpoints - Fix AnyRouter base_url inconsistency (add /v1 suffix) - Add configuration wizard shortcut link for Codex custom mode - Improve accessibility with aria-label for wizard button - Remove unused isCustomMode prop from CodexConfigEditor - Add internationalization for new UI elements (zh/en) --- .../providers/forms/CodexConfigEditor.tsx | 2 -- .../providers/forms/ProviderForm.tsx | 7 +++++- .../forms/ProviderPresetSelector.tsx | 24 +++++++++++++++++- src/config/codexProviderPresets.ts | 25 ++++++++++++++----- src/i18n/locales/en.json | 1 + src/i18n/locales/zh.json | 1 + 6 files changed, 50 insertions(+), 10 deletions(-) diff --git a/src/components/providers/forms/CodexConfigEditor.tsx b/src/components/providers/forms/CodexConfigEditor.tsx index 86c9f46..4e11430 100644 --- a/src/components/providers/forms/CodexConfigEditor.tsx +++ b/src/components/providers/forms/CodexConfigEditor.tsx @@ -28,8 +28,6 @@ interface CodexConfigEditorProps { configError: string; // config.toml 错误提示 - isCustomMode?: boolean; // 是否为自定义模式 - onWebsiteUrlChange?: (url: string) => void; // 更新网址回调 isTemplateModalOpen?: boolean; // 模态框状态 diff --git a/src/components/providers/forms/ProviderForm.tsx b/src/components/providers/forms/ProviderForm.tsx index ebc274d..0c5bd59 100644 --- a/src/components/providers/forms/ProviderForm.tsx +++ b/src/components/providers/forms/ProviderForm.tsx @@ -453,6 +453,12 @@ export function ProviderForm({ presetCategoryLabels={presetCategoryLabels} onPresetChange={handlePresetChange} category={category} + appId={appId} + onOpenWizard={ + appId === "codex" + ? () => setIsCodexTemplateModalOpen(true) + : undefined + } /> )} @@ -523,7 +529,6 @@ export function ProviderForm({ commonConfigError={codexCommonConfigError} authError={codexAuthError} configError={codexConfigError} - isCustomMode={selectedPresetId === "custom"} onWebsiteUrlChange={(url) => form.setValue("websiteUrl", url)} onNameChange={(name) => form.setValue("name", name)} isTemplateModalOpen={isCodexTemplateModalOpen} diff --git a/src/components/providers/forms/ProviderPresetSelector.tsx b/src/components/providers/forms/ProviderPresetSelector.tsx index 7f63967..c318000 100644 --- a/src/components/providers/forms/ProviderPresetSelector.tsx +++ b/src/components/providers/forms/ProviderPresetSelector.tsx @@ -5,6 +5,7 @@ import { Zap } from "lucide-react"; import type { ProviderPreset } from "@/config/claudeProviderPresets"; import type { CodexProviderPreset } from "@/config/codexProviderPresets"; import type { ProviderCategory } from "@/types"; +import type { AppId } from "@/lib/api"; type PresetEntry = { id: string; @@ -18,6 +19,8 @@ interface ProviderPresetSelectorProps { presetCategoryLabels: Record; onPresetChange: (value: string) => void; category?: ProviderCategory; // 新增:当前选中的分类 + appId?: AppId; + onOpenWizard?: () => void; // Codex 专用:打开配置向导 } export function ProviderPresetSelector({ @@ -27,11 +30,13 @@ export function ProviderPresetSelector({ presetCategoryLabels, onPresetChange, category, + appId, + onOpenWizard, }: ProviderPresetSelectorProps) { const { t } = useTranslation(); // 根据分类获取提示文字 - const getCategoryHint = () => { + const getCategoryHint = (): React.ReactNode => { switch (category) { case "official": return t("providerForm.officialHint", { @@ -50,6 +55,23 @@ export function ProviderPresetSelector({ defaultValue: "💡 第三方供应商需要填写 API Key 和请求地址", }); case "custom": + // Codex 自定义:在此位置显示"手动配置…或者 使用配置向导" + if (appId === "codex" && onOpenWizard) { + return ( + <> + {t("providerForm.manualConfig")} + + + ); + } + // 其他情况沿用原提示 return t("providerForm.customApiKeyHint", { defaultValue: "💡 自定义配置需手动填写所有必要字段", }); diff --git a/src/config/codexProviderPresets.ts b/src/config/codexProviderPresets.ts index a841cc3..3cd3ada 100644 --- a/src/config/codexProviderPresets.ts +++ b/src/config/codexProviderPresets.ts @@ -70,6 +70,21 @@ export const codexProviderPresets: CodexProviderPreset[] = [ textColor: "#FFFFFF", }, }, + { + name: "AiHubMix", + websiteUrl: "https://aihubmix.com", + category: "cn_official", + auth: generateThirdPartyAuth(""), + config: generateThirdPartyConfig( + "aihubmix", + "https://aihubmix.com/v1", + "gpt-5-codex", + ), + endpointCandidates: [ + "https://aihubmix.com/v1", + "https://api.aihubmix.com/v1", + ], + }, { name: "PackyCode", websiteUrl: "https://www.packyapi.com", @@ -80,7 +95,6 @@ export const codexProviderPresets: CodexProviderPreset[] = [ "https://www.packyapi.com/v1", "gpt-5-codex", ), - // Codex 请求地址候选(用于地址管理/测速) endpointCandidates: [ "https://www.packyapi.com/v1", "https://api-slb.packyapi.com/v1", @@ -93,14 +107,13 @@ export const codexProviderPresets: CodexProviderPreset[] = [ auth: generateThirdPartyAuth(""), config: generateThirdPartyConfig( "anyrouter", - "https://anyrouter.top", + "https://anyrouter.top/v1", "gpt-5-codex", ), - // Codex 请求地址候选(用于地址管理/测速) endpointCandidates: [ - "https://anyrouter.top", - "https://q.quuvv.cn", - "https://pmpjfbhq.cn-nb1.rainapp.top", + "https://anyrouter.top/v1", + "https://q.quuvv.cn/v1", + "https://pmpjfbhq.cn-nb1.rainapp.top/v1", ], }, ]; diff --git a/src/i18n/locales/en.json b/src/i18n/locales/en.json index 71fa567..0c0ae08 100644 --- a/src/i18n/locales/en.json +++ b/src/i18n/locales/en.json @@ -226,6 +226,7 @@ "manageAndTest": "Manage & Test", "configContent": "Config Content", "useConfigWizard": "Use Configuration Wizard", + "openConfigWizard": "Open configuration wizard", "manualConfig": "Manually configure provider, requires complete configuration, or", "officialNoApiKey": "Official login does not require API Key, save directly", "codexOfficialNoApiKey": "Official does not require API Key, save directly", diff --git a/src/i18n/locales/zh.json b/src/i18n/locales/zh.json index 88be667..29e849a 100644 --- a/src/i18n/locales/zh.json +++ b/src/i18n/locales/zh.json @@ -226,6 +226,7 @@ "manageAndTest": "管理与测速", "configContent": "配置内容", "useConfigWizard": "使用配置向导", + "openConfigWizard": "打开配置向导", "manualConfig": "手动配置供应商,需要填写完整的配置信息,或者", "officialNoApiKey": "官方登录无需填写 API Key,直接保存即可", "codexOfficialNoApiKey": "官方无需填写 API Key,直接保存即可",