fix(ui): stabilize agent model selection on switch (#72328)

* fix(ui): stabilize agent model selection on switch

* docs(changelog): credit projectclownfish fixes
This commit is contained in:
Vincent Koc
2026-04-27 12:06:02 -07:00
committed by GitHub
parent b393febbfa
commit 3cb460873d
3 changed files with 112 additions and 20 deletions

View File

@@ -1,5 +1,5 @@
import { render } from "lit";
import { describe, expect, it } from "vitest";
import { describe, expect, it, vi } from "vitest";
import { renderAgentFiles } from "./agents-panels-status-files.ts";
import { renderAgents, type AgentsProps } from "./agents.ts";
@@ -123,6 +123,73 @@ function createProps(overrides: Partial<AgentsProps> = {}): AgentsProps {
}
describe("renderAgents", () => {
it("remounts overview model controls when switching selected agents", async () => {
const container = document.createElement("div");
const configForm = {
agents: {
defaults: {
models: {
"anthropic/claude-sonnet-4-6": {},
"openai/gpt-5.4": {},
},
},
list: [
{ id: "alpha", model: { primary: "anthropic/claude-sonnet-4-6" } },
{ id: "beta", model: { primary: "openai/gpt-5.4" } },
],
},
};
render(
renderAgents(
createProps({
selectedAgentId: "beta",
config: {
form: configForm,
loading: false,
saving: false,
dirty: false,
},
}),
),
container,
);
const betaSelect = await vi.waitFor(() => {
const select = container.querySelector<HTMLSelectElement>(".agent-model-fields select");
expect(
Array.from(select?.options ?? []).some((option) => option.value === "openai/gpt-5.4"),
).toBe(true);
return select;
});
render(
renderAgents(
createProps({
selectedAgentId: "alpha",
config: {
form: configForm,
loading: false,
saving: false,
dirty: false,
},
}),
),
container,
);
const alphaSelect = await vi.waitFor(() => {
const select = container.querySelector<HTMLSelectElement>(".agent-model-fields select");
expect(
Array.from(select?.options ?? []).some(
(option) => option.value === "anthropic/claude-sonnet-4-6",
),
).toBe(true);
return select;
});
expect(alphaSelect).not.toBe(betaSelect);
});
it("shows the skills count only for the selected agent's report", async () => {
const container = document.createElement("div");
render(

View File

@@ -1,4 +1,5 @@
import { html, nothing } from "lit";
import { keyed } from "lit/directives/keyed.js";
import { t } from "../../i18n/index.ts";
import type {
AgentIdentityResult,
@@ -220,25 +221,28 @@ export function renderAgents(props: AgentsProps) {
tabCounts,
)}
${props.activePanel === "overview"
? renderAgentOverview({
agent: selectedAgent,
basePath: props.basePath,
defaultId,
configForm: props.config.form,
agentFilesList: props.agentFiles.list,
agentIdentity: props.agentIdentityById[selectedAgent.id] ?? null,
agentIdentityError: props.agentIdentityError,
agentIdentityLoading: props.agentIdentityLoading,
configLoading: props.config.loading,
configSaving: props.config.saving,
configDirty: props.config.dirty,
modelCatalog: props.modelCatalog,
onConfigReload: props.onConfigReload,
onConfigSave: props.onConfigSave,
onModelChange: props.onModelChange,
onModelFallbacksChange: props.onModelFallbacksChange,
onSelectPanel: props.onSelectPanel,
})
? keyed(
selectedAgent.id,
renderAgentOverview({
agent: selectedAgent,
basePath: props.basePath,
defaultId,
configForm: props.config.form,
agentFilesList: props.agentFiles.list,
agentIdentity: props.agentIdentityById[selectedAgent.id] ?? null,
agentIdentityError: props.agentIdentityError,
agentIdentityLoading: props.agentIdentityLoading,
configLoading: props.config.loading,
configSaving: props.config.saving,
configDirty: props.config.dirty,
modelCatalog: props.modelCatalog,
onConfigReload: props.onConfigReload,
onConfigSave: props.onConfigSave,
onModelChange: props.onModelChange,
onModelFallbacksChange: props.onModelFallbacksChange,
onSelectPanel: props.onSelectPanel,
}),
)
: nothing}
${props.activePanel === "files"
? renderAgentFiles({