Skip to content

fix(provider): isolate profile mutations from focused tasks - #1087

Open
edelauna wants to merge 5 commits into
mainfrom
agent/provider-profile-isolation
Open

fix(provider): isolate profile mutations from focused tasks#1087
edelauna wants to merge 5 commits into
mainfrom
agent/provider-profile-isolation

Conversation

@edelauna

@edelauna edelauna commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Summary

PR 2 of 3 for #369, extracted from #1046.

  • Serializes provider profile and mode mutations with the existing 30-second timeout while preserving errors for the initiating caller.
  • Allows pending-child mode/profile preparation without rebuilding, reconfiguring, or posting the currently focused task.
  • Persists supplied modeApiConfigs mappings through ProviderSettingsManager.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.ts
  • pnpm --dir src exec vitest run extension/__tests__/api-configuration.spec.ts
  • pnpm --dir src exec tsc --noEmit -p tsconfig.json
  • Targeted ESLint suppression-pruning checks and repository lint

Summary by CodeRabbit

  • New Features
    • API configuration updates can save settings for multiple modes in one operation.
    • Profile and mode changes are coordinated more reliably during simultaneous updates.
  • Bug Fixes
    • Switching profiles or modes avoids unnecessary active-task rebuilds and webview refreshes.
    • Pending tasks retain the correct configuration and active state.
    • Updates recover cleanly after delayed or failed profile and mode changes.
    • Cross-profile workflows fully restore previous settings after completion.

@coderabbitai

coderabbitai Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It 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 reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The 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.

Changes

Profile and mode configuration

Layer / File(s) Summary
Mode-aware API configuration
src/extension/api.ts, src/extension/__tests__/api-configuration.spec.ts
API.setConfiguration applies each modeApiConfigs entry and posts updated state once. Tests cover configured and omitted mappings.
Serialized provider mutations
src/core/webview/ClineProvider.ts, src/core/webview/__tests__/ClineProvider.apiHandlerRebuild.spec.ts, src/core/webview/__tests__/ClineProvider.lockApiConfig.spec.ts
ClineProvider queues profile mutations, handles rejection and timeout recovery, and activates profiles through providerSettingsManager.
Targeted mode switching
src/core/webview/ClineProvider.ts, src/core/webview/__tests__/ClineProvider.apiHandlerRebuild.spec.ts, src/core/webview/__tests__/ClineProvider.sticky-mode.spec.ts
Mode switching accepts explicit task targets and suppresses task, history, provider-state, and webview updates during null-target preparation.
Configuration snapshot and restoration
apps/vscode-e2e/src/suite/subtasks.test.ts, src/eslint-suppressions.json
The cross-profile subtask test restores the complete prior configuration and active profile. The lint suppression count is updated.

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
Loading

Possibly related PRs

Suggested labels: awaiting-review

Suggested reviewers: taltas, navedmerchant, hannesrudolph

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description explains the changes and validation, but it omits most required template sections, including the checklist and documentation impact. Use the repository template and add the linked issue field, detailed description, test procedure, completed checklist, documentation impact, and any required notes.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the primary change: isolating provider profile mutations from focused tasks.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch agent/provider-profile-isolation

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@edelauna
edelauna force-pushed the agent/provider-profile-isolation branch from 4daeec7 to 57e9032 Compare August 1, 2026 12:47
@codecov

codecov Bot commented Aug 1, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 89.79592% with 5 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/core/webview/ClineProvider.ts 89.13% 2 Missing and 3 partials ⚠️

📢 Thoughts on this report? Let us know!

@edelauna
edelauna force-pushed the agent/provider-profile-isolation branch from 4a976b5 to bb936be Compare August 1, 2026 15:38
@edelauna
edelauna marked this pull request as ready for review August 1, 2026 15:55

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

contextProxy writes are not gated by skipCurrentTaskRebuild.

activateProviderProfileUnlocked skips task rebuild (line 1838), sticky-history persistence (lines 1842-1844), postStateToWebview (lines 1846-1848), and the ProviderProfileChanged emit (lines 1850-1852) when skipCurrentTaskRebuild is 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 currentApiConfigName and provider settings into the shared contextProxy regardless of skipCurrentTaskRebuild. Any other consumer that reads getState().apiConfiguration/currentApiConfigName afterward (a different code path calling postStateToWebview, or a brand-new task reading getState() 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 on contextProxy/getState().apiConfiguration after handleModeSwitch(..., null), so this gap is not currently caught.

Gate this block on skipCurrentTaskRebuild too, 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

📥 Commits

Reviewing files that changed from the base of the PR and between 2ecb300 and bb936be.

📒 Files selected for processing (6)
  • apps/vscode-e2e/src/suite/subtasks.test.ts
  • src/core/webview/ClineProvider.ts
  • src/core/webview/__tests__/ClineProvider.apiHandlerRebuild.spec.ts
  • src/core/webview/__tests__/ClineProvider.lockApiConfig.spec.ts
  • src/extension/__tests__/api-configuration.spec.ts
  • src/extension/api.ts

Comment thread src/core/webview/ClineProvider.ts
Comment thread src/core/webview/ClineProvider.ts
@github-actions github-actions Bot added the awaiting-review PR changes are ready and waiting for maintainer re-review label Aug 1, 2026
@github-actions github-actions Bot removed the awaiting-review PR changes are ready and waiting for maintainer re-review label Aug 1, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between bb936be and 8273a44.

📒 Files selected for processing (2)
  • src/core/webview/ClineProvider.ts
  • src/core/webview/__tests__/ClineProvider.apiHandlerRebuild.spec.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/core/webview/ClineProvider.ts

Comment thread src/core/webview/__tests__/ClineProvider.apiHandlerRebuild.spec.ts Outdated
@edelauna
edelauna force-pushed the agent/provider-profile-isolation branch from 5ddb92c to 6a03068 Compare August 1, 2026 17:38
@github-actions github-actions Bot added the awaiting-review PR changes are ready and waiting for maintainer re-review label Aug 1, 2026
@github-actions github-actions Bot removed the awaiting-review PR changes are ready and waiting for maintainer re-review label Aug 1, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 lift

Do not continue child creation while a timed-out mutation is still running.

The caller promise rejects after 30 seconds, but run continues. delegateParentAndOpenChild catches the handleModeSwitch error 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 win

Route upsertProviderProfile through the provider-profile queue.

providerProfileMutationQueue is an instance field, while shared webview commands select a visible ClineProvider via ClineProvider.getVisibleInstance(). handleModeSwitch and activateProviderProfile serialize through that field, but upsertProviderProfile persists settings before activation, so an upsertApiConfiguration call can overlap with another instance’s mode/profile activation. Move serialization beyond upsertProviderProfile or 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 win

Use 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

📥 Commits

Reviewing files that changed from the base of the PR and between 6a03068 and 71ba421.

📒 Files selected for processing (3)
  • src/core/webview/ClineProvider.ts
  • src/core/webview/__tests__/ClineProvider.apiHandlerRebuild.spec.ts
  • src/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

@github-actions github-actions Bot added the awaiting-review PR changes are ready and waiting for maintainer re-review label Aug 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

awaiting-review PR changes are ready and waiting for maintainer re-review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant