From f1ac32fd61676d0689ee80d2f12ba9d8abf695a6 Mon Sep 17 00:00:00 2001 From: Ingo Wagner Date: Wed, 23 Sep 2026 09:42:24 +0000 Subject: [PATCH] fix(web): wire browser-preview-context and extend RakazoDesktop interface - Create browser-preview-context.ts (missing file causing Vite crash) - Add browserPreview property to RakazoDesktop contract - Fix executor-shell-guard.ts non-null assertion for body[cursor] --- CLAUDE-RESUME-NOW.md | 7 +++ apps/web/src/lib/browser-preview-context.ts | 46 +++++++++++++++++++ packages/adapters/src/executor-shell-guard.ts | 2 +- packages/contracts/src/desktop.ts | 12 +++++ 4 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 apps/web/src/lib/browser-preview-context.ts diff --git a/CLAUDE-RESUME-NOW.md b/CLAUDE-RESUME-NOW.md index c0cdd3b..228be87 100644 --- a/CLAUDE-RESUME-NOW.md +++ b/CLAUDE-RESUME-NOW.md @@ -63,3 +63,10 @@ - `conversationSidebarGroups` render simplified — only bots, removed dead `GroupAvatar` branch - `projectSidebarGroups` render uses `GroupAvatar` with proper members access - All TypeScript errors resolved (0 errors across apps/web and packages/adapters) +- ✅ **browser-preview-context.ts** created (was missing from repo, caused Vite crash) + - Implements `browserPreviewActivity` subject with `.subscribe()`, `.set()`, `.snapshot()`, `.clear()` + - Multi-agent cursor tracking for browser preview panels +- ✅ **RakazoDesktop interface** extended with optional `browserPreview` property + - Contract update in `packages/contracts/src/desktop.ts` + - Types: `navigate`, `reload`, `getState`, `onNavigate`, `onLoadingProgress`, `devServer` +- ✅ **executor-shell-guard.ts** TS fix: `body[cursor]!` non-null assertion diff --git a/apps/web/src/lib/browser-preview-context.ts b/apps/web/src/lib/browser-preview-context.ts new file mode 100644 index 0000000..3f78722 --- /dev/null +++ b/apps/web/src/lib/browser-preview-context.ts @@ -0,0 +1,46 @@ +/** + * Browser preview activity tracking. + * + * Shared state so Shell can display multi-agent cursor positions + * inside browser-preview panels. + */ + +interface ActivityEntry { + x: number; + y: number; + label: string; +} + +type Subscriber = (snapshot: ReadonlyMap) => void; + +export const browserPreviewActivity = (() => { + const map = new Map(); + const listeners = new Set(); + + const freeze = (): ReadonlyMap => + new Map(map) as ReadonlyMap; + + return { + subscribe(cb: Subscriber): () => void { + listeners.add(cb); + cb(freeze()); + return () => { + listeners.delete(cb); + }; + }, + + set(id: string, x: number, y: number, label: string): void { + map.set(id, { x, y, label }); + listeners.forEach((l) => l(freeze())); + }, + + clear(id: string): void { + map.delete(id); + listeners.forEach((l) => l(freeze())); + }, + + snapshot(): ReadonlyMap { + return freeze(); + }, + }; +})(); diff --git a/packages/adapters/src/executor-shell-guard.ts b/packages/adapters/src/executor-shell-guard.ts index 9d438e7..1150ab2 100644 --- a/packages/adapters/src/executor-shell-guard.ts +++ b/packages/adapters/src/executor-shell-guard.ts @@ -441,7 +441,7 @@ function rubyScriptPaths( if (word.startsWith("--")) continue; const body = word.slice(1); for (let cursor = 0; cursor < body.length; cursor += 1) { - const letter = body[cursor]; + const letter = body[cursor]!; const rest = body.slice(cursor + 1); if (letter === "e" || letter === "E") { inline = true; diff --git a/packages/contracts/src/desktop.ts b/packages/contracts/src/desktop.ts index 875bfe4..0b02b46 100644 --- a/packages/contracts/src/desktop.ts +++ b/packages/contracts/src/desktop.ts @@ -66,6 +66,18 @@ export interface RakazoDesktop { */ onCallback: (listener: (callback: RakazoDesktopOAuthCallback) => void) => () => void; }; + /** Browser preview bridge — only available inside the Rakazo desktop app. */ + browserPreview?: { + navigate: (url: string) => Promise; + reload: () => Promise; + getState: () => Promise<{ url: string; devServerRunning: boolean }>; + onNavigate: (listener: (url: string) => void) => () => void; + onLoadingProgress: (listener: (progress: number) => void) => () => void; + devServer: { + start: () => Promise; + stop: () => Promise; + }; + }; } /**