mirror of
https://github.com/Kilo-Org/kilocode.git
synced 2026-10-29 18:52:45 +08:00
fix(vscode): allow clearing agent model override by sending null
Clearing the Model Override field for native agents (e.g. Explore,
General) sent the patch as `{ model: undefined }`. JSON.stringify drops
undefined, so the backend received an empty patch, the override stayed
in kilo.json, and the next configUpdated push repopulated the field.
Send `null` instead — the backend's patchJsonc already treats null as
a delete sentinel (matches the pattern already used in ModelsTab and
AutoApproveTab). Fixes #9527.
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"kilo-code": patch
|
||||
---
|
||||
|
||||
Fix clearing an agent's Model Override in Agent Behaviour settings. Previously, clearing the field and saving would repopulate the old value because the empty input was sent as `undefined` and dropped by `JSON.stringify`, so the backend never received a delete instruction. The field now reverts to the global default model as expected.
|
||||
@@ -155,4 +155,53 @@ describe("ConfigState", () => {
|
||||
expect(s.config.snapshot).toBe(true)
|
||||
expect(s.dirty).toBe(false)
|
||||
})
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Issue #9527: clearing an agent model override must unset it, not repopulate
|
||||
// -------------------------------------------------------------------------
|
||||
describe("clearing an agent model override (issue #9527)", () => {
|
||||
it("keeps null in the draft so the backend receives a delete sentinel", () => {
|
||||
const s = new ConfigState()
|
||||
s.handleConfigLoaded({ agent: { explore: { model: "anthropic/claude-sonnet-4-20250514" } } })
|
||||
|
||||
// User clears the Model Override field. ModeEditView now sends `null`
|
||||
// instead of `undefined` (the fix). null is the delete sentinel that
|
||||
// patchJsonc maps to jsonc-parser's remove operation.
|
||||
s.updateConfig({ agent: { explore: { model: null } } })
|
||||
|
||||
// Optimistic UI: stripNulls removes the key so the field renders empty.
|
||||
expect(s.config.agent?.explore?.model).toBeUndefined()
|
||||
expect(s.dirty).toBe(true)
|
||||
|
||||
// Draft must retain the null so it survives JSON.stringify on the wire
|
||||
// and reaches patchJsonc as an explicit delete.
|
||||
expect(s.draft.agent?.explore?.model).toBeNull()
|
||||
expect(JSON.parse(JSON.stringify(s.draft))).toEqual({
|
||||
agent: { explore: { model: null } },
|
||||
})
|
||||
})
|
||||
|
||||
it("undefined (the old buggy behavior) is dropped by JSON.stringify", () => {
|
||||
// Reproduction of the pre-fix bug: sending `undefined` results in an
|
||||
// empty patch on the wire, so the backend never deletes the override
|
||||
// and the next configUpdated pushes the stale model back into the UI.
|
||||
const draft = { agent: { explore: { model: undefined } } }
|
||||
expect(JSON.parse(JSON.stringify(draft))).toEqual({ agent: { explore: {} } })
|
||||
})
|
||||
|
||||
it("confirms the save and drops the draft once the backend acks", () => {
|
||||
const s = new ConfigState()
|
||||
s.handleConfigLoaded({ agent: { explore: { model: "anthropic/claude-sonnet-4-20250514" } } })
|
||||
s.updateConfig({ agent: { explore: { model: null } } })
|
||||
s.saveConfig()
|
||||
|
||||
// Backend removed the override and pushes the stripped config back.
|
||||
s.handleConfigUpdated({ agent: { explore: {} } })
|
||||
|
||||
expect(s.config.agent?.explore?.model).toBeUndefined()
|
||||
expect(s.dirty).toBe(false)
|
||||
expect(s.saving).toBe(false)
|
||||
expect(Object.keys(s.draft).length).toBe(0)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -145,7 +145,7 @@ const ModeEditView: Component<Props> = (props) => {
|
||||
<TextField
|
||||
value={cfg().model ?? ""}
|
||||
placeholder="e.g. anthropic/claude-sonnet-4-20250514"
|
||||
onChange={(val) => update({ model: val || undefined })}
|
||||
onChange={(val) => update({ model: val || null })}
|
||||
/>
|
||||
</SettingsRow>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user