feat: --session-preference CLI overrides and AI Allow-All Mode banner#17731
Open
ndoschek wants to merge 2 commits into
Open
feat: --session-preference CLI overrides and AI Allow-All Mode banner#17731ndoschek wants to merge 2 commits into
ndoschek wants to merge 2 commits into
Conversation
- Add `PreferenceScope.Session`, a highest-precedence in-memory preference scope that never persists to disk, backed by a new `SessionPreferenceProvider` - Add `--session-preference KEY=JSONVALUE` CLI flag parallel to `--set-preference`; repeatable, supports a `base64:` value prefix, and skips malformed entries with a clear warning instead of throwing - Forward session preferences to remote backends via `RemoteCliContribution.enhanceArgs` so values reach the remote process after dev-container attach - Drop the session override when the same key is written to a persistent scope (`evictSessionOverride`) so an explicit user edit always wins for the rest of the session; the eviction emits its own Session-scope change event so listeners stay in sync. Session is excluded from regular edit-target selection - Map the session scope to monaco's `MEMORY` configuration target - Indicate session-overridden preferences in the Settings UI with a subtle "Overridden by session" suffix styled like the existing "Modified in:" treatment, visible across all scope tabs. Editing the preference clears the session override - Add a status bar item that lists active session overrides in a markdown tooltip; each entry links to its row in the Settings view, and the footer notes how to clear or restore values - Apply CLI session and persistent preferences after the preference service is ready, fetching both buckets in parallel; log only the keys (not values) on startup to avoid leaking sensitive overrides - Cover the new behaviour with unit tests for the session provider, override eviction (including the Session-scope change event it emits and the no-op when writing to Session itself), CLI parsing (including malformed entries), and remote-arg forwarding
- Add `ChatBannerProvider` contribution point and `ChatBannerWidget` host in @theia/ai-chat-ui for persistent banners above the chat content
- Add `AiAllowAllModeChatBanner` in @theia/ai-ide: a dismissible strip surfaced above the chat content when an AI tool confirmation preference (`ai-features.chat.defaultToolConfirmation` or `ai-features.chat.toolConfirmation`) is set in the session scope via `--session-preference`
- Render in red ("Theia AI Allow-All Mode") only when the global default is forced to Allow-All; per-tool `always_allow` entries use warning styling ("AI Tool Confirmation Overrides")
- Watch only the two tool confirmation preferences here. Other AI session overrides (enable AI, agent mode, default chat agent) stay in the generic Session Preferences status bar item so the banner and the status bar do not duplicate the same list
- Announce changes via `role='status'` + `aria-live='polite'` so screen readers report updates without interrupting
- Cover the bypass-detection rule with a unit test so widening it later is an intentional change
87d22eb to
28ecaa3
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What it does
Adds a new in-memory preference scope and a
--session-preferenceCLI flag that lets adopters (and dev-container launch configs) pin preferences for the duration of a single process without touching the user's persisted settings. Builds on top of that a small UI surface so users always know which settings are being forced.Preferences foundation:
PreferenceScope.Session, a highest-precedence in-memory scope that never persists to disk, backed bySessionPreferenceProvider.--session-preference KEY=JSONVALUECLI flag parallel to--set-preference. Repeatable, supports abase64:value prefix for shell-unfriendly values, and skips malformed entries with a warning instead of throwing.RemoteCliContribution.enhanceArgs, so values reach the remote process after a dev-container attach.evictSessionOverride) and emits a Session-scope change event so listeners stay in sync. The session scope is excluded from regular edit-target selection.MEMORYconfiguration target.--set-preferenceand--session-preference) are fetched in parallel afterpreferenceService.ready. Only preference keys are logged at startup; values are intentionally omitted so security-sensitive overrides (AI auto-approve, etc.) cannot leak into logs or screenshots.AI surfacing:
ChatBannerProvidercontribution point andChatBannerWidgethost in@theia/ai-chat-uifor persistent banners above the chat content.AiAllowAllModeChatBannerin@theia/ai-ide: a dismissible strip that appears above the chat content when an AI tool confirmation preference (ai-features.chat.defaultToolConfirmationorai-features.chat.toolConfirmation) is set in the session scope.always_allowentries.role='status'+aria-live='polite'.Tests cover the session provider, override eviction (including the Session-scope change event and the no-op when writing to Session itself), CLI parsing including malformed entries, remote-arg forwarding, and the banner's bypass-detection rule.
How to test
Add a few
--session-preferenceentries to theLaunch Electron Backend(orLaunch Browser Backend) configuration in.vscode/launch.json:Note: values must be valid JSON, so bare strings need escaped quotes (
\"Coder\") and objects need their inner quotes escaped too. For complex values you can also usebase64:<base64-encoded JSON>to avoid shell escaping.Launch the application and check:
defaultToolConfirmationis forced to Allow-All. Dismiss it with the close button; it stays dismissed for the rest of the process and comes back on the next launch.defaultToolConfirmationline and relaunch: the strip turns yellow ("AI Tool Confirmation Overrides") becausetoolConfirmationstill has a per-tool Allow-All entry forshellExecute.--session-preferenceflags and relaunch: the status bar item, the suffix in the Settings UI, and the chat banner all disappear.--session-preferenceflags are forwarded to the remote backend; the same UI signals should appear there as well.Test the CLI guards by passing a malformed entry (e.g.
--session-preference=foowith no=, or--session-preference=foo=notJson): the application starts normally and logs a warning in the dev tools console; the malformed entry is skipped, valid ones still apply.Follow-ups
preferenceService.inspect(key)?.sessionValue !== undefined. Leaving this out of this PR to avoid double work since the layout is changing.settings.jsondo not evict session overrides.evictSessionOverrideonly fires fromPreferenceServiceImpl.set(), so an edit in the JSON file is saved correctly but the session value still wins for the rest of the session. Status bar item remains the discoverable signal. A future improvement could either show a one-shot notification when the JSON is opened while a session override is active, or evict on file-based change events as well.applyCliPreferencesapplies values unconditionally. Whether to gate security-sensitive overrides (such as AI tool auto-approval) at the CLI-application layer is a policy decision left for a follow-up.SessionPreferenceProvideris global and does not honorresourceUri; per-language overrides (e.g.[typescript].editor.tabSize) are not supported through--session-preference. Sufficient for the current use cases (process-level AI configuration); revisit if a real need appears.Breaking changes
Attribution
Review checklist
nlsservice (for details, please see the Internationalization/Localization section in the Coding Guidelines)Reminder for reviewers