Skip to content

Commit 8902fac

Browse files
fix: Apply updated API profile settings when provider/model unchanged (#9208) (#9210)
fix: apply updated API profile settings when provider/model unchanged (#9208)
1 parent 62d8cc0 commit 8902fac

File tree

2 files changed

+35
-18
lines changed

2 files changed

+35
-18
lines changed

src/core/webview/ClineProvider.ts

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1301,23 +1301,31 @@ export class ClineProvider
13011301
// Provider Profile Management
13021302

13031303
/**
1304-
* Updates the current task's API handler if the provider or model has changed.
1305-
* Also synchronizes the task.apiConfiguration so subsequent comparisons and logic
1306-
* (protocol selection, reasoning display, model metadata) use the latest profile.
1304+
* Updates the current task's API handler.
1305+
* Rebuilds when:
1306+
* - provider or model changes, OR
1307+
* - explicitly forced (e.g., user-initiated profile switch/save to apply changed settings like headers/baseUrl/tier).
1308+
* Always synchronizes task.apiConfiguration with latest provider settings.
13071309
* @param providerSettings The new provider settings to apply
1310+
* @param options.forceRebuild Force rebuilding the API handler regardless of provider/model equality
13081311
*/
1309-
private updateTaskApiHandlerIfNeeded(providerSettings: ProviderSettings): void {
1312+
private updateTaskApiHandlerIfNeeded(
1313+
providerSettings: ProviderSettings,
1314+
options: { forceRebuild?: boolean } = {},
1315+
): void {
13101316
const task = this.getCurrentTask()
13111317
if (!task) return
13121318

1319+
const { forceRebuild = false } = options
1320+
13131321
// Determine if we need to rebuild using the previous configuration snapshot
13141322
const prevConfig = task.apiConfiguration
13151323
const prevProvider = prevConfig?.apiProvider
13161324
const prevModelId = prevConfig ? getModelId(prevConfig) : undefined
13171325
const newProvider = providerSettings.apiProvider
13181326
const newModelId = getModelId(providerSettings)
13191327

1320-
if (prevProvider !== newProvider || prevModelId !== newModelId) {
1328+
if (forceRebuild || prevProvider !== newProvider || prevModelId !== newModelId) {
13211329
task.api = buildApiHandler(providerSettings)
13221330
}
13231331

@@ -1373,7 +1381,7 @@ export class ClineProvider
13731381

13741382
// Change the provider for the current task.
13751383
// TODO: We should rename `buildApiHandler` for clarity (e.g. `getProviderClient`).
1376-
this.updateTaskApiHandlerIfNeeded(providerSettings)
1384+
this.updateTaskApiHandlerIfNeeded(providerSettings, { forceRebuild: true })
13771385
} else {
13781386
await this.updateGlobalState("listApiConfigMeta", await this.providerSettingsManager.listConfig())
13791387
}
@@ -1428,9 +1436,8 @@ export class ClineProvider
14281436
if (id) {
14291437
await this.providerSettingsManager.setModeConfig(mode, id)
14301438
}
1431-
14321439
// Change the provider for the current task.
1433-
this.updateTaskApiHandlerIfNeeded(providerSettings)
1440+
this.updateTaskApiHandlerIfNeeded(providerSettings, { forceRebuild: true })
14341441

14351442
await this.postStateToWebview()
14361443

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

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ describe("ClineProvider - API Handler Rebuild Guard", () => {
250250
})
251251

252252
describe("upsertProviderProfile", () => {
253-
test("does NOT rebuild API handler when provider and model unchanged, but task.apiConfiguration is synced", async () => {
253+
test("rebuilds API handler when provider/model unchanged but profile settings changed (explicit save)", async () => {
254254
// Create a task with the current config
255255
const mockTask = new Task({
256256
...defaultTaskOptions,
@@ -285,10 +285,15 @@ describe("ClineProvider - API Handler Rebuild Guard", () => {
285285
true,
286286
)
287287

288-
// Verify buildApiHandler was NOT called since provider/model unchanged
289-
expect(buildApiHandlerMock).not.toHaveBeenCalled()
290-
// Verify the task's api property was NOT reassigned (still same reference)
291-
expect(mockTask.api).toBe(originalApi)
288+
// Verify buildApiHandler WAS called because we force rebuild on explicit save/switch
289+
expect(buildApiHandlerMock).toHaveBeenCalledWith(
290+
expect.objectContaining({
291+
apiProvider: "openrouter",
292+
openRouterModelId: "openai/gpt-4",
293+
}),
294+
)
295+
// Verify the task's api property was reassigned (new client)
296+
expect(mockTask.api).not.toBe(originalApi)
292297
// Verify task.apiConfiguration was synchronized with non-model fields
293298
expect((mockTask as any).apiConfiguration.openRouterModelId).toBe("openai/gpt-4")
294299
expect((mockTask as any).apiConfiguration.rateLimitSeconds).toBe(5)
@@ -390,7 +395,7 @@ describe("ClineProvider - API Handler Rebuild Guard", () => {
390395
})
391396

392397
describe("activateProviderProfile", () => {
393-
test("does NOT rebuild API handler when provider and model unchanged, but task.apiConfiguration is synced", async () => {
398+
test("rebuilds API handler when provider/model unchanged but settings differ (explicit profile switch)", async () => {
394399
const mockTask = new Task({
395400
...defaultTaskOptions,
396401
apiConfiguration: {
@@ -423,10 +428,15 @@ describe("ClineProvider - API Handler Rebuild Guard", () => {
423428

424429
await provider.activateProviderProfile({ name: "test-config" })
425430

426-
// Verify buildApiHandler was NOT called
427-
expect(buildApiHandlerMock).not.toHaveBeenCalled()
428-
// Verify the API reference wasn't changed
429-
expect(mockTask.api).toBe(originalApi)
431+
// Verify buildApiHandler WAS called due to forced rebuild on explicit switch
432+
expect(buildApiHandlerMock).toHaveBeenCalledWith(
433+
expect.objectContaining({
434+
apiProvider: "openrouter",
435+
openRouterModelId: "openai/gpt-4",
436+
}),
437+
)
438+
// Verify the API reference changed
439+
expect(mockTask.api).not.toBe(originalApi)
430440
// Verify task.apiConfiguration was synchronized
431441
expect((mockTask as any).apiConfiguration.openRouterModelId).toBe("openai/gpt-4")
432442
expect((mockTask as any).apiConfiguration.modelTemperature).toBe(0.9)

0 commit comments

Comments
 (0)