Skip to content

feat: add lock toggle to pin API config across all modes in workspace#11295

Merged
hannesrudolph merged 2 commits intomainfrom
feat/lock-api-config-across-modes
Feb 8, 2026
Merged

feat: add lock toggle to pin API config across all modes in workspace#11295
hannesrudolph merged 2 commits intomainfrom
feat/lock-api-config-across-modes

Conversation

@hannesrudolph
Copy link
Collaborator

@hannesrudolph hannesrudolph commented Feb 7, 2026

Summary

image

Add a lock/unlock toggle inside the API config selector popover (next to the settings gear icon) that, when enabled, pins the currently selected API configuration across all mode switches in the current workspace.

When unlocked (default), switching modes loads each mode's saved API configuration (existing behavior). When locked, mode switches skip per-mode config loading entirely — the current API config stays active regardless of mode. Per-mode config mappings are not modified; they are simply bypassed at read time. Disabling the lock restores normal per-mode sticky behavior with all original mappings intact.

The setting is stored in workspaceState (per-workspace), so locking in one workspace does not affect other workspaces.

How It Works

The lock is implemented as a read-time override, not a write-time fan-out:

  • handleModeSwitch() checks the lock flag before loading per-mode config. If locked, it early-returns keeping the current API config active.
  • createTaskWithHistoryItem() checks the lock flag before restoring mode-based API config from task history. If locked, the restoration is skipped.
  • activateProviderProfile() has no lock-related logic — it writes to the current mode's config as normal, regardless of lock state.
  • The lock toggle handler simply sets a boolean in workspaceState and posts state to the webview. No fan-out, no global side effects.

This design ensures the workspace-scoped lock never mutates the global per-mode config mappings, preventing cross-workspace data destruction.

Changes

Core Implementation

  • packages/types/src/vscode-extension-host.ts — Added lockApiConfigAcrossModes to ExtensionState and WebviewMessage types
  • src/core/webview/ClineProvider.ts — Reads lock state from workspaceState; handleModeSwitch() and createTaskWithHistoryItem() skip per-mode config loading when locked; getState() exposes lock flag
  • src/core/webview/webviewMessageHandler.ts — Handler writes lock state to workspaceState and posts state to webview
  • webview-ui/src/components/chat/ApiConfigSelector.tsx — Lock/unlock icon button in popover bottom bar next to settings gear
  • webview-ui/src/components/chat/ChatTextArea.tsx — Passes lock state + callback props to ApiConfigSelector
  • webview-ui/src/context/ExtensionStateContext.tsx — Default lockApiConfigAcrossModes: false

i18n (18 locales)

  • All chat.json locale files updated with proper native translations for lock/unlock tooltip strings
  • English strings explicitly mention "in this workspace" for clarity

Tests

  • src/core/webview/__tests__/ClineProvider.lockApiConfig.spec.ts — Tests read-time override behavior (lock skips per-mode config, unlock preserves normal behavior)
  • src/core/webview/__tests__/webviewMessageHandler.lockApiConfig.spec.ts — Tests handler sets flag without fan-out
  • webview-ui/src/components/chat/__tests__/ChatTextArea.lockApiConfig.spec.tsx — UI component tests
  • Fixed workspaceState mock gaps in 4 existing test files

@dosubot dosubot bot added size:XL This PR changes 500-999 lines, ignoring generated files. Enhancement New feature or request labels Feb 7, 2026
Add a lock/unlock toggle inside the API config selector popover (next to
the settings gear) that, when enabled, applies the selected API
configuration to all modes in the current workspace.

- Add lockApiConfigAcrossModes to ExtensionState and WebviewMessage types
- Store setting in workspaceState (per-workspace, not global)
- When locked, activateProviderProfile sets config for all modes
- Lock icon in ApiConfigSelector popover bottom bar next to gear
- Full i18n: English + 17 locale translations (all mention workspace scope)
- 9 new tests: 2 ClineProvider, 2 handler, 5 UI (77 total pass)
@hannesrudolph hannesrudolph force-pushed the feat/lock-api-config-across-modes branch from 7f74f5f to fc49ed0 Compare February 7, 2026 22:37
@roomote
Copy link
Contributor

roomote bot commented Feb 7, 2026

Rooviewer Clock   See task

No issues found. The latest commit refactors from write-fan-out to read-time override, which resolves the previous redundant getState() comment.

  • Consolidate redundant getState() calls in ClineProvider.activateProviderProfile (comment) -- resolved: fan-out code removed entirely
Previous reviews

Mention @roomote in a comment to request specific changes to this pull request or fix all unresolved issues.

…config

The original lock implementation used setModeConfig() fan-out to write the
locked config to ALL modes globally. Since the lock flag lives in workspace-
scoped workspaceState but modeApiConfigs are in global secrets, this caused
cross-workspace data destruction.

Replaced with read-time guards:
- handleModeSwitch: early return when lock is on (skip per-mode config load)
- createTaskWithHistoryItem: skip mode-based config restoration under lock
- activateProviderProfile: removed fan-out block
- lockApiConfigAcrossModes handler: simplified to flag + state post only
- Fixed pre-existing workspaceState mock gap in ClineProvider.spec.ts and
  ClineProvider.sticky-profile.spec.ts
@dosubot dosubot bot added the lgtm This PR has been approved by a maintainer label Feb 8, 2026
@hannesrudolph hannesrudolph merged commit 5d17f56 into main Feb 8, 2026
13 checks passed
@github-project-automation github-project-automation bot moved this from New to Done in Roo Code Roadmap Feb 8, 2026
@hannesrudolph hannesrudolph deleted the feat/lock-api-config-across-modes branch February 8, 2026 03:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Enhancement New feature or request lgtm This PR has been approved by a maintainer size:XL This PR changes 500-999 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants