fix(provider): isolate profile mutations from focused tasks - #1087
fix(provider): isolate profile mutations from focused tasks#1087edelauna wants to merge 5 commits into
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughThe change persists mode-specific API configurations, serializes provider profile mutations, supports targeted mode switching without unnecessary task updates, and expands tests for concurrency, recovery, state notifications, configuration persistence, and profile restoration. ChangesProfile and mode configuration
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant API
participant ClineProvider
participant ProviderSettingsManager
participant Task
participant Webview
API->>ProviderSettingsManager: Set mode-specific configuration
API->>Webview: Post synchronized configuration state
ClineProvider->>ClineProvider: Queue profile or mode mutation
ClineProvider->>ProviderSettingsManager: Activate profile
ProviderSettingsManager-->>ClineProvider: Return profile data
ClineProvider->>Task: Update targeted task when enabled
ClineProvider->>Webview: Post state and events when not suppressed
Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
4daeec7 to
57e9032
Compare
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
4a976b5 to
bb936be
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/core/webview/ClineProvider.ts (1)
1799-1853: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift
contextProxywrites are not gated byskipCurrentTaskRebuild.
activateProviderProfileUnlockedskips task rebuild (line 1838), sticky-history persistence (lines 1842-1844),postStateToWebview(lines 1846-1848), and theProviderProfileChangedemit (lines 1850-1852) whenskipCurrentTaskRebuildis true. But the earlier, unconditional block still runs:await Promise.all([ this.contextProxy.setValue("listApiConfigMeta", await this.providerSettingsManager.listConfig()), this.contextProxy.setValue("currentApiConfigName", name), this.contextProxy.setProviderSettings(providerSettings), ])This writes the pending-child profile's
currentApiConfigNameand provider settings into the sharedcontextProxyregardless ofskipCurrentTaskRebuild. Any other consumer that readsgetState().apiConfiguration/currentApiConfigNameafterward (a different code path callingpostStateToWebview, or a brand-new task readinggetState()for its own configuration) will observe the pending child's profile instead of the still-focused task's actual profile. This directly contradicts the stated goal of preparing a pending child "without rebuilding, reconfiguring, or posting the currently focused task" — the focused task object is left alone, but the shared "current" configuration state is not.The test in
ClineProvider.apiHandlerRebuild.spec.ts(lines 475-513) does not assert oncontextProxy/getState().apiConfigurationafterhandleModeSwitch(..., null), so this gap is not currently caught.Gate this block on
skipCurrentTaskRebuildtoo, or persist the pending-child profile through a mechanism that does not overwrite the globally-visible "current" configuration.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/core/webview/ClineProvider.ts` around lines 1799 - 1853, Gate the contextProxy writes in activateProviderProfileUnlocked behind !skipCurrentTaskRebuild so pending-child activation does not overwrite the globally visible current configuration. Preserve the existing writes for normal activation, including listApiConfigMeta, currentApiConfigName, and providerSettings.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/core/webview/ClineProvider.ts`:
- Around line 199-229: Update enqueueProviderProfileMutation and
withProviderProfileMutationTimeout so a timed-out mutation cannot permanently
block provider-profile or mode-switch operations. Log when the timeout fires,
and attach settlement logging to the abandoned raw run if it later resolves or
rejects. Advance or reset providerProfileMutationQueue through a bounded
recovery path after timeout while preserving serialized execution for active
mutations.
- Around line 1532-1543: Defer resolving the default task in handleModeSwitch
until the queued mutation executes, rather than using the parameter default on
handleModeSwitch. Preserve explicit Task and null arguments, while resolving
undefined via getCurrentTask inside the closure passed to
enqueueProviderProfileMutation before calling handleModeSwitchUnlocked.
---
Outside diff comments:
In `@src/core/webview/ClineProvider.ts`:
- Around line 1799-1853: Gate the contextProxy writes in
activateProviderProfileUnlocked behind !skipCurrentTaskRebuild so pending-child
activation does not overwrite the globally visible current configuration.
Preserve the existing writes for normal activation, including listApiConfigMeta,
currentApiConfigName, and providerSettings.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 20f79951-58fb-470c-ae35-d458672683e1
📒 Files selected for processing (6)
apps/vscode-e2e/src/suite/subtasks.test.tssrc/core/webview/ClineProvider.tssrc/core/webview/__tests__/ClineProvider.apiHandlerRebuild.spec.tssrc/core/webview/__tests__/ClineProvider.lockApiConfig.spec.tssrc/extension/__tests__/api-configuration.spec.tssrc/extension/api.ts
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/core/webview/__tests__/ClineProvider.apiHandlerRebuild.spec.ts`:
- Around line 528-529: Replace the double assertions in the firstTask and
secondTask _taskMode expectations with TypeScript bracket-notation access,
preserving the existing assertions and Mode typing. If bracket notation is not
viable, retain the casts only with a concise comment explaining why they are
necessary as a last resort.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: d6739a34-d626-4b7a-b15b-fba2aefc8564
📒 Files selected for processing (2)
src/core/webview/ClineProvider.tssrc/core/webview/__tests__/ClineProvider.apiHandlerRebuild.spec.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- src/core/webview/ClineProvider.ts
5ddb92c to
6a03068
Compare
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
src/core/webview/ClineProvider.ts (2)
206-238: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy liftDo not continue child creation while a timed-out mutation is still running.
The caller promise rejects after 30 seconds, but
runcontinues.delegateParentAndOpenChildcatches thehandleModeSwitcherror and creates the child immediately. If the raw mutation later activates a profile,getCurrentTask()can return the new child. The late mutation can then rebuild its API handler, update sticky history, and post state.Wait for the raw mutation to settle before creating the child, or stop and roll back the child flow on timeout.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/core/webview/ClineProvider.ts` around lines 206 - 238, Update the child-creation flow around delegateParentAndOpenChild so a timeout from handleModeSwitch does not immediately continue to child creation while the underlying provider profile mutation is still running. Await the raw mutation’s settlement before proceeding, or abort and roll back the child flow on timeout, ensuring late mutation side effects cannot affect the newly created child.
198-208: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick winRoute
upsertProviderProfilethrough the provider-profile queue.
providerProfileMutationQueueis an instance field, while shared webview commands select a visibleClineProviderviaClineProvider.getVisibleInstance().handleModeSwitchandactivateProviderProfileserialize through that field, butupsertProviderProfilepersists settings before activation, so anupsertApiConfigurationcall can overlap with another instance’s mode/profile activation. Move serialization beyondupsertProviderProfileor reuse shared serialization state.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/core/webview/ClineProvider.ts` around lines 198 - 208, The upsertProviderProfile flow must use the same provider-profile mutation serialization as handleModeSwitch and activateProviderProfile, including persistence before activation. Update upsertProviderProfile to route its full mutation through enqueueProviderProfileMutation on the selected visible ClineProvider, or otherwise reuse shared serialization state so calls across provider instances cannot overlap.
🧹 Nitpick comments (1)
src/extension/__tests__/api-configuration.spec.ts (1)
50-57: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winUse a typed test double or document the cast.
Lines [56-57] coerce partial objects into concrete production types with double assertions. Use a typed test double. If the constructor type makes the assertion unavoidable, add a comment that explains why.
As per coding guidelines, use precise test doubles and explain any unavoidable double assertion.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/extension/__tests__/api-configuration.spec.ts` around lines 50 - 57, Update the test setup around the provider and outputChannel fixtures to use typed test doubles matching the required ClineProvider and vscode.OutputChannel shapes instead of unexplained double assertions. If the constructor contract makes a double assertion unavoidable, retain it only with a concise comment documenting why it is necessary.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@src/core/webview/ClineProvider.ts`:
- Around line 206-238: Update the child-creation flow around
delegateParentAndOpenChild so a timeout from handleModeSwitch does not
immediately continue to child creation while the underlying provider profile
mutation is still running. Await the raw mutation’s settlement before
proceeding, or abort and roll back the child flow on timeout, ensuring late
mutation side effects cannot affect the newly created child.
- Around line 198-208: The upsertProviderProfile flow must use the same
provider-profile mutation serialization as handleModeSwitch and
activateProviderProfile, including persistence before activation. Update
upsertProviderProfile to route its full mutation through
enqueueProviderProfileMutation on the selected visible ClineProvider, or
otherwise reuse shared serialization state so calls across provider instances
cannot overlap.
---
Nitpick comments:
In `@src/extension/__tests__/api-configuration.spec.ts`:
- Around line 50-57: Update the test setup around the provider and outputChannel
fixtures to use typed test doubles matching the required ClineProvider and
vscode.OutputChannel shapes instead of unexplained double assertions. If the
constructor contract makes a double assertion unavoidable, retain it only with a
concise comment documenting why it is necessary.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 95228718-d72d-42a4-a06d-609b7db9a03b
📒 Files selected for processing (3)
src/core/webview/ClineProvider.tssrc/core/webview/__tests__/ClineProvider.apiHandlerRebuild.spec.tssrc/extension/__tests__/api-configuration.spec.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- src/core/webview/tests/ClineProvider.apiHandlerRebuild.spec.ts
Summary
PR 2 of 3 for #369, extracted from #1046.
modeApiConfigsmappings throughProviderSettingsManager.setModeConfig().This prepares safe provider mode/profile handling for future concurrent delegation, but does not enable concurrency or fan-out. #1085 is the complementary task-local isolation extraction.
Validation
pnpm --dir src exec vitest run core/webview/__tests__/ClineProvider.apiHandlerRebuild.spec.tspnpm --dir src exec vitest run extension/__tests__/api-configuration.spec.tspnpm --dir src exec tsc --noEmit -p tsconfig.jsonSummary by CodeRabbit