Open
Conversation
Scaffold a VS Code extension that embeds the TypeAgent shell chat: - Extension host: activation, sidebar WebviewViewProvider, editor panel command, agent server lifecycle manager, status bar item - Webview: chat UI (messages, input, status), WebSocket connection to agent server using the same RPC protocol as the shell renderer - Theming: uses VS Code CSS variables for full theme integration - esbuild: dual bundle (extension + webview), watch mode support - Settings: serverUrl, autoStart, serverPort configuration Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace the broken raw WebSocket approach with the proper channel-multiplexed RPC protocol. The agent server uses createWebSocketChannelServer with named channels (agent-server, dispatcher:<session>, clientio:<session>). Architecture change: - Extension host (Node.js) now manages the real RPC connection using connectAgentServer() from @typeagent/agent-server-client - Webview communicates with extension host via postMessage bridge - Extension host implements ClientIO and forwards display events to webview Key changes: - New: agentServerBridge.ts - manages RPC connection + webview bridge - Removed: agentServerManager.ts (HTTP probe approach didn't work) - Removed: webview/agentConnection.ts (raw WebSocket didn't match protocol) - Updated: chatViewProvider.ts - uses bridge instead of server manager - Updated: webview/main.ts - uses postMessage instead of direct WebSocket - Updated: chatUI.ts - handles typed display events from the server - Updated: package.json - adds @typeagent/* workspace dependencies - Updated: esbuild.mjs - suppresses import.meta.url warning Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… agent progress - Handle DisplayContent types (string, string[], TypedDisplayContent) properly - Use appendDisplay mode 'temporary' for replaceable status messages - Add filter:true to joinSession to only see own request responses - Show user message immediately on send (no lag waiting for server echo) - Add commandComplete event to clean up temporary status on finish - Dedup consecutive identical inline content - Remove debug logging Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Switch Session: QuickPick to list and switch between sessions - New Session: Create a named session and switch to it - Rename Session: Rename the current session - Delete Session: Pick and delete a non-current session (with confirmation) - Status bar shows session name instead of truncated ID - Chat clears and shows notification on session switch - Commands registered in VS Code command palette (TypeAgent: *) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add reconnectAndJoin fallback when channel conflicts occur during session switch - Validate session names for uniqueness (case-insensitive) on create and rename - Trim whitespace from session names Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Align extension UI with the rest of the project's terminology change from 'session' to 'conversation'. Internal API identifiers (command IDs, message types, SessionInfo fields) remain unchanged. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add isSwitching flag to suppress disconnect handler during intentional reconnects (prevents 'Agent channel disconnected' error surfacing) - Cancel pending auto-reconnect timers in reconnectAndJoin - Move webview notifications to after the try/finally so they always fire regardless of which code path (direct join or reconnect) succeeded Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The agent server's default port changed to 8999 (see server.ts). Update extension defaults to match. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add 'switching' message type from bridge to webview - Disable input/send button while a conversation switch is in progress - Display target conversation name in the status bar and input placeholder - Add CSS class for the switching state Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- On connect and after every conversation switch, call dispatcher.getDisplayHistory() and replay entries through the same display channels live messages use (setUserRequest, setDisplay, appendDisplay, setDisplayInfo). - Wrap replay in historyStart/historyEnd messages so the webview can mark replayed bubbles with a 'history' class for muted styling. - Refactor joinSpecificSession to use the join-before-leave pattern (matching the shell's sessionManager); this also eliminates the channel-already-exists error so reconnectAndJoin is no longer needed. - Display 'conversation history' / 'now' separators around replayed content for clarity. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Remove '--- conversation history ---' and '--- now ---' separators - Each user/agent bubble now shows a small timestamp above its content - Format: HH:MM for today, 'Yesterday HH:MM' for yesterday, 'Mon DD HH:MM' otherwise - Full datetime shown on hover via title attribute - Bridge forwards the entry timestamp during history replay; live messages default to Date.now() - History bubbles still rendered muted via the existing .history class Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Previously replay sent N postMessages (one per history entry) and live events could be interleaved mid-replay, causing: - Long delay rendering history (slow per-entry postMessage round trips) - User's live messages getting absorbed into history replay flow and marked as .history (they appeared grayed out or didn't show correctly) Fix: send the entire history as a single 'historyReplay' message. The webview processes all entries synchronously, then marks just those bubbles with the .history class. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replaying history on every reconnect (which can happen during long LLM calls) caused the live user message bubble and its incoming response to appear interleaved with muted duplicates from the replay, making it look like the original message disappeared. Track lastReplayedSessionId and only replay when we first join a session (or switch to a different one). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The agent dispatcher emits help text and other content with ANSI escape sequences (e.g. for bold/colored text). Previously those raw sequences were HTML-escaped and shown verbatim, producing output like '[0m[1m[4mSubcommands' instead of styled text. Bring rendering in line with the Electron shell: - ansi_up converts ANSI sequences to <span> with classes - markdown-it renders markdown DisplayContent (lists, tables, code) - DOMPurify sanitises the resulting HTML - Added ANSI color CSS bound to VS Code terminal theme variables and basic markdown styles for code/lists/tables/paragraphs Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Switch agent bubble background from inactiveSelectionBackground (very faint) to input-background with a subtle border for visibility - Replace VS Code terminal ANSI variables (designed for terminal background) with palette tuned to read against the chat bubble in both light and dark themes, scoped via body.vscode-light / vscode-dark classes - White / bright-white now map to foreground so they're never invisible Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The dispatcher emits @config (and similar) output as text+ANSI primary with an HTML alternate. The HTML alternate uses hardcoded slate colors (#1e293b, #64748b, #475569) designed for a light background — they're nearly invisible on VS Code's dark theme. Skip the HTML preference and use the text/markdown primary, which our ANSI/markdown renderer themes correctly via CSS variables. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Restore preference for HTML alternates so we get the richer rendering (emojis, layout, two-column tables) but post-process the HTML to drop hard-coded color/background/border-color from inline styles before sanitising. The remaining theme-variable-based CSS then applies, so content is readable on both light and dark themes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Restructured the message DOM so each message is a row with: - Avatar (circular, 28px) on the outside (right for user, left for agent) - Header above the bubble showing source · timestamp in dim text - Bubble itself contains only the message content Agent avatars use a per-source emoji (browser→🌐, calendar→📅, etc.) falling back to the source's first letter. User avatar shows 'T' for now (will become a real username later). Other tweaks: - Bubbles get larger border-radius (12px) with a small flat corner on the side closest to the avatar, like the shell - Timestamp format now includes seconds (matches shell '2:14:24 PM') - System/error messages override the new flex layout to keep their centered block style Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- User bubbles now show a 🪶 (sent) icon when posted and flip to ✅ (done) when the matching commandComplete arrives. Replayed history user messages render with ✅ since they already finished. - Bridge sends a 'userInfo' message (from os.userInfo().username) on webview registration; ChatUI uses it for the user avatar initial and the bubble header label instead of the hard-coded 'T'/'you'. - Expanded the agent emoji map to mirror the values declared in each agent's manifest (browser 🌐, calendar 📅, code ⚛, github-cli 🐙, weather ⛅, etc.), so agent avatars match what the Electron shell shows. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The webview now generates a unique requestId for each send, tags the pending user bubble with it (data-request-id), and passes it to the extension host. The host forwards it to dispatcher.processCommand and echoes it back in commandComplete. The webview maps requestId → bubble in a Map and flips the matching bubble's icon to ✅ on completion, so concurrent or out-of-order completions are handled correctly. Falls back to FIFO if a requestId is missing. Also send commandComplete on the error path so the bubble doesn't stay stuck on 🪶 if dispatch throws. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The Electron shell shows a roadrunner SVG inside the user bubble that reflects translation/cache state (not request completion). Match that: - Embed the same roadrunner SVG from the shell's icon.ts and render it hidden inside each new live user bubble. - Forward 'explained' notify events through the bridge (now carrying requestId) and surface them in the webview: green if served from a named cache, gold if translated by the model, light blue if there was nothing to cache. The tooltip mirrors the shell's 'Translated by X. Explained at Y' phrasing. - 'grammarRule' notify with success=false recolors the icon to cornflowerblue and appends the reason to the tooltip. - onCommandComplete no longer flips an icon — completion is unrelated to translation state — but still cleans up the pending-bubble map. - onNotify returns whether the event was consumed so we don't also surface it as a noisy system message. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Two bugs were keeping the roadrunner stuck on the default grey:
1. RequestId is actually an object {requestId, clientRequestId}, not a
string. The notify forwarder was passing the whole object as the
bridge message's requestId, so the webview's string lookup never
matched any bubble. Extract clientRequestId in the bridge before
broadcasting so the webview can match it against the data-request-id
it set on the bubble.
2. The icon sat below the bubble text on its own line. Position it
absolutely in the top-right corner of the bubble (matching the
Electron shell's '.chat-message-explained-icon' style), reserve
right padding so it doesn't overlap the message text.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The roadrunner is only meaningful for action translations: pure chat responses go through the chat agent and never emit an 'explained' event, so the icon was sitting permanently grey on those bubbles showing the misleading default 'Waiting for translation…' tooltip. Start hidden and only reveal it when _applyExplained sets a real color and tooltip. Bubbles for chat-only requests now show no icon at all, matching the actual state. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Keep the roadrunner visible on every user bubble (so the layout is consistent), but use a richer tooltip lifecycle: - New live bubble: tooltip 'Translating…' (waiting for explained) - explained event arrives: color green/gold/blue + 'Translated by X. Explained at HH:MM:SS' (sets data-explained=true) - commandComplete arrives without explained (chat agent, system command, etc.): tooltip becomes 'No translation (handled directly)' and the icon stays muted Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…curs" This reverts commit 9ea1ba9.
- Forward clientRequestId on display events; tag agent bubbles by request id so setDisplayInfo and metrics target the right bubble. - setDisplayInfo now updates the agent bubble's source label to `schemaName.actionName` and makes it clickable to expand a pretty-printed JSON panel of the action payload (mirrors shell swapContent pattern). - onCommandComplete reads result.metrics (RequestMetrics) and applies a multi-line tooltip (Total / Parse / Command / per-action durations) to the user and agent bubbles for the request, viewable on hover. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace the hover-tooltip metrics with a two-column row inside the agent bubble that mirrors the Electron shell: left: First Message: <parse> right: Action Elapsed Time: <sum> / Total Elapsed Time: <duration> Times are formatted reader-friendly (ms / s) like the shell. Add lightweight JSON syntax highlighting in the action JSON expand panel, using VS Code's symbolIcon token color variables (with sensible fallbacks) so keys, strings, numbers, booleans and null are color-coded just like in the editor. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- .bubble-metrics is now hidden by default (opacity 0, max-height 0) and fades in only when the .message row is hovered, matching the user's expectation of a hover-revealed timing display. - Switch JSON token colors to the more reliably-defined VS Code --vscode-debugTokenExpression-* variables for higher visibility across themes (still with hardcoded dark fallbacks). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Render the timing row inside the bubble (instead of below it) and style it as an attached footer: - background tinted with --vscode-editorWidget-background - top border separator - bottom corners rounded to match the bubble - left/right columns truly aligned via flex (text-align + flex 0 0) Reveal the footer on bubble hover with combined opacity, max-height and padding transitions so it visually slides in. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- code-vscode-shell: defaultEnabled=false. The schema's vscode-shell-action client action is only implemented by the vscode-shell extension; in any other host (Electron shell etc.) the LLM could route a conversation request here and the dispatcher would report success while doing nothing. Document the one-time '@config schema code-vscode-shell on' opt-in step in the vscode-shell README. The setting persists across sessions. - demo script: 'launch vscode' -> 'launch Code' to match the DEMO_SETUP rule that presenters use the exact Start Menu name (vscode is the fragile fuzzy-match phrasing the rule warns against). - README: also fix stale 'New Chat (Side Panel)' label to match the renamed 'New Chat in Editor' command. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The bridge already includes the dispatcher-resolved sourceIcon (from each agent's manifest emojiChar) in the broadcast IAgentMessage payload, but the webview was discarding it and passing undefined to chat-ui. That forced every bubble through chat-ui's static DEFAULT_AVATAR_MAP fallback, which means new agents wouldn't show their emoji and changes to a manifest's emojiChar wouldn't reach the UI without a chat-ui release. Pass msg.message.sourceIcon through for setDisplay/appendDisplay so the authoritative manifest-driven icon reaches the bubble. setDisplayInfo still falls back to chat-ui's avatar map (the dispatcher's IClientIO .setDisplayInfo signature does not carry sourceIcon) — that's the remaining narrow case the DEFAULT_AVATAR_MAP exists for. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ment, demo tweaks - editorCodeActionsSchema.ts: restore inline parameter comments on EditorActionCreateFile while keeping the DEPRECATED banner. - codeActionHandler.ts: clarify that the shared WebSocket bridges to the Coda VS Code extension (ts/packages/coda). - vscode_shell_extension_part2.txt: presenter pause tweaks; comment out create-issue/label steps for now. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
completion-ui no longer depends on agent-dispatcher just to import a single SearchMenuItem type. Move the canonical SearchMenuItem definition into completion-ui and have agent-dispatcher import (and re-export) the type from there. Why: completion-ui is a small DOM widget package consumed by chat-ui (vscode-shell, Chrome extension, future hosts). Declaring agent-dispatcher as a dependency dragged the entire dispatcher graph (Azure SDK, Anthropic SDK, etc.) into every consumer of the menu. Inverting the direction is a 5-LOC change today and unblocks lightweight downstream consumers. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…rt 5680)
VisualStudioBridge was instantiated per-session in initializeAgentContext, so the second session/conversation to enable the visualStudio agent would call `new WebSocketServer({ port: 5680 })` while the first session's server was already listening, producing:
bridge WebSocketServer failed on port 5680: Error: listen EADDRINUSE
The failure was logged but not thrown, so subsequent sessions silently lost the bridge (their bridge.client stayed undefined and any action routed through it errored with 'No host plugin connected').
Mirror the pattern used by codeAgent's CodeAgentWebSocketServer: maintain a single module-scoped bridge with a refcount; first initializeAgentContext starts it, subsequent ones reuse it, last closeAgentContext stops it.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
robgruen
reviewed
May 6, 2026
| const validationResult = validator.validate(actionJson); | ||
| if (!validationResult.success) { | ||
| throw new Error(validationResult.message); | ||
| // Cross-schema hint: if the (unknown) actionName is |
Collaborator
There was a problem hiding this comment.
See my previous comment in the claude reasoning.
| let actionSchema = actionSchemaGroup.actionSchemas.get( | ||
| value.actionName, | ||
| ); | ||
| if ( |
Collaborator
There was a problem hiding this comment.
This is another piece of logic I would like to understand. When everything works correctly it seems like an unnecessary patch. If there are hallucinations with schema names we should understand why those happened before we put in hallucination guards within the dispatcher. We do support this type of namespace lookup for entity resolution which is a more narrow field correction. I don't know if it applies to actions, let's discuss.
| actionSchemaGroup.actionSchemas.keys(), | ||
| ).slice(0, 30); | ||
| return error( | ||
| `Unknown action name: "${value.actionName}". The actionName must be one of the action types defined in the schema (e.g. "newFile", "createFile"), NOT a schema/agent name (e.g. "code", "code-editor"). Available actions in this schema include: ${validNames.join(", ")}.`, |
Collaborator
There was a problem hiding this comment.
Shouldn't be polluting specific agent/action names here.
Collaborator
There was a problem hiding this comment.
can we break this file up?
- Sort C# DllImports alphabetically in WindowsWindowService.cs - Strip negative-assertion language from code-general/code-editor descriptions - fileName literal-union (string | 'untitled') in NewFileAction - Drop redundant CodeLanguage comment - Add themeName?: string to ApplyThemeAction - TODO above hardcoded port 8082 in codeActionHandler - TODO above conversation-folder migration in conversationManager - Rename VscodeShellActions -> VSCodeConversationActions (file + type) to disambiguate from VS Code's terminal 'shell' - Revert PlayTrackAction comment to original wording Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
asc parser doesn't accept JSDoc /** */ blocks (only line comments), so use line-comment form with the same minimal @deprecated content Rob suggested. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…list Replace the if-chain that enumerated newConversation/renameConversation/ switchConversation before falling through to the Coda WS bridge with a single `action.schemaName === 'code-vscode-shell'` check. Adding a new conversation action no longer requires touching the top-level dispatcher — only the extracted `executeConversationAction` helper. Addresses Rob's PR comment on codeActionHandler.ts:307. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ions union Narrows the parameter from AppAction to the schema union, eliminating the (action as any).parameters cast and giving each case body fully typed access to action.parameters. Adds an assertNever default branch so adding a new action without a corresponding case becomes a compile error. Matches the typed-union pattern used by email/calendar/markdown/weather/ player/etc.; addresses Rob's underlying concern about magic-string coupling between schema and dispatcher. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- desktop SwitchToWindowAction: replace USE-THIS / NEVER prompt wall with a single User/Agent example (Rob's preferred style). - code-vscode-shell manifest entry: drop trigger-keyword soup and the 'Does NOT handle…' negative assertions from the description; keep only the positive description. Manifest entry name 'code-vscode-shell' kept as-is for now since it persists in opted-in users' user-settings.json (separate breaking-change consideration). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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.
TypeAgent chat panel for VS Code
Brings the TypeAgent chat experience into VS Code as a first-class host
alongside the Electron shell. Same dispatcher, same agents, same chat UI —
now embedded in VS Code with multi-panel session sharing, a scripted demo
runner, and a polished reconnect/cancel UX.
Branch:
talzacc/vscode-shell-chat· 85 files · ~14.2k / -650 vsmain.VS Code chat experience
Chat UX polish (shared with Electron shell)
⚠ Cancelled.Disconnected — retrying in Ns · <error>) instead of error spam in the chat area.chat-uipackage so the new vscode-shell host gets inline ghost + dropdown, arrow-key cycling, Ctrl+Space re-summon, Tab-snaps-to-first on auto-opened dropdowns, and Enter-submits-typed-text in inline mode.emojiChar(forwarded through the agent-server bridge → webview → chat-ui).Demo runner (vscode-shell)
.txtscript from any text editor right-click → "Run TypeAgent Demo Script".@pauseForInputmarkers stop on a paused state; Ctrl+→ continues.[Demo Mode (Running)/(Paused)]; pause hint shown as input ghost.demoStartingflag closes a startup race when two invocations fire close together during the file-picker await.(Independent of the shell-side
@shell run/@shell breakdemo improvements in PR #2277 — different host, different code path.)VS Code integrations (new agent actions)
newFilewrites to disk before opening so the file persists).code-vscode-shellsub-schema in thecodeagent. Opt-in:defaultEnabled: false; new vscode-shell users run@config schema code-vscode-shell ononce (documented ints/packages/vscode-shell/README.md).New
github-cliagentghCLI in natural language (@github-cli list my prs, …).Package architecture
@typeagent/completion-uiis now a zero-runtime-dependency shared widget package. The canonicalSearchMenuItemtype lives here;agent-dispatcherimports (and re-exports) it for backwards compatibility. Lightweight downstream consumers (Chrome extension, future hosts) no longer drag the entire dispatcher graph through the menu.Server / dispatcher infrastructure
SharedDispatcherinagentServerthat multiplexes ClientIO across all clients joined to the same conversation; also bridgesprocessCommand's RPC return value into a server-emittedcommandCompletenotify so peer panels stay in sync with the originator.DisplayLogcaptures display events so a freshly-joined client can replay the conversation.ConversationManager.Bug fixes worth calling out
codeagent —nextCallIdwas per-session but the pending-calls map is module-global, so concurrent sessions collided and routed responses to the wrong place. Fixed by making the counter module-global.Verification
Try it
cd ts/packages/agentServer/server && npm start(ws://localhost:8999, ~3 min full init).cd ts/packages/vscode-shell && npm run deploy:local.ts/packages/shell/demo/vscode_shell_extension_part1.txt→ Run TypeAgent Demo Script. Ctrl+→ at pauses; Esc to cancel.