Voice Mode: migrate from vendored libs to VS Code patterns#321168
Merged
Conversation
Replace signal(), computed(), effect() from vendored signals-core with observableValue(), derived(), autorun() from VS Code's observable system. - 23 signal() → observableValue() - 1 computed() → derived() - 3 effect() → autorun() - All .value reads → .get() (untracked) or .read(reader) (tracked in autorun) - All .value writes → .set(value, undefined) Part of #321142 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace all lit-html html`` tagged templates and render() calls with VS Code-style
imperative DOM construction using dom.$(), document.createElement(), and
addEventListener().
Each component is now a factory function returning { element, update(props) }:
- element: stable HTMLElement created once
- update(): targeted DOM mutations (no full rebuilds)
Key improvements:
- Glow animation decoupled from autorun — direct RAF style updates
eliminates 60fps observable thrashing
- Stable DOM structure preserves focus, scroll position, and textarea state
- No more vendored lit-html dependency
Components migrated (8 files, ~860 lines):
- confirmationComponent.ts
- voiceBarComponent.ts
- statusRowsComponent.ts
- transcriptComponent.ts
- onboardingComponent.ts
- feedbackDialog.ts
- headerComponent.ts
- sessionListComponent.ts
Widget (agentsVoiceWidget.ts):
- Replaced _view() returning TemplateResult with _updateDOM() doing targeted updates
- Components created once in field initializers, updated in autorun
- Removed _glowIntensity and _glowPhase observables (now local to RAF loop)
Part of #321142
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
These vendored libraries are no longer used after migrating to VS Code's native DOM construction and observable patterns. - Removed src/vs/base/common/lit-html/ (11 files) - Removed src/vs/base/common/signals-core/ (3 files) Part of #321142 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Remove toggleWindow() call from pushToTalk action (prevents Space from opening the mini aux window) - Add dynamic PTT key tracking: captures last keydown code at document level, snapshots it on pttDown, matches on keyup — works with any rebound key, not just hardcoded Space - Add keydown preventDefault to block role='button' click activation during hold-to-talk Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR migrates the Agents Voice UI away from vendored lit-html and @preact/signals-core to VS Code’s native observable/reactive patterns and imperative DOM construction, while also removing the now-unused vendored libraries.
Changes:
- Replaced
signal/computed/effectusage withobservableValue/derived/autoruninAgentsVoiceWidget, and moved the glow animation to direct DOM updates in the RAF loop. - Reworked Agents Voice UI components from
lit-htmltemplates into stable DOM factories (createX(): { element, update(...) }) with targeted updates. - Deleted the vendored
lit-htmlandsignals-coreimplementations and their CG manifests.
Show a summary per file
| File | Description |
|---|---|
| src/vs/workbench/contrib/agentsVoice/browser/agentsVoiceWidget.ts | Migrates widget state to VS Code observables, replaces templated rendering with imperative DOM updates, and decouples the glow animation from reactivity. |
| src/vs/workbench/contrib/agentsVoice/browser/components/headerComponent.ts | Converts the header from lit-html to DOM factory/update pattern and rewires header actions imperatively. |
| src/vs/workbench/contrib/agentsVoice/browser/components/onboardingComponent.ts | Converts onboarding UI from template rendering to imperative DOM construction with an update() pass. |
| src/vs/workbench/contrib/agentsVoice/browser/components/sessionListComponent.ts | Converts session list rendering to imperative DOM; rebuilds list on update and rewires per-row actions. |
| src/vs/workbench/contrib/agentsVoice/browser/components/statusRowsComponent.ts | Converts status row rendering to imperative DOM and integrates tool confirmations via component factory. |
| src/vs/workbench/contrib/agentsVoice/browser/components/transcriptComponent.ts | Converts transcript rendering to imperative DOM and performs per-update rebuilding of visible turns. |
| src/vs/workbench/contrib/agentsVoice/browser/components/feedbackDialog.ts | Replaces lit-html dialog rendering with a component factory and updates controller to use update()/clearNode(). |
| src/vs/workbench/contrib/agentsVoice/browser/components/confirmationComponent.ts | Converts tool confirmation rendering to imperative DOM factory/update pattern. |
| src/vs/workbench/contrib/agentsVoice/browser/components/voiceBarComponent.ts | Converts the voice bar from template rendering to imperative DOM factory/update pattern. |
| src/vs/base/common/signals-core/signals-core.js | Removed vendored @preact/signals-core runtime. |
| src/vs/base/common/signals-core/signals-core.d.ts | Removed vendored @preact/signals-core types. |
| src/vs/base/common/signals-core/cgmanifest.json | Removed CG manifest for vendored @preact/signals-core. |
| src/vs/base/common/lit-html/lit-html.js | Removed vendored lit-html runtime. |
| src/vs/base/common/lit-html/lit-html.d.ts | Removed vendored lit-html types. |
| src/vs/base/common/lit-html/lit-html.d.ts.map | Removed vendored lit-html type map. |
| src/vs/base/common/lit-html/directive.js | Removed vendored lit-html directive helpers. |
| src/vs/base/common/lit-html/directive.d.ts | Removed vendored lit-html directive types. |
| src/vs/base/common/lit-html/directive.d.ts.map | Removed vendored lit-html directive type map. |
| src/vs/base/common/lit-html/directive-helpers.js | Removed vendored lit-html directive helper utilities. |
| src/vs/base/common/lit-html/directive-helpers.d.ts | Removed vendored lit-html directive helper types. |
| src/vs/base/common/lit-html/directive-helpers.d.ts.map | Removed vendored lit-html directive helper type map. |
| src/vs/base/common/lit-html/directives/repeat.js | Removed vendored lit-html repeat directive runtime. |
| src/vs/base/common/lit-html/directives/repeat.d.ts | Removed vendored lit-html repeat directive types. |
| src/vs/base/common/lit-html/directives/repeat.d.ts.map | Removed vendored lit-html repeat directive type map. |
| src/vs/base/common/lit-html/cgmanifest.json | Removed CG manifest for vendored lit-html. |
Copilot's findings
Comments suppressed due to low confidence (1)
src/vs/workbench/contrib/agentsVoice/browser/agentsVoiceWidget.ts:582
- The fallback feedback error message is user-visible but not localized (
'Failed to submit'). This should uselocalize(...)like the rest of the voice UI strings.
}
}
/**
- Files reviewed: 17/26 changed files
- Comments generated: 15
…ice-libs # Conflicts: # src/vs/workbench/contrib/agentsVoice/browser/agentsVoiceWidget.ts
- Fix style injection bug: move transcript CSS outside clearNode scope - Add Enter/Space keyboard activation to all role='button' elements via shared addKeyboardActivation() helper in tokens.ts - Change mousedown→click handlers for session row actions (keyboard compat) - Add focusin/focusout to session rows to reveal actions for keyboard users - Fix popout button visibility in centerConnectButton mode - Make chevron wrapper a proper button (role, tabIndex, key handler) - Localize 'Failed to submit' fallback string Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
rzhao271
approved these changes
Jun 12, 2026
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.
Resolves #321142
Summary
Migrates the voice UI from vendored
lit-htmland@preact/signals-coreto VS Code's native patterns.1. preact-signals → VS Code observables
signal()→observableValue()computed()→derived()effect()→autorun().valuereads →.read(reader)(tracked) or.get()(untracked).valuewrites →.set(value, undefined)2. lit-html → imperative DOM construction
Each component is now a factory function returning
{ element, update(props) }:element: stable DOM node created onceupdate(): targeted mutations (no full rebuilds)This preserves focus, scroll position, and textarea state across re-renders.
3. Glow animation decoupled from reactive system
The glow/waveform animation (running at 60fps via requestAnimationFrame) previously updated two observables each frame, triggering full autorun re-renders. Now it directly updates the glow element's CSS — the autorun only fires for actual state changes.
4. Vendored libraries removed
src/vs/base/common/lit-html/(11 files)src/vs/base/common/signals-core/(3 files)No other consumers existed.
Files changed
agentsVoiceWidget.ts— signals + render loop migrationcomponents/— lit-html → DOM