You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: codev/specs/0602-vscode-extension.md
+51-16Lines changed: 51 additions & 16 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,9 +1,15 @@
1
+
---
2
+
approved: 2026-04-06
3
+
validated: [gemini, codex, claude]
4
+
---
5
+
1
6
# Specification: VS Code Extension for Codev Agent Farm
2
7
3
8
## Metadata
4
9
-**ID**: 0602
5
-
-**Status**: draft
10
+
-**Status**: approved
6
11
-**Created**: 2026-03-11
12
+
-**Approved**: 2026-04-06
7
13
-**Protocol**: SPIR
8
14
-**Related**: Spec 0066
9
15
@@ -111,13 +117,17 @@ Users can use the browser dashboard, the VS Code extension, or both simultaneous
111
117
112
118
### Technical Constraints
113
119
120
+
**Why native Pseudoterminal, not xterm.js in a Webview:**
121
+
Tower's WebSocket speaks a binary protocol (`0x00`/`0x01` framing). xterm.js handles this natively — it's what the browser dashboard uses. An alternative approach would embed xterm.js in a VS Code Webview, avoiding any protocol translation. However, Webview terminals have significant UX issues: keyboard shortcuts (Ctrl+C, arrows, paste) require custom passthrough, they can't appear in VS Code's native terminal panel or editor groups, they don't respect VS Code theming or focus management, and they feel like a browser embedded in an IDE. A native `Pseudoterminal` avoids all of this at the cost of a small binary adapter (~50 lines) that translates between Tower's binary protocol and VS Code's string-based API. This is a one-time implementation cost for a permanently better UX.
122
+
114
123
**VS Code Pseudoterminal API:**
115
-
-`Pseudoterminal.onDidWrite` expects UTF-8 strings, not binary — requires translation from the`0x01` data frames
116
-
-`Pseudoterminal.handleInput` provides strings — must encode to binary `0x01` frames for Tower
124
+
-`Pseudoterminal.onDidWrite` expects UTF-8 strings, not binary — requires a binary protocol adapter to translate from`0x01` data frames
125
+
-`Pseudoterminal.handleInput` provides strings — adapter encodes to binary `0x01` frames for Tower
117
126
-`Pseudoterminal.setDimensions` maps to `0x00` control frames for PTY resize
118
127
- No native stdout capture — but irrelevant since Tower/shellper handle observation
119
128
120
-
**WebSocket Binary Protocol Translation:**
129
+
**Binary Protocol Adapter:**
130
+
Translates between Tower's binary WebSocket protocol and VS Code's string-based Pseudoterminal API:
121
131
- Incoming `0x01` frames: strip first byte, decode `Uint8Array` → UTF-8 string via `TextDecoder('utf-8', { stream: true })` (streaming mode required to handle multi-byte Unicode split across frames), fire to `onDidWrite`
- Control frames (`0x00`): handle resize, ping/pong, sequence numbers for replay
@@ -293,7 +303,7 @@ This mirrors the browser dashboard exactly: architect on the left, builders on t
293
303
- Terminal scrollback is preserved via shellper — no data loss
294
304
295
305
**Escape sequence buffering:**
296
-
WebSocket frames can split ANSI escape sequences mid-sequence (e.g., CSI, OSC, DCS). Writing a partial escape to `onDidWrite` corrupts terminal state (production Bugfix #630). The Pseudoterminal adapter must buffer incomplete trailing sequences and prepend them to the next frame — same logic as `dashboard/src/lib/escapeBuffer.ts`. This should be extracted into `@cluesmith/codev-api-client` as a shared utility.
306
+
WebSocket frames can split ANSI escape sequences mid-sequence (e.g., CSI, OSC, DCS). Writing a partial escape to `onDidWrite` corrupts terminal state (production Bugfix #630). The Pseudoterminal adapter must buffer incomplete trailing sequences and prepend them to the next frame — same logic as `dashboard/src/lib/escapeBuffer.ts`. This should be extracted into `@cluesmith/codev-shared` as a shared utility.
297
307
298
308
**Resize deferral during replay:**
299
309
On reconnect, the ring buffer replays potentially large scrollback. Sending a resize control frame (`0x00` with `type: 'resize'`) while replay data is being written causes garbled rendering (production Bugfix #625). The adapter must queue resize events and flush them only after the replay write completes.
@@ -491,7 +501,7 @@ Single Webview panel embedding the existing Recharts analytics page:
491
501
Extract shared code to avoid triple-duplicating types and API client logic across server, dashboard, and extension. **Phased approach** — do not block V1 on extracting everything.
**Phase 2 (after V1 ships)**: Extract `@cluesmith/codev-api-client` once patterns stabilize across two real consumers (dashboard + extension).
504
+
**Phase 2 (after V1 ships)**: Extract `@cluesmith/codev-shared` once patterns stabilize across two real consumers (dashboard + extension).
495
505
496
506
**Monorepo prerequisite**: Add a root `package.json` with `"workspaces": ["packages/*"]` before extracting. Currently no workspace manager exists. Without this, `file:` dependencies will break `vsce` packaging.
497
507
@@ -506,9 +516,9 @@ Zero-dependency package with shared TypeScript interfaces currently duplicated b
506
516
507
517
Without this package, the extension becomes a third independent copy of these types, making protocol drift inevitable.
508
518
509
-
### `@cluesmith/codev-api-client` (Recommended, Phase 2 — after V1)
519
+
### `@cluesmith/codev-shared` (Recommended, Phase 2 — after V1)
510
520
511
-
Environment-agnostic Tower API client shared between dashboard and extension:
521
+
Shared runtime utilities and API client logic used by dashboard and extension:
512
522
513
523
- REST client with authenticated fetch (local-key header)
514
524
- SSE client with reconnection logic and heartbeat handling
@@ -546,11 +556,13 @@ Environment-agnostic Tower API client shared between dashboard and extension:
546
556
547
557
## Default Keyboard Shortcuts
548
558
559
+
Chord bindings using `Cmd+K` (macOS) / `Ctrl+K` (Windows/Linux) as prefix — no conflicts with built-in VS Code shortcuts:
560
+
549
561
| Shortcut | Command |
550
562
|----------|---------|
551
-
|`Ctrl+Shift+A` / `Cmd+Shift+A`| Codev: Open Architect Terminal |
0 commit comments