Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions NOTICE
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,7 @@ mechanism were adapted from misofm/app at commit
7485693e9bbcf2f65a91a4e5950e22d678d99062.
The TypeScript ring/feed move and packaged asset are retained under the
engine-web-adapter lineage above; this notice applies to both sources.

The browser scratch Worker client/entry and default host construction are
adapted from misofm/engine-web-adapter at commit
63b4ee6212287000ff85e1cfa969d385f6246d2d, under Apache-2.0.
24 changes: 20 additions & 4 deletions sdk/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,11 @@ consumer that reads its rate from it cannot be told 48000 by a fallback that nev
## Browser

```ts
import { createEngine, scratchBootInWorker } from "@misofm/engine/browser";
import { createEngine } from "@misofm/engine/browser";

const engine = await createEngine({ document });
await engine.context.resume();
engine.host.node.connect(engine.context.destination);
```

The order matters, and each step exists because the next is expensive to undo: refuse what web
Expand All @@ -190,9 +194,21 @@ verify and if necessary close-and-retry the `AudioContext` → refuse a quantum

Both boots read the same policy object, so the ring, the memory budget and all four console words
are identical by construction; the two `require_*` words are role-defined (zero in the scratch boot,
physical in the worklet). Source plumbing is bring-your-own: SDK core has no opinions about audio
plumbing — no OPFS, no fetch, no Workers — so the Worker boot and the context constructor are
injected rather than reached for.
physical in the worklet). The browser entry supplies a packaged scratch module Worker, a guarded
`AudioContext` constructor, and the shipped host factory. Source delivery remains caller-owned.

`createContext`, `scratchBoot`, and `createHost` are optional independent overrides. An injected
context factory preserves its exact return type; a default DOM consumer receives its native
`AudioContext` type. The `simd128ModuleUrl`, `workletModuleUrl`, `hostModuleUrl`, and
`scratchWorkerModuleUrl` overrides select individual assets. `createWorker(url, { type })` can
forward the exported package Worker URL directly to `new Worker`; the packaged entry contains its
imports, including after Vite copies it. `requestDeadlineMs` (default 5000) bounds each scratch
handshake/request phase, and `signal` cancels scratch work. Every outcome terminates the Worker.

For callers that compose boot explicitly, `scratchBootWithWorker` performs one scratch request
and `createDefaultHost` imports and invokes the shipped host with `toWebBootOptions` mapping.
`scratchBootInWorker` remains the low-level primitive for custom Worker entries. The browser
helpers install no PCM feed or storage service.

`await engine.console()` binds the same semantic console shown above to the shipped browser host.
It resolves the browser session map once, then submits the same whole-batch edits over MessagePort.
Expand Down
14 changes: 14 additions & 0 deletions sdk/codegen/stage-package.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#!/usr/bin/env node
/** Stage the exact gated browser artifact closure under the emitted package tree. */

import { build } from "esbuild";
import { createHash } from "node:crypto";
import { copyFile, mkdir, readFile, readdir, rm, writeFile } from "node:fs/promises";
import { dirname, resolve } from "node:path";
Expand Down Expand Up @@ -67,3 +68,16 @@ await copyFile(
);
await copyFile(resolve(repoRoot, "NOTICE"), resolve(sdkRoot, "dist", "NOTICE"));
console.log(`staged ${expected.length} Engine V1 artifacts and package manifest`);

// A consumer bundler may copy an exported new-URL asset without following its imports. Emit an
// import-complete Worker so both that URL and the default literal Worker constructor are valid.
await build({
entryPoints: [resolve(sdkRoot, "dist", "browser", "scratch-worker.js")],
outfile: resolve(sdkRoot, "dist", "browser", "scratch-worker.js"),
allowOverwrite: true,
bundle: true,
format: "esm",
platform: "browser",
target: "es2022",
legalComments: "inline",
});
Loading