/** * Implicit HTTP steps (P6.1) — the undici dispatcher interceptor. * * This is the sanctioned extension point behind global `fetch` (Design Law * 10): we compose an interceptor onto the existing global dispatcher rather * than reassigning `globalThis.fetch`, so we stack cleanly with OTel * auto-instrumentation and anything else that also composes. * * Scope is decided by the AsyncLocalStorage in `runtime-context.ts`: * * - No active workflow host (a plain script, or a fetch inside an activity * body) → we call downstream `dispatch` untouched: byte-identical * pass-through, no observable interceptor effect (Design Law 10, the * pass-through litmus test). * * - Active host, implicit steps enabled → this is a durable step: * * re-run (checkpoint exists) → synthesize a Response from the recorded * status/headers/body WITHOUT touching the network, adding an * `x-memoflow-replayed: 1` header — or, for a recorded FAILURE (F4), * rethrow the same error without re-issuing the request. * * first encounter → drive the real request to completion, buffer the * response, record it DURABLY, then serve the Response FROM the * recorded bytes so replay and first-run are byte-identical. The * record is durable BEFORE the Response is delivered on every tier * (Design Law 2, per step): LITE awaits the engine's SQLite commit; the * SERVER tier awaits the DurableAck of a mid-slice RecordEffects * session frame (P9.3 eager flush). A flush rejection — a stale task * token after a reap, a dead session — rejects the fetch loudly. * * Installed once per process (idempotent). The `x-memoflow-raw` escape hatch * (set by `ctx.raw.fetch`) forces pass-through for a single call. * * VERSION ENTANGLEMENT (N1) — the contract this file depends on, written * down: global `fetch` is served by NODE'S BUNDLED undici, while this SDK * imports npm `undici` (^7). They meet through undici's versioned global * dispatcher bridge: current undici owns the `.2` dispatcher slot and mirrors * `.1` through Dispatcher1Wrapper for Node's built-in fetch. Consequences: * - The collector and replay plumbing implement both the modern * onRequestStart/onResponse* handler contract and the legacy * onConnect/onHeaders/onData/onComplete contract used through that bridge. * - A future Node or undici release that changes the dispatcher bridge or * handler API could silently disconnect us from global fetch. * - Therefore Worker/WorkerLite startup runs `probeHttpInterception()` — * an end-to-end loopback fetch through a synthetic scope — and REFUSES * to start if the interceptor wasn't hit (never silently-non-durable * implicit steps). CI runs the suite on Node 22 and 24 (different * bundled undici majors); published packages declare engines >=22. * - App code must never `setGlobalDispatcher(new Agent())` after a worker * started — compose onto the existing dispatcher instead. The probe * catches the clobber at the NEXT worker start; mid-flight clobbers are * outside what a probe can see. */ /** * Install the interceptor onto the global dispatcher (idempotent). Called * lazily the first time a Worker/WorkerLite runs a workflow — never on import, * so merely importing the SDK has zero effect on `fetch` (Design Law 10). */ export declare function ensureHttpInterceptorInstalled(): void; /** * N1: interception is version-entangled by construction. The SDK imports npm * `undici` and composes onto its versioned global-dispatcher bridge, which * also serves Node's bundled undici behind global `fetch`. That contract is * version-entangled: a Node or undici release that changes the bridge, an * incompatible handler API, or app code that later replaces the global * dispatcher would all make bare `fetch` SILENTLY skip recording — implicit * steps would look durable and be nothing. This error is that failure mode * made loud, at worker startup, before any workflow runs. */ export declare class InterceptionProbeFailedError extends Error { constructor(detail: string); } /** * N1 startup self-probe: prove END-TO-END that a bare `fetch` inside a * workflow scope actually reaches this interceptor and records its effect, * on THIS runtime, before the worker accepts any task. One loopback request * against an ephemeral server, driven through a synthetic ImplicitStepHost — * if the interceptor never sees it (version entanglement, a replaced global * dispatcher), throws InterceptionProbeFailedError instead of letting * implicit steps silently lose durability. */ export declare function probeHttpInterception(): Promise; export { RAW_FETCH_HEADER } from './http-interceptor-io.js'; export { reconstructResponse } from './http-effect.js';