mirror of
https://github.com/agentclientprotocol/claude-agent-acp.git
synced 2026-10-27 04:30:59 +00:00
feat: surface resolved model name in default model option description (#982)
## 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 <noreply@anthropic.com>
This commit is contained in:
@@ -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 };
|
||||
}),
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user