fix: persist /model selection for default conversations (#1239)

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Ari Webb
2026-03-03 12:52:00 -08:00
committed by GitHub
parent 200390ca33
commit d6d39fe0cf
2 changed files with 22 additions and 5 deletions

View File

@@ -3269,8 +3269,12 @@ export default function App({
const syncConversationModel = async () => {
// "default" is a virtual sentinel for the agent's primary message history,
// not a real conversation object — skip the API call.
// If the user just switched models via /model, honour the local override
// until the next agent state refresh brings back the updated model.
if (conversationId === "default") {
applyAgentModelLocally();
if (!hasConversationModelOverrideRef.current) {
applyAgentModelLocally();
}
return;
}
@@ -11014,8 +11018,10 @@ ${SYSTEM_REMINDER_CLOSE}
phase: "running",
});
// "default" is a virtual sentinel, not a real conversation object —
// skip the API call and fall through with undefined model_settings.
// Persist model change to the backend.
// For real conversations, update the conversation-scoped override.
// For "default" (virtual sentinel with no real conversation object),
// update the agent itself so the model sticks across messages.
let conversationModelSettings:
| AgentState["model_settings"]
| null
@@ -11034,6 +11040,14 @@ ${SYSTEM_REMINDER_CLOSE}
model_settings?: AgentState["model_settings"] | null;
}
).model_settings;
} else {
const { updateAgentLLMConfig } = await import("../agent/modify");
const updatedAgent = await updateAgentLLMConfig(
agentId,
modelHandle,
model.updateArgs,
);
conversationModelSettings = updatedAgent.model_settings;
}
// The API may not echo reasoning_effort back, so populate it from

View File

@@ -71,7 +71,7 @@ describe("model preset refresh wiring", () => {
expect(updateSegment).not.toContain("client.agents.update(");
});
test("/model handler updates conversation model (not agent model)", () => {
test("/model handler updates conversation model and falls back to agent for default", () => {
const path = fileURLToPath(new URL("../../cli/App.tsx", import.meta.url));
const source = readFileSync(path, "utf-8");
@@ -86,7 +86,10 @@ describe("model preset refresh wiring", () => {
expect(segment).toContain("updateConversationLLMConfig(");
expect(segment).toContain("conversationIdRef.current");
expect(segment).not.toContain("updateAgentLLMConfig(");
// For the "default" virtual conversation (no real conversation object),
// the handler falls back to updating the agent directly.
expect(segment).toContain("updateAgentLLMConfig(");
expect(segment).toContain('conversationIdRef.current !== "default"');
});
test("App defines helper to carry over active conversation model", () => {