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]
This commit is contained in:
Ingo Wagner 2026-09-23 09:42:24 +00:00
parent 5a03ae014c
commit f1ac32fd61
4 changed files with 66 additions and 1 deletions

View File

@ -63,3 +63,10 @@
- `conversationSidebarGroups` render simplified — only bots, removed dead `GroupAvatar` branch - `conversationSidebarGroups` render simplified — only bots, removed dead `GroupAvatar` branch
- `projectSidebarGroups` render uses `GroupAvatar` with proper members access - `projectSidebarGroups` render uses `GroupAvatar` with proper members access
- All TypeScript errors resolved (0 errors across apps/web and packages/adapters) - 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

View File

@ -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<string, ActivityEntry>) => void;
export const browserPreviewActivity = (() => {
const map = new Map<string, ActivityEntry>();
const listeners = new Set<Subscriber>();
const freeze = (): ReadonlyMap<string, ActivityEntry> =>
new Map(map) as ReadonlyMap<string, ActivityEntry>;
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<string, ActivityEntry> {
return freeze();
},
};
})();

View File

@ -441,7 +441,7 @@ function rubyScriptPaths(
if (word.startsWith("--")) continue; if (word.startsWith("--")) continue;
const body = word.slice(1); const body = word.slice(1);
for (let cursor = 0; cursor < body.length; cursor += 1) { for (let cursor = 0; cursor < body.length; cursor += 1) {
const letter = body[cursor]; const letter = body[cursor]!;
const rest = body.slice(cursor + 1); const rest = body.slice(cursor + 1);
if (letter === "e" || letter === "E") { if (letter === "e" || letter === "E") {
inline = true; inline = true;

View File

@ -66,6 +66,18 @@ export interface RakazoDesktop {
*/ */
onCallback: (listener: (callback: RakazoDesktopOAuthCallback) => void) => () => void; onCallback: (listener: (callback: RakazoDesktopOAuthCallback) => void) => () => void;
}; };
/** Browser preview bridge — only available inside the Rakazo desktop app. */
browserPreview?: {
navigate: (url: string) => Promise<void>;
reload: () => Promise<void>;
getState: () => Promise<{ url: string; devServerRunning: boolean }>;
onNavigate: (listener: (url: string) => void) => () => void;
onLoadingProgress: (listener: (progress: number) => void) => () => void;
devServer: {
start: () => Promise<void>;
stop: () => Promise<void>;
};
};
} }
/** /**