Files
ai-agent/frontend/src/main.tsx
Gabriel Vidal 703282ec40 feat(ai-agent): in-browser mock backend behind the generated API types
Adds `frontend/src/mock/` — a fake backend that runs in the page, so the whole
PWA can be demoed and driven by an automated frontend test with no FastAPI, no
sidecar and no transcripts on disk. `?mock=1` on any URL (sticky, works against
the deployed app) or `npm run dev:mock`.

It swaps `window.fetch` (every `/api/*` route) and `window.EventSource` (the
`meta`/`transcript` SSE events) for versions served from an in-memory,
localStorage-persisted database. Writes really mutate it, and spawn/resume/
interrupt actually run: a scripted turn streams into the conversation item by
item over SSE, then stamps the notification + DONE that mark it finished.

The seed is combinatorial — harness × state × lifecycle × archived conversations,
a kitchen-sink thread with every ThreadItemKind and tool card, every
FileEntryKind, every service auth, every plan status, every FileDiffStatus /
DiffLineType — so every visual state is reachable from a cold load, and it is
deterministic (fixed clock, no RNG). Test hooks on `window.__mock`.

Rows are typed with the orval-generated models, so a backend schema change breaks
the seed at tsc time instead of letting the mock drift. main.tsx is now a boot
shim (mock installs before the app tree is imported — the server-backed Zustand
stores fetch at import time); the app tree moved to root.tsx.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 16:29:36 +02:00

25 lines
896 B
TypeScript

import { isMockEnabled } from "./mock/enabled";
/**
* Entry point — nothing but boot ordering.
*
* In demo / test mode (`?mock=1` on any URL, or a `VITE_MOCK=1` build) the
* in-browser mock backend (`src/mock/`) must install its `fetch` +
* `EventSource` interceptors **before the app tree is even imported**: modules
* in there fetch at import time (the server-backed Zustand stores hydrate
* immediately), and those calls have to hit the seeded local database, not a
* backend that isn't there. Hence both the app and the mock are pulled in with
* dynamic imports, in that order. In a normal build the mock stays in its own
* lazy chunk and is never fetched.
*/
async function boot(): Promise<void> {
if (isMockEnabled()) {
const { installMock } = await import("./mock");
installMock();
}
const { renderApp } = await import("./root");
renderApp();
}
void boot();