Skip to content

Commit de8886a

Browse files
fix: auto-close files setting cannot be unchecked — always reverts to checked (#668)
* fix: include auto-close settings in getState and getStateToPostToWebview The autoCloseZooOpenedFiles, autoCloseZooOpenedFilesAfterUserEdited, and autoCloseZooOpenedNewFiles settings were saved to global state but never included in the state posted back to the webview (getStateToPostToWebview) or returned by getState. This caused the checkbox to always revert to checked after saving, and the DiffViewProvider to always use the default value regardless of the user's preference. Also adds a changeset instruction to AGENTS.md. Closes #667 * test: move auto-close settings tests to ClineProvider.spec.ts and assert all three fields Address review comments on PR #668: - Move the auto-close settings test block from ClineProvider.taskHistory.spec.ts to ClineProvider.spec.ts, where existing getState settings coverage (autoCondenseContext, writeDelayMs) already lives. - Expand the getState regression test to assert autoCloseZooOpenedFiles, autoCloseZooOpenedFilesAfterUserEdited, and autoCloseZooOpenedNewFiles so a regression dropping any of the three fields is caught.
1 parent ccf07eb commit de8886a

3 files changed

Lines changed: 60 additions & 0 deletions

File tree

AGENTS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
This file provides guidance to agents when working with code in this repository.
44

55
- Settings View Pattern: When working on `SettingsView`, inputs must bind to the local `cachedState`, NOT the live `useExtensionState()`. The `cachedState` acts as a buffer for user edits, isolating them from the `ContextProxy` source-of-truth until the user explicitly clicks "Save". Wiring inputs directly to the live state causes race conditions.
6+
- Changesets: Do NOT create `.changeset` files for each commit or code change. Changesets are managed separately by maintainers and should not be generated by agents during normal development.
67

78
## Test Placement Guidance
89

src/core/webview/ClineProvider.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2278,6 +2278,9 @@ export class ClineProvider
22782278
openRouterImageApiKey,
22792279
openRouterImageGenerationSelectedModel,
22802280
lockApiConfigAcrossModes,
2281+
autoCloseZooOpenedFiles,
2282+
autoCloseZooOpenedFilesAfterUserEdited,
2283+
autoCloseZooOpenedNewFiles,
22812284
} = await this.getState()
22822285

22832286
let cloudOrganizations: CloudOrganizationMembership[] = []
@@ -2457,6 +2460,9 @@ export class ClineProvider
24572460
imageGenerationProvider,
24582461
openRouterImageApiKey,
24592462
openRouterImageGenerationSelectedModel,
2463+
autoCloseZooOpenedFiles: autoCloseZooOpenedFiles ?? true,
2464+
autoCloseZooOpenedFilesAfterUserEdited: autoCloseZooOpenedFilesAfterUserEdited ?? false,
2465+
autoCloseZooOpenedNewFiles: autoCloseZooOpenedNewFiles ?? false,
24602466
openAiCodexIsAuthenticated: await (async () => {
24612467
try {
24622468
const { openAiCodexOAuthManager } = await import("../../integrations/openai-codex/oauth")
@@ -2657,6 +2663,9 @@ export class ClineProvider
26572663
imageGenerationProvider: stateValues.imageGenerationProvider,
26582664
openRouterImageApiKey: stateValues.openRouterImageApiKey,
26592665
openRouterImageGenerationSelectedModel: stateValues.openRouterImageGenerationSelectedModel,
2666+
autoCloseZooOpenedFiles: stateValues.autoCloseZooOpenedFiles,
2667+
autoCloseZooOpenedFilesAfterUserEdited: stateValues.autoCloseZooOpenedFilesAfterUserEdited,
2668+
autoCloseZooOpenedNewFiles: stateValues.autoCloseZooOpenedNewFiles,
26602669
}
26612670
}
26622671

src/core/webview/__tests__/ClineProvider.spec.ts

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1010,6 +1010,56 @@ describe("ClineProvider", () => {
10101010
expect(mockPostMessage).toHaveBeenCalled()
10111011
})
10121012

1013+
describe("auto-close settings are included in posted state", () => {
1014+
it("getStateToPostToWebview returns saved autoCloseZooOpenedFiles value", async () => {
1015+
await provider.resolveWebviewView(mockWebviewView)
1016+
1017+
// Simulate the updateSettings handler storing the value.
1018+
await provider.contextProxy.setValue("autoCloseZooOpenedFiles", false)
1019+
await provider.contextProxy.setValue("autoCloseZooOpenedFilesAfterUserEdited", true)
1020+
await provider.contextProxy.setValue("autoCloseZooOpenedNewFiles", true)
1021+
1022+
const state = await provider.getStateToPostToWebview()
1023+
1024+
// The saved values must be present in the state posted to the webview.
1025+
expect(state.autoCloseZooOpenedFiles).toBe(false)
1026+
expect(state.autoCloseZooOpenedFilesAfterUserEdited).toBe(true)
1027+
expect(state.autoCloseZooOpenedNewFiles).toBe(true)
1028+
})
1029+
1030+
it("getStateToPostToWebview defaults autoCloseZooOpenedFiles to true when unset", async () => {
1031+
await provider.resolveWebviewView(mockWebviewView)
1032+
1033+
// Ensure the settings are not set.
1034+
await provider.contextProxy.setValue("autoCloseZooOpenedFiles", undefined)
1035+
await provider.contextProxy.setValue("autoCloseZooOpenedFilesAfterUserEdited", undefined)
1036+
await provider.contextProxy.setValue("autoCloseZooOpenedNewFiles", undefined)
1037+
1038+
const state = await provider.getStateToPostToWebview()
1039+
1040+
// Unset values should default to their documented defaults.
1041+
expect(state.autoCloseZooOpenedFiles).toBe(true)
1042+
expect(state.autoCloseZooOpenedFilesAfterUserEdited).toBe(false)
1043+
expect(state.autoCloseZooOpenedNewFiles).toBe(false)
1044+
})
1045+
1046+
it("getState returns saved autoCloseZooOpenedFiles value for DiffViewProvider", async () => {
1047+
await provider.resolveWebviewView(mockWebviewView)
1048+
1049+
await provider.contextProxy.setValue("autoCloseZooOpenedFiles", false)
1050+
await provider.contextProxy.setValue("autoCloseZooOpenedFilesAfterUserEdited", true)
1051+
await provider.contextProxy.setValue("autoCloseZooOpenedNewFiles", true)
1052+
1053+
const state = await provider.getState()
1054+
1055+
// DiffViewProvider reads from getState(); all three fields must be present
1056+
// so a regression that drops any of them is caught.
1057+
expect(state.autoCloseZooOpenedFiles).toBe(false)
1058+
expect(state.autoCloseZooOpenedFilesAfterUserEdited).toBe(true)
1059+
expect(state.autoCloseZooOpenedNewFiles).toBe(true)
1060+
})
1061+
})
1062+
10131063
it("loads saved API config when switching modes", async () => {
10141064
await provider.resolveWebviewView(mockWebviewView)
10151065
const messageHandler = (mockWebviewView.webview.onDidReceiveMessage as any).mock.calls[0][0]

0 commit comments

Comments
 (0)