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
-**`headless`** — all `full` features except embedded assets (UI, docs, catalog). Used by `cargo install` and for deployments that serve the frontend separately.
88
+
-**`wasm`** — Browser-only build targeting `wasm32-unknown-unknown`. OpenAI + Anthropic + Test providers, wasm-sqlite (sql.js FFI), no server/concurrency/CLI/JWT/SSO features. Built with `wasm-pack`.
Run `hadrian features` to list enabled/disabled features at runtime. CI tests `minimal`, `standard`, and `headless` profiles; Windows uses `minimal` to avoid OpenSSL.
**Database:**`WasmSqlitePool` is a zero-size type; actual SQLite runs in JavaScript via sql.js. Queries cross the FFI boundary via `wasm_bindgen` extern functions. The `backend.rs` abstraction provides cfg-switched type aliases (`Pool`, `Row`, `BackendError`) and traits (`ColDecode`, `RowExt`) so SQLite repo code compiles against either `sqlx::SqlitePool` or `WasmSqlitePool` without changes.
246
+
247
+
**Persistence:** Database is persisted to IndexedDB with a debounced save (500ms) after write operations.
248
+
249
+
**Auth:** WASM mode uses `AuthMode::None` with a bootstrapped anonymous user and org. Permissive `AuthzContext` and `AdminAuth` extensions are injected as layers.
250
+
251
+
**Setup flow:**`WasmSetupGuard` detects if providers are configured; if not, shows a setup wizard (`WasmSetup`) supporting OpenRouter OAuth (PKCE), Ollama auto-detection, and manual API key entry for OpenAI/Anthropic/etc.
252
+
253
+
**Known limitations:**
254
+
- Streaming responses are fully buffered (no real-time SSE token streaming for LLM calls)
255
+
- No usage tracking (no `TaskTracker`/`UsageLogBuffer` in WASM)
256
+
- No caching layer, rate limiting, or budget enforcement
257
+
- Module service workers require Chrome 91+ / Edge 91+ (Firefox support may be limited)
258
+
218
259
### Document Processing Flow (RAG)
219
260
220
261
1.**File Upload** (`POST /v1/files`) — Store raw file in database
@@ -469,6 +510,17 @@ See `agent_instructions/adding_admin_endpoint.md` for implementation patterns (r
469
510
-`src/validation/` — Response validation against OpenAI schema
-`ui/src/service-worker/sw.ts` — Service worker: intercepts API calls, lazily initializes `HadrianGateway` WASM module, routes requests through Axum router
566
+
-`ui/src/service-worker/sqlite-bridge.ts` — sql.js bridge: `globalThis.__hadrian_sqlite` with `init_database()`, `query()`, `execute()`, `execute_script()`; persists to IndexedDB with debounced save
567
+
-`ui/src/service-worker/register.ts` — Service worker registration with `CLAIM` message handling for hard refreshes
568
+
-`ui/src/service-worker/wasm.d.ts` — Type declarations for the WASM module exports
569
+
-`ui/src/components/WasmSetup/WasmSetup.tsx` — Three-step setup wizard (welcome → providers → done) with OpenRouter OAuth, Ollama detection, manual API key entry
570
+
-`ui/src/components/WasmSetup/WasmSetupGuard.tsx` — Guard component: auto-shows wizard when no providers configured, handles OAuth callback
571
+
-`ui/src/components/WasmSetup/openrouter-oauth.ts` — OpenRouter OAuth PKCE flow (code verifier in sessionStorage)
572
+
-`ui/src/routes/AppRoutes.tsx` — Routes extracted from App.tsx
573
+
511
574
### Frontend — Pages & Layout
512
575
513
576
-`ui/src/pages/studio/` — Studio feature (image gen, TTS, transcription)
@@ -561,6 +624,30 @@ pnpm test-storybook # Run Storybook tests with vitest
561
624
pnpm openapi-ts # Regenerate from /api/openapi.json
562
625
```
563
626
627
+
### WASM Frontend Development
628
+
629
+
The WASM mode is controlled by the `VITE_WASM_MODE=true` environment variable. When set:
630
+
- The Vite dev server uses a custom service worker plugin instead of `VitePWA`
631
+
- The proxy configuration is disabled (service worker handles API routing)
632
+
-`main.tsx` registers the service worker before rendering React
633
+
-`App.tsx` wraps the app in `WasmSetupGuard`
634
+
635
+
```bash
636
+
# Build WASM module first (from repo root)
637
+
./scripts/build-wasm.sh
638
+
639
+
# Then run frontend in WASM mode
640
+
cd ui && VITE_WASM_MODE=true pnpm dev
641
+
```
642
+
643
+
The service worker (`sw.ts`) is built separately from the Vite bundle using esbuild (via the custom `wasmServiceWorkerPlugin` in `vite.config.ts`). In dev mode it's compiled on each request; in production it's written to `dist/sw.js` during the `writeBundle` hook.
644
+
645
+
When modifying WASM-related code:
646
+
- The `wasm_routing` module (`src/compat.rs`) provides drop-in replacements for `axum::routing::{get, post, put, patch, delete}` — route modules use cfg-switched imports
647
+
- All async trait definitions use `#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]` / `#[cfg_attr(not(target_arch = "wasm32"), async_trait)]`
648
+
- The `backend.rs` abstraction means SQLite repo code is written once — modify repos normally and both native/WASM will compile
649
+
- Server-only routes (multipart file upload, audio transcription/translation) are excluded with `#[cfg(feature = "server")]`
650
+
564
651
### Frontend Conventions
565
652
566
653
- Run the `./scripts/generate-openapi.sh` script to generate the OpenAPI client
0 commit comments