refactor(claude-desktop): lock route IDs to sonnet/opus/haiku roles

Adapt to Claude Desktop 1.6259.1+ fail-all validation which only
accepts claude-(sonnet|opus|haiku)-* route IDs. Branded model names
(DeepSeek, Kimi, GLM, etc.) now live in a new labelOverride field
instead of being embedded in route IDs.

- Backend auto-repairs legacy unsafe routes to the next free
  sonnet/opus/haiku slot instead of erroring
- Frontend swaps the free-form route input for a role dropdown plus
  menu display name field
- Add CLAUDE_DESKTOP_ROLE_ROUTE_IDS as the single source of truth
  for role-to-route mapping; presets and form both consume it
- Drop the dead displayName alias on ClaudeDesktopModelRoute and the
  ineffective /v1/models display_name injection (UI ignores it)
- Update i18n (en/ja/zh) and form focus test for the new fields
This commit is contained in:
Jason
2026-05-13 15:22:23 +08:00
parent edf28b6422
commit 84bac6dce6
10 changed files with 493 additions and 233 deletions
@@ -28,7 +28,7 @@ function renderForm(
}
describe("ClaudeDesktopProviderForm", () => {
it("编辑模型映射的 Desktop 模型 ID 时保持输入框焦点", () => {
it("编辑模型映射的菜单显示名时保持输入框焦点", () => {
renderForm({
name: "Proxy Provider",
settingsConfig: {
@@ -47,15 +47,17 @@ describe("ClaudeDesktopProviderForm", () => {
},
});
const input = screen.getByPlaceholderText("gpt-5.5") as HTMLInputElement;
const input = screen.getByPlaceholderText(
"DeepSeek V4 Pro",
) as HTMLInputElement;
input.focus();
fireEvent.change(input, { target: { value: "12345" } });
fireEvent.change(input, { target: { value: "DeepSeek V4 Pro" } });
const currentInput = screen.getByPlaceholderText(
"gpt-5.5",
"DeepSeek V4 Pro",
) as HTMLInputElement;
expect(currentInput).toHaveValue("12345");
expect(currentInput).toHaveValue("DeepSeek V4 Pro");
expect(document.activeElement).toBe(currentInput);
});