Skip to content

Commit 08af5cb

Browse files
committed
fix(webview): rebuild active task handlers when a pinned profile is saved
A non-activating save refreshed the pinned views' buffers but not their active tasks' API handlers, and the posted state prefers the task's own apiConfiguration: a conversation running in a view pinned to the saved profile kept sending the old token (e.g. after the Zoo Gateway callback rotated it) even though the view's buffer had caught up. The refresh now rebuilds the affected tasks' handlers in the sibling views, and the non-activating branch rebuilds this view's own handler when it holds the pin. Proofs: ClineProvider.spec 258/258 (the pinned-sibling refresh test now asserts the active task's handler is rebuilt with the saved settings, not just the private buffer); negative control: dropping the rebuild from the refresh reddens exactly that assertion, restores byte-exact (hash match); sticky-mode 32/32, webviewMessageHandler 82/82; eslint --max-warnings=0 clean; prettier clean.
1 parent 74825b2 commit 08af5cb

2 files changed

Lines changed: 26 additions & 0 deletions

File tree

‎src/core/webview/ClineProvider.ts‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2418,6 +2418,7 @@ export class ClineProvider
24182418
// serving the settings captured before the save under the same name.
24192419
if (this.pinnedProfileName === name) {
24202420
await this._saveViewLocalStateFromMutation({ apiConfiguration: providerSettings })
2421+
this.updateTaskApiHandlerIfNeeded(providerSettings, { forceRebuild: true })
24212422
}
24222423
await this.refreshViewLocalStateForUpdatedProfile(name, providerSettings)
24232424
}
@@ -2672,6 +2673,13 @@ export class ClineProvider
26722673
affected.map(async (instance) => {
26732674
// Direct private access: compile-time safe across sibling instances.
26742675
await instance._saveViewLocalStateFromMutation({ apiConfiguration: providerSettings })
2676+
2677+
// The active task of a pinned view holds its own API handler built from
2678+
// the profile's settings: rebuild it with the saved settings or the
2679+
// running conversation keeps sending the old token even though the
2680+
// view's buffer has caught up. Direct private access across sibling
2681+
// instances of the same class is compile-time safe.
2682+
instance.updateTaskApiHandlerIfNeeded(providerSettings, { forceRebuild: true })
26752683
await instance.postStateToWebview()
26762684
}),
26772685
)

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8286,6 +8286,17 @@ describe("ClineProvider - Comprehensive Edit/Delete Edge Cases", () => {
82868286
apiKey: "old-key",
82878287
}
82888288
vi.spyOn(sibling, "postStateToWebview").mockResolvedValue(undefined)
8289+
8290+
// The sibling has an active task built from the pre-save settings.
8291+
// Task is a class; the double assertion is the only way to attach a
8292+
// minimal double without the full provider/services graph.
8293+
const siblingTask = {
8294+
apiConfiguration: { apiProvider: providerIdentifiers.anthropic, apiKey: "old-key" },
8295+
updateApiConfiguration: vi.fn(),
8296+
}
8297+
vi.spyOn(sibling, "getCurrentTask").mockReturnValue(
8298+
siblingTask as unknown as ReturnType<typeof sibling.getCurrentTask>,
8299+
)
82898300
vi.spyOn(provider, "postStateToWebview").mockResolvedValue(undefined)
82908301
// @ts-ignore - Replace providerSettingsManager with a test double.
82918302
provider.providerSettingsManager = {
@@ -8306,6 +8317,13 @@ describe("ClineProvider - Comprehensive Edit/Delete Edge Cases", () => {
83068317
apiProvider: providerIdentifiers.anthropic,
83078318
apiKey: "new-key",
83088319
})
8320+
8321+
// The active task's handler must be rebuilt with the saved settings,
8322+
// not just the view buffer.
8323+
expect(siblingTask.updateApiConfiguration).toHaveBeenCalledWith({
8324+
apiProvider: providerIdentifiers.anthropic,
8325+
apiKey: "new-key",
8326+
})
83098327
} finally {
83108328
await sibling.dispose()
83118329
}

0 commit comments

Comments
 (0)