Skip to content

sessions: add a context key gating the classic-window actions - #336910

Open
Roi Dayan (roidayan1) wants to merge 4 commits into
microsoft:mainfrom
roidayan1:roid/sessions-classic-window-context-key
Open

Roi Dayan (roidayan1) wants to merge 4 commits into
microsoft:mainfrom
roidayan1:roid/sessions-classic-window-context-key

Conversation

@roidayan1

@roidayan1 Roi Dayan (roidayan1) commented Sep 20, 2026

Copy link
Copy Markdown

The Agents window is usable as the only window a product ships, but four actions reach for a classic VS Code window and there is currently no supported way to gate them:

Action Today
OpenVSCodeWindowAction f1: true, bound to Cmd/Ctrl+Shift+A, no precondition and no when clause at all
ReturnToVSCodeEditorAction no precondition, and invoked directly by the sign-in dialog
OpenInVSCodeAction gates on IsAuxiliaryWindowContext / SessionsWelcomeVisibleContext only
OpenSessionInVSCodeAction same

The first is the awkward one: it is in the command palette and on a keybinding, with nothing to hang a condition on.

What this does

Adds SessionsClassicWindowUnavailableContext (sessionsClassicWindowUnavailable) in sessions/common/contextkeys.ts and negates it at every use.

It is stated as an opt-out on purpose. Nothing binds the key, and a RawContextKey's default is written only by bindTo() — so an expression that is false when the key is unset would hide these actions in stock VS Code. Negating a default-false key gives the intended behaviour with no binder to run and no ordering between that binder and a product that opts out: unset means available, and a product that cannot open a classic window sets it to true.

It is applied in two places:

  • the precondition of OpenVSCodeWindowAction, OpenInVSCodeAction and OpenSessionInVSCodeAction, and the when of the two title-bar menu items;
  • inside ShouldShowReturnToVSCodeEditorAction.run(), because the sign-in dialog renders its footer button from that answer and then executes RETURN_TO_VSCODE_EDITOR_COMMAND_ID directly — Action2 handlers do not enforce preconditions, so a precondition there would gate nothing.

ReturnToVSCodeEditorAction has no f1 and no menu, so it carries no precondition: the real gate is the decision command above.

Test

vscodeActions.test.ts covers unset, true and false against the real desc.precondition of OpenVSCodeWindowAction and OpenSessionInVSCodeAction — bare and inside a conjunction, since ContextKeyExpr canonicalizes.

Notes

  • No existing condition is removed or loosened, and there is no behaviour change without an explicit opt-out.
  • The key gets its own //#region, since it describes neither the welcome overlay nor the editor area.

🤖 Generated with Claude Code

The Agents window can be the only window a product ships, but four actions
reach for a classic VS Code window with no way to gate them:

- `OpenVSCodeWindowAction` is `f1: true` and bound to Cmd/Ctrl+Shift+A with
  no precondition and no when clause at all
- `ReturnToVSCodeEditorAction` has no precondition
- `OpenInVSCodeAction` and `OpenSessionInVSCodeAction` gate only on
  `IsAuxiliaryWindowContext` and `SessionsWelcomeVisibleContext`

Adds `SessionsClassicWindowAvailableContext`, defaulting to `true` so VS
Code's own behaviour is unchanged, and includes it in all four. A product
that cannot open a classic window sets it to `false` once and the actions
stop offering themselves, instead of each embedder finding its own way to
suppress a command it cannot fulfil.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings September 20, 2026 09:43
@roidayan1

Copy link
Copy Markdown
Author

@microsoft-github-policy-service agree

Copilot AI 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.

Copilot review overview

🟡 Changes recommended

The key is never initialized, disabling actions by default, while the sign-in dialog bypasses its precondition.

Get a fresh assessment by requesting another Copilot review.

Review effort: Balanced
Findings: 1 High severity · 1 Medium severity

Open (2)
What changed in this PR

Adds an opt-out context key for actions that open classic VS Code windows from the Agents window.

Changes:

  • Adds sessionsClassicWindowAvailable.
  • Applies it to four actions and two title-bar menu entries.
File Description
src/​vs/​sessions/​common/​contextkeys.ts Defines the availability context key.
src/​vs/​sessions/​browser/​actions/​vscodeActions.ts Gates web “Open in Editor” UI.
src/​vs/​sessions/​electron-browser/​actions/​vscodeActions.ts Gates desktop window actions.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/vs/sessions/common/contextkeys.ts Outdated
Comment thread src/vs/sessions/electron-browser/actions/vscodeActions.ts Outdated
Two fixes from review.

A `RawContextKey`'s default is written only by `bindTo()`, and nothing binds
this key -- so it reads as `undefined` and every positive check evaluated
false, disabling the actions by default rather than leaving them alone.
Consumers now test `notEqualsTo(false)`, so unset and `true` both mean
available and stock VS Code is genuinely unchanged.

`ReturnToVSCodeEditorAction` has no `f1` and no menu, so a precondition on
it gates nothing: the sign-in dialog renders its footer button from
`agents.shouldShowReturnToVSCodeEditor` and then executes the command
directly, and `Action2` handlers do not enforce preconditions. The
decorative precondition is removed and the availability check moves into
the decision command, which is what the button is rendered from.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

Copilot AI 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.

Copilot review overview

🟡 Changes recommended

The Boolean expression canonicalization disables the gated actions when the new key is unset.

Get a fresh assessment by requesting another Copilot review.

Review effort: Balanced
Findings: 2 High severity · 1 Low severity

Open (3)
Resolved since last review (1)

Comment thread src/vs/sessions/common/contextkeys.ts Outdated
Comment thread src/vs/sessions/electron-browser/actions/vscodeActions.ts Outdated
`notEqualsTo(false)` did not fix the previous round: `ContextKeyNotEqualsExpr.create`
canonicalizes a boolean `false` comparison straight back to `ContextKeyDefinedExpr`
(contextkey.ts:1046-1052), so the expression was identical to the one it replaced and
an unbound key still evaluated false.

Inverted instead. `sessionsClassicWindowUnavailable` defaults to `false` and every
consumer negates it, so `ContextKeyNotExpr` evaluates `!undefined` -- unset means
available, no binding and no ordering between a binder and a product that opts out.

Adds a regression test over unset, `true` and `false`, against the real preconditions
of `OpenVSCodeWindowAction` and `OpenSessionInVSCodeAction` -- bare and inside a
conjunction, since `and()` canonicalizes too. Also condenses the guard comment in
`ShouldShowReturnToVSCodeEditorAction`.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

Copilot AI 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.

Copilot review overview

🟡 Changes recommended

The sign-in-dialog gating branch needs focused regression coverage, and added comments exceed repository limits.

Get a fresh assessment by requesting another Copilot review.

Review effort: Balanced
Findings: 2 High severity · 1 Medium severity · 2 Low severity

Open (5)
Resolved since last review (1)


override async run(accessor: ServicesAccessor): Promise<boolean> {
// The sign-in dialog invokes the command directly, which no precondition can gate.
if (SessionsClassicWindowUnavailableContext.getValue(accessor.get(IContextKeyService)) === true) {

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Good catch, and it is the sharpest of the three: the test would have passed with that guard deleted. Covered in e67dc0f over unset, false and true, against ShouldShowReturnToVSCodeEditorAction.run() itself rather than a reconstruction — and the true case asserts queriedWindows === false, so the short-circuit before INativeHostService is pinned as you asked rather than implied by the return value.

Comment thread src/vs/sessions/common/contextkeys.ts Outdated
Comment thread src/vs/sessions/test/electron-browser/vscodeActions.test.ts Outdated
The regression test only evaluated action preconditions, so removing the
guard in `ShouldShowReturnToVSCodeEditorAction.run()` would still have
passed while the Return button stayed visible in an opted-out product. It
is now covered over unset, `false` and `true`, including that opting out
short-circuits before the native host is asked for windows.

Trims the context key's JSDoc to the opt-out invariant -- the
canonicalization history it carried is what the test protects -- and the
two-line narration in the test to one line.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

Copilot AI 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.

Copilot review overview

🟢 Approval recommended

The opt-out preserves default behavior, covers all identified entry points, and has focused regression tests.

Review effort: Balanced
Findings: 1 Medium severity

Open (1)
Resolved since last review (4)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants