From ec73cd8560be7d5e8b9741e404d7d45e17336996 Mon Sep 17 00:00:00 2001 From: nikita-ashihmin Date: Tue, 11 Aug 2026 13:21:42 +0400 Subject: [PATCH] feat: surface resolved model name in default model option description (#982) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary - When the SDK's `"default"` model entry carries a `resolvedModel` (e.g. `"claude-sonnet-5"`), `buildConfigOptions` now sets the option's `description` to the human-readable `displayName` of the matching named model (e.g. `"Claude Sonnet 5"`) - Falls back to the raw `resolvedModel` string if no named entry shares that resolved ID - No behaviour change when `resolvedModel` is absent This lets ACP clients show the actual model behind "Default" — e.g. "Default (Claude Sonnet 5)" — instead of just "Default (recommended)". ## Test plan - [ ] `buildConfigOptions model option resolved description > sets description to the named model's displayName when resolvedModel matches` - [ ] `buildConfigOptions model option resolved description > falls back to resolvedModel itself when no named model shares it` - [ ] `buildConfigOptions model option resolved description > leaves description undefined when default model has no resolvedModel` - [ ] All 753 existing tests still pass 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Sonnet 4.6 --- src/acp-agent.ts | 22 ++++++++--- src/tests/acp-agent.test.ts | 77 +++++++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+), 5 deletions(-) diff --git a/src/acp-agent.ts b/src/acp-agent.ts index 2f4c65bd..22d4f77b 100644 --- a/src/acp-agent.ts +++ b/src/acp-agent.ts @@ -6946,11 +6946,23 @@ export function buildConfigOptions( category: "model", type: "select", currentValue: models.currentModelId, - options: models.availableModels.map((m) => ({ - value: m.modelId, - name: m.name, - description: m.description ?? undefined, - })), + options: models.availableModels.map((m) => { + if (m.modelId === "default") { + const defaultInfo = modelInfos.find((mi) => mi.value === "default"); + const resolvedModel = defaultInfo?.resolvedModel; + if (resolvedModel) { + const namedMatch = modelInfos.find( + (mi) => mi.value !== "default" && mi.resolvedModel === resolvedModel, + ); + return { + value: m.modelId, + name: m.name, + description: namedMatch?.displayName ?? resolvedModel, + }; + } + } + return { value: m.modelId, name: m.name, description: m.description ?? undefined }; + }), }, ]; diff --git a/src/tests/acp-agent.test.ts b/src/tests/acp-agent.test.ts index 9fba24d6..5c4d180f 100644 --- a/src/tests/acp-agent.test.ts +++ b/src/tests/acp-agent.test.ts @@ -13462,6 +13462,83 @@ describe("agent selection config option", () => { }); }); + describe("buildConfigOptions model option resolved description", () => { + const modes = { currentModeId: "default", availableModes: [] }; + const models = { + currentModelId: "default", + availableModels: [{ modelId: "default", name: "Default", description: "" }], + }; + + it("sets description to the named model's displayName when resolvedModel matches", () => { + const modelInfos = [ + { + value: "default", + displayName: "Default", + description: "", + resolvedModel: "claude-sonnet-5", + }, + { + value: "sonnet", + displayName: "Claude Sonnet 5", + description: "Balanced", + resolvedModel: "claude-sonnet-5", + }, + ]; + const options = buildConfigOptions( + modes, + models, + modelInfos as any, + undefined, + [], + "default", + ); + const modelOption = options.find((o) => o.id === "model"); + const defaultEntry = (modelOption as any).options.find((o: any) => o.value === "default"); + expect(defaultEntry.description).toBe("Claude Sonnet 5"); + }); + + it("falls back to resolvedModel itself when no named model shares it", () => { + const modelInfos = [ + { + value: "default", + displayName: "Default", + description: "", + resolvedModel: "claude-opus-5-20251201", + }, + ]; + const options = buildConfigOptions( + modes, + models, + modelInfos as any, + undefined, + [], + "default", + ); + const modelOption = options.find((o) => o.id === "model"); + const defaultEntry = (modelOption as any).options.find((o: any) => o.value === "default"); + expect(defaultEntry.description).toBe("claude-opus-5-20251201"); + }); + + it("leaves description undefined when default model has no resolvedModel", () => { + const modelsNoDesc = { + currentModelId: "default", + availableModels: [{ modelId: "default", name: "Default" }], + }; + const modelInfos = [{ value: "default", displayName: "Default", description: "" }]; + const options = buildConfigOptions( + modes, + modelsNoDesc, + modelInfos as any, + undefined, + [], + "default", + ); + const modelOption = options.find((o) => o.id === "model"); + const defaultEntry = (modelOption as any).options.find((o: any) => o.value === "default"); + expect(defaultEntry.description).toBeUndefined(); + }); + }); + describe("switching the agent", () => { function createMockAgent() { const mockClient = { sessionUpdate: async () => {} } as unknown as AcpClient;