Recurring surface across all three upcoming TUI corpus targets (pi → kimi-code → opencode). Filing as one cross-cutting decision issue: implement real WebAssembly support, or adopt a per-module replacement/stub policy.
Where WASM appears in the targets
pi (@earendil-works/pi-coding-agent 0.80.10):
@silvia-odwyer/photon-node (wasm-bindgen image ops) — lazy + nullable: coding-agent/src/utils/photon.ts wraps loading in a promise that resolves null on failure; image resize/clipboard-image degrade gracefully. A graceful-fail stub is acceptable here.
undici 8.5.0 — pi's cli.js unconditionally calls configureHttpDispatcher() which sets undici as global dispatcher (+ undici.install?.() replacing global fetch). Bundled undici instantiates llhttp WASM on the first HTTP request (new WebAssembly.Module(require_llhttp_wasm())). Planned mitigation is a bundle-time undici alias shim onto perry's native fetch (tracked in the pi target issue), so llhttp WASM never runs — but any target that bundles undici un-shimmed will hit this.
kimi-code (@moonshot-ai/kimi-code 0.27.0, single 15MB dist/main.mjs):
- Embedded webp decoder from
@jsquash/webp (base64 wasm, WebAssembly.compile + WebAssembly.instantiate) in the media/attachment path (agent-core*/src/**/webp-decode.ts).
opencode (anomalyco/opencode):
@silvia-odwyer/photon-node again (core/src/image/photon.ts, opencode/src/image/image.ts) — same library as pi, one solution serves both.
Options
- Real WASM engine in the runtime (interpreter-tier is enough; these are cold paths) — full parity, biggest lift.
- Per-module native replacement: photon → native image ops; webp → native decoder; llhttp → never needed if fetch is native.
- Graceful-fail stubs (
WebAssembly.compile rejects) where callers already degrade (photon's loader is written for this).
Recommendation: start with a per-module policy — (3) for photon paths, bundle-shim for undici, decide on (2) vs (1) only if kimi's webp path proves load-bearing in practice. Real WASM support remains the long-term parity answer (Node supports it), so keeping this issue open past the first mitigations is expected.
Recurring surface across all three upcoming TUI corpus targets (pi → kimi-code → opencode). Filing as one cross-cutting decision issue: implement real WebAssembly support, or adopt a per-module replacement/stub policy.
Where WASM appears in the targets
pi (
@earendil-works/pi-coding-agent0.80.10):@silvia-odwyer/photon-node(wasm-bindgen image ops) — lazy + nullable:coding-agent/src/utils/photon.tswraps loading in a promise that resolvesnullon failure; image resize/clipboard-image degrade gracefully. A graceful-fail stub is acceptable here.undici8.5.0 — pi'scli.jsunconditionally callsconfigureHttpDispatcher()which sets undici as global dispatcher (+undici.install?.()replacing global fetch). Bundled undici instantiates llhttp WASM on the first HTTP request (new WebAssembly.Module(require_llhttp_wasm())). Planned mitigation is a bundle-timeundicialias shim onto perry's native fetch (tracked in the pi target issue), so llhttp WASM never runs — but any target that bundles undici un-shimmed will hit this.kimi-code (
@moonshot-ai/kimi-code0.27.0, single 15MBdist/main.mjs):@jsquash/webp(base64 wasm,WebAssembly.compile+WebAssembly.instantiate) in the media/attachment path (agent-core*/src/**/webp-decode.ts).opencode (anomalyco/opencode):
@silvia-odwyer/photon-nodeagain (core/src/image/photon.ts,opencode/src/image/image.ts) — same library as pi, one solution serves both.Options
WebAssembly.compilerejects) where callers already degrade (photon's loader is written for this).Recommendation: start with a per-module policy — (3) for photon paths, bundle-shim for undici, decide on (2) vs (1) only if kimi's webp path proves load-bearing in practice. Real WASM support remains the long-term parity answer (Node supports it), so keeping this issue open past the first mitigations is expected.