Loading workspace insights... Statistics interval
7 days30 daysLatest CI Pipeline Executions
cde8d279 fix(ai-isolate-cloudflare): port worker from unsafe_eval to worker_loader (#523)
* fix(ai-isolate-cloudflare): port worker from unsafe_eval to worker_loader
Cloudflare gates the `unsafe_eval` binding for all customer prod
accounts (no public entitlement); the previous driver was unusable in
production and broken in `wrangler dev` on current Wrangler 4.x.
Swap `env.UNSAFE_EVAL.eval(code)` for the supported `worker_loader`
(Dynamic Workers) binding — load the wrapped code as an ES module into
a fresh child Worker isolate via `env.LOADER.load({...}).getEntrypoint()
.fetch(...)` and read the structured result back as JSON.
The HTTP tool-callback protocol, driver, and public API are unchanged.
~120 LOC change in worker; tests + wrangler.toml + README updated.
Workers Paid plan is required for any edge usage (deploy or
`wrangler dev --remote`); local `wrangler dev` works on the Free plan.
The custom Miniflare `dev-server.mjs` is removed since `wrangler dev`
now binds `worker_loader` natively.
Closes #522.
* fix(ai-isolate-cloudflare): cancel in-flight fetch on timeout + happy-path tests
Address CodeRabbit review on #523:
1. Promise.race timeout left `entrypoint.fetch` running, leaking the loaded
child Worker isolate. Add an AbortController whose signal flows into the
Request passed to entrypoint.fetch — the timeout now actually cancels the
in-flight request. Promise.race remains as a belt-and-suspenders guard.
2. Add three integration tests against a mocked LOADER binding:
- happy path: full load → getEntrypoint → fetch chain, asserts the
load() arguments (mainModule, modules, globalOutbound) and that the
Request carries an AbortSignal
- need_tools: forwards toolCalls + continuationId from sandbox
- TimeoutError: AbortSignal-driven cancellation triggers the right
error shape
Tests: 39/39 pass.
* fix(ai-isolate-cloudflare): tighten timeout test + happy-path assertions
Address CodeRabbit second-pass review:
1. happy-path test: hoist load() argument assertions out of the synchronous
mock. Inside load() they get swallowed by the worker's outer try/catch and
surface as a generic 500. Capture options into a local + assert after
worker.fetch() resolves.
2. timeout test: `expect(receivedSignal).not.toBeNull()` is trivially true
per the Fetch spec (Request.signal is always present). Drop it from the
happy-path test and instead assert `signal.aborted === true` in the
timeout test, which actually proves the outer worker's AbortController
fired.
3. worker fix: when the AbortController fires first, fetchPromise rejects
before timeoutPromise. Detect the timeout via either TIMEOUT_SENTINEL or
`controller.signal.aborted` so the right error surfaces regardless of
which branch of the race wins.
Tests: 39/39 pass.
* Updated wrangler
* chore(ai-isolate-cloudflare): drop unused esbuild and miniflare devDeps
These were only used by the deleted dev-server.mjs, which existed to
work around wrangler dev not surfacing the old unsafe_eval binding.
With the worker_loader port, wrangler dev handles dev natively.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Tom Beckenham <34339192+tombeckenham@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> cde8d279 fix(ai-isolate-cloudflare): port worker from unsafe_eval to worker_loader (#523)
* fix(ai-isolate-cloudflare): port worker from unsafe_eval to worker_loader
Cloudflare gates the `unsafe_eval` binding for all customer prod
accounts (no public entitlement); the previous driver was unusable in
production and broken in `wrangler dev` on current Wrangler 4.x.
Swap `env.UNSAFE_EVAL.eval(code)` for the supported `worker_loader`
(Dynamic Workers) binding — load the wrapped code as an ES module into
a fresh child Worker isolate via `env.LOADER.load({...}).getEntrypoint()
.fetch(...)` and read the structured result back as JSON.
The HTTP tool-callback protocol, driver, and public API are unchanged.
~120 LOC change in worker; tests + wrangler.toml + README updated.
Workers Paid plan is required for any edge usage (deploy or
`wrangler dev --remote`); local `wrangler dev` works on the Free plan.
The custom Miniflare `dev-server.mjs` is removed since `wrangler dev`
now binds `worker_loader` natively.
Closes #522.
* fix(ai-isolate-cloudflare): cancel in-flight fetch on timeout + happy-path tests
Address CodeRabbit review on #523:
1. Promise.race timeout left `entrypoint.fetch` running, leaking the loaded
child Worker isolate. Add an AbortController whose signal flows into the
Request passed to entrypoint.fetch — the timeout now actually cancels the
in-flight request. Promise.race remains as a belt-and-suspenders guard.
2. Add three integration tests against a mocked LOADER binding:
- happy path: full load → getEntrypoint → fetch chain, asserts the
load() arguments (mainModule, modules, globalOutbound) and that the
Request carries an AbortSignal
- need_tools: forwards toolCalls + continuationId from sandbox
- TimeoutError: AbortSignal-driven cancellation triggers the right
error shape
Tests: 39/39 pass.
* fix(ai-isolate-cloudflare): tighten timeout test + happy-path assertions
Address CodeRabbit second-pass review:
1. happy-path test: hoist load() argument assertions out of the synchronous
mock. Inside load() they get swallowed by the worker's outer try/catch and
surface as a generic 500. Capture options into a local + assert after
worker.fetch() resolves.
2. timeout test: `expect(receivedSignal).not.toBeNull()` is trivially true
per the Fetch spec (Request.signal is always present). Drop it from the
happy-path test and instead assert `signal.aborted === true` in the
timeout test, which actually proves the outer worker's AbortController
fired.
3. worker fix: when the AbortController fires first, fetchPromise rejects
before timeoutPromise. Detect the timeout via either TIMEOUT_SENTINEL or
`controller.signal.aborted` so the right error surfaces regardless of
which branch of the race wins.
Tests: 39/39 pass.
* Updated wrangler
* chore(ai-isolate-cloudflare): drop unused esbuild and miniflare devDeps
These were only used by the deleted dev-server.mjs, which existed to
work around wrangler dev not surfacing the old unsafe_eval binding.
With the worker_loader port, wrangler dev handles dev natively.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Tom Beckenham <34339192+tombeckenham@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> c9f692f0 fix(ai-isolate-cloudflare): port worker from unsafe_eval to worker_loader (#523)
* fix(ai-isolate-cloudflare): port worker from unsafe_eval to worker_loader
Cloudflare gates the `unsafe_eval` binding for all customer prod
accounts (no public entitlement); the previous driver was unusable in
production and broken in `wrangler dev` on current Wrangler 4.x.
Swap `env.UNSAFE_EVAL.eval(code)` for the supported `worker_loader`
(Dynamic Workers) binding — load the wrapped code as an ES module into
a fresh child Worker isolate via `env.LOADER.load({...}).getEntrypoint()
.fetch(...)` and read the structured result back as JSON.
The HTTP tool-callback protocol, driver, and public API are unchanged.
~120 LOC change in worker; tests + wrangler.toml + README updated.
Workers Paid plan is required for any edge usage (deploy or
`wrangler dev --remote`); local `wrangler dev` works on the Free plan.
The custom Miniflare `dev-server.mjs` is removed since `wrangler dev`
now binds `worker_loader` natively.
Closes #522.
* fix(ai-isolate-cloudflare): cancel in-flight fetch on timeout + happy-path tests
Address CodeRabbit review on #523:
1. Promise.race timeout left `entrypoint.fetch` running, leaking the loaded
child Worker isolate. Add an AbortController whose signal flows into the
Request passed to entrypoint.fetch — the timeout now actually cancels the
in-flight request. Promise.race remains as a belt-and-suspenders guard.
2. Add three integration tests against a mocked LOADER binding:
- happy path: full load → getEntrypoint → fetch chain, asserts the
load() arguments (mainModule, modules, globalOutbound) and that the
Request carries an AbortSignal
- need_tools: forwards toolCalls + continuationId from sandbox
- TimeoutError: AbortSignal-driven cancellation triggers the right
error shape
Tests: 39/39 pass.
* fix(ai-isolate-cloudflare): tighten timeout test + happy-path assertions
Address CodeRabbit second-pass review:
1. happy-path test: hoist load() argument assertions out of the synchronous
mock. Inside load() they get swallowed by the worker's outer try/catch and
surface as a generic 500. Capture options into a local + assert after
worker.fetch() resolves.
2. timeout test: `expect(receivedSignal).not.toBeNull()` is trivially true
per the Fetch spec (Request.signal is always present). Drop it from the
happy-path test and instead assert `signal.aborted === true` in the
timeout test, which actually proves the outer worker's AbortController
fired.
3. worker fix: when the AbortController fires first, fetchPromise rejects
before timeoutPromise. Detect the timeout via either TIMEOUT_SENTINEL or
`controller.signal.aborted` so the right error surfaces regardless of
which branch of the race wins.
Tests: 39/39 pass.
* Updated wrangler
* chore(ai-isolate-cloudflare): drop unused esbuild and miniflare devDeps
These were only used by the deleted dev-server.mjs, which existed to
work around wrangler dev not surfacing the old unsafe_eval binding.
With the worker_loader port, wrangler dev handles dev natively.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Tom Beckenham <34339192+tombeckenham@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> a9fc3165 fix(ai-isolate-cloudflare): port worker from unsafe_eval to worker_loader (#523)
* fix(ai-isolate-cloudflare): port worker from unsafe_eval to worker_loader
Cloudflare gates the `unsafe_eval` binding for all customer prod
accounts (no public entitlement); the previous driver was unusable in
production and broken in `wrangler dev` on current Wrangler 4.x.
Swap `env.UNSAFE_EVAL.eval(code)` for the supported `worker_loader`
(Dynamic Workers) binding — load the wrapped code as an ES module into
a fresh child Worker isolate via `env.LOADER.load({...}).getEntrypoint()
.fetch(...)` and read the structured result back as JSON.
The HTTP tool-callback protocol, driver, and public API are unchanged.
~120 LOC change in worker; tests + wrangler.toml + README updated.
Workers Paid plan is required for any edge usage (deploy or
`wrangler dev --remote`); local `wrangler dev` works on the Free plan.
The custom Miniflare `dev-server.mjs` is removed since `wrangler dev`
now binds `worker_loader` natively.
Closes #522.
* fix(ai-isolate-cloudflare): cancel in-flight fetch on timeout + happy-path tests
Address CodeRabbit review on #523:
1. Promise.race timeout left `entrypoint.fetch` running, leaking the loaded
child Worker isolate. Add an AbortController whose signal flows into the
Request passed to entrypoint.fetch — the timeout now actually cancels the
in-flight request. Promise.race remains as a belt-and-suspenders guard.
2. Add three integration tests against a mocked LOADER binding:
- happy path: full load → getEntrypoint → fetch chain, asserts the
load() arguments (mainModule, modules, globalOutbound) and that the
Request carries an AbortSignal
- need_tools: forwards toolCalls + continuationId from sandbox
- TimeoutError: AbortSignal-driven cancellation triggers the right
error shape
Tests: 39/39 pass.
* fix(ai-isolate-cloudflare): tighten timeout test + happy-path assertions
Address CodeRabbit second-pass review:
1. happy-path test: hoist load() argument assertions out of the synchronous
mock. Inside load() they get swallowed by the worker's outer try/catch and
surface as a generic 500. Capture options into a local + assert after
worker.fetch() resolves.
2. timeout test: `expect(receivedSignal).not.toBeNull()` is trivially true
per the Fetch spec (Request.signal is always present). Drop it from the
happy-path test and instead assert `signal.aborted === true` in the
timeout test, which actually proves the outer worker's AbortController
fired.
3. worker fix: when the AbortController fires first, fetchPromise rejects
before timeoutPromise. Detect the timeout via either TIMEOUT_SENTINEL or
`controller.signal.aborted` so the right error surfaces regardless of
which branch of the race wins.
Tests: 39/39 pass.
* Updated wrangler
* chore(ai-isolate-cloudflare): drop unused esbuild and miniflare devDeps
These were only used by the deleted dev-server.mjs, which existed to
work around wrangler dev not surfacing the old unsafe_eval binding.
With the worker_loader port, wrangler dev handles dev natively.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Tom Beckenham <34339192+tombeckenham@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> a9fc3165 fix(ai-isolate-cloudflare): port worker from unsafe_eval to worker_loader (#523)
* fix(ai-isolate-cloudflare): port worker from unsafe_eval to worker_loader
Cloudflare gates the `unsafe_eval` binding for all customer prod
accounts (no public entitlement); the previous driver was unusable in
production and broken in `wrangler dev` on current Wrangler 4.x.
Swap `env.UNSAFE_EVAL.eval(code)` for the supported `worker_loader`
(Dynamic Workers) binding — load the wrapped code as an ES module into
a fresh child Worker isolate via `env.LOADER.load({...}).getEntrypoint()
.fetch(...)` and read the structured result back as JSON.
The HTTP tool-callback protocol, driver, and public API are unchanged.
~120 LOC change in worker; tests + wrangler.toml + README updated.
Workers Paid plan is required for any edge usage (deploy or
`wrangler dev --remote`); local `wrangler dev` works on the Free plan.
The custom Miniflare `dev-server.mjs` is removed since `wrangler dev`
now binds `worker_loader` natively.
Closes #522.
* fix(ai-isolate-cloudflare): cancel in-flight fetch on timeout + happy-path tests
Address CodeRabbit review on #523:
1. Promise.race timeout left `entrypoint.fetch` running, leaking the loaded
child Worker isolate. Add an AbortController whose signal flows into the
Request passed to entrypoint.fetch — the timeout now actually cancels the
in-flight request. Promise.race remains as a belt-and-suspenders guard.
2. Add three integration tests against a mocked LOADER binding:
- happy path: full load → getEntrypoint → fetch chain, asserts the
load() arguments (mainModule, modules, globalOutbound) and that the
Request carries an AbortSignal
- need_tools: forwards toolCalls + continuationId from sandbox
- TimeoutError: AbortSignal-driven cancellation triggers the right
error shape
Tests: 39/39 pass.
* fix(ai-isolate-cloudflare): tighten timeout test + happy-path assertions
Address CodeRabbit second-pass review:
1. happy-path test: hoist load() argument assertions out of the synchronous
mock. Inside load() they get swallowed by the worker's outer try/catch and
surface as a generic 500. Capture options into a local + assert after
worker.fetch() resolves.
2. timeout test: `expect(receivedSignal).not.toBeNull()` is trivially true
per the Fetch spec (Request.signal is always present). Drop it from the
happy-path test and instead assert `signal.aborted === true` in the
timeout test, which actually proves the outer worker's AbortController
fired.
3. worker fix: when the AbortController fires first, fetchPromise rejects
before timeoutPromise. Detect the timeout via either TIMEOUT_SENTINEL or
`controller.signal.aborted` so the right error surfaces regardless of
which branch of the race wins.
Tests: 39/39 pass.
* Updated wrangler
* chore(ai-isolate-cloudflare): drop unused esbuild and miniflare devDeps
These were only used by the deleted dev-server.mjs, which existed to
work around wrangler dev not surfacing the old unsafe_eval binding.
With the worker_loader port, wrangler dev handles dev natively.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Tom Beckenham <34339192+tombeckenham@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>