290 Chat Ux V2 Technical Summary
Documentation for Sessions
S290.20 — Chat UX v2 Technical Summary
Session: S290.20 | Date: 2026-03-31 | Version: 0.21.0 | Branch: session-290-299
Commits: 12 (38083e19f..71e123fd5)
Architecture
Component Model
Three new reusable Lit components in components/shared/, composed into the existing agent-chat-view (2064 lines pre-change). No new Angular libraries — all changes are within the extension source.
apps/vitto-vscode-extension/src/
panels/
main-panel.ts # +5 case handlers, +1 helper method
webview/
api.ts # +request/response resolver for file search
types.ts # +2 interfaces, +7 message variants
components/
shared/
drop-zone-overlay.ts # NEW: reusable drag overlay
mention-autocomplete.ts # NEW: provider-based @mention
context-chips.ts # NEW: context transparency pills
markdown-view.ts # Modified: 4 action buttons on code blocks
agent/
agent-chat-view.ts # Modified: integration of all features
agent-message.ts # Modified: streaming caret, context chips
Message Protocol Extensions
Seven new message types following the existing MessageToExtension / MessageFromExtension union pattern:
| Message | Direction | Handler | VSCode API |
|---|---|---|---|
insertAtCursor |
webview -> host | activeTextEditor.insertSnippet() |
SnippetString at cursor |
sendToTerminal |
webview -> host | createTerminal().sendText() |
Named "Vitto" terminal |
applyCodeToFile |
webview -> host | vscode.diff or untitled doc |
Diff view or beside editor |
searchWorkspaceFiles |
webview -> host | workspace.findFiles() |
Glob search, 50 max, excludes node_modules |
readFileForContext |
webview -> host | openTextDocument().getText() |
60-line preview |
workspaceFilesResult |
host -> webview | Resolves request() promise |
Via requestId correlation |
fileContextResult |
host -> webview | Resolves request() promise |
Via requestId correlation |
Provider Architecture (@mentions)
interface MentionSource {
id: string; // 'file', 'selection', 'terminal', 'errors'
label: string; // 'Files'
icon: string; // emoji
search(query: string): Promise<MentionItem[]>;
showOnEmpty?: boolean; // show in initial dropdown
}
Shipped: FileMentionSource — searches workspace via searchWorkspaceFiles message, falls back to open files from ideContext.openFiles.
Planned providers (one class + one array push each):
SelectionMentionSource— current editor selectionTerminalMentionSource— last N lines of terminal outputErrorsMentionSource— diagnostics fromideContext.diagnostics
Context Snapshot Flow
User types message
-> captureContextSnapshot() reads ideContext + pendingMentions + pendingAttachments
-> ContextSnapshot stored in messages[] alongside user message
-> Persisted in NativeChatPersistedMessage (survives panel reload)
-> <context-chips> component renders pills from ContextSnapshot
-> File chips dispatch 'chip-click' -> 'open-file' -> send({ type: 'openFile' })
Drag-Drop MIME Type Handling
Priority 1: Files (OS file drops — images, documents)
-> ingestFiles() -> Canvas compression -> PendingAgentAttachment
Priority 2: text/uri-list (editor tabs, file explorer)
-> addFileContextFromUri() -> readFileForContext -> PendingMention
Priority 3: text/plain (fallback, path-like strings)
-> addFileContextFromUri() if starts with / or file://
Code Block Action Visibility
markdown-it fence renderer extracts:
- lang: first token of fence info
- filename: parsed from colon (ts:file.ts) or space (typescript file.ts)
Button visibility:
Copy -> always
Insert -> always
Terminal -> SHELL_LANGS.has(lang) // bash, sh, shell, zsh, powershell, cmd, console, bat
Apply -> filename !== null
Files Changed
Created (3)
| File | Lines | Purpose |
|---|---|---|
components/shared/drop-zone-overlay.ts |
~110 | Reusable overlay: visible prop, message, Shift hint, upload SVG, frosted glass animation |
components/shared/mention-autocomplete.ts |
~270 | Provider interface (MentionSource/MentionItem/PendingMention), debounced search, keyboard nav (navigateUp/Down, selectCurrent), grouped results |
components/shared/context-chips.ts |
~120 | Builds chips from ContextSnapshot (active file, branch, errors, attachments, mentions), deduplicates, clickable file chips |
Modified (6)
| File | Insertions | Deletions | Key Changes |
|---|---|---|---|
types.ts |
+31 | -2 | ContextSnapshot, FileSearchResult interfaces; contextSnapshot on NativeChatPersistedMessage; mentionedFiles on agentMessage; 5 new MessageToExtension, 2 new MessageFromExtension |
main-panel.ts |
+85 | -2 | 5 case handlers (insertAtCursor, sendToTerminal, applyCodeToFile, searchWorkspaceFiles, readFileForContext); inferLanguageFromFilename helper; mentionedFiles passthrough |
markdown-view.ts |
+90 | -30 | SHELL_LANGS set, parseFenceFilename, new fence renderer with 4 buttons, code-block-actions CSS, decodeDataCode/flashButton helpers, unified handleClick |
agent-message.ts |
+35 | -5 | streaming-caret CSS + keyframes, streaming-text class, caret in text render, contextSnapshot on AgentMessage, context-chips import + render, handleChipClick |
agent-chat-view.ts |
+254 | -21 | FileMentionSource class, 6 new state properties, mention chip CSS, enhanced drag handlers (URI + vscode types), addFileContextFromUri, handleMentionSelect, captureContextSnapshot, handleOpenFile, @mention detection in handleInput, mention nav in handleKeydown, mention autocomplete + chips in render, contextSnapshot persistence |
api.ts |
+13 | 0 | requestId correlation resolver for workspaceFilesResult and fileContextResult |
Commit Log
71e123fd5 [S290.20] chore: bump to v0.21.0 Chat UX v2
0c21c168d [S290.20] feat: integrate @mention autocomplete, tab drag-drop, mention chips, and context snapshots
dde77ca6a [S290.20] feat: wire workspaceFilesResult and fileContextResult to request/response correlation
91b334319 [S290.20] feat: add reusable <context-chips> component showing per-message context transparency
b8a74d5ac [S290.20] feat: add reusable <mention-autocomplete> with provider interface and keyboard navigation
beb0fd5a1 [S290.20] feat: add keyboard shortcut hints to chat header buttons
cdcc9fea2 [S290.20] feat: add Insert, Terminal, Apply action buttons to code blocks in markdown-view
c48765663 [S290.20] feat: add reusable <drop-zone-overlay> with Shift hint, replace CSS pseudo-element
fec37a13d [S290.20] feat: add extension host handlers for insertAtCursor, sendToTerminal, applyCodeToFile, searchWorkspaceFiles, readFileForContext
f9e38ddf0 [S290.20] feat: add blinking streaming caret to AI text messages
38083e19f [S290.20] feat: add Chat UX v2 types — ContextSnapshot, FileSearchResult, 7 new message variants
3402cac98 [S290.20] docs: add Chat UX v2 spec and implementation plan
MCP Intelligence
Decisions Logged (7)
| ID | Type | Summary |
|---|---|---|
dev_..._z0fi7g8 |
architecture | 3 reusable Lit components, not inlined — agent-chat-view already 2064 lines |
dev_..._ddvtw4v |
implementation | Code block data-action event delegation — cleanest for markdown-it HTML |
dev_..._hpg4tee |
architecture | Provider-based MentionSource — extensible without rewrites |
dev_..._iulytbm |
implementation | ContextSnapshot at send-time, not render-time — correct moment |
dev_..._c55mtsl |
implementation | URI list + vnd.code MIME types for tab drag-drop |
dev_..._zvymzei |
implementation | Reusable overlay component with Shift hint |
dev_..._adkzyfh |
milestone | 7 features, 12 commits, v0.21.0, matches industry standard |
Conventions Added (4)
| Convention | Rule |
|---|---|
| Component extraction | New webview features must be Lit components in shared/, not inlined |
| Code block actions | Use data-action event delegation in markdown-view.ts |
| @mention providers | Implement MentionSource interface, register in mentionSources[] |
| Drag-drop MIME types | Handle Files + text/uri-list + application/vnd.code.*, show Shift hint |
Reflections (7 lessons)
- Cross-product research before implementation ensures features match industry standards
- Parallel subagent dispatch (4 simultaneous) = 3-4x faster than sequential
- Provider interfaces add minimal overhead but prevent architectural rewrites
- Event delegation with data-action is the cleanest pattern for markdown-it rendered HTML
- ContextSnapshot must be captured at send-time, not render-time
- Textarea + chip row avoids contenteditable complexity trap
- Extension host message protocol (types.ts union + main-panel.ts switch) scales well
Edge Cases and Known Limitations
| Case | Status |
|---|---|
workspace.findFiles slow in large monorepo |
Mitigated: 200ms debounce, 50 max results, excludes node_modules/dist/.git/tmp |
| Tab drag MIME varies across VSCode/Cursor | Handled: checks Files, text/uri-list, text/plain, application/vnd.code.* |
| No active editor for "Insert" | Warning shown via vscode.window.showWarningMessage |
| Mention dropdown covers textarea | Positioned above (relative z-index 60), capped at 250px height |
| Large files via @mention | Only 60-line preview sent (same as ContextProviderService.getFilePreview) |
| Old messages lack contextSnapshot | Render nothing — chips only appear on messages sent after v0.21.0 |
| "Apply" smart placement | Phase 1: opens diff view or untitled editor. Smart Apply (find exact insert point) deferred |
Testing Checklist
- Drag OS file -> overlay appears with Shift hint -> file attaches
- Drag editor tab -> adds as mention chip in composer
- Type
@con-> dropdown shows matching files -> select -> chip appears - ArrowUp/Down navigates mention dropdown, Enter selects, Escape dismisses
- Send message with @mention -> context chips show below user bubble
- Click a file chip -> file opens in editor
- AI code response -> see Copy, Insert buttons on all blocks
- Bash code block -> see Terminal button
- Code block with
ts:src/config.ts-> see Apply button - Click Insert -> code appears at cursor position
- Click Terminal -> command sent to Vitto terminal
- Click Apply with filename -> diff view opens
- During streaming -> blinking cyan caret visible
- Header shows "New ⌘N" and "Copy ⌘⇧C" (Mac) or Ctrl variants
- New chat clears mention chips
- Session persistence -> context chips survive panel reload