mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-08-04 11:43:57 +08:00
feat(codex): support native Responses direct-connect with generated model catalog
Codex providers can now run in two modes per provider: - Proxy-Chat (route takeover): apiFormat=openai_chat, existing Responses<->Chat conversion. Unchanged. - Native-Responses (direct): apiFormat=openai_responses, no proxy. cc-switch generates ~/.codex/cc-switch-model-catalog.json so Codex shows the custom models and tools work without the freeform apply_patch (type=custom) tool that native gateways like MiMo reject; editing falls back to shell_command. Catalog generation is keyed on apiFormat (CodexCatalogToolProfile), decoupled from the takeover toggle, so native providers persist a catalog without enabling local route mapping. Codex's catalog parser requires base_instructions on every entry; the native template carries a neutral default and per-vendor official text overrides it (MiMo, MiniMax). Synthesized catalogs for Qwen/Doubao/LongCat use the neutral default. Existing native providers must be re-saved once to regenerate a valid catalog (no DB migration).
This commit is contained in:
@@ -180,10 +180,24 @@ export const normalizeCodexCatalogModelsForSave = (
|
||||
? Number.parseInt(rawContextWindow, 10)
|
||||
: undefined;
|
||||
|
||||
const inputModalities = item.inputModalities?.filter(
|
||||
(m) => typeof m === "string" && m.trim(),
|
||||
);
|
||||
|
||||
const baseInstructions = item.baseInstructions?.trim();
|
||||
|
||||
normalized.push({
|
||||
model,
|
||||
...(displayName ? { displayName } : {}),
|
||||
...(contextWindow && contextWindow > 0 ? { contextWindow } : {}),
|
||||
// Native Responses profile overrides (ignored by the chat/proxy profile).
|
||||
...(typeof item.supportsParallelToolCalls === "boolean"
|
||||
? { supportsParallelToolCalls: item.supportsParallelToolCalls }
|
||||
: {}),
|
||||
...(inputModalities && inputModalities.length > 0
|
||||
? { inputModalities }
|
||||
: {}),
|
||||
...(baseInstructions ? { baseInstructions } : {}),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -599,7 +613,12 @@ function ProviderFormFull({
|
||||
// 接管已开)。只在 useState 初始化与预设重置点设置,跟 localCodexApiFormat
|
||||
// 对称,避免漂移。
|
||||
const [codexTakeoverEnabled, setCodexTakeoverEnabled] = useState<boolean>(
|
||||
() => codexCatalogCountFromSettings(initialData?.settingsConfig) > 0,
|
||||
() =>
|
||||
// Native (openai_responses) providers run DIRECT (no proxy takeover) yet
|
||||
// still carry a modelCatalog so cc-switch can generate model-catalogs.json.
|
||||
// So a catalog must NOT auto-enable takeover for native providers.
|
||||
initialCodexApiFormat !== "openai_responses" &&
|
||||
codexCatalogCountFromSettings(initialData?.settingsConfig) > 0,
|
||||
);
|
||||
|
||||
const { configError: codexConfigError, debouncedValidate } =
|
||||
@@ -1277,8 +1296,13 @@ function ProviderFormFull({
|
||||
category !== "official" && (codexConfig ?? "").trim()
|
||||
? setCodexWireApi(codexConfig ?? "", "responses")
|
||||
: (codexConfig ?? "");
|
||||
// Persist the catalog for proxy-takeover (Mode A) OR native-direct
|
||||
// (Mode B, apiFormat=openai_responses). Native providers run without the
|
||||
// proxy but still need cc-switch to generate model-catalogs.json, so the
|
||||
// catalog must survive even when the takeover toggle is off.
|
||||
const normalizedCatalogModels =
|
||||
category !== "official" && codexTakeoverEnabled
|
||||
category !== "official" &&
|
||||
(codexTakeoverEnabled || localCodexApiFormat === "openai_responses")
|
||||
? normalizeCodexCatalogModelsForSave(codexCatalogModels)
|
||||
: [];
|
||||
// Sync first catalog row's model into config.toml so Codex uses it as default
|
||||
@@ -1671,8 +1695,12 @@ function ProviderFormFull({
|
||||
codexApiFormatFromWireApi(extractCodexWireApi(config)) ??
|
||||
"openai_responses",
|
||||
);
|
||||
// 路由开关与格式无关,仅按预设是否带模型映射决定
|
||||
setCodexTakeoverEnabled((preset.modelCatalog?.length ?? 0) > 0);
|
||||
// 接管开关:原生(openai_responses)预设走直连、不开接管,即便带 catalog
|
||||
//(catalog 用于生成 model-catalogs.json);只有 chat 预设按是否带映射开启。
|
||||
setCodexTakeoverEnabled(
|
||||
(preset.apiFormat ?? "openai_responses") !== "openai_responses" &&
|
||||
(preset.modelCatalog?.length ?? 0) > 0,
|
||||
);
|
||||
|
||||
form.reset({
|
||||
name: preset.nameKey ? t(preset.nameKey) : preset.name,
|
||||
|
||||
Reference in New Issue
Block a user