This repository has no description
flarebot docs effect-customer-runtime.md
9.3 kB
Markdown
at main

Effect customer runtime #

The customer Worker composes application work with Effect while Cloudflare Agents, Think, Workers AI, Browser Run, and Sandbox retain their native responsibilities. This implements the migration plan from 945d0cd. Dependency versions, exported Durable Object classes, storage formats, native callback names, and public payloads remain unchanged.

No additional Distilled package is needed for these paths. Distilled continues to serve Cloudflare management operations in the control plane. Customer operations use native bindings or Flarebot's own publisher protocol; they do not acquire publisher management credentials. Alchemy is not introduced.

Where the code lives #

Responsibility Application code Native boundary
Routing, sessions, login and update checks http.ts, session.ts, bridge.ts, update-on-visit.ts Worker fetch, socket hooks
Domain receipts and bootstrap health instance-management.ts, server/bridge.ts Parent RPC and waitUntil
Models, credentials, instructions and memory personal-models.ts, model-settings.ts, personal-memory.ts Validated parent callables/RPC
Conversation creation, naming and deletion personal-conversations.ts Parent facet registry and lifecycle
Turn preparation, actions and task submissions conversation-turn.ts, conversation-actions.ts, conversation-tasks.ts Think hooks, actions and submission queue
Research web-search.ts, web-read.ts, browser-read.ts, browser-session.ts AI binding, Think fetch and native CDP
Temporary resources browser-leases.ts, shell-leases.ts, shell-execution.ts Parent leases/alarms and native Sandbox
Tasks and reconciliation task-store.ts, task-execution.ts Native schedules and Think receipts
Model streams and diagnostics model-provider.ts, gateway-model.ts, diagnostic-export.ts AI SDK middleware, stream callbacks and native observers

Paths without a prefix are under worker/. Modules accept small capabilities, not a shared runtime containing every binding. The native parent remains the composition point. Synchronous SQL transactions, validation, projections, model factories and metadata hooks stay synchronous.

Execution and resource ownership #

Application programs return Effects. HTTP, RPC, SDK callbacks and async iterators run them at the native boundary. agent-io.ts supplies a small native RPC adapter, safe tagged failures, and a pre-abort check. Provider adapters retain HTTP failure metadata only long enough to classify it; public errors and observations remain sanitized. Shared server crypto is separate from frontend-safe bridge contracts.

Cancellation does not imply that a native RPC stopped. Conversation deletion gates access before asynchronous cleanup. Browser creation and shell launch continuations remain owned by the surviving parent, with durable leases and native alarms as the restart fallback. A late shell launch still requires another destroy after an earlier close. Pending teardown continues to occupy capacity.

WebDeadline is now an Effect adapter around one absolute browser lifetime. Its native signal and timer also govern detached acquisition; interrupting only the waiting fiber would lose that guarantee. CDP connections and remote sessions have scoped finalizers. Cleanup uses its own budget. HTTP reader cancellation is bounded and releases its lock even when cancellation never resolves.

Shell output is an Effect Stream exposed through the AI SDK's async-iterator contract. Its scope lasts through consumption, closes on early iterator return, and finishes cleanup before emitting the final result. The native Sandbox SSE parser, incremental output, UTF-8 byte limit, and parent-owned late launch remain intact. Model streams retain their native backpressure and reasoning metadata.

Native Agents still own retries and durable scheduling. Reconciliation reuses the same task/submission identity and rechecks authorization after asynchronous work. Repair batches retain their row limit and now enforce their time budget even when a native observation stalls. There is no additional blanket Effect retry layer.

The remaining async methods are native protocol adapters or synchronous native hooks whose Promise signatures support SDK/fixture overrides. Remaining Promises coordinate parent-owned in-flight cleanup, adapt SDK/native results, or carry work to waitUntil; none is persisted. Ephemeral fibers and scopes are rebuilt after activation.

Validation #

The migration includes focused type contracts and behavioral tests in tests/customer-runtime-effect.*. They cover pre-abort without a request, native body cancellation, stalled finalizers, safe provider failures, native SSE cleanup, early iterator return, late reservation, and bounded UTF-8 output. Existing native fixtures exercise version checks, deletion, replay, background work and restart.

Local validation completed against the migrated application:

Check Result
Application and Worker typechecks; customer release build Passed
Focused customer Effect behavior 8 passed
Native runtime, conversations, memory, tools, diagnostics and tasks 29 passed
Unattended execution, races and restart recovery 17 passed
Packaged chat, settings, domain, tasks and update UI 30 passed
Model provider protocol and stream behavior 18 passed
Publisher OAuth and bundle separation 4 passed
Catalog, deployment, gateway, installation UI and native orchestration 46 passed
Pre-migration artifact upgrade Passed

Control-plane Effect, signed bridge, domain, ownership, update and permission manifest regressions also pass. The OAuth fixture closes its HTTP connections because it restarts different Workers behind the same origin; pooled connections could otherwise target the stopped process.

The upgrade gate can compile its first artifact from a separate source checkout:

FLAREBOT_UPGRADE_BASELINE=/path/to/baseline pnpm test:upgrade-state

The checkout needs the pinned dependencies and generated SSR bundle. The gate compiles both immutable artifacts, replaces the Worker against the same native storage, checks login, SQLite, facets, encrypted credentials and scheduled execution, and verifies that the recorded artifact bytes have not changed. This migration was checked from 945d0cd to the candidate, not just with two builds of new code.

Build measurements on the same ARM workstation:

Dry-run customer upload Before After
Raw 11,442.89 KiB 11,646.76 KiB
Gzip 2,263.87 KiB 2,306.08 KiB

The gzip increase is about 42 KiB (1.9%). Wrangler dry-run did not report a startup CPU measurement. These are local build measurements, not production latency data.

Three alternating fresh Miniflare instances per artifact measured the first authenticated parent status request after Worker readiness, then the first conversation-facet creation over the native socket. Median parent readiness was 12.5 ms before and 13.0 ms after; median facet creation was 7.4 ms before and 7.2 ms after. This small local sample checks for an obvious regression and does not measure deployment startup CPU or production cold starts.

Native browser race cases pass, including late creation/connection, registration failure, cancellation and cleanup. Full rendered-browser testing is currently limited by Miniflare downloading an x86 Chrome binary on this ARM host; the FEX launcher fails. The native shell suite reaches the local Podman socket, but its network sidecar cannot start because crun rejects the requested memory-swappiness setting under cgroup v2. The two-site bridge suite reaches bootstrap health and then encounters the same container limitation. The connected golden-path suite was not run because it requires those native services. These are not passing end-to-end container/browser checks. Paid live search was skipped as opt-in.