Skip to content

Commit e507d13

Browse files
committed
fix: properly update Task API configuration when provider settings change
- Add updateApiConfiguration method to Task class to safely update config - Convert apiConfiguration to getter/setter pattern for controlled access - Update ClineProvider to use new method when updating provider settings - Ensure both API handler and configuration are updated together This ensures the Gemini API key (and other provider settings) are properly refreshed in active tasks when changed through the UI.
1 parent e8be1ab commit e507d13

File tree

3 files changed

+30
-10
lines changed

3 files changed

+30
-10
lines changed

src/core/task/Task.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -187,11 +187,23 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
187187
private pauseInterval: NodeJS.Timeout | undefined
188188

189189
// API
190-
readonly apiConfiguration: ProviderSettings
190+
private _apiConfiguration: ProviderSettings
191191
api: ApiHandler
192192
private static lastGlobalApiRequestTime?: number
193193
private autoApprovalHandler: AutoApprovalHandler
194194

195+
get apiConfiguration(): ProviderSettings {
196+
return this._apiConfiguration
197+
}
198+
199+
/**
200+
* Updates the API configuration and ensures consistency
201+
* This is used when the provider settings change (e.g., API key update)
202+
*/
203+
public updateApiConfiguration(newConfiguration: ProviderSettings): void {
204+
this._apiConfiguration = newConfiguration
205+
}
206+
195207
/**
196208
* Reset the global API request timestamp. This should only be used for testing.
197209
* @internal
@@ -301,7 +313,7 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
301313
console.error("Failed to initialize RooIgnoreController:", error)
302314
})
303315

304-
this.apiConfiguration = apiConfiguration
316+
this._apiConfiguration = apiConfiguration
305317
this.api = buildApiHandler(apiConfiguration)
306318
this.autoApprovalHandler = new AutoApprovalHandler()
307319

src/core/webview/ClineProvider.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1144,7 +1144,7 @@ export class ClineProvider
11441144

11451145
if (task) {
11461146
task.api = buildApiHandler(providerSettings)
1147-
task.apiConfiguration = providerSettings
1147+
task.updateApiConfiguration(providerSettings)
11481148
}
11491149
} else {
11501150
await this.updateGlobalState("listApiConfigMeta", await this.providerSettingsManager.listConfig())
@@ -1206,7 +1206,7 @@ export class ClineProvider
12061206

12071207
if (task) {
12081208
task.api = buildApiHandler(providerSettings)
1209-
task.apiConfiguration = providerSettings
1209+
task.updateApiConfiguration(providerSettings)
12101210
}
12111211

12121212
await this.postStateToWebview()

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

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,18 @@ vi.mock("../../../api", () => ({
2020
vi.mock("../../task/Task", () => ({
2121
Task: vi.fn().mockImplementation(function (this: any, options: any) {
2222
this.api = options.apiConfiguration ? buildApiHandler(options.apiConfiguration) : null
23-
this.apiConfiguration = options.apiConfiguration
23+
this._apiConfiguration = options.apiConfiguration
2424
this.taskId = "test-task-id"
2525
this.providerRef = { deref: () => options.provider }
26+
this.updateApiConfiguration = vi.fn((newConfig) => {
27+
this._apiConfiguration = newConfig
28+
})
29+
Object.defineProperty(this, "apiConfiguration", {
30+
get: function () {
31+
return this._apiConfiguration
32+
},
33+
configurable: true,
34+
})
2635
}),
2736
}))
2837

@@ -186,7 +195,7 @@ describe("ClineProvider - Gemini API Key Update", () => {
186195

187196
// Verify that the task's API handler was updated
188197
expect(mockTask.api).toBeDefined()
189-
expect(mockTask.apiConfiguration).toEqual(newProviderSettings)
198+
expect(mockTask.updateApiConfiguration).toHaveBeenCalledWith(newProviderSettings)
190199

191200
// Verify that context proxy was updated with new settings
192201
expect(mockContextProxy.setProviderSettings).toHaveBeenCalledWith(newProviderSettings)
@@ -228,7 +237,7 @@ describe("ClineProvider - Gemini API Key Update", () => {
228237

229238
// Verify that the task's API handler and configuration were updated
230239
expect(mockTask.api).toBeDefined()
231-
expect(mockTask.apiConfiguration).toEqual(newProviderSettings)
240+
expect(mockTask.updateApiConfiguration).toHaveBeenCalledWith(newProviderSettings)
232241

233242
// Verify that context proxy was updated
234243
expect(mockContextProxy.setProviderSettings).toHaveBeenCalledWith(newProviderSettings)
@@ -247,7 +256,6 @@ describe("ClineProvider - Gemini API Key Update", () => {
247256
}) as any
248257

249258
const originalApi = mockTask.api
250-
const originalConfig = mockTask.apiConfiguration
251259

252260
// Add the task to the provider's stack
253261
provider["clineStack"] = [mockTask]
@@ -264,7 +272,7 @@ describe("ClineProvider - Gemini API Key Update", () => {
264272

265273
// Verify that the task's API handler was NOT updated
266274
expect(mockTask.api).toBe(originalApi)
267-
expect(mockTask.apiConfiguration).toBe(originalConfig)
275+
expect(mockTask.updateApiConfiguration).not.toHaveBeenCalled()
268276

269277
// Verify that context proxy was NOT updated
270278
expect(mockContextProxy.setProviderSettings).not.toHaveBeenCalled()
@@ -321,7 +329,7 @@ describe("ClineProvider - Gemini API Key Update", () => {
321329
await provider.upsertProviderProfile("test-profile", newProviderSettings, true)
322330

323331
// Verify that all settings are preserved except the API key
324-
expect(mockTask.apiConfiguration).toEqual({
332+
expect(mockTask.updateApiConfiguration).toHaveBeenCalledWith({
325333
apiProvider: "gemini",
326334
geminiApiKey: "new-key",
327335
apiModelId: "gemini-1.5-pro",

0 commit comments

Comments
 (0)