v0.2.3 — Dev-mode kokoro + embed workers
Patch on top of v0.2.2. Closes the dev/prod gap on TTS + embedding crashes.
Why
In production, Kokoro TTS and sentence-transformer embeddings run in dedicated utilityProcess.fork workers — main.cjs forks them at startup and publishes their RPCs on globalThis so the api-server bundle (which Electron require()s into the same V8 isolate) reads them at request time.
In dev, the api-server runs inside Vite's Node process — a separate process from Electron main — so those globalThis hooks were never visible. The kokoro-local provider then fell back to inline ONNX execution and crashed loading Kokoro-82M-v1.0-ONNX on most setups. Visible symptom:
kokoro-js couldn't load the ONNX model files. Common causes:
• Bundled model dir was found at .../resources/kokoro/onnx-community/Kokoro-82M-v1.0-ONNX but transformers.js couldn't read a file inside it.
Fix
Spawn the same workers from inside Vite, so dev gets the same crash isolation packaged builds have.
tts-worker.cjs + embed-worker.cjs — dual-mode IPC
Workers now detect the launch context once at startup and expose a uniform onMessage / postMessage interface:
| Launch context | Inbound | Outbound |
|---|---|---|
Electron utilityProcess.fork (prod) |
process.parentPort.on("message", e => e.data) |
process.parentPort.postMessage(reply) |
Node child_process.fork (dev) |
process.on("message", msg) |
process.send(reply) |
Otherwise unchanged — same Kokoro pipeline, same handler types (speak, embed, ping), same lazy model loading, same self-healing on crash.
apps/desktop/src/server/dev-workers.mjs — new
Forks both workers via child_process.fork (lazy, self-healing on exit), wires their RPC callables onto globalThis.__notebooklmTtsRpc and __notebooklmEmbedRpc matching the production interface exactly.
vite.config.ts — wired
The notebooklm-server-middleware plugin now calls installDevWorkers() before loading @notebooklm/server, so by the time the api-server module evaluates and the kokoro-local / local-embed providers register their globalThis lookups, the hooks are already present.
Verified
Dev startup now logs:
[dev-workers] tts + embed workers wired to globalThis — kokoro-local
+ sentence-transformer requests will route through child processes
instead of inline ONNX
Audio overview generation in dev now uses the same child-process boundary as packaged builds. Same crash isolation, same main-thread responsiveness, same model loading path — no more dev-only inline ONNX failures.
Commits
da65cc3 feat(desktop): wire kokoro + embed workers in dev too — bump 0.2.3
Full diff: v0.2.2...v0.2.3