Floating chat-input window with multi-session routing#326698
Draft
meganrogge wants to merge 13 commits into
Draft
Floating chat-input window with multi-session routing#326698meganrogge wants to merge 13 commits into
meganrogge wants to merge 13 commits into
Conversation
Introduces a frameless, always-on-top auxiliary window that hosts the real chat input (dictation, voice mode, and the input glow) via a compact, input-only ChatWidget. Submissions are scored against the current session list by a new ISessionRouter and dispatched with three outcomes: - low confidence -> start a brand-new session - several comparable high matches -> ask the user which session - a single clear match -> dispatch straight to it ISessionRouter keeps prompt/parse/heuristic logic pure so the scoring backend (renderer language model now; CAPI utility or a local model later) can be swapped without changing the contract; it degrades to a token-overlap heuristic when no model is available. Toggle via the command "Toggle Floating Chat Input Window". Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: aba188ca-29fb-4099-b0f9-e460fcb20613
Contributor
There was a problem hiding this comment.
Pull request overview
Adds a floating chat-input window that routes requests to matching agent sessions.
Changes:
- Adds model-backed and heuristic session routing.
- Adds the floating ChatWidget, disambiguation picker, and fallback routing.
- Registers the services, command, contribution, and helper tests.
Show a summary per file
| File | Description |
|---|---|
src/vs/workbench/workbench.common.main.ts |
Loads the floating-window contribution. |
src/vs/workbench/contrib/chat/test/common/sessionRouter.test.ts |
Tests routing helpers. |
src/vs/workbench/contrib/chat/common/sessionRouter.ts |
Defines routing contracts and pure helpers. |
src/vs/workbench/contrib/chat/common/chatInputWindow.ts |
Defines the window service contract. |
src/vs/workbench/contrib/chat/browser/sessionRouter/sessionRouterService.ts |
Implements model-backed routing. |
src/vs/workbench/contrib/chat/browser/chatInputWindow/chatInputWindowService.ts |
Implements the window and dispatch workflow. |
src/vs/workbench/contrib/chat/browser/chatInputWindow/chatInputWindow.contribution.ts |
Registers the toggle command. |
src/vs/workbench/contrib/chat/browser/chat.shared.contribution.ts |
Registers the router service. |
Review details
- Files reviewed: 8/8 changed files
- Comments generated: 16
- Review effort level: Medium
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
- Fix hygiene failure: replace non-ASCII box-drawing separator comment in sessionRouter.ts with ASCII; move $(add) icon outside the localized string. - Draggable frameless window: add a -webkit-app-region drag handle strip. - Localize the window document title with a placeholder. - Reapply themed colors on onDidColorThemeChange. - Dedicated accessibility help (routing + how to close) via inChatInputWindow context key, outranking the generic Quick Chat help. - Forward and clear explicit attachments through the routing submit contract. - Dedicated scoped ChatInputWindowSide menu + Close action (no longer closes the unrelated Quick Chat surface). - Only clear the input if the editor still holds the submitted text. - Window-scoped submission CancellationTokenSource, canceled on close. - Await agent-sessions model.resolve before snapshotting candidates. - Retain at most one session reference per resource (ResourceMap dedupe). - Calibrate the offline heuristic against candidate metadata + threshold test. - Coalesce concurrent openWindow calls; guard unload cleanup by window identity. - Use dom.addDisposableListener for the beforeunload listener. - Rethrow CancellationError from the router instead of degrading to heuristic. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 8904e5b5-6e65-4b9c-8ec5-ac060df81978
The session router scores candidate sessions as a background classification task. Pin it to the small utility model (vendor: copilot, id: copilot-utility-small) like other internal utility features (chatGoalSummaryService, chatToolRiskAssessmentService, etc.) instead of grabbing the first available Copilot model, which could be an expensive premium model and is ordering-dependent. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: ece96f2d-c878-4a57-97c5-884542b8581e
…uting
Routing is no longer silent. After scoring the utterance against existing
sessions, the window resolves a single pending target (top match above the
confidence threshold, biased toward the last-used session; otherwise a new
session) and shows an inline badge naming that target with a short countdown.
When the countdown elapses the request auto-sends. The user can redirect it
("Change"), abort it ("Cancel"), or just keep typing — any edit cancels the
auto-send — so a request is never dispatched without a visible, correctable
step.
- Add ROUTE_AUTOSEND_DELAY_MS countdown + pending-send badge in the aux window.
- Remember the last routed session (workspace storage) and pre-select it.
- Generalize the target picker to list all scored candidates with a preselected
entry, reused by the badge's "Change" action.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: ece96f2d-c878-4a57-97c5-884542b8581e
Collaborator
Author
|
Reworked routing from silent auto-dispatch to an advisory badge with auto-send, based on a design rethink:
Known follow-up: the "Change" quick-pick still opens on the main window rather than the aux window (per-window quick input is a larger change); the badge itself is inline in the aux window. |
… wire Quick Chat Extracts the advisory-badge session routing from ChatInputWindowService into a reusable ChatSessionRoutingController (shared CSS with generic class names) and wires Quick Chat to it behind a new `chat.omni.enabled` setting. - New `chat.omni.enabled` (experimental, default off) gates the omni experience on omni surfaces such as Quick Chat. - No-match case no longer delays: it creates and sends to a new chat immediately and the badge links to that session (via IChatWidgetService.openSession) as soon as it exists. - Confident-match case keeps the countdown + Change/Cancel/type-to-cancel flow. - The floating input window now delegates to the shared controller. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: ece96f2d-c878-4a57-97c5-884542b8581e
When the router auto-sends to a matched session, show a brief inline
confirmation badge ("Sent to «session»") with an Open link, so omni
surfaces that don't render the response inline (Quick Chat, aux input
window) still confirm where the request went. Auto-dismisses after 4s.
Guarded on the current submission so a newer submit isn't overwritten.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: ece96f2d-c878-4a57-97c5-884542b8581e
Give more time to redirect or cancel before the matched send fires. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: ece96f2d-c878-4a57-97c5-884542b8581e
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: ece96f2d-c878-4a57-97c5-884542b8581e
The disambiguation picker renders into the focused aux window's container; since that frameless window is only tall enough for the input, the options were clipped. Resize the window to fit the rows while the picker is open (via an onPickerVisibility host hook on the shared routing controller) and restore the height on close. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: ece96f2d-c878-4a57-97c5-884542b8581e
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.
Fixes https://github.com/microsoft/vscode-internalbacklog/issues/8461
What
Adds a floating, frameless, always-on-top chat-input window that hosts the real chat input — dictation, voice mode, and the input glow — via a compact, input-only
ChatWidget. When you submit, the request is scored against your existing sessions and routed to the best match, but never silently: an advisory badge shows the chosen target and a short countdown, then auto-sends unless you intervene.Toggle with the command "Toggle Floating Chat Input Window" (
workbench.action.chat.toggleInputWindow).Routing — advisory badge with auto-send
On submit, the utterance is scored against the current session list (
IAgentSessionsService) viaISessionRouter, and the window resolves a single pending target:ROUTE_CONFIDENCE_THRESHOLD, biased toward the last-used session when it's withinROUTE_AMBIGUITY_MARGINof the top) → that session.It then shows an inline badge in the window —
Sending to «target» · N% match · sending in 3…2…1— and dispatches when the countdown (ROUTE_AUTOSEND_DELAY_MS) elapses. Before it fires you can:N% match+ rationale), preselected to the current target, plus "New session"; retargets and restarts the countdown.The last routed session is remembered (workspace storage) so repeated turns bias toward the same session. This keeps a hands-free/voice flow fast while ensuring a request is never dispatched without a visible, correctable step.
Design
ISessionRouter(chat/common/sessionRouter.ts) keeps prompt/parse/heuristic logic pure so the scoring backend (renderer language model now — the smallcopilot-utility-smallutility model — a CAPI utility completion or a local model later) can be swapped without changing the contract. It degrades to a zero-dependency token-overlap heuristic when no model is available.ChatInputWindowService(chat/browser/chatInputWindow/) mirrors the provenAgentsVoiceWindowServiceaux-window shell and hosts aChatWidgetwithrenderStyle:'compact',renderInputOnTop,filter:() => false(input-only), andenableImplicitContext:false(no attachment row). The glow applies for free since the aux container tracks themonaco-workbenchclass. The badge, countdown timers, and their listeners are window-scoped disposables cleared on cancel / retarget / resend / window close.Files
chat/common/sessionRouter.ts,chat/browser/sessionRouter/sessionRouterService.ts(+ unit test)chat/common/chatInputWindow.ts,chat/browser/chatInputWindow/{chatInputWindowService,chatInputWindow.contribution}.ts,chat/browser/chatInputWindow/media/chatInputWindow.csschat.shared.contribution.tsandworkbench.common.main.tsNotes / follow-ups
ROUTE_CONFIDENCE_THRESHOLD,ROUTE_AMBIGUITY_MARGIN) and the auto-send delay (ROUTE_AUTOSEND_DELAY_MS) are constants that could be promoted to settings / tuned with telemetry.🤖 Generated with GitHub Copilot CLI