@actcore/web-runtime 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/LICENSE +10 -0
  2. package/README.md +148 -0
  3. package/dist/cache.d.ts +70 -0
  4. package/dist/cache.d.ts.map +1 -0
  5. package/dist/cache.js +0 -0
  6. package/dist/cache.js.map +1 -0
  7. package/dist/host-api.d.ts +81 -0
  8. package/dist/host-api.d.ts.map +1 -0
  9. package/dist/host-api.js +46 -0
  10. package/dist/host-api.js.map +1 -0
  11. package/dist/index.d.ts +30 -0
  12. package/dist/index.d.ts.map +1 -0
  13. package/dist/index.js +23 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/locale.d.ts +32 -0
  16. package/dist/locale.d.ts.map +1 -0
  17. package/dist/locale.js +64 -0
  18. package/dist/locale.js.map +1 -0
  19. package/dist/patches.d.ts +38 -0
  20. package/dist/patches.d.ts.map +1 -0
  21. package/dist/patches.js +76 -0
  22. package/dist/patches.js.map +1 -0
  23. package/dist/shims/sockets.d.ts +130 -0
  24. package/dist/shims/sockets.d.ts.map +1 -0
  25. package/dist/shims/sockets.js +128 -0
  26. package/dist/shims/sockets.js.map +1 -0
  27. package/dist/shims/wasi-http-internal.d.ts +7 -0
  28. package/dist/shims/wasi-http-internal.d.ts.map +1 -0
  29. package/dist/shims/wasi-http-internal.js +19 -0
  30. package/dist/shims/wasi-http-internal.js.map +1 -0
  31. package/dist/shims/wasi-http.d.ts +83 -0
  32. package/dist/shims/wasi-http.d.ts.map +1 -0
  33. package/dist/shims/wasi-http.js +452 -0
  34. package/dist/shims/wasi-http.js.map +1 -0
  35. package/dist/streaming-fallback.d.ts +16 -0
  36. package/dist/streaming-fallback.d.ts.map +1 -0
  37. package/dist/streaming-fallback.js +52 -0
  38. package/dist/streaming-fallback.js.map +1 -0
  39. package/dist/timing.d.ts +22 -0
  40. package/dist/timing.d.ts.map +1 -0
  41. package/dist/timing.js +48 -0
  42. package/dist/timing.js.map +1 -0
  43. package/dist/transpile.d.ts +10 -0
  44. package/dist/transpile.d.ts.map +1 -0
  45. package/dist/transpile.js +277 -0
  46. package/dist/transpile.js.map +1 -0
  47. package/dist/transpile.worker.d.ts +36 -0
  48. package/dist/transpile.worker.d.ts.map +1 -0
  49. package/dist/transpile.worker.js +43 -0
  50. package/dist/transpile.worker.js.map +1 -0
  51. package/dist/version.d.ts +2 -0
  52. package/dist/version.d.ts.map +1 -0
  53. package/dist/version.js +5 -0
  54. package/dist/version.js.map +1 -0
  55. package/dist/webmcp.d.ts +92 -0
  56. package/dist/webmcp.d.ts.map +1 -0
  57. package/dist/webmcp.js +189 -0
  58. package/dist/webmcp.js.map +1 -0
  59. package/package.json +69 -0
package/LICENSE ADDED
@@ -0,0 +1,10 @@
1
+ This project is dual-licensed under your choice of:
2
+
3
+ - MIT License (see LICENSE-MIT or https://opensource.org/licenses/MIT)
4
+ - Apache License, Version 2.0 (see LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
5
+
6
+ at your option.
7
+
8
+ Unless you explicitly state otherwise, any contribution intentionally submitted
9
+ for inclusion in this project by you, as defined in the Apache-2.0 license,
10
+ shall be dual-licensed as above, without any additional terms or conditions.
package/README.md ADDED
@@ -0,0 +1,148 @@
1
+ # @actcore/web-runtime
2
+
3
+ > Web runtime for [ACT](https://actcore.dev) — load and run signed wasm agent tools in the browser, and expose them to browser agents via WebMCP.
4
+
5
+ The whole agent stack, no server:
6
+
7
+ | | Where it lives |
8
+ |---|---|
9
+ | LLM | wherever you want — remote API, or local via [WebLLM](https://github.com/mlc-ai/web-llm) |
10
+ | **Tools** | **the browser, via this package** |
11
+ | User data | the browser (IndexedDB, OPFS) |
12
+
13
+ ACT components are sandboxed wasm modules signed by their author and distributed via OCI registries. This package loads one in a browser tab using [jco](https://github.com/bytecodealliance/jco)'s in-browser transpiler — no server, no Node, no `npm install` required for the *tool*. The end user opens a page; the tool runs in their tab.
14
+
15
+ ## Status
16
+
17
+ `0.1.0`. The runtime works end-to-end for `act:tools/tool-provider@0.2.0` (immediate **and** streaming results) and `act:sessions/session-provider@0.2.0`. Loaded tools can be exposed to a browser agent via **WebMCP** (`document.modelContext`). OCI pull and Sigstore verification are scheduled for follow-up versions.
18
+
19
+ ## Browser support
20
+
21
+ Requires [JSPI (JavaScript Promise Integration)](https://github.com/WebAssembly/js-promise-integration) for WebAssembly:
22
+
23
+ | Browser | JSPI status (2026) | Source |
24
+ |---|---|---|
25
+ | Chrome 137+ stable / Edge | **shipped by default** | [Interop 2026 #10](https://webkit.org/blog/17818/announcing-interop-2026/) |
26
+ | Firefox Nightly 152+ | 93% WPT pass rate | [wpt.fyi](https://wpt.fyi/results/wasm/jsapi/jspi?label=master&label=experimental&aligned&view=interop&q=label%3Ainterop-2026-jspi-for-wasm) |
27
+ | Safari Tech Preview 243+ | 93% WPT pass rate | wpt.fyi |
28
+ | Firefox stable / Safari stable | shipping during 2026 per [Interop 2026 pledge](https://webkit.org/blog/17818/announcing-interop-2026/) | — |
29
+
30
+ All four major browsers committed to JSPI parity in Interop 2026.
31
+
32
+ ## Install
33
+
34
+ ```sh
35
+ npm install @actcore/web-runtime @bytecodealliance/jco @bytecodealliance/preview2-shim
36
+ ```
37
+
38
+ `jco` (which pulls in `@bytecodealliance/jco-transpile`) and `preview2-shim` are
39
+ runtime dependencies; bundle them with your app or load via importmap.
40
+
41
+ > **jco browser note.** jco's documented browser entry
42
+ > (`@bytecodealliance/jco/component`) is broken in the published package — the
43
+ > `obj/` glue it imports is gitignored out of the tarball — and
44
+ > `@bytecodealliance/jco-transpile`'s `.` export statically imports node:
45
+ > builtins, so it can't load under native ESM. This package therefore drives the
46
+ > one browser-safe artifact jco ships: the vendored, componentized bindgen at
47
+ > `@bytecodealliance/jco-transpile/vendor/js-component-bindgen-component.js`
48
+ > (the same `generate()` jco's browser entry wraps). That subpath is not in
49
+ > jco-transpile's `exports` map, so map it explicitly in your importmap (see
50
+ > [`examples/basic.html`](examples/basic.html)) or add a bundler resolve alias.
51
+
52
+ ## Quick start
53
+
54
+ ```ts
55
+ import { runComponent } from '@actcore/web-runtime';
56
+
57
+ const wasm = new Uint8Array(await (await fetch('/time.wasm')).arrayBuffer());
58
+
59
+ const { toolProvider } = await runComponent(wasm, {
60
+ // Where the @bytecodealliance/preview2-shim browser files live. Use a CDN,
61
+ // your bundler's resolved path, or your dev-server alias. preview2-shim 0.19
62
+ // serves its browser build from dist/browser/ (it was lib/browser/ before).
63
+ shimBase: 'https://esm.sh/@bytecodealliance/preview2-shim@0.19.0/dist/browser/',
64
+ });
65
+
66
+ const { tools } = await toolProvider.listTools([]);
67
+ console.log(tools); // [{ name: 'get_current_time', description: ..., parametersSchema: ... }]
68
+
69
+ const result = await toolProvider.callTool(
70
+ 'get_current_time',
71
+ new Uint8Array([0xa0]), // CBOR {} — empty args
72
+ [],
73
+ );
74
+
75
+ if (result.tag === 'immediate') {
76
+ for (const ev of result.val) {
77
+ if (ev.tag === 'content') {
78
+ console.log(new TextDecoder().decode(ev.val.data)); // → "2026-05-11T15:13:23.464+00:00"
79
+ }
80
+ }
81
+ }
82
+ ```
83
+
84
+ See [`examples/basic.html`](examples/basic.html) for a runnable demo. From a fresh
85
+ clone, `npm run sync-wit` once to fetch the WIT deps (via [`wkg`](https://github.com/bytecodealliance/wasm-pkg-tools); see [`wit/README.md`](wit/README.md)), then `npm run build`. Run the demo with `npm run example` (serves the package root so the importmap's `/node_modules/…` paths resolve) and open `http://localhost:8765/examples/basic.html`.
86
+
87
+ ## Expose tools to a browser agent (WebMCP)
88
+
89
+ Once a component is loaded, register its tools on the browser's native
90
+ [WebMCP](https://webmachinelearning.github.io/webmcp/) surface
91
+ (`document.modelContext`) so a WebMCP-capable agent can discover and call them:
92
+
93
+ ```ts
94
+ import { runComponent, exposeToWebmcp, isWebmcpAvailable } from '@actcore/web-runtime';
95
+
96
+ const { toolProvider } = await runComponent(wasm, { shimBase });
97
+ const { tools } = await toolProvider.listTools([]);
98
+
99
+ if (isWebmcpAvailable()) {
100
+ const exposure = await exposeToWebmcp(toolProvider, tools);
101
+ console.log(`${exposure.count} tools exposed on document.modelContext`);
102
+
103
+ // …later, when swapping components or tearing down:
104
+ exposure.dispose(); // unregisters every tool (aborts the registration signal)
105
+ }
106
+ ```
107
+
108
+ `exposeToWebmcp(provider, tools, options?)` is opt-in and headless — no UI, no
109
+ side effects until you call it. It maps each ACT tool to a WebMCP descriptor
110
+ (the tool's JSON-Schema parameters become `inputSchema`; `std:read-only`
111
+ metadata becomes `readOnlyHint`; output is marked `untrustedContentHint`),
112
+ bridges each descriptor's `execute` to the component's `callTool` (dcbor-encoded
113
+ args, `std:session-id` forwarding via `options.getSessionId`, tool-events
114
+ drained to text), and unregisters via an `AbortSignal` when you call `dispose()`.
115
+
116
+ Native WebMCP ships in Chrome 149 behind an origin trial /
117
+ `chrome://flags/#enable-webmcp-testing`. Where it is absent,
118
+ `isWebmcpAvailable()` returns `false` and `exposeToWebmcp` no-ops
119
+ (`{ count: 0, available: false }`), so this is safe to call unconditionally.
120
+
121
+ ## How it works
122
+
123
+ `runComponent(bytes, options)`:
124
+
125
+ 1. Calls jco's low-level bindgen `generate()` with `asyncMode: jspi` and an explicit `map` pointing WASI specifiers at `preview2-shim` browser builds (and `wasi:http` p3 at the bundled shim). Driving `generate()` directly — rather than `transpileBytes` — keeps the transpiler node-free and lets us own the WASI map, sidestepping jco's default map that routes p3 WASI onto the Node-only `preview3-shim`. `generate()` is a single synchronous wasm call that blocks for ~250ms on a 1MB component but several **seconds** on a large one (e.g. a 100 MB+ Python component), so it runs in a **Web Worker** — the page stays responsive while a big component transpiles. If a worker can't be created or loaded (e.g. an importmap-only page, where workers can't resolve the bindgen specifier), it transparently falls back to a main-thread transpile.
126
+ 2. **Caches** the transpile output in IndexedDB, keyed by `@actcore/web-runtime`'s version and the SHA-256 of the component bytes. A second load of the same component skips `generate()` entirely (no worker, no multi-second wait). Bumping the package version invalidates the cache, since a new release may ship a different transpiler. Pass `cache: false` to bypass it; call `clearTranspileCache()` to wipe it. The cache silently disables itself where IndexedDB / `crypto.subtle` is unavailable.
127
+ 3. Applies a thin patch to the emitted JS:
128
+ - rewrite bare `preview2-shim` specifiers to absolute URLs (blob: contexts can't see the page's importmap),
129
+ - short-circuit future/stream drops whose wasm-side end was already transferred (a wit-bindgen Rust quirk on the wasi:http path).
130
+ 4. Materialises the patched JS + `.core.wasm` as blob URLs, dynamic-imports the entry module, and returns the exported `toolProvider` (and `sessionProvider`, if the component exports one).
131
+
132
+ The wasip3-async lift bugs that needed heavy patching under jco 1.19 (STREAM_TABLES/FUTURE_TABLES declarations, `HostFuture`, host-resource lowering, `_liftFlatRecord` task-return, storageLen accounting) are all fixed upstream as of jco 1.24 (bindgen 2.0.3) — jco lifts `list-tools` / `call-tool` results natively. This package is now a thin glue layer.
133
+
134
+ > **Bundler note (Web Worker).** The transpile worker is created with
135
+ > `new Worker(new URL('./transpile.worker.js', import.meta.url), { type: 'module' })`
136
+ > and dynamic-imports the bindgen, so it code-splits. Configure your bundler to
137
+ > emit workers as ES modules — in Vite that's `worker: { format: 'es' }` (the
138
+ > default `iife` rejects code-splitting workers). No config is needed for
139
+ > importmap / no-bundler pages: they hit the main-thread fallback.
140
+
141
+ ## Roadmap
142
+
143
+ - v0.2 — OCI pull and Sigstore (cosign) signature verification, via a shared `act-oci-verify` Rust crate compiled to both native (for `act-cli`) and `wasm32-wasip2` (loaded here, hash-pinned in source).
144
+ - v0.x — Web Worker isolation (run *components* off the main thread; transpilation already runs in a worker).
145
+
146
+ ## License
147
+
148
+ MIT OR Apache-2.0
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Persistent cache for jco transpile output.
3
+ *
4
+ * Transpiling a wasm component (jco's `generate()`) is the expensive step in
5
+ * {@link ./transpile.ts}: for large components (tens of MB) it runs for several
6
+ * seconds. The output is a pure function of the input bytes plus a handful of
7
+ * options, so we cache it in IndexedDB keyed by a content hash and replay it on
8
+ * subsequent loads, skipping `generate()` entirely.
9
+ *
10
+ * Cache key (see {@link deriveTranspileCacheKey}) includes, by construction:
11
+ * - {@link HOST_VERSION} — a new @actcore/host release may ship new transpiler
12
+ * patches or a new bundled jco/bindgen, so its output format can change.
13
+ * - the SHA-256 of the original component bytes ("original module hash").
14
+ * - the transpile options that change `generate()`'s output (`name`, and the
15
+ * shim URLs that get baked into the emitted import specifiers).
16
+ *
17
+ * Everything here is best-effort and browser-only: if IndexedDB or
18
+ * `crypto.subtle` is unavailable (non-secure context, Node, old engine) the
19
+ * cache silently disables itself and callers fall back to a live transpile.
20
+ */
21
+ /** jco transpile output: `[filename, bytes]` pairs (entry .js, .core.wasm, …). */
22
+ export type TranspiledFiles = Array<[string, Uint8Array]>;
23
+ /**
24
+ * The same files as `Blob`s — the shape we persist and replay.
25
+ *
26
+ * IndexedDB structured-clones a stored value: a `Uint8Array` is copied byte for
27
+ * byte (a full ~100MB+ copy of the core wasm on *every* write and *every* read),
28
+ * whereas a `Blob` is cloned by reference and stored disk-backed. Replaying a
29
+ * cached `Blob` is then a zero-copy `URL.createObjectURL(blob)` instead of
30
+ * materializing the bytes and wrapping them in a fresh `Blob`. So we store and
31
+ * hand back Blobs; the caller converts `generate()`'s Uint8Array output once.
32
+ */
33
+ export type CachedFiles = Array<[string, Blob]>;
34
+ /** Inputs that determine a transpile output, and thus the cache key. */
35
+ export interface TranspileCacheKeyInput {
36
+ /** The original (packed) wasm component bytes. */
37
+ bytes: Uint8Array;
38
+ /** jco output basename — affects emitted filenames and identifiers. */
39
+ name: string;
40
+ /** preview2-shim base URL — baked into emitted WASI import specifiers. */
41
+ shimBase: string;
42
+ /** wasi:http p3 shim URL — baked into emitted wasi:http import specifiers. */
43
+ wasiHttpShimUrl: string;
44
+ /** wasi:sockets shim URL — baked into emitted wasi:sockets import specifiers. */
45
+ wasiSocketsShimUrl: string;
46
+ }
47
+ /**
48
+ * Derive the stable cache key for a transpile. Pure (modulo the SHA-256 of the
49
+ * bytes) and deterministic — same inputs always yield the same key. NUL
50
+ * separators keep the otherwise-free-form fields unambiguous.
51
+ *
52
+ * The returned string always contains {@link HOST_VERSION} and the module hash,
53
+ * satisfying the "key must include host-browser version + original module hash"
54
+ * contract.
55
+ */
56
+ export declare function deriveTranspileCacheKey(input: TranspileCacheKeyInput): Promise<string>;
57
+ /**
58
+ * Look up a cached transpile output. Returns `null` on miss, on any error, or
59
+ * when the cache is unavailable — never throws. A record written by a different
60
+ * `HOST_VERSION` is ignored (defensive; the key already encodes the version).
61
+ */
62
+ export declare function getCachedFiles(key: string): Promise<CachedFiles | null>;
63
+ /**
64
+ * Store a transpile output. Best-effort: quota errors and the like are swallowed
65
+ * (caching is an optimization, never a correctness requirement).
66
+ */
67
+ export declare function putCachedFiles(key: string, files: CachedFiles): Promise<void>;
68
+ /** Drop every cached transpile output. Useful for debugging / "force refresh". */
69
+ export declare function clearTranspileCache(): Promise<void>;
70
+ //# sourceMappingURL=cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAIH,kFAAkF;AAClF,MAAM,MAAM,eAAe,GAAG,KAAK,CAAC,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;AAE1D;;;;;;;;;GASG;AACH,MAAM,MAAM,WAAW,GAAG,KAAK,CAAC,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC;AAEhD,wEAAwE;AACxE,MAAM,WAAW,sBAAsB;IACrC,kDAAkD;IAClD,KAAK,EAAE,UAAU,CAAC;IAClB,uEAAuE;IACvE,IAAI,EAAE,MAAM,CAAC;IACb,0EAA0E;IAC1E,QAAQ,EAAE,MAAM,CAAC;IACjB,8EAA8E;IAC9E,eAAe,EAAE,MAAM,CAAC;IACxB,iFAAiF;IACjF,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AA6BD;;;;;;;;GAQG;AACH,wBAAsB,uBAAuB,CAC3C,KAAK,EAAE,sBAAsB,GAC5B,OAAO,CAAC,MAAM,CAAC,CAWjB;AAwBD;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAqB7E;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAwBnF;AAED,kFAAkF;AAClF,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC,CAiBzD"}
package/dist/cache.js ADDED
Binary file
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.js","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,81 @@
1
+ import type { ListToolsResponse, ToolResult } from './generated/interfaces/act-tools-tool-provider.js';
2
+ import type { Cbor, Metadata } from './generated/interfaces/act-core-types.js';
3
+ /**
4
+ * Typed mirror of the `act:tools/tool-provider@0.2.0` interface as exposed
5
+ * by jco-transpiled modules. Matches the generated types in
6
+ * `./generated/interfaces/act-tools-tool-provider.js`.
7
+ */
8
+ export interface ToolProvider {
9
+ listTools(metadata: Metadata): Promise<ListToolsResponse>;
10
+ callTool(name: string, args: Cbor, metadata: Metadata): Promise<ToolResult>;
11
+ }
12
+ /**
13
+ * Typed mirror of `act:sessions/session-provider@0.2.0` as exposed by
14
+ * jco-transpiled modules (present only on session-provider components).
15
+ */
16
+ export interface SessionProvider {
17
+ getOpenSessionArgsSchema(metadata: Metadata): Promise<string>;
18
+ openSession(args: Metadata, metadata: Metadata): Promise<{
19
+ id: string;
20
+ metadata: Metadata;
21
+ }>;
22
+ closeSession(sessionId: string): void;
23
+ }
24
+ export interface ComponentInstance {
25
+ /** `act:tools/tool-provider@0.2.0` if the component exports it. */
26
+ toolProvider: ToolProvider;
27
+ /** `act:sessions/session-provider@0.2.0` if the component exports it. */
28
+ sessionProvider?: SessionProvider;
29
+ }
30
+ export interface RunComponentOptions {
31
+ /** Human-readable component name; used for output filenames during transpile. */
32
+ name?: string;
33
+ /**
34
+ * Absolute base URL for the `@bytecodealliance/preview2-shim` browser-build
35
+ * directory (`dist/browser/` as of preview2-shim 0.19; it was `lib/browser/`
36
+ * before). Required: we drive jco's low-level bindgen `generate()` directly
37
+ * and pass our own WASI specifier map, so callers must point at a concrete
38
+ * shim location (CDN, vendored copy, or bundler-resolved path).
39
+ *
40
+ * Example: `'https://cdn.jsdelivr.net/npm/@bytecodealliance/preview2-shim@0.19.0/dist/browser/'`
41
+ */
42
+ shimBase: string;
43
+ /**
44
+ * Optional absolute URL of `dist/shims/wasi-http.js` from `@actcore/web-runtime`.
45
+ * Defaults to the bundled shim resolved relative to host-api's module URL.
46
+ * Override when `@actcore/web-runtime` is loaded from one origin and you want the
47
+ * wasi:http p3 shim served from another.
48
+ */
49
+ wasiHttpShimUrl?: string;
50
+ /**
51
+ * Optional absolute URL of `dist/shims/sockets.js` from `@actcore/web-runtime`.
52
+ * Defaults to the bundled shim resolved relative to host-api's module URL.
53
+ * host-browser ships its own wasi:sockets shim because preview2-shim's
54
+ * browser build omits the resource-class constructors (ResolveAddressStream,
55
+ * Network, TcpSocket, UdpSocket, …) that any wasi:http-importing component
56
+ * needs present at instantiation. Override when serving shims from another
57
+ * origin (same reason as {@link wasiHttpShimUrl}).
58
+ */
59
+ wasiSocketsShimUrl?: string;
60
+ /**
61
+ * Persist + reuse the jco transpile output in IndexedDB, keyed by
62
+ * `@actcore/web-runtime`'s version and the SHA-256 of the component bytes. Defaults
63
+ * to `true`. Set `false` to always transpile fresh (e.g. when debugging the
64
+ * transpiler). No effect where IndexedDB / `crypto.subtle` is unavailable —
65
+ * the cache silently disables itself there. See {@link clearTranspileCache}.
66
+ */
67
+ cache?: boolean;
68
+ }
69
+ /**
70
+ * Transpile and instantiate an ACT wasm component in the current page,
71
+ * returning a typed handle to its exported provider interfaces.
72
+ *
73
+ * Requires:
74
+ * - `WebAssembly.promising` (JSPI). Available by default in Chrome 137+,
75
+ * in Firefox Nightly 152+, and in Safari Tech Preview 243+. Tracking
76
+ * issue: Interop 2026 focus area #10.
77
+ * - The component must be a `wasip3`-style ACT component packed via
78
+ * `act-build pack` and exporting `act:tools/tool-provider@0.2.0`.
79
+ */
80
+ export declare function runComponent(bytes: Uint8Array, options: RunComponentOptions): Promise<ComponentInstance>;
81
+ //# sourceMappingURL=host-api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host-api.d.ts","sourceRoot":"","sources":["../src/host-api.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,iBAAiB,EACjB,UAAU,EACX,MAAM,mDAAmD,CAAC;AAC3D,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,0CAA0C,CAAC;AAM/E;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,SAAS,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAC1D,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;CAC7E;AAED;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,wBAAwB,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC9D,WAAW,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,QAAQ,CAAA;KAAE,CAAC,CAAC;IAC7F,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CACvC;AAED,MAAM,WAAW,iBAAiB;IAChC,mEAAmE;IACnE,YAAY,EAAE,YAAY,CAAC;IAC3B,yEAAyE;IACzE,eAAe,CAAC,EAAE,eAAe,CAAC;CACnC;AAED,MAAM,WAAW,mBAAmB;IAClC,iFAAiF;IACjF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;;;;OAQG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;;OAKG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;;;;;OAQG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,YAAY,CAChC,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,iBAAiB,CAAC,CA2C5B"}
@@ -0,0 +1,46 @@
1
+ import { transpileToBlobUrl } from './transpile.js';
2
+ import { fmtDuration, measurePhase } from './timing.js';
3
+ import { installCompileStreamingFallback } from './streaming-fallback.js';
4
+ /**
5
+ * Transpile and instantiate an ACT wasm component in the current page,
6
+ * returning a typed handle to its exported provider interfaces.
7
+ *
8
+ * Requires:
9
+ * - `WebAssembly.promising` (JSPI). Available by default in Chrome 137+,
10
+ * in Firefox Nightly 152+, and in Safari Tech Preview 243+. Tracking
11
+ * issue: Interop 2026 focus area #10.
12
+ * - The component must be a `wasip3`-style ACT component packed via
13
+ * `act-build pack` and exporting `act:tools/tool-provider@0.2.0`.
14
+ */
15
+ export async function runComponent(bytes, options) {
16
+ if (typeof WebAssembly.promising !== 'function') {
17
+ throw new Error('@actcore/web-runtime requires JSPI (WebAssembly.promising). Use Chrome 137+ ' +
18
+ '(stable), Firefox Nightly 152+, or Safari Technology Preview 243+. ' +
19
+ 'Per Interop 2026 commitment, stable Firefox/Safari ship JSPI in 2026.');
20
+ }
21
+ installCompileStreamingFallback();
22
+ const { url: entryBlobUrl, revoke: revokeBlobUrls } = await transpileToBlobUrl(bytes, options);
23
+ // Dynamic import from a blob: URL compiles + instantiates the component's core
24
+ // wasm in the page realm — a synchronous, main-thread-blocking step that, for
25
+ // large components, freezes the tab *after* the off-thread transpile above.
26
+ // Measure it separately so that freeze is quantified, not hidden.
27
+ const tInstantiate = performance.now();
28
+ let mod;
29
+ try {
30
+ mod = (await import(/* @vite-ignore */ entryBlobUrl));
31
+ }
32
+ finally {
33
+ // The module has fetched + compiled its (~100MB) core wasm by now; free the
34
+ // blob URLs so they don't accumulate (leak ~100MB) across runs.
35
+ revokeBlobUrls();
36
+ }
37
+ measurePhase('actcore:instantiate', tInstantiate, { component: options.name ?? 'component' });
38
+ console.debug(`[@actcore/web-runtime] instantiated on main thread in ${fmtDuration(performance.now() - tInstantiate)}`);
39
+ if (!mod.toolProvider) {
40
+ throw new Error('Component does not export act:tools/tool-provider@0.2.0');
41
+ }
42
+ // sessionProvider is present only on session-provider components; pass it
43
+ // through so callers can open sessions (stateful components need it).
44
+ return { toolProvider: mod.toolProvider, sessionProvider: mod.sessionProvider };
45
+ }
46
+ //# sourceMappingURL=host-api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host-api.js","sourceRoot":"","sources":["../src/host-api.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,+BAA+B,EAAE,MAAM,yBAAyB,CAAC;AAqE1E;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,KAAiB,EACjB,OAA4B;IAE5B,IAAI,OAAQ,WAAkD,CAAC,SAAS,KAAK,UAAU,EAAE,CAAC;QACxF,MAAM,IAAI,KAAK,CACb,8EAA8E;YAC5E,qEAAqE;YACrE,uEAAuE,CAC1E,CAAC;IACJ,CAAC;IAED,+BAA+B,EAAE,CAAC;IAElC,MAAM,EAAE,GAAG,EAAE,YAAY,EAAE,MAAM,EAAE,cAAc,EAAE,GAAG,MAAM,kBAAkB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IAE/F,+EAA+E;IAC/E,8EAA8E;IAC9E,4EAA4E;IAC5E,kEAAkE;IAClE,MAAM,YAAY,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;IACvC,IAAI,GAAuE,CAAC;IAC5E,IAAI,CAAC;QACH,GAAG,GAAG,CAAC,MAAM,MAAM,CAAC,kBAAkB,CAAC,YAAY,CAAC,CAGnD,CAAC;IACJ,CAAC;YAAS,CAAC;QACT,4EAA4E;QAC5E,gEAAgE;QAChE,cAAc,EAAE,CAAC;IACnB,CAAC;IACD,YAAY,CAAC,qBAAqB,EAAE,YAAY,EAAE,EAAE,SAAS,EAAE,OAAO,CAAC,IAAI,IAAI,WAAW,EAAE,CAAC,CAAC;IAC9F,OAAO,CAAC,KAAK,CACX,yDAAyD,WAAW,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,YAAY,CAAC,EAAE,CACzG,CAAC;IAEF,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CACb,yDAAyD,CAC1D,CAAC;IACJ,CAAC;IAED,0EAA0E;IAC1E,sEAAsE;IACtE,OAAO,EAAE,YAAY,EAAE,GAAG,CAAC,YAAY,EAAE,eAAe,EAAE,GAAG,CAAC,eAAe,EAAE,CAAC;AAClF,CAAC"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * @actcore/web-runtime — browser host for ACT (Agent Component Tools).
3
+ *
4
+ * Loads ACT wasm components in a browser tab via {@link
5
+ * https://github.com/bytecodealliance/jco | jco}'s in-browser transpiler and
6
+ * exposes the component's `act:tools/tool-provider` as a typed JS object.
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * import { runComponent } from '@actcore/web-runtime';
11
+ *
12
+ * const wasm = new Uint8Array(await (await fetch('/time.wasm')).arrayBuffer());
13
+ * const { toolProvider } = await runComponent(wasm);
14
+ *
15
+ * const { tools } = await toolProvider.listTools([]);
16
+ * const result = await toolProvider.callTool('get_current_time', new Uint8Array([0xa0]), []);
17
+ * ```
18
+ */
19
+ export type { ToolDefinition, ContentPart, ToolEvent, ToolEventContent, ToolEventError, ListToolsResponse, } from './generated/interfaces/act-tools-types.js';
20
+ export type { ToolResult, ToolResultImmediate, ToolResultStreaming, } from './generated/interfaces/act-tools-tool-provider.js';
21
+ export type { Cbor, LocalizedString, LocalizedStringPlain, LocalizedStringLocalized, Metadata, Error as ActError, } from './generated/interfaces/act-core-types.js';
22
+ export type { Session, } from './generated/interfaces/act-sessions-types.js';
23
+ export type { RunComponentOptions, ComponentInstance, ToolProvider } from './host-api.js';
24
+ export { runComponent } from './host-api.js';
25
+ export { clearTranspileCache } from './cache.js';
26
+ export type { ResolveLocalizedStringOptions } from './locale.js';
27
+ export { resolveLocalizedString } from './locale.js';
28
+ export { isWebmcpAvailable, exposeToWebmcp } from './webmcp.js';
29
+ export type { ModelContext, WebmcpToolDescriptor, WebmcpCallResult, ExposeWebmcpOptions, WebmcpExposure, } from './webmcp.js';
30
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,YAAY,EACV,cAAc,EACd,WAAW,EACX,SAAS,EACT,gBAAgB,EAChB,cAAc,EACd,iBAAiB,GAClB,MAAM,2CAA2C,CAAC;AACnD,YAAY,EACV,UAAU,EACV,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,mDAAmD,CAAC;AAC3D,YAAY,EACV,IAAI,EACJ,eAAe,EACf,oBAAoB,EACpB,wBAAwB,EACxB,QAAQ,EACR,KAAK,IAAI,QAAQ,GAClB,MAAM,0CAA0C,CAAC;AAClD,YAAY,EACV,OAAO,GACR,MAAM,8CAA8C,CAAC;AAEtD,YAAY,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC1F,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE7C,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEjD,YAAY,EAAE,6BAA6B,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAErD,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAChE,YAAY,EACV,YAAY,EACZ,oBAAoB,EACpB,gBAAgB,EAChB,mBAAmB,EACnB,cAAc,GACf,MAAM,aAAa,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,23 @@
1
+ /**
2
+ * @actcore/web-runtime — browser host for ACT (Agent Component Tools).
3
+ *
4
+ * Loads ACT wasm components in a browser tab via {@link
5
+ * https://github.com/bytecodealliance/jco | jco}'s in-browser transpiler and
6
+ * exposes the component's `act:tools/tool-provider` as a typed JS object.
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * import { runComponent } from '@actcore/web-runtime';
11
+ *
12
+ * const wasm = new Uint8Array(await (await fetch('/time.wasm')).arrayBuffer());
13
+ * const { toolProvider } = await runComponent(wasm);
14
+ *
15
+ * const { tools } = await toolProvider.listTools([]);
16
+ * const result = await toolProvider.callTool('get_current_time', new Uint8Array([0xa0]), []);
17
+ * ```
18
+ */
19
+ export { runComponent } from './host-api.js';
20
+ export { clearTranspileCache } from './cache.js';
21
+ export { resolveLocalizedString } from './locale.js';
22
+ export { isWebmcpAvailable, exposeToWebmcp } from './webmcp.js';
23
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AA4BH,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE7C,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAGjD,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAErD,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,32 @@
1
+ import type { LocalizedString } from './generated/interfaces/act-core-types.js';
2
+ export interface ResolveLocalizedStringOptions {
3
+ /**
4
+ * BCP 47 language tag declared by the component under
5
+ * `act:component.std.default-language`. Used as a fallback when none of
6
+ * the user's preferred locales is present.
7
+ */
8
+ defaultLanguage?: string;
9
+ /**
10
+ * Caller-preferred locales in priority order. Defaults to
11
+ * `navigator.languages` if available, else `[navigator.language]`,
12
+ * else `[]`.
13
+ */
14
+ userLocales?: readonly string[];
15
+ }
16
+ /**
17
+ * Resolve an {@link LocalizedString} to a concrete UTF-8 string.
18
+ *
19
+ * Resolution order:
20
+ * 1. If `plain` — return `val` (language undefined; callers may assume it
21
+ * matches `act:component.std.default-language` if declared).
22
+ * 2. Each entry in `userLocales` (BCP 47), preferring exact match
23
+ * (`en-US` → `en-US`), then language-only match (`en-US` → `en`).
24
+ * 3. `defaultLanguage`, same matching rules.
25
+ * 4. `en`, same matching rules.
26
+ * 5. First entry in the list.
27
+ * 6. Empty string if the list is empty.
28
+ *
29
+ * Matching is case-insensitive on language tags.
30
+ */
31
+ export declare function resolveLocalizedString(loc: LocalizedString, options?: ResolveLocalizedStringOptions): string;
32
+ //# sourceMappingURL=locale.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"locale.d.ts","sourceRoot":"","sources":["../src/locale.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0CAA0C,CAAC;AAEhF,MAAM,WAAW,6BAA6B;IAC5C;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACjC;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,eAAe,EACpB,OAAO,GAAE,6BAAkC,GAC1C,MAAM,CAmBR"}
package/dist/locale.js ADDED
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Resolve an {@link LocalizedString} to a concrete UTF-8 string.
3
+ *
4
+ * Resolution order:
5
+ * 1. If `plain` — return `val` (language undefined; callers may assume it
6
+ * matches `act:component.std.default-language` if declared).
7
+ * 2. Each entry in `userLocales` (BCP 47), preferring exact match
8
+ * (`en-US` → `en-US`), then language-only match (`en-US` → `en`).
9
+ * 3. `defaultLanguage`, same matching rules.
10
+ * 4. `en`, same matching rules.
11
+ * 5. First entry in the list.
12
+ * 6. Empty string if the list is empty.
13
+ *
14
+ * Matching is case-insensitive on language tags.
15
+ */
16
+ export function resolveLocalizedString(loc, options = {}) {
17
+ if (loc.tag === 'plain')
18
+ return loc.val;
19
+ const entries = loc.val;
20
+ if (entries.length === 0)
21
+ return '';
22
+ const userLocales = options.userLocales ?? defaultUserLocales();
23
+ const candidates = [];
24
+ for (const l of userLocales)
25
+ if (l)
26
+ candidates.push(l);
27
+ if (options.defaultLanguage)
28
+ candidates.push(options.defaultLanguage);
29
+ candidates.push('en');
30
+ for (const candidate of candidates) {
31
+ const hit = matchLocale(entries, candidate);
32
+ if (hit !== undefined)
33
+ return hit;
34
+ }
35
+ return entries[0][1];
36
+ }
37
+ function matchLocale(entries, candidate) {
38
+ const want = candidate.toLowerCase();
39
+ for (const [lang, text] of entries) {
40
+ if (lang.toLowerCase() === want)
41
+ return text;
42
+ }
43
+ const wantPrimary = primarySubtag(want);
44
+ for (const [lang, text] of entries) {
45
+ if (primarySubtag(lang.toLowerCase()) === wantPrimary)
46
+ return text;
47
+ }
48
+ return undefined;
49
+ }
50
+ function primarySubtag(tag) {
51
+ const dash = tag.indexOf('-');
52
+ return dash === -1 ? tag : tag.slice(0, dash);
53
+ }
54
+ function defaultUserLocales() {
55
+ const nav = globalThis.navigator;
56
+ if (!nav)
57
+ return [];
58
+ if (nav.languages && nav.languages.length > 0)
59
+ return nav.languages;
60
+ if (nav.language)
61
+ return [nav.language];
62
+ return [];
63
+ }
64
+ //# sourceMappingURL=locale.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"locale.js","sourceRoot":"","sources":["../src/locale.ts"],"names":[],"mappings":"AAiBA;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,sBAAsB,CACpC,GAAoB,EACpB,UAAyC,EAAE;IAE3C,IAAI,GAAG,CAAC,GAAG,KAAK,OAAO;QAAE,OAAO,GAAG,CAAC,GAAG,CAAC;IAExC,MAAM,OAAO,GAAG,GAAG,CAAC,GAAG,CAAC;IACxB,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAEpC,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,kBAAkB,EAAE,CAAC;IAEhE,MAAM,UAAU,GAAa,EAAE,CAAC;IAChC,KAAK,MAAM,CAAC,IAAI,WAAW;QAAE,IAAI,CAAC;YAAE,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACvD,IAAI,OAAO,CAAC,eAAe;QAAE,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;IACtE,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEtB,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,MAAM,GAAG,GAAG,WAAW,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QAC5C,IAAI,GAAG,KAAK,SAAS;YAAE,OAAO,GAAG,CAAC;IACpC,CAAC;IAED,OAAO,OAAO,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,CAAC;AACxB,CAAC;AAED,SAAS,WAAW,CAClB,OAAiD,EACjD,SAAiB;IAEjB,MAAM,IAAI,GAAG,SAAS,CAAC,WAAW,EAAE,CAAC;IACrC,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,OAAO,EAAE,CAAC;QACnC,IAAI,IAAI,CAAC,WAAW,EAAE,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC;IAC/C,CAAC;IACD,MAAM,WAAW,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;IACxC,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,OAAO,EAAE,CAAC;QACnC,IAAI,aAAa,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,KAAK,WAAW;YAAE,OAAO,IAAI,CAAC;IACrE,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,aAAa,CAAC,GAAW;IAChC,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC9B,OAAO,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;AAChD,CAAC;AAED,SAAS,kBAAkB;IACzB,MAAM,GAAG,GAAI,UAAmF,CAAC,SAAS,CAAC;IAC3G,IAAI,CAAC,GAAG;QAAE,OAAO,EAAE,CAAC;IACpB,IAAI,GAAG,CAAC,SAAS,IAAI,GAAG,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,GAAG,CAAC,SAAS,CAAC;IACpE,IAAI,GAAG,CAAC,QAAQ;QAAE,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACxC,OAAO,EAAE,CAAC;AACZ,CAAC"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Runtime patches applied to a jco-transpiled entry-module source string.
3
+ *
4
+ * History: under jco 1.19 this file carried eight patches working around
5
+ * wasip3-async bugs in jco's emitted code, plus a hand-rolled lift (`lift.ts`)
6
+ * that walked `act:tools` task-return records out of linear memory because jco
7
+ * mis-decoded the flat-fields ABI. The jco 1.20→1.24 upgrade (bindgen
8
+ * 1.17→2.0.3) fixed all of them upstream. Verified by transpiling real
9
+ * components (`time.wasm`, `http-client.wasm`) with jco 1.24.3 and running them
10
+ * under JSPI: the anchors are gone or the declarations now emitted, and the
11
+ * native lift returns correct results (tool descriptions, option/variant
12
+ * shapes, metadata, and error events all decode correctly):
13
+ *
14
+ * - STREAM_TABLES / FUTURE_TABLES now declared (jco 1.20, PR #1464)
15
+ * - `class HostFuture` now emitted (jco 1.20+)
16
+ * - host-imported resource lowers now populated (no more throw-stubs)
17
+ * - `rscTableCreateOwn` reshaped, resource origination tracked at runtime
18
+ * - `StreamWritableEnd.write` count reshaped
19
+ * - async-import `resultPtr: params[0]` → direct-param lifts (bindgen 2.0)
20
+ * - `_liftFlatU{8,16,32}` storageLen accounting fixed (jco 1.23.1)
21
+ * - flat-fields `act:tools` task-return lift (bindgen 2.0 — `lift.ts`
22
+ * deleted; the custom lift now produces *worse* output than jco's native one)
23
+ *
24
+ * What remains is one defensive splice: short-circuiting future/stream drops
25
+ * whose wasm-side end was already transferred. It only matters for components
26
+ * importing wasi:http p3 (futures/streams in request/response bodies), goes
27
+ * through `replaceOrWarn` so a moved anchor warns instead of silently no-opping,
28
+ * and is a no-op for components that don't use host-boundary futures/streams.
29
+ */
30
+ export declare function applyPatches(src: string): string;
31
+ /**
32
+ * Bare-specifier imports for `@bytecodealliance/preview2-shim/*` are emitted
33
+ * by jco's transpile (matching the `map` option we pass), but ES modules
34
+ * loaded from blob: URLs can't see the document's importmap. Rewrite to
35
+ * absolute URLs in-place.
36
+ */
37
+ export declare function rewriteBareImports(src: string, shimBase: string): string;
38
+ //# sourceMappingURL=patches.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"patches.d.ts","sourceRoot":"","sources":["../src/patches.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAwBhD;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAiBxE"}