Visitar URL original
Agents window: add the Agents Launcher to start sessions from anywhere by ulugbekna · Pull Request #347677 · microsoft/vscode · GitHub
Skip to content

Agents window: add the Agents Launcher to start sessions from anywhere - #347677

Merged
Ulugbek Abdullaev (ulugbekna) merged 13 commits into
mainfrom
ulugbekna/agents/vscode-agent-window-keybinding-exploration
Nov 13, 2026
Merged

Ulugbek Abdullaev (ulugbekna) merged 13 commits into
mainfrom
ulugbekna/agents/vscode-agent-window-keybinding-exploration

Conversation

@ulugbekna

@ulugbekna Ulugbek Abdullaev (ulugbekna) commented Nov 11, 2026 •

Copy link
Copy Markdown
Contributor

Adds the Agents Launcher: a system-wide shortcut summons a small floating composer from any application, so you can start an Agents window session without switching to it. Similar features exist in other desktop AI apps: ChatGPT's Chat Bar, Claude's Quick entry and OpenClaw's Quick Chat.

No issue tracks this yet. It builds on the system-wide keybindings of the Agents window (#344954).

What it does

  • Opt in with a user keybinding; there is no default:
    { "key": "ctrl+space", "command": "workbench.action.agentsLauncher", "systemWide": true }
    
  • Enter starts the session, hides the launcher, and opens the session in the Agents window.
  • Cmd+Enter or Alt+Enter starts it in the background. The launcher stays open, with Message sent ✓ Open Session below the input.
  • Escape, or switching away, hides the launcher and keeps the draft. The shortcut toggles it.
  • Show Agents Launcher in an editor window asks the Agents window to show the launcher, opening the Agents window first if none is open, without bringing it to the front.
Dark Light
The Agents Launcher in a dark theme The Agents Launcher in a light theme

After Cmd+Enter, the launcher stays open with the status below the input (video):

The Agents Launcher after Cmd+Enter, showing Message sent and Open Session below the input

How it works

  • The launcher is an always-on-top panel auxiliary window of the Agents window. On macOS it is an NSPanel, so showing it never activates the application. It hosts the existing new-session composer with a draft slot and SessionHost of its own, and is hidden rather than closed when dismissed.
  • AgentsLauncherPresenter sequences each show: prepare, opacity 0, position, show, focus, wait for a rendered frame, opacity 1. Any later show or hide interrupts it, so a quick double press never leaves an invisible window with keyboard focus. Staying transparent until painted avoids a stale frame flashing on re-show.
  • Every send is a background send, so a failed send gives its prompt back to the launcher. The new INewSessionBackgroundSend.requestedInBackground tells the launcher whether the user asked for a background send (stay open) or pressed Enter (leave for the Agents window).
  • The Agents window owns the system-wide registration, as it does for Open Agents Window, so the shortcut keeps working with no editor window open.

Changes outside the launcher

  • NativeHostMainService.positionWindow no longer falls back to the calling window when the window a request targets has closed: a request for a closed auxiliary window moved its owner instead. The new showWindow, hideWindow and setWindowOpacity resolve their target the same way. Like the other native host methods that would reveal a window, showWindow does nothing in hidden-window mode (--hidden-window).
  • Auxiliary windows gain panel and opacity open options.
  • A new-session composer host can opt in with hideChatWidgetWhileHidden, so that its chat widget is visible only while the composer is. The launcher stays rendered while hidden, and its composer counted as a foreground chat, which suppresses chat tips. Only the launcher opts in; existing hosts keep their behavior.
  • INewSessionBackgroundSend has a new required requestedInBackground field.
  • dom.getActiveDocument (and so getActiveWindow and the layout service's active container) takes the window that received focus last, or that had focus as it registered, when several windows report focus. On macOS the launcher's panel takes focus without the Agents window losing it, so both report focus: popups of the launcher opened in the Agents window, and Close Window (Cmd+Shift+W) in the launcher closed the Agents window. With at most one window reporting focus, nothing changes.
  • ChatWindowComposerBackgroundSends gives the prompt of an ordinary send back to its composer when the send does not start, such as when workspace trust is declined, without an error. Such sends (requestedInBackground: false) come only from hosts that send everything in the background, which today is only the launcher; chat windows' Send in Background is unchanged.

Reviewing

Thirteen commits, each of which type-checks and passes its tests on its own. Read them in order:

  1. Native host: ignore a window request whose target window has closed
  2. Native host: show, hide and set the opacity of a window
  3. Auxiliary windows: open as a panel and with an initial opacity
  4. Sessions composer: let a host hide its composer's chat widget while hidden
  5. Sessions composer: tell its host whether the user sent in the background
  6. Agents Launcher: place its window and sequence its shows and hides
  7. Agents Launcher: a floating new-session composer of the Agents window
  8. Agents Launcher: open the session of an ordinary send in the Agents window
  9. Agents Launcher: show it from editor windows
  10. Agents window: own the system-wide keybindings of the Agents Launcher
  11. Agents Launcher: hide after leaving it once a send or popup no longer defers it (from review)
  12. Windows: take the window focused last as active when several report focus (from review)
  13. Sessions composer: give back the prompt of an ordinary send that does not start (from review)

How to test

  1. Add the keybinding above to your user keybindings.json and open the Agents window.
  2. Switch to another application and press the shortcut. The launcher appears near the top of the display under the pointer, with its input focused, and the other application stays active.
  3. Type a prompt and press Cmd+Enter. The launcher stays open with Message sent ✓ Open Session; Open Session opens the session.
  4. Type a prompt and press Enter. The launcher hides, and the Agents window comes to the front and opens the session.
  5. Press the shortcut twice quickly: the launcher ends hidden. Escape hides it and keeps the draft. While it is open, change the color theme and the zoom level: it keeps its layout and fits its content.

Validation

On every commit:

  • pnpm run typecheck-client: passed
  • pnpm run oxlint <changed .ts files>: passed
  • node --experimental-strip-types build/hygiene.ts <changed files>: passed
  • node build/next/index.ts transpile, then ./scripts/test.sh --run for the launcher, newChatWidget, chatWindowComposer, sharedChatInputComposer, openAgentsWindow.contribution, sessionsChatAccessibilityHelp and both agentSessionsActions suites: passed (488 tests at the tip, including dom)

At the tip:

  • node build/stylelint.ts: passed
  • pnpm run valid-layers-check: passed
  • ./scripts/test.sh --run for the composer hosts and the Agents window workbench (dom, contextview, sessionView, workbench, chatEditor, mobileChatShell, mobileChatEditRow, newChatUserInteraction and the suites above): 827 passed

Manually, in Code OSS on macOS, summoned like the global shortcut:

  • Two toggles 0 to 120 ms apart, including while the window is created, always end hidden and unfocused.
  • Theme change while open: the launcher keeps its styles.
  • Zoom level 1: the window is 768×170 for 640×142 CSS pixels, with nothing clipped.
  • Reopening: the window fits the composer on every show (142 px empty; 202 px with a five-line draft kept while hidden), also after Escape; clearing the draft while shown shrinks it back.
  • The foreground chat count returns to 1 whenever the launcher hides; the Agents window's own composer still takes input.
  • With the Agents window focused before the launcher shows, the launcher's mode picker opens in the launcher, and afterwards the Agents window's own picker opens in the Agents window.
  • With both windows reporting focus (focus emulation over CDP, on the launcher's first show), the launcher's picker opens in the launcher, and Cmd+Shift+W closes only the launcher; the Agents window stays open, and the launcher's draft survives when it is summoned again.
  • An Enter send whose preparation fails with WorkspaceNotTrustedError (injected with a conditional breakpoint) hides the launcher as usual and gives the prompt back to it, without an error notification. An Enter send with the same input sends exactly what was typed.
  • Keyboard submit target: a key on a toolbar button keeps focus; a key in the input reclaims the submit target.
  • Cmd+Enter keeps the launcher open with its status; Enter opens the started session in the Agents window.

Not run: Windows, Linux (including Wayland), VoiceOver, smoke and integration tests.

Known limitations and follow-ups

  • Slow Enter sends: after Enter, the launcher opens the session once it has started. If the user opens another session meanwhile, the started session still opens over it.

  • Cold start: with only editor windows open, the shortcut opens the Agents window in the foreground before showing the launcher. Opening it without activating the application needs a hidden or minimized open in windowsMainService.

  • Gating: system-wide keybindings run commands without preconditions. The editor-window command checks agent mode but not whether AI features are disabled; the Agents window checks AI features but not chat.agent.enabled.

  • Linux: Electron does not support the cursor position or always-on-top on Wayland, nor window opacity on Linux. The launcher needs a fallback there, or should be gated.

  • src/vs/sessions/SYSTEM_WIDE_KEYBINDING.md still describes the Agents window as owning Open Agents Window only.

  • Clicking the Agents window while a picker of the launcher is open closes the picker, which gives focus back to its button and so to the launcher; the launcher then stays open. Switching to another application hides it as expected.

  • Prompts of a send, such as workspace trust, show in the Agents window, which the always-on-top launcher can cover until it hides.

  • The draft survives hiding, but not a reload of the Agents window.

Copilot AI balanced review requested due to automatic review settings November 11, 2026 17:31

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.

🟡 Changes recommended

Launcher requests can unexpectedly activate the full Agents window, and deferred dismissal can leave the always-on-top launcher visible over other applications.

2 open issues
What changed in this PR

Adds an opt-in Agents Launcher that reuses the new-session composer in a floating desktop window, extending the Agents window’s system-wide shortcut support.

Changes:

  • Adds launcher presentation, draft retention, background sends, and navigation to started sessions.
  • Extends native and auxiliary-window APIs with panel, visibility, opacity, and exact-target handling.
  • Updates composer visibility tracking, shortcut ownership, accessibility help, localization, and focused tests.
File Description
src/​vs/​workbench/​test/​electron-browser/​workbenchTestServices.ts Adds native-host test stubs.
src/​vs/​workbench/​services/​auxiliaryWindow/​browser/​auxiliaryWindowService.ts Adds panel and initial-opacity options.
src/​vs/​workbench/​contrib/​sessions/​browser/​parts/​chatView.ts Records explicit background-send intent.
src/​vs/​workbench/​contrib/​sessions/​browser/​chat/​sharedChatInputComposer.ts Tracks chat visibility from composer visibility.
src/​vs/​workbench/​contrib/​sessions/​browser/​chat/​newChatWidget.ts Passes background-send intent to the host.
src/​vs/​workbench/​contrib/​chat/​electron-browser/​chat.contribution.ts Registers the editor-window launcher action.
src/​vs/​workbench/​contrib/​chat/​electron-browser/​agentSessions/​agentSessionsActions.ts Adds the Show Agents Launcher action.
src/​vs/​workbench/​contrib/​chat/​common/​constants.ts Defines the launcher command ID.
src/​vs/​sessions/​sessions.desktop.main.ts Loads the desktop launcher contribution.
src/​vs/​sessions/​contrib/​openAgentsWindow/​test/​electron-browser/​openAgentsWindow.contribution.test.ts Tests launcher shortcut ownership and conflicts.
src/​vs/​sessions/​contrib/​openAgentsWindow/​electron-browser/​openAgentsWindow.contribution.ts Includes launcher shortcuts in Agents window ownership.
src/​vs/​sessions/​contrib/​chatWindow/​test/​browser/​chatWindowComposer.test.ts Updates fixtures with background-send intent.
src/​vs/​sessions/​contrib/​chat/​test/​browser/​newChatWidget.test.ts Tests explicit and host-forced background sends.
src/​vs/​sessions/​contrib/​chat/​browser/​sessionsChatAccessibilityHelp.ts Documents launcher keyboard interactions.
src/​vs/​sessions/​contrib/​agentsLauncher/​test/​electron-browser/​agentsLauncher.test.ts Tests presentation sequencing, bounds, and session handoff.
src/​vs/​sessions/​contrib/​agentsLauncher/​electron-browser/​media/​agentsLauncher.css Styles the compact launcher composer.
src/​vs/​sessions/​contrib/​agentsLauncher/​electron-browser/​agentsLauncher.ts Implements bounds, presentation sequencing, and send tracking.
src/​vs/​sessions/​contrib/​agentsLauncher/​electron-browser/​agentsLauncher.contribution.ts Implements the launcher service, window lifecycle, and commands.
src/​vs/​platform/​windows/​electron-main/​windows.ts Applies native panel and opacity options.
src/​vs/​platform/​window/​common/​window.ts Adds launcher IPC and window-open source identifiers.
src/​vs/​platform/​native/​electron-main/​nativeHostMainService.ts Routes launcher requests and adds exact-target window operations.
src/​vs/​platform/​native/​common/​native.ts Declares launcher and window-control APIs.
src/​vs/​platform/​auxiliaryWindow/​electron-main/​auxiliaryWindowsMainService.ts Parses panel and opacity window features.
build/​lib/​i18n.resources.json Registers launcher localization resources.

Review effort: Balanced

@ulugbekna
Ulugbek Abdullaev (ulugbekna) force-pushed the ulugbekna/agents/vscode-agent-window-keybinding-exploration branch 3 times, most recently from 0d3b7f3 to 15d5832 Compare November 12, 2026 15:31
@ulugbekna
Ulugbek Abdullaev (ulugbekna) marked this pull request as ready for review November 12, 2026 17:25
@ulugbekna
Ulugbek Abdullaev (ulugbekna) force-pushed the ulugbekna/agents/vscode-agent-window-keybinding-exploration branch from 15d5832 to 04cbe2c Compare November 12, 2026 18:49

@connor4312 Connor Peet (connor4312) left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Reviewed the complete diff and relevant remote source at 04cbe2c. No high-confidence P1/P2 security or correctness findings identified. Review was source-only; tests and platform behavior were not independently exercised.

Written by Connor's agent running GPT-6.1 Sol

positionWindow resolves its target with windowById, which falls back to the
calling window when the window a request targets no longer exists. A request
meant for an auxiliary window that closed meanwhile then moved and resized
the main window that owned it. A request that targets a window now applies
to that window only.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Adds showWindow, hideWindow and setWindowOpacity, for a floating auxiliary
window that is hidden rather than closed when dismissed, and stays
transparent until it has painted. Like positionWindow, they apply to the
window a request targets only.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The panel option opens an auxiliary window that does not activate the
application as it takes the keyboard focus: an NSPanel on macOS, and a
window without a taskbar button elsewhere. Neither can it be made full
screen. The opacity option sets the opacity it opens with.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…idden

A composer's chat widget is visible for as long as it is rendered. A
composer that stays rendered while hidden, such as one in a floating
window, then counts as a foreground chat, which suppresses chat tips in
other composers. A host can now opt in with hideChatWidgetWhileHidden, so
that its composer's chat widget follows the visibility of its host and
view. Existing hosts keep their behavior.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
A composer whose view sends all its requests in the background
(backgroundSend) sends an ordinary send in the background too, as Send in
Background does. Its host now learns which of the two each background send
was, with INewSessionBackgroundSend.requestedInBackground.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The Agents Launcher is a small floating composer of the Agents window. Its
window is placed on the display beneath the pointer, sized for its content
at its zoom level. A presenter sequences the window operations of a show:
each show or hide is a new request, which interrupts a show in progress, so
that a hide while showing never leaves the window shown, focused or
transparent.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Show Agents Launcher toggles a floating, always-on-top panel of the Agents
window, which hosts the new-session composer with a draft of its own.
Escape, or leaving it, hides it and keeps its draft. It sends its requests
in the background, so that a failure gives the prompt back to it, and shows
their status below its input, which offers to open the session.

The window stays transparent until it has painted, as a window shown again
can present an old frame for a moment. Shows do not activate the
application.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…indow

Enter leaves the Agents Launcher for the Agents window as the request goes
out, and opens its session there once it has started. Cmd+Enter, or
Alt+Enter, starts the session in the background and keeps the Agents
Launcher open, with its status.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Show Agents Launcher in an editor window asks the Agents window to toggle
the Agents Launcher, without bringing the Agents window to the front, and
opens the Agents window first should none be open.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
As for Open Agents Window, the Agents window registers the system-wide
keybindings of Show Agents Launcher, so that they keep working once no
editor window is open.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… defers it

Leaving the launcher hides it, unless a send is under way or one of its
popups is open then. That check ran once: once the send finished or the
popup closed, the always-on-top launcher stayed over the application the
user had switched to. It now checks again until nothing defers hiding,
the launcher is focused again, or it hides.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ocus

On macOS a panel window, such as the Agents Launcher, takes focus
without the window focused before it losing focus, so that both report
focus. The active window was then the one registered first: popups of
the launcher opened in the Agents window, and window commands such as
Close Window acted on the Agents window. The active window is now the
one that received focus last, while it still has focus; a window that
has focus as it registers, such as one that opened focused, counts as
focused last. With at most one window reporting focus, nothing changes.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… not start

The Agents Launcher sends all of its requests in the background, so that
a failed send gives its prompt back to it. A send that the user did not
start, such as by declining to trust its workspace or cancelling its
preparation, gave nothing back, and its prompt was lost, unlike that of
the same send from a composer that sends in the foreground. The prompt
of an ordinary send that its composer sent in the background now goes
back to the composer when the send does not start, without an error.
Sends the user sent in the background are unchanged.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@ulugbekna
Ulugbek Abdullaev (ulugbekna) force-pushed the ulugbekna/agents/vscode-agent-window-keybinding-exploration branch from c177fdd to c5aec3e Compare November 13, 2026 10:39
@ulugbekna
Ulugbek Abdullaev (ulugbekna) added this pull request to the merge queue Nov 13, 2026
Merged via the queue into main with commit f1cf69d Nov 13, 2026
52 of 53 checks passed
@ulugbekna
Ulugbek Abdullaev (ulugbekna) deleted the ulugbekna/agents/vscode-agent-window-keybinding-exploration branch November 13, 2026 12:06
@vs-code-engineering vs-code-engineering Bot added this to the 1.147.0 milestone Nov 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants