diff --git a/src/components/providers/forms/CodexFormFields.tsx b/src/components/providers/forms/CodexFormFields.tsx
index cbb181e5b..d603b3a40 100644
--- a/src/components/providers/forms/CodexFormFields.tsx
+++ b/src/components/providers/forms/CodexFormFields.tsx
@@ -616,7 +616,7 @@ export function CodexFormFields({
const supportsEffort = codexChatReasoning.supportsEffort === true;
// 高级区在有任何可见配置时自动展开(仅折叠→展开,不会自动折叠):自定义 UA /
- // 请求覆盖 / 已填模型映射 / 原生 Responses(需维护 catalog)/ 已配置思考能力。
+ // 请求覆盖 / 非默认的上游格式 / 已配置思考能力。模型列表在高级区外面,不算。
const hasRequestOverrides = Boolean(
localProxyHeadersOverride.trim() || localProxyBodyOverride.trim(),
);
@@ -624,8 +624,6 @@ export function CodexFormFields({
isCopilotPreset ||
!!customUserAgent ||
hasRequestOverrides ||
- catalogModels.length > 0 ||
- effectiveApiFormat === "openai_responses" ||
isAnthropicFormat ||
supportsThinking ||
supportsEffort ||
@@ -1027,8 +1025,8 @@ export function CodexFormFields({
seen.add(id);
suggestions.push({
id,
- ownedBy: t("codexConfig.modelMappingTitle", {
- defaultValue: "模型映射",
+ ownedBy: t("codexConfig.modelListTitle", {
+ defaultValue: "模型列表",
}),
});
}
@@ -1827,8 +1825,45 @@ export function CodexFormFields({
{apiKeySection}
{endpointSection}
+ {/* 模型列表 —— 生成 Codex 的模型目录(model_catalog_json):/model 菜单列哪些模型,
+ 各自的窗口和思考等级。留空不生成。默认模型、子代理从这里选,所以排在它们前面。 */}
+ {category !== "official" && canEditCatalog && (
+
)}
@@ -2062,58 +2100,10 @@ export function CodexFormFields({
)}
- {/* 模型映射 / 模型目录 —— 与「路由接管」解耦,常驻显示(可编辑即渲染)。
- 填了才生成 catalog:Chat 模式生成兼容路由、原生 Responses 生成
- model-catalogs.json;留空则不生成。排在自定义 UA 之前。 */}
- {canEditCatalog && (
-
-
-
-
- {t("codexConfig.modelMappingTitle", {
- defaultValue: "模型映射",
- })}
-
- {renderCatalogActionButtons(
- handleAddCatalogRow,
- t("codexConfig.addCatalogModel", {
- defaultValue: "手动添加",
- }),
- )}
-
-
- {t("codexConfig.modelMappingHint", {
- defaultValue:
- "选择模型角色后,CC Switch 会自动生成 Codex 兼容路由;菜单显示名可以填 DeepSeek、Kimi 等品牌模型,实际请求模型按右侧填写内容发送。",
- })}
-
-
-
- {fetchedModels.length > 0 && (
-
- row.model.trim(),
- )}
- onAdd={handleAddFetchedCatalogRows}
- />
- )}
- {catalogRows.length > 0 && renderCatalogRows()}
-
- )}
-
diff --git a/src/i18n/locales/en.json b/src/i18n/locales/en.json
index d71b55c62..22c5987af 100644
--- a/src/i18n/locales/en.json
+++ b/src/i18n/locales/en.json
@@ -1912,17 +1912,15 @@
"modelMetadataAdvancedHint": "Overrides Codex metadata for unknown models; clearing a field removes the matching config.toml entry.",
"defaultModelLabel": "Default Model",
"defaultModelPlaceholder": "e.g. gpt-5.6-sol",
- "defaultModelHint": "The model Codex requests by default; change it anytime without waiting for a preset update. If left empty while model mapping is configured, the first mapping row is used.",
- "defaultModelNotInCatalog": "This model is not in the model mapping, so the Codex /model menu won't list it (direct requests still work).",
+ "defaultModelHint": "The model Codex requests by default; change it anytime without waiting for a preset update. If left empty, the first row of the model list is used.",
+ "defaultModelNotInCatalog": "This model is not in the model list, so the Codex /model menu won't list it (direct requests still work).",
"subagentModelLabel": "Sub-agent Model",
"subagentModelPlaceholder": "Leave empty to follow the main model",
"subagentReasoningEffortLabel": "Sub-agent reasoning effort",
"subagentReasoningEffortDefault": "Default effort",
"subagentModelHint": "The model and reasoning effort Codex sub-agents use by default. When empty, sub-agents use the main agent's; with only a model set, they use that model's default effort. Not applied in Aggregation mode, where sub-agents follow the main model.",
- "subagentModelNotInCatalog": "This model is not in the model mapping: Codex can't get its context window, and when routing converts requests to Chat / Anthropic it is replaced by the default model.",
- "addToModelMapping": "Add to mapping",
- "modelMappingTitle": "Model Mapping",
- "modelMappingHint": "Generates Codex model_catalog_json so /model can show these third-party model names; entries are saved exactly as listed. Codex must be restarted to refresh the model list after changes.",
+ "subagentModelNotInCatalog": "This model is not in the model list: Codex can't get its context window, and when routing converts requests to Chat / Anthropic it is replaced by the default model.",
+ "modelListHint": "These models appear in Codex's /model menu with their own context window and reasoning levels. Restart Codex after changes.",
"addCatalogModel": "Add manually",
"modelListTitle": "Models",
"stackModelListHint": "These models appear in Codex's /model menu; picking one sends requests straight to this provider. Restart Codex after changes.",
@@ -1951,7 +1949,7 @@
"reasoningEffortHint": "Enable when the upstream supports thinking-depth control such as low/high/max. Enabling this also turns on thinking mode and converts Codex's reasoning.effort into the upstream Chat parameter.",
"reasoningGroupTitle": "Reasoning Capability",
"reasoningSectionHint": "Preset providers are configured automatically; custom providers are inferred from name/URL. Override manually only when auto-detection is wrong.",
- "advancedSectionHint": "Includes upstream format, model mapping, reasoning overrides and custom User-Agent. Providers using the Chat Completions protocol require routing takeover to be enabled.",
+ "advancedSectionHint": "Includes upstream format, reasoning overrides and custom User-Agent. Providers using the Chat Completions / Anthropic Messages protocol require routing to be enabled.",
"keyFieldsHint": "The endpoint, key, model, reasoning effort, context window and compatibility switches follow the provider; everything else is a global Codex setting that applies to every provider once saved.",
"inactiveFieldsHint": "This provider still stores {{count}} settings that are not applied when switching. Click one to copy its TOML and paste it above if you need it; the stored values are kept.",
"inactiveFieldCopied": "Copied"
diff --git a/src/i18n/locales/ja.json b/src/i18n/locales/ja.json
index d967aa25d..cf9d98a8d 100644
--- a/src/i18n/locales/ja.json
+++ b/src/i18n/locales/ja.json
@@ -1912,17 +1912,15 @@
"modelMetadataAdvancedHint": "未知のモデル向けに Codex メタデータを上書きします。空にすると対応する config.toml 設定を削除します。",
"defaultModelLabel": "デフォルトモデル",
"defaultModelPlaceholder": "例: gpt-5.6-sol",
- "defaultModelHint": "Codex がデフォルトでリクエストするモデルです。プリセットの更新を待たずにいつでも変更できます。空欄のままモデルマッピングを設定している場合は、マッピングの先頭行が使われます。",
- "defaultModelNotInCatalog": "このモデルはモデルマッピングにないため、Codex の /model メニューには表示されません(直接リクエストは有効です)。",
+ "defaultModelHint": "Codex がデフォルトでリクエストするモデルです。プリセットの更新を待たずにいつでも変更できます。空欄のときはモデル一覧の先頭行が使われます。",
+ "defaultModelNotInCatalog": "このモデルはモデル一覧にないため、Codex の /model メニューには表示されません(直接リクエストは有効です)。",
"subagentModelLabel": "サブエージェントモデル",
"subagentModelPlaceholder": "空欄ならメインモデルに従う",
"subagentReasoningEffortLabel": "サブエージェントの推論強度",
"subagentReasoningEffortDefault": "デフォルト強度",
"subagentModelHint": "Codex が起動するサブエージェントのデフォルトのモデルと推論強度です。空欄ならメインエージェントと同じものを使い、モデルだけ指定するとそのモデルのデフォルト強度を使います。集約モードでは適用されず、サブエージェントはメインモデルに従います。",
- "subagentModelNotInCatalog": "このモデルはモデルマッピングにありません。Codex はコンテキストウィンドウを取得できず、ルーティングで Chat / Anthropic 形式に変換する際はデフォルトモデルに置き換えられます。",
- "addToModelMapping": "マッピングに追加",
- "modelMappingTitle": "モデルマッピング",
- "modelMappingHint": "Codex model_catalog_json を生成し、/model コマンドでこれらの第三者モデル名を表示できるようにします。リストの内容はそのまま保存されます。変更後、モデルリストを更新するには Codex の再起動が必要です。",
+ "subagentModelNotInCatalog": "このモデルはモデル一覧にありません。Codex はコンテキストウィンドウを取得できず、ルーティングで Chat / Anthropic 形式に変換する際はデフォルトモデルに置き換えられます。",
+ "modelListHint": "これらのモデルは、それぞれのコンテキストウィンドウと思考レベル付きで Codex の /model に表示されます。変更後は Codex を再起動してください。",
"addCatalogModel": "手動で追加",
"modelListTitle": "モデル一覧",
"stackModelListHint": "これらのモデルは Codex の /model に表示され、選ぶとリクエストがこのプロバイダーへ直接送られます。変更後は Codex を再起動してください。",
@@ -1951,7 +1949,7 @@
"reasoningEffortHint": "上流が low/high/max などの思考の深さの制御に対応している場合に有効化します。有効にすると思考モードも自動的にオンになり、Codex の reasoning.effort を上流の Chat パラメータに変換します。",
"reasoningGroupTitle": "思考能力",
"reasoningSectionHint": "プリセットの供給元は自動的に設定され、カスタム供給元は名前/URL から自動推論されます。自動識別が正しくない場合のみ手動で上書きしてください。",
- "advancedSectionHint": "上流フォーマット、モデルマッピング、思考能力、カスタム User-Agent の設定を含みます。Chat Completions プロトコルを使用するプロバイダーはルーティング引き継ぎの有効化が必要です。",
+ "advancedSectionHint": "上流フォーマット、思考能力、カスタム User-Agent の設定を含みます。Chat Completions / Anthropic Messages プロトコルを使用するプロバイダーはルーティングの有効化が必要です。",
"keyFieldsHint": "エンドポイント、キー、モデル、推論レベル、コンテキストウィンドウ、互換スイッチはプロバイダーに合わせて切り替わります。それ以外は Codex のグローバル設定で、保存するとすべてのプロバイダーに適用されます。",
"inactiveFieldsHint": "このプロバイダーには切り替え時に適用されない設定が {{count}} 件保存されています。クリックすると TOML をコピーできるので、必要なら上に貼り付けてください。保存済みの値は削除されません。",
"inactiveFieldCopied": "コピーしました"
diff --git a/src/i18n/locales/zh-TW.json b/src/i18n/locales/zh-TW.json
index e95ff14ee..fe7739137 100644
--- a/src/i18n/locales/zh-TW.json
+++ b/src/i18n/locales/zh-TW.json
@@ -1907,17 +1907,15 @@
"promptCacheRoutingHint": "自動模式僅對已確認相容的上游傳送 prompt_cache_key;開啟可用於其他相容閘道,關閉可避免嚴格閘道因未知欄位回傳 400。只使用客戶端提供的穩定工作階段 ID。",
"defaultModelLabel": "預設模型",
"defaultModelPlaceholder": "例如: gpt-5.6-sol",
- "defaultModelHint": "Codex 預設請求的模型,隨時可改,無需等待軟體更新供應商範本。留空且設定了模型映射時,預設使用映射第一行。",
- "defaultModelNotInCatalog": "該模型不在模型映射中,Codex 的 /model 選單不會列出它(直接請求仍然有效)。",
+ "defaultModelHint": "Codex 預設請求的模型,隨時可改,無需等待軟體更新供應商範本。留空時使用模型列表第一行。",
+ "defaultModelNotInCatalog": "該模型不在模型列表中,Codex 的 /model 選單不會列出它(直接請求仍然有效)。",
"subagentModelLabel": "子代理模型",
"subagentModelPlaceholder": "留空則跟隨主模型",
"subagentReasoningEffortLabel": "子代理推理強度",
"subagentReasoningEffortDefault": "預設強度",
"subagentModelHint": "Codex 派出的子代理預設使用的模型和推理強度。留空時子代理沿用主代理的;只填模型時使用該模型自己的預設強度。聚合模式下不生效,子代理跟隨主模型。",
- "subagentModelNotInCatalog": "該模型不在模型映射中:Codex 取得不到它的上下文視窗;經路由轉成 Chat / Anthropic 協定時會被換成預設模型。",
- "addToModelMapping": "加入映射",
- "modelMappingTitle": "模型映射",
- "modelMappingHint": "產生 Codex model_catalog_json,讓 /model 指令顯示這些第三方模型名;表中條目按填寫內容原樣儲存。修改後需要重新啟動 Codex 才能重新整理模型清單。",
+ "subagentModelNotInCatalog": "該模型不在模型列表中:Codex 取得不到它的上下文視窗;經路由轉成 Chat / Anthropic 協定時會被換成預設模型。",
+ "modelListHint": "這些模型會出現在 Codex 的 /model 裡,帶上各自的上下文視窗和思考等級。修改後需要重新啟動 Codex。",
"addCatalogModel": "手動新增",
"modelListTitle": "模型列表",
"stackModelListHint": "這些模型會出現在 Codex 的 /model 裡,選中後請求直達這家。修改後需要重新啟動 Codex。",
@@ -1952,7 +1950,7 @@
"reasoningEffortHint": "上游支援 low/high/max 等思考深度控制時啟用。啟用後會自動啟用思考模式,並把 Codex 的 reasoning.effort 轉成上游 Chat 參數。",
"reasoningGroupTitle": "思考能力",
"reasoningSectionHint": "預設供應商已自動設定;自訂供應商會按名稱/位址自動推斷。僅當自動識別不準時才需手動覆寫。",
- "advancedSectionHint": "包含上游格式、模型映射、思考能力與自訂 User-Agent。使用 Chat Completions 協定的供應商需開啟路由接管才能使用。",
+ "advancedSectionHint": "包含上游格式、思考能力與自訂 User-Agent。使用 Chat Completions / Anthropic Messages 協定的供應商需開啟路由才能使用。",
"keyFieldsHint": "位址、Key、模型、推理檔位、上下文視窗和相容開關隨供應商切換;其餘是 Codex 全域設定,儲存後對所有供應商生效。",
"inactiveFieldsHint": "這個供應商還保存著 {{count}} 個不隨切換生效的設定。點擊可複製它的 TOML,依需要貼到上方;供應商裡保存的原值不會刪除。",
"inactiveFieldCopied": "已複製"
diff --git a/src/i18n/locales/zh.json b/src/i18n/locales/zh.json
index 44005c22b..8c7605b9e 100644
--- a/src/i18n/locales/zh.json
+++ b/src/i18n/locales/zh.json
@@ -1912,17 +1912,15 @@
"modelMetadataAdvancedHint": "用于未知模型的 Codex 元数据覆盖;清空字段会从 config.toml 删除对应配置。",
"defaultModelLabel": "默认模型",
"defaultModelPlaceholder": "例如: gpt-5.6-sol",
- "defaultModelHint": "Codex 默认请求的模型,随时可改,无需等待预设更新。留空且配置了模型映射时,默认使用映射第一行。",
- "defaultModelNotInCatalog": "该模型不在模型映射中,Codex 的 /model 菜单不会列出它(直接请求仍然有效)。",
+ "defaultModelHint": "Codex 默认请求的模型,随时可改,无需等待预设更新。留空时用模型列表第一行。",
+ "defaultModelNotInCatalog": "该模型不在模型列表中,Codex 的 /model 菜单不会列出它(直接请求仍然有效)。",
"subagentModelLabel": "子代理模型",
"subagentModelPlaceholder": "留空则跟随主模型",
"subagentReasoningEffortLabel": "子代理推理强度",
"subagentReasoningEffortDefault": "默认强度",
"subagentModelHint": "Codex 派出的子代理默认用的模型和推理强度。留空时子代理沿用主代理的;只填模型时用该模型自己的默认强度。聚合模式下不生效,子代理跟随主模型。",
- "subagentModelNotInCatalog": "该模型不在模型映射中:Codex 拿不到它的上下文窗口;经路由转成 Chat / Anthropic 协议时会被换成默认模型。",
- "addToModelMapping": "加入映射",
- "modelMappingTitle": "模型映射",
- "modelMappingHint": "生成 Codex model_catalog_json,让 /model 命令显示这些第三方模型名;表中条目按填写内容原样保存。修改后需要重启 Codex 才能刷新模型列表。",
+ "subagentModelNotInCatalog": "该模型不在模型列表中:Codex 拿不到它的上下文窗口;经路由转成 Chat / Anthropic 协议时会被换成默认模型。",
+ "modelListHint": "这些模型会出现在 Codex 的 /model 里,带上各自的上下文窗口和思考等级。修改后需要重启 Codex。",
"addCatalogModel": "手动添加",
"modelListTitle": "模型列表",
"stackModelListHint": "这些模型会出现在 Codex 的 /model 里,选中后请求直达这家。修改后需要重启 Codex。",
@@ -1951,7 +1949,7 @@
"reasoningEffortHint": "上游支持 low/high/max 等思考深度控制时启用。启用后会自动启用思考模式,并把 Codex 的 reasoning.effort 转成上游 Chat 参数。",
"reasoningGroupTitle": "思考能力",
"reasoningSectionHint": "预设供应商已自动配置;自定义供应商会按名称/地址自动推断。仅当自动识别不准时才需手动覆盖。",
- "advancedSectionHint": "包含上游格式、模型映射、思考能力与自定义 User-Agent。使用 Chat Completions 协议的供应商需开启路由接管才能使用。",
+ "advancedSectionHint": "包含上游格式、思考能力与自定义 User-Agent。使用 Chat Completions / Anthropic Messages 协议的供应商需开启路由才能使用。",
"keyFieldsHint": "地址、Key、模型、推理档位、上下文窗口和兼容开关随供应商切换;其余是 Codex 全局设置,保存后对所有供应商生效。",
"inactiveFieldsHint": "这个供应商还保存着 {{count}} 个不随切换生效的设置。点击复制它的 TOML,按需粘贴到上方;供应商里保存的原值不会删除。",
"inactiveFieldCopied": "已复制"
diff --git a/tests/components/CodexFormFields.subagent.test.tsx b/tests/components/CodexFormFields.subagent.test.tsx
index 05b039fe7..534434894 100644
--- a/tests/components/CodexFormFields.subagent.test.tsx
+++ b/tests/components/CodexFormFields.subagent.test.tsx
@@ -16,7 +16,7 @@ const FormShell = ({ children }: PropsWithChildren) => {
return ;
};
-const NOT_IN_CATALOG = /该模型不在模型映射中:Codex 拿不到它的上下文窗口/;
+const NOT_IN_CATALOG = /该模型不在模型列表中:Codex 拿不到它的上下文窗口/;
function renderCodexForm(overrides: Partial = {}) {
const props: CodexFormFieldsProps = {
@@ -82,7 +82,7 @@ describe("CodexFormFields sub-agent defaults", () => {
expect(subagentInput()).toBeNull();
});
- it("offers to add a model outside the mapping, with the default model when the mapping is empty", () => {
+ it("offers to add a model outside the list, with the default model when the list is empty", () => {
const onCatalogModelsChange = vi.fn();
renderCodexForm({
apiFormat: "openai_chat",
@@ -93,7 +93,7 @@ describe("CodexFormFields sub-agent defaults", () => {
expect(screen.getByText(NOT_IN_CATALOG)).toBeTruthy();
onCatalogModelsChange.mockClear();
- fireEvent.click(screen.getByRole("button", { name: "加入映射" }));
+ fireEvent.click(screen.getByRole("button", { name: "加入列表" }));
const rows = onCatalogModelsChange.mock.calls.at(-1)?.[0] ?? [];
expect(rows.map((row: { model: string }) => row.model)).toEqual([
"gpt-a",
@@ -101,8 +101,38 @@ describe("CodexFormFields sub-agent defaults", () => {
]);
});
- it("stays quiet for a native Responses provider without a mapping", () => {
+ it("stays quiet for a native Responses provider without a list", () => {
renderCodexForm({ subagentModel: "k3-mini", catalogModels: [] });
expect(screen.queryByText(NOT_IN_CATALOG)).toBeNull();
});
});
+
+describe("CodexFormFields direct layout", () => {
+ it("shows the model list outside the advanced section, before the default model", () => {
+ renderCodexForm({
+ catalogModels: [{ model: "gpt-a" }],
+ onCatalogModelsChange: vi.fn(),
+ });
+
+ const listTitle = screen.getByText("模型列表");
+ expect(listTitle).toBeVisible();
+ expect(screen.queryByText("上游格式")).toBeNull();
+ const defaultModel = document.getElementById("codexDefaultModel")!;
+ expect(
+ listTitle.compareDocumentPosition(defaultModel) &
+ Node.DOCUMENT_POSITION_FOLLOWING,
+ ).toBeTruthy();
+ // 列表上已有「获取模型列表」,默认模型旁不再放第二个。
+ expect(
+ screen.getAllByRole("button", { name: /providerForm\.fetchModels/ }),
+ ).toHaveLength(1);
+ });
+
+ it("keeps the fetch button on the default model when there is no list (Grok Build)", () => {
+ renderCodexForm();
+ expect(screen.queryByText("模型列表")).toBeNull();
+ expect(
+ screen.getByRole("button", { name: "providerForm.fetchModels" }),
+ ).toBeInTheDocument();
+ });
+});
diff --git a/tests/components/GrokBuildProviderForm.test.tsx b/tests/components/GrokBuildProviderForm.test.tsx
index 73235b7cc..667944f81 100644
--- a/tests/components/GrokBuildProviderForm.test.tsx
+++ b/tests/components/GrokBuildProviderForm.test.tsx
@@ -127,6 +127,9 @@ describe("GrokBuildProviderForm", () => {
expect(container.querySelector("#grokbuild-context-window")).toHaveValue(
500000,
);
+ // 默认的 Responses 格式不再把高级区自动展开。
+ expect(screen.queryByText("上游格式")).toBeNull();
+ fireEvent.click(screen.getByRole("button", { name: /高级选项/ }));
expect(screen.getByText("上游格式")).toBeInTheDocument();
});
diff --git a/tests/components/ProviderForm.codexCopilot.test.tsx b/tests/components/ProviderForm.codexCopilot.test.tsx
index 1b3f9fb3a..1f42ec30d 100644
--- a/tests/components/ProviderForm.codexCopilot.test.tsx
+++ b/tests/components/ProviderForm.codexCopilot.test.tsx
@@ -224,7 +224,7 @@ describe("Codex Copilot provider form", () => {
expect(screen.getAllByDisplayValue("272000")).toHaveLength(4);
expect(screen.getByDisplayValue("200000")).toBeVisible();
expect(formatControl()).toHaveTextContent(formatLabels.auto);
- expect(screen.getByText("模型映射")).toBeVisible();
+ expect(screen.getByText("模型列表")).toBeVisible();
});
it.each(["auto", "openai_chat", "openai_responses"])(
@@ -232,7 +232,7 @@ describe("Codex Copilot provider form", () => {
async (format) => {
const onSubmit = renderForm();
await selectFormat(format);
- expect(screen.getByText("模型映射")).toBeVisible();
+ expect(screen.getByText("模型列表")).toBeVisible();
fireEvent.click(screen.getByRole("button", { name: "save" }));
await waitFor(() => expect(onSubmit).toHaveBeenCalledTimes(1));
const saved = onSubmit.mock.calls[0][0];
@@ -490,7 +490,7 @@ describe("Codex Copilot provider form", () => {
it("keeps legacy cards automatic and shows mapping even with an empty catalog", () => {
renderForm({ providerType: "github_copilot", apiFormat: "openai_chat" });
expect(formatControl()).toHaveTextContent(formatLabels.auto);
- expect(screen.getByText("模型映射")).toBeVisible();
+ expect(screen.getByText("模型列表")).toBeVisible();
});
it("does not offer preset switching while editing an existing Copilot card", () => {
@@ -543,6 +543,8 @@ requires_openai_auth = true`;
screen.queryByTestId("selected-copilot-account"),
).not.toBeInTheDocument();
+ // 普通 Responses 卡的高级区默认折叠,上游格式在里面。
+ fireEvent.click(screen.getByRole("button", { name: /高级选项/ }));
await selectFormat("openai_chat");
fireEvent.click(screen.getByRole("button", { name: "save" }));
await waitFor(() => expect(onSubmit).toHaveBeenCalledTimes(1));
@@ -584,7 +586,7 @@ requires_openai_auth = true`;
);
fireEvent.click(screen.getByRole("button", { name: /DeepSeek/ }));
expect(formatControl()).toHaveTextContent("Responses(原生)");
- expect(screen.getByText("模型映射")).toBeVisible();
+ expect(screen.getByText("模型列表")).toBeVisible();
fireEvent.keyDown(formatControl(), { key: "ArrowDown" });
expect(
await screen.findByRole("option", { name: /Anthropic Messages/ }),
@@ -592,6 +594,6 @@ requires_openai_auth = true`;
fireEvent.click(screen.getByRole("option", { name: "Responses(原生)" }));
fireEvent.click(screen.getByRole("button", { name: /GitHub Copilot/ }));
expect(formatControl()).toHaveTextContent(formatLabels.auto);
- expect(screen.getByText("模型映射")).toBeVisible();
+ expect(screen.getByText("模型列表")).toBeVisible();
});
});
diff --git a/tests/components/ProviderForm.stackModels.test.tsx b/tests/components/ProviderForm.stackModels.test.tsx
index 10e2b904d..520bb7aa1 100644
--- a/tests/components/ProviderForm.stackModels.test.tsx
+++ b/tests/components/ProviderForm.stackModels.test.tsx
@@ -360,7 +360,8 @@ describe("ProviderForm Stack layout (Codex)", () => {
it("没开 Stack 设置时仍是完整表单", () => {
settingsState.enableStackMode = false;
renderForm("codex", vi.fn());
- expect(screen.queryByText("模型列表")).toBeNull();
+ // 完整表单也有模型列表,但说明是直连版的。
+ expect(screen.queryByText(/选中后请求直达这家/)).toBeNull();
expect(document.getElementById("codexDefaultModel")).not.toBeNull();
expect(screen.getByTestId("codex-config-editor")).toBeInTheDocument();
});