mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-09-07 08:26:51 +00:00
fix: prevent stale cache when editing prompts across multiple windows
Add refreshGlobalStateKey() method to ContextProxy that reads fresh values from VS Code's globalState before performing read-modify-write operations. This fixes a bug where editing the context condensing prompt or mode prompts would revert to a previous value when multiple VS Code windows are open, because each window had its own stale cache.
This commit is contained in:
parent
06c5c7f980
commit
33f8e58833
3 changed files with 70 additions and 2 deletions
|
|
@ -208,6 +208,19 @@ export class ContextProxy {
|
|||
return this.originalContext.globalState.update(key, value)
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh a specific key from globalState and update the cache.
|
||||
* This is useful for settings that may be edited across multiple VS Code windows,
|
||||
* ensuring we read the latest value before making modifications.
|
||||
* @param key The global state key to refresh
|
||||
* @returns The fresh value from globalState
|
||||
*/
|
||||
refreshGlobalStateKey<K extends GlobalStateKey>(key: K): GlobalState[K] {
|
||||
const value = this.originalContext.globalState.get<GlobalState[K]>(key)
|
||||
this.stateCache[key] = value
|
||||
return value as GlobalState[K]
|
||||
}
|
||||
|
||||
private getAllGlobalState(): GlobalState {
|
||||
return Object.fromEntries(GLOBAL_STATE_KEYS.map((key) => [key, this.getGlobalState(key)]))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -185,6 +185,57 @@ describe("ContextProxy", () => {
|
|||
})
|
||||
})
|
||||
|
||||
describe("refreshGlobalStateKey", () => {
|
||||
it("should read fresh value from globalState and update cache", async () => {
|
||||
// Set up initial cache value
|
||||
await proxy.updateGlobalState("customSupportPrompts", { OLD: "old-prompt" })
|
||||
|
||||
// Simulate another window updating globalState directly (bypassing our cache)
|
||||
const newValue = { OLD: "old-prompt", NEW: "new-prompt" }
|
||||
mockGlobalState.get.mockReturnValue(newValue)
|
||||
|
||||
// Refresh the key
|
||||
const result = proxy.refreshGlobalStateKey("customSupportPrompts")
|
||||
|
||||
// Should return the fresh value from globalState
|
||||
expect(result).toEqual(newValue)
|
||||
|
||||
// Should have updated the cache (subsequent getGlobalState should return new value)
|
||||
const cachedValue = proxy.getGlobalState("customSupportPrompts")
|
||||
expect(cachedValue).toEqual(newValue)
|
||||
})
|
||||
|
||||
it("should return undefined when globalState has no value", async () => {
|
||||
// Set up initial cache value
|
||||
await proxy.updateGlobalState("customModePrompts", { code: { roleDefinition: "test" } })
|
||||
|
||||
// Simulate globalState being cleared (e.g., by another window)
|
||||
mockGlobalState.get.mockReturnValue(undefined)
|
||||
|
||||
// Refresh the key
|
||||
const result = proxy.refreshGlobalStateKey("customModePrompts")
|
||||
|
||||
// Should return undefined
|
||||
expect(result).toBeUndefined()
|
||||
|
||||
// Cache should also be updated to undefined
|
||||
const cachedValue = proxy.getGlobalState("customModePrompts")
|
||||
expect(cachedValue).toBeUndefined()
|
||||
})
|
||||
|
||||
it("should call globalState.get with the correct key", async () => {
|
||||
// Clear mock call history
|
||||
mockGlobalState.get.mockClear()
|
||||
mockGlobalState.get.mockReturnValue({ ENHANCE: "test-prompt" })
|
||||
|
||||
// Refresh a specific key
|
||||
proxy.refreshGlobalStateKey("customSupportPrompts")
|
||||
|
||||
// Should have called get with the correct key
|
||||
expect(mockGlobalState.get).toHaveBeenCalledWith("customSupportPrompts")
|
||||
})
|
||||
})
|
||||
|
||||
describe("getSecret", () => {
|
||||
it("should return value from cache when it exists", async () => {
|
||||
// Manually set a value in the cache
|
||||
|
|
|
|||
|
|
@ -1485,7 +1485,9 @@ export const webviewMessageHandler = async (
|
|||
break
|
||||
case "updatePrompt":
|
||||
if (message.promptMode && message.customPrompt !== undefined) {
|
||||
const existingPrompts = getGlobalState("customModePrompts") ?? {}
|
||||
// Use refreshGlobalStateKey to get the latest value from globalState,
|
||||
// avoiding stale cache issues when multiple VS Code windows are open.
|
||||
const existingPrompts = provider.contextProxy.refreshGlobalStateKey("customModePrompts") ?? {}
|
||||
const updatedPrompts = { ...existingPrompts, [message.promptMode]: message.customPrompt }
|
||||
await updateGlobalState("customModePrompts", updatedPrompts)
|
||||
const currentState = await provider.getStateToPostToWebview()
|
||||
|
|
@ -1571,7 +1573,9 @@ export const webviewMessageHandler = async (
|
|||
case "updateCondensingPrompt":
|
||||
// Store the condensing prompt in customSupportPrompts["CONDENSE"]
|
||||
// instead of customCondensingPrompt.
|
||||
const currentSupportPrompts = getGlobalState("customSupportPrompts") ?? {}
|
||||
// Use refreshGlobalStateKey to get the latest value from globalState,
|
||||
// avoiding stale cache issues when multiple VS Code windows are open.
|
||||
const currentSupportPrompts = provider.contextProxy.refreshGlobalStateKey("customSupportPrompts") ?? {}
|
||||
const updatedSupportPrompts = { ...currentSupportPrompts, CONDENSE: message.text }
|
||||
await updateGlobalState("customSupportPrompts", updatedSupportPrompts)
|
||||
// Also update the old field for backward compatibility during migration.
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue