@@ -9397,6 +9439,8 @@ const form = reactive({
fallback_model_openai: "gpt-4o",
fallback_model_gemini: "gemini-2.5-pro",
fallback_model_antigravity: "gemini-2.5-pro",
+ grok_default_text_model: "grok-4.5",
+ grok_cross_client_model_map_enabled: false,
// Identity patch (Claude -> Gemini)
enable_identity_patch: true,
identity_patch_prompt: "",
@@ -10972,6 +11016,10 @@ async function saveSettings() {
fallback_model_openai: form.fallback_model_openai,
fallback_model_gemini: form.fallback_model_gemini,
fallback_model_antigravity: form.fallback_model_antigravity,
+ grok_default_text_model:
+ form.grok_default_text_model.trim() || "grok-4.5",
+ grok_cross_client_model_map_enabled:
+ form.grok_cross_client_model_map_enabled,
enable_identity_patch: form.enable_identity_patch,
identity_patch_prompt: form.identity_patch_prompt,
min_claude_code_version: form.min_claude_code_version,
diff --git a/frontend/src/views/admin/__tests__/SettingsView.spec.ts b/frontend/src/views/admin/__tests__/SettingsView.spec.ts
index edcd879a9..75c36bac1 100644
--- a/frontend/src/views/admin/__tests__/SettingsView.spec.ts
+++ b/frontend/src/views/admin/__tests__/SettingsView.spec.ts
@@ -444,6 +444,8 @@ const baseSettingsResponse = {
fallback_model_openai: "",
fallback_model_gemini: "",
fallback_model_antigravity: "",
+ grok_default_text_model: "grok-4.5",
+ grok_cross_client_model_map_enabled: false,
enable_identity_patch: false,
identity_patch_prompt: "",
ops_monitoring_enabled: false,
@@ -1265,6 +1267,34 @@ describe("admin SettingsView payment visible method controls", () => {
expect(showSuccess).toHaveBeenCalledWith("上游倍率自动探测设置已保存");
});
+ it("loads and saves configurable Grok cross-client model mapping", async () => {
+ getSettings.mockResolvedValueOnce({
+ ...baseSettingsResponse,
+ grok_default_text_model: "grok-4.1-fast",
+ grok_cross_client_model_map_enabled: true,
+ });
+ const wrapper = mountView();
+
+ await flushPromises();
+ await openGatewayTab(wrapper);
+
+ const modelInput = wrapper.get('[data-testid="grok-default-text-model"]');
+ const mappingToggle = wrapper.get(
+ '[data-testid="grok-cross-client-model-map-toggle"]',
+ );
+ expect((modelInput.element as HTMLInputElement).value).toBe("grok-4.1-fast");
+ expect((mappingToggle.element as HTMLInputElement).checked).toBe(true);
+
+ await modelInput.setValue("grok-custom-text");
+ await mappingToggle.setValue(false);
+ await wrapper.find("form").trigger("submit.prevent");
+ await flushPromises();
+
+ const payload = updateSettings.mock.calls.at(-1)?.[0] as Record;
+ expect(payload.grok_default_text_model).toBe("grok-custom-text");
+ expect(payload.grok_cross_client_model_map_enabled).toBe(false);
+ });
+
it("loads fail-safe-off Ollama Cloud usage refresh settings and saves an explicit opt-in", async () => {
const wrapper = mountView();