diff --git a/AGENTS.md b/AGENTS.md index b93d6a76cc..c32cb8c64b 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -3,6 +3,7 @@ This file provides guidance to agents when working with code in this repository. - 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. +- 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. ## Test Placement Guidance diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts index 8cd0bdd911..30b1e7f185 100644 --- a/src/core/webview/ClineProvider.ts +++ b/src/core/webview/ClineProvider.ts @@ -2278,6 +2278,9 @@ export class ClineProvider openRouterImageApiKey, openRouterImageGenerationSelectedModel, lockApiConfigAcrossModes, + autoCloseZooOpenedFiles, + autoCloseZooOpenedFilesAfterUserEdited, + autoCloseZooOpenedNewFiles, } = await this.getState() let cloudOrganizations: CloudOrganizationMembership[] = [] @@ -2457,6 +2460,9 @@ export class ClineProvider imageGenerationProvider, openRouterImageApiKey, openRouterImageGenerationSelectedModel, + autoCloseZooOpenedFiles: autoCloseZooOpenedFiles ?? true, + autoCloseZooOpenedFilesAfterUserEdited: autoCloseZooOpenedFilesAfterUserEdited ?? false, + autoCloseZooOpenedNewFiles: autoCloseZooOpenedNewFiles ?? false, openAiCodexIsAuthenticated: await (async () => { try { const { openAiCodexOAuthManager } = await import("../../integrations/openai-codex/oauth") @@ -2657,6 +2663,9 @@ export class ClineProvider imageGenerationProvider: stateValues.imageGenerationProvider, openRouterImageApiKey: stateValues.openRouterImageApiKey, openRouterImageGenerationSelectedModel: stateValues.openRouterImageGenerationSelectedModel, + autoCloseZooOpenedFiles: stateValues.autoCloseZooOpenedFiles, + autoCloseZooOpenedFilesAfterUserEdited: stateValues.autoCloseZooOpenedFilesAfterUserEdited, + autoCloseZooOpenedNewFiles: stateValues.autoCloseZooOpenedNewFiles, } } diff --git a/src/core/webview/__tests__/ClineProvider.spec.ts b/src/core/webview/__tests__/ClineProvider.spec.ts index e1ddd881b8..158238ce7e 100644 --- a/src/core/webview/__tests__/ClineProvider.spec.ts +++ b/src/core/webview/__tests__/ClineProvider.spec.ts @@ -1010,6 +1010,56 @@ describe("ClineProvider", () => { expect(mockPostMessage).toHaveBeenCalled() }) + describe("auto-close settings are included in posted state", () => { + it("getStateToPostToWebview returns saved autoCloseZooOpenedFiles value", async () => { + await provider.resolveWebviewView(mockWebviewView) + + // Simulate the updateSettings handler storing the value. + await provider.contextProxy.setValue("autoCloseZooOpenedFiles", false) + await provider.contextProxy.setValue("autoCloseZooOpenedFilesAfterUserEdited", true) + await provider.contextProxy.setValue("autoCloseZooOpenedNewFiles", true) + + const state = await provider.getStateToPostToWebview() + + // The saved values must be present in the state posted to the webview. + expect(state.autoCloseZooOpenedFiles).toBe(false) + expect(state.autoCloseZooOpenedFilesAfterUserEdited).toBe(true) + expect(state.autoCloseZooOpenedNewFiles).toBe(true) + }) + + it("getStateToPostToWebview defaults autoCloseZooOpenedFiles to true when unset", async () => { + await provider.resolveWebviewView(mockWebviewView) + + // Ensure the settings are not set. + await provider.contextProxy.setValue("autoCloseZooOpenedFiles", undefined) + await provider.contextProxy.setValue("autoCloseZooOpenedFilesAfterUserEdited", undefined) + await provider.contextProxy.setValue("autoCloseZooOpenedNewFiles", undefined) + + const state = await provider.getStateToPostToWebview() + + // Unset values should default to their documented defaults. + expect(state.autoCloseZooOpenedFiles).toBe(true) + expect(state.autoCloseZooOpenedFilesAfterUserEdited).toBe(false) + expect(state.autoCloseZooOpenedNewFiles).toBe(false) + }) + + it("getState returns saved autoCloseZooOpenedFiles value for DiffViewProvider", async () => { + await provider.resolveWebviewView(mockWebviewView) + + await provider.contextProxy.setValue("autoCloseZooOpenedFiles", false) + await provider.contextProxy.setValue("autoCloseZooOpenedFilesAfterUserEdited", true) + await provider.contextProxy.setValue("autoCloseZooOpenedNewFiles", true) + + const state = await provider.getState() + + // DiffViewProvider reads from getState(); all three fields must be present + // so a regression that drops any of them is caught. + expect(state.autoCloseZooOpenedFiles).toBe(false) + expect(state.autoCloseZooOpenedFilesAfterUserEdited).toBe(true) + expect(state.autoCloseZooOpenedNewFiles).toBe(true) + }) + }) + it("loads saved API config when switching modes", async () => { await provider.resolveWebviewView(mockWebviewView) const messageHandler = (mockWebviewView.webview.onDidReceiveMessage as any).mock.calls[0][0]