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
Embed objectiveai-viewer into objectiveai-web so the viewer is usable both as a desktop client (Tauri) and in the browser / cloud.
This is doable today: our infrastructure already supports local and cloud execution end-to-end (api.mode=Local vs Remote, viewer.mode=Local vs Remote, secret/signature pair generated by objectiveai viewer generate-secret-signature-pair). The viewer's UI layer is plain React 19 + Vite — there's no hard Tauri lock-in in the rendering code, only in the IPC bridge.
Why
Lower the barrier to trying ObjectiveAI: no install, just open a tab.
Let users watch / steer cloud-hosted runs from anywhere, without spinning up the desktop binary.
Single source of truth for the viewer UI — fix once, ships to both surfaces.
Event transport — Tauri IPC today (@tauri-apps/api/event.listen on 4 channels: agent-completions, functions-executions, functions-inventions-recursive, laboratories-executions). In the browser this becomes SSE / WebSocket against the remote API.
Local axum receiver (objectiveai-viewer/src-tauri/src/run.rs) — desktop-only. The browser build skips this entirely and subscribes directly to the API stream.
Proposed layout:
Extract the React UI into a shared package (e.g. objectiveai-viewer/ui/) consumed by both the Tauri shell and objectiveai-web.
Behind a transport interface (subscribe(channel, handler)), provide two implementations: tauri-transport.ts (existing) and web-transport.ts (SSE/WebSocket against objectiveai-api).
Add a route to objectiveai-web (e.g. /viewer or /viewer/[sessionId]) that mounts the shared UI with the web transport.
Reuse the HMAC secret/signature pair model already used between CLI and viewer — api.mode=Remote + viewer.mode=Remote is the existing config path; verify it works end-to-end.
Scope
In scope
Refactor objectiveai-viewer/src/ into a reusable UI package.
Web transport implementation against the remote objectiveai-api.
New route in objectiveai-web mounting the shared UI.
Wire HMAC auth for the browser surface (or document why the existing pair suffices).
Parity with current desktop viewer features (agent completions, function executions, recursive inventions, laboratory executions).
Does the web transport tail the existing SSE endpoints, or do we add a new /viewer/subscribe?session=... aggregator that fans out the four event types?
Auth in the browser: do we reuse the HMAC secret/signature pair, or move to per-user tokens issued by objectiveai-web's session?
Is the shared UI a workspace package (pnpm workspace), or do we publish objectiveai-viewer-ui to the same npm scope as objectiveai?
objectiveai-viewer/src/ → split into a shared UI package; introduce a transport abstraction.
objectiveai-viewer/src-tauri/src/run.rs → unchanged behavior; just consumes the shared UI via the Tauri transport.
objectiveai-web/ → new route, mount shared UI, web transport wiring.
objectiveai-api/src/... → confirm the streaming endpoints are reachable from the browser (CORS, auth headers); add an aggregator if we go that route.
Acceptance
A user can open objectiveai-web in a browser, navigate to the viewer route, and watch a remote execution stream in real time with the same fidelity as the desktop viewer.
Desktop viewer continues to work unchanged.
Single shared UI codebase between the two surfaces.
Summary
Embed
objectiveai-viewerintoobjectiveai-webso the viewer is usable both as a desktop client (Tauri) and in the browser / cloud.This is doable today: our infrastructure already supports local and cloud execution end-to-end (
api.mode=LocalvsRemote,viewer.mode=LocalvsRemote, secret/signature pair generated byobjectiveai viewer generate-secret-signature-pair). The viewer's UI layer is plain React 19 + Vite — there's no hard Tauri lock-in in the rendering code, only in the IPC bridge.Why
Approach
The viewer splits cleanly into three layers; only the bottom one is platform-specific:
objectiveai-viewer/src/App.tsx+ view components) — platform-agnostic, reuse as-is.@tauri-apps/api/event.listenon 4 channels:agent-completions,functions-executions,functions-inventions-recursive,laboratories-executions). In the browser this becomes SSE / WebSocket against the remote API.objectiveai-viewer/src-tauri/src/run.rs) — desktop-only. The browser build skips this entirely and subscribes directly to the API stream.Proposed layout:
objectiveai-viewer/ui/) consumed by both the Tauri shell andobjectiveai-web.subscribe(channel, handler)), provide two implementations:tauri-transport.ts(existing) andweb-transport.ts(SSE/WebSocket againstobjectiveai-api).objectiveai-web(e.g./vieweror/viewer/[sessionId]) that mounts the shared UI with the web transport.api.mode=Remote+viewer.mode=Remoteis the existing config path; verify it works end-to-end.Scope
In scope
objectiveai-viewer/src/into a reusable UI package.objectiveai-api.objectiveai-webmounting the shared UI.Out of scope (track separately)
Open questions
/viewer/subscribe?session=...aggregator that fans out the four event types?objectiveai-web's session?objectiveai-viewer-uito the same npm scope asobjectiveai?Files most likely to be touched
objectiveai-viewer/src/→ split into a shared UI package; introduce a transport abstraction.objectiveai-viewer/src-tauri/src/run.rs→ unchanged behavior; just consumes the shared UI via the Tauri transport.objectiveai-web/→ new route, mount shared UI, web transport wiring.objectiveai-api/src/...→ confirm the streaming endpoints are reachable from the browser (CORS, auth headers); add an aggregator if we go that route.Acceptance
objectiveai-webin a browser, navigate to the viewer route, and watch a remote execution stream in real time with the same fidelity as the desktop viewer.