feat: add Claude subagent model config (#4830)

* feat: add Claude subagent takeover config

* feat: add Claude subagent model field

* i18n: add Claude subagent model labels

* fix(proxy): preserve configured subagent model mapping

* fix(providers): exclude subagent model from Claude common config

* style: format rust code
This commit is contained in:
秋澪Akimio
2026-07-07 10:28:36 +08:00
committed by GitHub
parent e606adfae7
commit b3e5e32c89
12 changed files with 257 additions and 33 deletions
@@ -85,6 +85,7 @@ const renderCopilotForm = (overrides: Partial<ClaudeFormFieldsProps> = {}) => {
defaultOpusModelName: "",
defaultFableModel: "",
defaultFableModelName: "",
subagentModel: "",
onModelChange: vi.fn(),
speedTestEndpoints: [],
apiFormat: "anthropic",
@@ -173,4 +174,25 @@ describe("ClaudeFormFields", () => {
);
});
});
it("一键设置会同时写入 Subagent 模型", () => {
const onModelChange = vi.fn();
renderCopilotForm({
claudeModel: "shared-model[1M]",
defaultSonnetModel: "",
defaultSonnetModelName: "",
onModelChange,
});
fireEvent.click(
screen.getByRole("button", {
name: "一键设置",
}),
);
expect(onModelChange).toHaveBeenCalledWith(
"CLAUDE_CODE_SUBAGENT_MODEL",
"shared-model[1M]",
);
});
});
+38
View File
@@ -17,6 +17,7 @@ describe("useModelState", () => {
ANTHROPIC_DEFAULT_SONNET_MODEL_NAME: "DeepSeek V4 Pro",
ANTHROPIC_DEFAULT_OPUS_MODEL: "kimi-k2",
ANTHROPIC_DEFAULT_OPUS_MODEL_NAME: "Kimi K2",
CLAUDE_CODE_SUBAGENT_MODEL: "subagent-model[1M]",
},
});
@@ -34,6 +35,7 @@ describe("useModelState", () => {
expect(result.current.defaultOpusModelName).toBe("Kimi K2");
expect(result.current.defaultHaikuModel).toBe("legacy-small");
expect(result.current.defaultHaikuModelName).toBe("legacy-small");
expect(result.current.subagentModel).toBe("subagent-model[1M]");
});
it("writes and clears role display-name env fields without changing model mapping", () => {
@@ -94,6 +96,42 @@ describe("useModelState", () => {
expect(result.current.defaultSonnetModelName).toBe("deepseek-v4-pro");
});
it("writes and clears the Claude Code subagent model env field", () => {
let latestConfig = JSON.stringify({
env: {
ANTHROPIC_MODEL: "fallback-model",
},
});
const onConfigChange = vi.fn((config: string) => {
latestConfig = config;
});
const { result } = renderHook(() =>
useModelState({
settingsConfig: latestConfig,
onConfigChange,
}),
);
act(() => {
result.current.handleModelChange(
"CLAUDE_CODE_SUBAGENT_MODEL",
"subagent-model[1M]",
);
});
let env = JSON.parse(latestConfig).env;
expect(env.ANTHROPIC_MODEL).toBe("fallback-model");
expect(env.CLAUDE_CODE_SUBAGENT_MODEL).toBe("subagent-model[1M]");
act(() => {
result.current.handleModelChange("CLAUDE_CODE_SUBAGENT_MODEL", "");
});
env = JSON.parse(latestConfig).env;
expect(env.CLAUDE_CODE_SUBAGENT_MODEL).toBeUndefined();
});
it("normalizes Claude Code 1M markers for UI toggles", () => {
expect(hasClaudeOneMMarker("deepseek-v4-pro[1m]")).toBe(true);
expect(hasClaudeOneMMarker("deepseek-v4-pro [1M] ")).toBe(true);