Summary
group-translate calls res.json() on the result of ctx.net.fetch, but the sandbox runtime returns a plain object with no methods — so res.json() throws at runtime, the call fails-open, and translation is very likely a silent no-op in production.
Root cause
The host returns a serializable response and it crosses the worker boundary via structuredClone, which cannot carry functions. Traced in OpenWA core:
performPluginFetch returns { ok, status, statusText, headers, body: string } — no .json()/.text()/.arrayBuffer() (src/core/plugins/plugin-net.ts).
- The worker capability client returns that result verbatim; there is no wrapper that re-adds the methods (
src/core/plugins/sandbox/worker-capability.ts, worker-bootstrap.ts).
So at runtime ctx.net.fetch(...) resolves to { ok, status, statusText, headers, body }. res.json() is undefined → TypeError → caught by the client's try/catch → counted as a failure / returned empty.
The vendored type (types/openwa.d.ts) declared the method form (.json() etc.), which doesn't match the runtime — that's why this wasn't caught at compile time, and the unit tests pass only because they fake a .json()-bearing response (testing the mock, not the runtime shape).
Fix
- In
group-translate/libretranslate.client.ts, read JSON.parse(res.body) instead of await res.json().
- Update the
libretranslate.client.test.ts fakes to the real shape ({ ..., body: string }) so the test exercises reality.
(The vendored type was already corrected to expose body: string in #9.)
Verify
After the fix, a live round-trip against a real LibreTranslate instance should produce an actual translation (today it does not).
Summary
group-translatecallsres.json()on the result ofctx.net.fetch, but the sandbox runtime returns a plain object with no methods — sores.json()throws at runtime, the call fails-open, and translation is very likely a silent no-op in production.Root cause
The host returns a serializable response and it crosses the worker boundary via
structuredClone, which cannot carry functions. Traced in OpenWA core:performPluginFetchreturns{ ok, status, statusText, headers, body: string }— no.json()/.text()/.arrayBuffer()(src/core/plugins/plugin-net.ts).src/core/plugins/sandbox/worker-capability.ts,worker-bootstrap.ts).So at runtime
ctx.net.fetch(...)resolves to{ ok, status, statusText, headers, body }.res.json()isundefined→TypeError→ caught by the client's try/catch → counted as a failure / returned empty.The vendored type (
types/openwa.d.ts) declared the method form (.json()etc.), which doesn't match the runtime — that's why this wasn't caught at compile time, and the unit tests pass only because they fake a.json()-bearing response (testing the mock, not the runtime shape).Fix
group-translate/libretranslate.client.ts, readJSON.parse(res.body)instead ofawait res.json().libretranslate.client.test.tsfakes to the real shape ({ ..., body: string }) so the test exercises reality.(The vendored type was already corrected to expose
body: stringin #9.)Verify
After the fix, a live round-trip against a real LibreTranslate instance should produce an actual translation (today it does not).