We embed Monty's protocol worker in a WASI host: wazero, from Go. It runs sandboxed Python transforms on each request in an LLM API gateway. We drive monty-proto's worker::Child over the framed monty.v1 protocol and always feed with skip_type_check, so the type checker is never used. But it can't be left out of the build: monty-proto's worker feature is
worker = ["dep:monty", "dep:monty-type-checking", "monty-types/tzdb-bundled"]so every worker links ty, ruff_db, salsa and the typeshed stubs. monty-wasm-runtime depends on monty-proto with worker as well, so the JS worker carries the checker too.
What it costs, measured at 1.3.0 (ca1b75be), wasm32-wasip1 release, same stack size:
| With checker | Without | |
|---|---|---|
| Module | 24.3 MB | 10.4 MB |
| wazero compile (Apple M-series, cold) | 5.8–6.5 s | 2.4 s |
Runtime behaviour was otherwise unchanged in our tests: limits, per-call latency, and all feeds with skip_type_check. To get these numbers we replaced monty-type-checking in the workspace with an API-compatible stub. It provides SourceFile, TypeCheckContext, TypeChecker and scan_imports, and its run_with returns an error. Those four items are all worker.rs uses.
Proposal (non-breaking):
worker-core = ["dep:monty", "monty-types/tzdb-bundled"]
worker = ["worker-core", "dep:monty-type-checking"]- Gate the type-checking paths in
worker.rson the checker being present: theTypeCheckerfield,type_check_feed, thescan_importscall, and theresetcall. - When a worker built without it receives
Configure { type_check: true, .. }, reject it with a clear error, for example "type checking is not built into this worker". - Existing users of
workersee no change. Embedders that never type-check can depend onworker-core.
Thanks for #1113, by the way: we hit the same 32-bit HeapData size assertion when the checker's dependency tree was the only thing turning on smallvec/union.
Happy to send a PR for this if the approach looks right to you.
Activity
0No activity yet.