Skip to content

Commit e1fb929

Browse files
authored
Merge pull request #1396 from samhvw8/refactor-context-proxy-more
feat(contextProxy): add setValue and setValues methods to simplify
2 parents 1807408 + b1b51f8 commit e1fb929

File tree

3 files changed

+148
-18
lines changed

3 files changed

+148
-18
lines changed

src/core/__tests__/contextProxy.test.ts

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,4 +154,105 @@ describe("ContextProxy", () => {
154154
expect(storedValue).toBeUndefined()
155155
})
156156
})
157+
158+
describe("setValue", () => {
159+
it("should route secret keys to storeSecret", async () => {
160+
// Spy on storeSecret
161+
const storeSecretSpy = jest.spyOn(proxy, "storeSecret")
162+
163+
// Test with a known secret key
164+
await proxy.setValue("openAiApiKey", "test-api-key")
165+
166+
// Should have called storeSecret
167+
expect(storeSecretSpy).toHaveBeenCalledWith("openAiApiKey", "test-api-key")
168+
169+
// Should have stored the value in secret cache
170+
const storedValue = proxy.getSecret("openAiApiKey")
171+
expect(storedValue).toBe("test-api-key")
172+
})
173+
174+
it("should route global state keys to updateGlobalState", async () => {
175+
// Spy on updateGlobalState
176+
const updateGlobalStateSpy = jest.spyOn(proxy, "updateGlobalState")
177+
178+
// Test with a known global state key
179+
await proxy.setValue("apiModelId", "gpt-4")
180+
181+
// Should have called updateGlobalState
182+
expect(updateGlobalStateSpy).toHaveBeenCalledWith("apiModelId", "gpt-4")
183+
184+
// Should have stored the value in state cache
185+
const storedValue = proxy.getGlobalState("apiModelId")
186+
expect(storedValue).toBe("gpt-4")
187+
})
188+
189+
it("should handle unknown keys as global state with warning", async () => {
190+
// Spy on the logger
191+
const warnSpy = jest.spyOn(logger, "warn")
192+
193+
// Spy on updateGlobalState
194+
const updateGlobalStateSpy = jest.spyOn(proxy, "updateGlobalState")
195+
196+
// Test with an unknown key
197+
await proxy.setValue("unknownKey", "some-value")
198+
199+
// Should have logged a warning
200+
expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining("Unknown key: unknownKey"))
201+
202+
// Should have called updateGlobalState
203+
expect(updateGlobalStateSpy).toHaveBeenCalledWith("unknownKey", "some-value")
204+
205+
// Should have stored the value in state cache
206+
const storedValue = proxy.getGlobalState("unknownKey")
207+
expect(storedValue).toBe("some-value")
208+
})
209+
})
210+
211+
describe("setValues", () => {
212+
it("should process multiple values correctly", async () => {
213+
// Spy on setValue
214+
const setValueSpy = jest.spyOn(proxy, "setValue")
215+
216+
// Test with multiple values
217+
await proxy.setValues({
218+
apiModelId: "gpt-4",
219+
apiProvider: "openai",
220+
mode: "test-mode",
221+
})
222+
223+
// Should have called setValue for each key
224+
expect(setValueSpy).toHaveBeenCalledTimes(3)
225+
expect(setValueSpy).toHaveBeenCalledWith("apiModelId", "gpt-4")
226+
expect(setValueSpy).toHaveBeenCalledWith("apiProvider", "openai")
227+
expect(setValueSpy).toHaveBeenCalledWith("mode", "test-mode")
228+
229+
// Should have stored all values in state cache
230+
expect(proxy.getGlobalState("apiModelId")).toBe("gpt-4")
231+
expect(proxy.getGlobalState("apiProvider")).toBe("openai")
232+
expect(proxy.getGlobalState("mode")).toBe("test-mode")
233+
})
234+
235+
it("should handle both secret and global state keys", async () => {
236+
// Spy on storeSecret and updateGlobalState
237+
const storeSecretSpy = jest.spyOn(proxy, "storeSecret")
238+
const updateGlobalStateSpy = jest.spyOn(proxy, "updateGlobalState")
239+
240+
// Test with mixed keys
241+
await proxy.setValues({
242+
apiModelId: "gpt-4", // global state
243+
openAiApiKey: "test-api-key", // secret
244+
unknownKey: "some-value", // unknown
245+
})
246+
247+
// Should have called appropriate methods
248+
expect(storeSecretSpy).toHaveBeenCalledWith("openAiApiKey", "test-api-key")
249+
expect(updateGlobalStateSpy).toHaveBeenCalledWith("apiModelId", "gpt-4")
250+
expect(updateGlobalStateSpy).toHaveBeenCalledWith("unknownKey", "some-value")
251+
252+
// Should have stored values in appropriate caches
253+
expect(proxy.getSecret("openAiApiKey")).toBe("test-api-key")
254+
expect(proxy.getGlobalState("apiModelId")).toBe("gpt-4")
255+
expect(proxy.getGlobalState("unknownKey")).toBe("some-value")
256+
})
257+
})
157258
})

src/core/contextProxy.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,4 +93,40 @@ export class ContextProxy {
9393
return this.originalContext.secrets.store(key, value)
9494
}
9595
}
96+
/**
97+
* Set a value in either secrets or global state based on key type.
98+
* If the key is in SECRET_KEYS, it will be stored as a secret.
99+
* If the key is in GLOBAL_STATE_KEYS or unknown, it will be stored in global state.
100+
* @param key The key to set
101+
* @param value The value to set
102+
* @returns A promise that resolves when the operation completes
103+
*/
104+
setValue(key: string, value: any): Thenable<void> {
105+
if (SECRET_KEYS.includes(key as any)) {
106+
return this.storeSecret(key, value)
107+
}
108+
109+
if (GLOBAL_STATE_KEYS.includes(key as any)) {
110+
return this.updateGlobalState(key, value)
111+
}
112+
113+
logger.warn(`Unknown key: ${key}. Storing as global state.`)
114+
return this.updateGlobalState(key, value)
115+
}
116+
117+
/**
118+
* Set multiple values at once. Each key will be routed to either
119+
* secrets or global state based on its type.
120+
* @param values An object containing key-value pairs to set
121+
* @returns A promise that resolves when all operations complete
122+
*/
123+
async setValues(values: Record<string, any>): Promise<void[]> {
124+
const promises: Thenable<void>[] = []
125+
126+
for (const [key, value] of Object.entries(values)) {
127+
promises.push(this.setValue(key, value))
128+
}
129+
130+
return Promise.all(promises)
131+
}
96132
}

src/core/webview/ClineProvider.ts

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1688,20 +1688,8 @@ export class ClineProvider implements vscode.WebviewViewProvider {
16881688
}
16891689
}
16901690

1691-
// Create an array of promises to update state
1692-
const promises: Promise<any>[] = []
1693-
1694-
// For each property in apiConfiguration, update the appropriate state
1695-
Object.entries(apiConfiguration).forEach(([key, value]) => {
1696-
// Check if this key is a secret
1697-
if (SECRET_KEYS.includes(key as SecretKey)) {
1698-
promises.push(this.storeSecret(key as SecretKey, value))
1699-
} else {
1700-
promises.push(this.updateGlobalState(key as GlobalStateKey, value))
1701-
}
1702-
})
1703-
1704-
await Promise.all(promises)
1691+
// Use the new setValues method to handle routing values to secrets or global state
1692+
await this.contextProxy.setValues(apiConfiguration)
17051693

17061694
if (this.cline) {
17071695
this.cline.api = buildApiHandler(apiConfiguration)
@@ -1805,8 +1793,11 @@ export class ClineProvider implements vscode.WebviewViewProvider {
18051793
}
18061794

18071795
const openrouter: ApiProvider = "openrouter"
1808-
await this.updateGlobalState("apiProvider", openrouter)
1809-
await this.storeSecret("openRouterApiKey", apiKey)
1796+
await this.contextProxy.setValues({
1797+
apiProvider: openrouter,
1798+
openRouterApiKey: apiKey,
1799+
})
1800+
18101801
await this.postStateToWebview()
18111802
if (this.cline) {
18121803
this.cline.api = buildApiHandler({ apiProvider: openrouter, openRouterApiKey: apiKey })
@@ -1833,8 +1824,10 @@ export class ClineProvider implements vscode.WebviewViewProvider {
18331824
}
18341825

18351826
const glama: ApiProvider = "glama"
1836-
await this.updateGlobalState("apiProvider", glama)
1837-
await this.storeSecret("glamaApiKey", apiKey)
1827+
await this.contextProxy.setValues({
1828+
apiProvider: glama,
1829+
glamaApiKey: apiKey,
1830+
})
18381831
await this.postStateToWebview()
18391832
if (this.cline) {
18401833
this.cline.api = buildApiHandler({

0 commit comments

Comments
 (0)