Skip to content

Commit 8e8079d

Browse files
authored
Merge pull request #1322 from RooVetGit/cte/fix-extension-state
ExtensionStateContext does not correctly merge state
2 parents 773e556 + e201ee8 commit 8e8079d

File tree

3 files changed

+80
-9
lines changed

3 files changed

+80
-9
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"roo-cline": patch
3+
---
4+
5+
ExtensionStateContext does not correctly merge state

webview-ui/src/context/ExtensionStateContext.tsx

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,32 @@ export interface ExtensionStateContextType extends ExtensionState {
6969

7070
export const ExtensionStateContext = createContext<ExtensionStateContextType | undefined>(undefined)
7171

72+
export const mergeExtensionState = (prevState: ExtensionState, newState: ExtensionState) => {
73+
const {
74+
apiConfiguration: prevApiConfiguration,
75+
customModePrompts: prevCustomModePrompts,
76+
customSupportPrompts: prevCustomSupportPrompts,
77+
experiments: prevExperiments,
78+
...prevRest
79+
} = prevState
80+
81+
const {
82+
apiConfiguration: newApiConfiguration,
83+
customModePrompts: newCustomModePrompts,
84+
customSupportPrompts: newCustomSupportPrompts,
85+
experiments: newExperiments,
86+
...newRest
87+
} = newState
88+
89+
const apiConfiguration = { ...prevApiConfiguration, ...newApiConfiguration }
90+
const customModePrompts = { ...prevCustomModePrompts, ...newCustomModePrompts }
91+
const customSupportPrompts = { ...prevCustomSupportPrompts, ...newCustomSupportPrompts }
92+
const experiments = { ...prevExperiments, ...newExperiments }
93+
const rest = { ...prevRest, ...newRest }
94+
95+
return { ...rest, apiConfiguration, customModePrompts, customSupportPrompts, experiments }
96+
}
97+
7298
export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
7399
const [state, setState] = useState<ExtensionState>({
74100
version: "",
@@ -123,13 +149,8 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
123149
switch (message.type) {
124150
case "state": {
125151
const newState = message.state!
126-
setState((prevState) => ({
127-
...prevState,
128-
...newState,
129-
}))
130-
const config = newState.apiConfiguration
131-
const hasKey = checkExistKey(config)
132-
setShowWelcome(!hasKey)
152+
setState((prevState) => mergeExtensionState(prevState, newState))
153+
setShowWelcome(!checkExistKey(newState.apiConfiguration))
133154
setDidHydrateState(true)
134155
break
135156
}

webview-ui/src/context/__tests__/ExtensionStateContext.test.tsx

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
1-
import React from "react"
1+
// npx jest webview-ui/src/context/__tests__/ExtensionStateContext.test.tsx
2+
23
import { render, screen, act } from "@testing-library/react"
3-
import { ExtensionStateContextProvider, useExtensionState } from "../ExtensionStateContext"
4+
5+
import { ExtensionState } from "../../../../src/shared/ExtensionMessage"
6+
import { ExtensionStateContextProvider, useExtensionState, mergeExtensionState } from "../ExtensionStateContext"
7+
import { ExperimentId } from "../../../../src/shared/experiments"
8+
import { ApiConfiguration } from "../../../../src/shared/api"
49

510
// Test component that consumes the context
611
const TestComponent = () => {
@@ -63,3 +68,43 @@ describe("ExtensionStateContext", () => {
6368
consoleSpy.mockRestore()
6469
})
6570
})
71+
72+
describe("mergeExtensionState", () => {
73+
it("should correctly merge extension states", () => {
74+
const baseState: ExtensionState = {
75+
version: "",
76+
mcpEnabled: false,
77+
enableMcpServerCreation: false,
78+
clineMessages: [],
79+
taskHistory: [],
80+
shouldShowAnnouncement: false,
81+
enableCheckpoints: true,
82+
preferredLanguage: "English",
83+
writeDelayMs: 1000,
84+
requestDelaySeconds: 5,
85+
rateLimitSeconds: 0,
86+
mode: "default",
87+
experiments: {} as Record<ExperimentId, boolean>,
88+
customModes: [],
89+
maxOpenTabsContext: 20,
90+
apiConfiguration: { providerId: "openrouter" } as ApiConfiguration,
91+
}
92+
93+
const prevState: ExtensionState = {
94+
...baseState,
95+
apiConfiguration: { modelMaxTokens: 1234, modelMaxThinkingTokens: 123 },
96+
}
97+
const newState: ExtensionState = {
98+
...baseState,
99+
apiConfiguration: { modelMaxThinkingTokens: 456, modelTemperature: 0.3 },
100+
}
101+
102+
const result = mergeExtensionState(prevState, newState)
103+
104+
expect(result.apiConfiguration).toEqual({
105+
modelMaxTokens: 1234,
106+
modelMaxThinkingTokens: 456,
107+
modelTemperature: 0.3,
108+
})
109+
})
110+
})

0 commit comments

Comments
 (0)