@bitfab/sdk 0.44.0 → 0.44.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/node.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/asyncStorage.ts","../src/version.generated.ts","../src/constants.ts","../src/readEnv.ts","../src/compress.ts","../src/errors.ts","../src/replayContext.ts","../src/payloadBudget.ts","../src/warnOnce.ts","../src/serializePayload.ts","../src/transportTypes.ts","../src/unrefTimer.ts","../src/otel.ts","../src/transport.ts","../src/http.ts","../src/serialize.ts","../src/randomUuid.ts","../src/mockOverride.ts","../src/codeChange.ts","../src/replay.ts","../src/node.ts","../src/asyncStorageNode.ts","../src/claudeAgentSdk.ts","../src/processorPayload.ts","../src/timestamp.ts","../src/client.ts","../src/autoTrace.ts","../src/optionalPeer.ts","../src/baml.ts","../src/captureSurface.ts","../src/datasets.ts","../src/dbSnapshot.ts","../src/langgraph.ts","../src/langgraphIntegration.ts","../src/openaiAgentSdk.ts","../src/replayBranch.ts","../src/seedContext.ts","../src/tracing.ts","../src/vercelAiSdk.ts","../src/index.ts","../src/finalizers.ts","../src/replayRegistry.ts"],"sourcesContent":["/**\n * Shared AsyncLocalStorage loader.\n *\n * Provides two ways to initialize AsyncLocalStorage:\n *\n * 1. **Synchronous registration** (preferred for Node.js):\n * `asyncStorageNode.ts` calls `registerAsyncLocalStorageClass()` at module\n * evaluation time, so the class is available immediately - no async gap.\n * The `node.ts` entry point imports it before anything else.\n *\n * 2. **Async dynamic import** (fallback for the default entry point):\n * Loads `node:async_hooks` via a bundler-safe dynamic import. This is used\n * by the default `index.ts` entry point so the SDK works in browsers\n * (where the import silently fails) and in Node.js when imported via the\n * default entry point.\n *\n * ## Why the dynamic import looks like this\n *\n * We need to handle three environments:\n *\n * 1. **Pure Node.js** - `import(\"node:async_hooks\")` works natively.\n * 2. **Webpack/Turbopack (Next.js server)** - The bundler processes\n * `import()` calls at build time. The `webpackIgnore` magic comment tells\n * webpack (and turbopack) to emit a native `import()` call instead of\n * trying to resolve it, so Node.js handles it at runtime.\n * 3. **Browsers / Edge** - The `process.versions?.node` guard prevents\n * execution entirely. If it somehow runs, `.catch(() => {})` swallows\n * the failure.\n */\n\nexport interface AsyncLocalStorageLike<T> {\n getStore(): T | undefined\n run<R>(store: T, fn: () => R): R\n}\n\nlet AsyncLocalStorageClass: (new () => AsyncLocalStorageLike<unknown>) | null =\n null\nlet initDone = false\n\n/**\n * Register the AsyncLocalStorage class synchronously.\n *\n * Called by `asyncStorageNode.ts` at module evaluation time so the class\n * is available before any span is created - no async gap, no race condition.\n *\n * Safe to call multiple times; subsequent calls are no-ops.\n */\nexport function registerAsyncLocalStorageClass(\n cls: new () => AsyncLocalStorageLike<unknown>,\n): void {\n if (!AsyncLocalStorageClass) {\n AsyncLocalStorageClass = cls\n }\n initDone = true\n}\n\n/**\n * Assert that AsyncLocalStorage was registered successfully.\n *\n * Called by `node.ts` after importing `asyncStorageNode.ts` to catch\n * import-order bugs at startup rather than silently degrading to the\n * browser fallback (flat spans with no nesting).\n *\n * This should ONLY be called from the Node.js entry point where we\n * know `node:async_hooks` must be available.\n */\nexport function assertAsyncStorageRegistered(): void {\n if (!AsyncLocalStorageClass) {\n console.warn(\n \"Bitfab: AsyncLocalStorage not available - nested span context will not propagate.\",\n )\n }\n}\n\nexport const asyncStorageReady: Promise<void> = (\n typeof process !== \"undefined\" && process.versions?.node\n ? // The join trick hides \"node:async_hooks\" from static analysis so\n // bundlers that ban Node.js built-ins don't fail at build time.\n // webpackIgnore tells webpack/turbopack to emit a native import()\n // so Node.js can resolve the module at runtime.\n import(\n /* webpackIgnore: true */\n [\"node\", \"async_hooks\"].join(\":\")\n )\n .then(\n (mod: {\n AsyncLocalStorage: new () => AsyncLocalStorageLike<unknown>\n }) => {\n registerAsyncLocalStorageClass(mod.AsyncLocalStorage)\n },\n )\n .catch(() => {})\n : Promise.resolve()\n).then(() => {\n initDone = true\n})\n\nexport function isAsyncStorageInitDone(): boolean {\n return initDone\n}\n\nexport function createAsyncLocalStorage<T>(): AsyncLocalStorageLike<T> | null {\n return AsyncLocalStorageClass\n ? (new AsyncLocalStorageClass() as AsyncLocalStorageLike<T>)\n : null\n}\n","/**\n * Auto-generated package metadata.\n * This file is generated by scripts/generate-version.ts during build.\n * DO NOT EDIT MANUALLY.\n */\n\n/**\n * SDK version from package.json (injected at build time)\n */\nexport const __version__ = \"0.44.0\"\n\n/**\n * Published npm package name from package.json (injected at build time)\n */\nexport const __packageName__ = \"@bitfab/sdk\"\n","/**\n * Constants for the Bitfab SDK.\n */\n\n/**\n * Default service URL for Bitfab API.\n */\nexport const DEFAULT_SERVICE_URL = \"https://bitfab.ai\"\n\n/**\n * SDK version from package.json (injected at build time)\n *\n * The version is generated at build time by scripts/generate-version.ts\n * to ensure compatibility with both Node.js and browser environments.\n */\nexport { __packageName__, __version__ } from \"./version.generated.js\"\n","/**\n * Read an environment variable without throwing in non-Node runtimes\n * (browsers, edge workers) where `process` is absent. The SDK ships to\n * browsers, so this must never assume `process` exists.\n */\nexport function readEnv(name: string): string | undefined {\n if (typeof process !== \"undefined\" && process.env) {\n return process.env[name]\n }\n return undefined\n}\n","import { readEnv } from \"./readEnv.js\"\n\nconst DISABLE_COMPRESSION_ENV = \"BITFAB_DISABLE_COMPRESSION\"\n\n/**\n * Below this, compressing costs more than the saved bytes are worth, so small\n * requests (function lookups, replay status polls, single-span batches) ride\n * uncompressed.\n */\nconst MIN_COMPRESSED_BYTES = 8_192\n\nexport interface EncodedRequestBody {\n body: string | ArrayBuffer\n contentEncoding?: \"gzip\"\n rawBytes: number\n wireBytes: number\n}\n\n/**\n * Node's gzip, loaded dynamically so browser bundlers never have to resolve\n * `node:zlib`. Deliberately the async form: it runs on libuv's threadpool\n * rather than the event loop. Measured on 8 concurrent 1 MB bodies, the\n * synchronous form stalled the loop for 326ms and the async form for 1ms,\n * while also finishing 3.8x sooner because the threadpool compresses in\n * parallel. A tracing SDK must not block its host's event loop.\n */\nlet gzipNode: ((data: Uint8Array) => Promise<Uint8Array>) | undefined\n\ntype NodeZlib = {\n gzip: (\n data: Uint8Array,\n callback: (error: Error | null, result: Uint8Array) => void,\n ) => void\n}\n\nexport const _nodeGzipReady: Promise<void> = (\n typeof process !== \"undefined\" && process.versions?.node\n ? // The join trick hides \"node:zlib\" from static analysis so bundlers that\n // ban Node.js built-ins don't fail at build time. webpackIgnore tells\n // webpack/turbopack to emit a native import() so Node.js can resolve the\n // module at runtime. Same pattern as `asyncStorage.ts`.\n import(\n /* webpackIgnore: true */\n [\"node\", \"zlib\"].join(\":\")\n )\n .then(({ gzip }: NodeZlib) => {\n gzipNode = (data) =>\n new Promise((resolve, reject) => {\n gzip(data, (error, result) => {\n if (error) {\n reject(error)\n } else {\n resolve(result)\n }\n })\n })\n })\n .catch(() => {})\n : Promise.resolve()\n).then(() => {})\n\n/** Test seam for exercising the browser path on Node. */\nexport function _setNodeGzip(\n impl: ((data: Uint8Array) => Promise<Uint8Array>) | undefined,\n): void {\n gzipNode = impl\n}\n\nfunction toArrayBuffer(view: Uint8Array): ArrayBuffer {\n return view.buffer.slice(\n view.byteOffset,\n view.byteOffset + view.byteLength,\n ) as ArrayBuffer\n}\n\nfunction compressedRequest(\n body: string,\n rawBytes: number,\n compressed: Uint8Array | ArrayBuffer,\n): EncodedRequestBody {\n if (compressed.byteLength >= rawBytes) {\n return { body, rawBytes, wireBytes: rawBytes }\n }\n return {\n body:\n compressed instanceof Uint8Array ? toArrayBuffer(compressed) : compressed,\n contentEncoding: \"gzip\",\n rawBytes,\n wireBytes: compressed.byteLength,\n }\n}\n\nasync function gzipViaStream(bytes: Uint8Array): Promise<ArrayBuffer> {\n const stream = new Blob([bytes as BlobPart])\n .stream()\n .pipeThrough(new CompressionStream(\"gzip\"))\n return await new Response(stream).arrayBuffer()\n}\n\n/**\n * Compression is best-effort: any failure sends the original body rather than\n * dropping the span. `CompressionStream` is absent on older browsers, so its\n * presence is checked rather than assumed.\n *\n * Returns a plain value (not a promise) whenever it can, so a request still\n * reaches `fetch` in the caller's tick rather than one microtask later. Callers\n * await the union.\n */\nexport function encodeRequestBody(\n body: string,\n): EncodedRequestBody | Promise<EncodedRequestBody> {\n if (readEnv(DISABLE_COMPRESSION_ENV)) {\n const rawBytes = new TextEncoder().encode(body).byteLength\n return { body, rawBytes, wireBytes: rawBytes }\n }\n const bytes = new TextEncoder().encode(body)\n if (bytes.byteLength < MIN_COMPRESSED_BYTES) {\n return {\n body,\n rawBytes: bytes.byteLength,\n wireBytes: bytes.byteLength,\n }\n }\n if (gzipNode) {\n return gzipNode(bytes).then(\n (compressed) => compressedRequest(body, bytes.byteLength, compressed),\n () => ({\n body,\n rawBytes: bytes.byteLength,\n wireBytes: bytes.byteLength,\n }),\n )\n }\n if (typeof CompressionStream === \"undefined\") {\n return {\n body,\n rawBytes: bytes.byteLength,\n wireBytes: bytes.byteLength,\n }\n }\n return gzipViaStream(bytes).then(\n (compressed) => compressedRequest(body, bytes.byteLength, compressed),\n () => ({\n body,\n rawBytes: bytes.byteLength,\n wireBytes: bytes.byteLength,\n }),\n )\n}\n","/**\n * Shared error type for Bitfab SDK runtime errors. Lives in its own\n * module to avoid import cycles between `http.ts` and modules that need\n * to throw structured errors (e.g. `dbSnapshot.ts` validation).\n */\n\nexport class BitfabError extends Error {\n constructor(\n message: string,\n public readonly url?: string,\n /**\n * HTTP status the request failed with, when it failed with one. The\n * transport's retry policy needs the code itself (retry 408/425/429/5xx,\n * never a 4xx the server will reject again), which a formatted message\n * cannot supply. Absent for network failures and non-HTTP errors.\n */\n public readonly status?: number,\n /**\n * `Retry-After` in milliseconds, when the server sent one. A 429 or 503\n * carries the server's own instruction about when to come back; retrying\n * on our own schedule ignores it and keeps the pressure on.\n */\n public readonly retryAfterMs?: number,\n ) {\n super(message)\n this.name = \"BitfabError\"\n }\n}\n\nexport class MixedTracingError extends Error {\n constructor(message: string) {\n super(message)\n this.name = \"MixedTracingError\"\n }\n}\n","/**\n * Replay context propagation via AsyncLocalStorage.\n *\n * When set, the withSpan wrapper injects testRunId into the span payload\n * so that new spans created during replay are linked to the test run.\n * Optionally carries a mock tree so child spans can return historical\n * outputs instead of executing.\n */\n\nimport {\n type AsyncLocalStorageLike,\n asyncStorageReady,\n createAsyncLocalStorage,\n} from \"./asyncStorage.js\"\nimport type { MockOverride } from \"./mockOverride.js\"\n\n/**\n * A single span entry in the mock tree.\n *\n * Under the eager path (`mock: \"all\"`) `output`/`outputMeta` are populated\n * inline, even when overrides are present. Under a non-`all` path that needs a\n * tree (`marked`, or `none` with overrides), they are absent and the recorded\n * output is fetched on demand via `externalSpanId` - see\n * {@link ReplayContext.fetchSpanOutput}.\n */\nexport interface MockSpan {\n sourceSpanId: string\n /** Row id accepted by `getExternalSpan`, for the lazy per-span output fetch. */\n externalSpanId?: string\n output?: unknown\n outputMeta?: unknown\n}\n\n/**\n * Per-item DB branch resolved by the Bitfab service from the source\n * trace's `dbSnapshotRef`. Carried on the replay context so that\n * customer code reads `databaseUrl` through `getCurrentReplayBranch()`, and so\n * the process-isolated replay runner can materialize it into a `.env`\n * overlay file before customer code initializes its DB client.\n *\n * `neonBranchId` is the literal Neon branch id; passing it to\n * `releaseDbBranchLease` deletes that branch.\n */\nexport interface DbBranchLease {\n neonBranchId: string\n /** Env var name the customer's app reads, e.g. \"DATABASE_URL\". */\n envKey: string\n databaseUrl: string\n expiresAt: string\n /**\n * The instant the branch was pinned to (the source trace's wall clock).\n * Echoed back in `db_snapshot_usage` on the replayed trace's completion.\n */\n snapshotTimestamp?: string\n providerConsoleUrl?: string\n readOnly?: boolean\n /**\n * The branch's region, e.g. `aws-us-east-1`. A compute runs in its project's\n * region, so a runner elsewhere pays that round trip on every query.\n */\n region?: string\n}\n\n/**\n * How long each phase of provisioning one replay branch took, measured\n * server-side. A runner in another region sees these plus its own round trip.\n *\n * Durations, not instants: an instant is approximately `startedAt` plus the\n * running sum, and per-phase wall-clock stamps would make clock skew between\n * the server and your runner look like latency. Approximately, because\n * `totalMs` is the resolve's true wall time and covers a little work no phase\n * owns, so the phases account for it without summing to it exactly.\n *\n * `startedAt` and `totalMs` are always present. The phases are optional\n * because a failed resolve reports only the ones it reached, and `totalMs` is\n * then time-to-failure. On success every phase is present except `warmupMs`,\n * which is absent when no warm-up SQL was supplied.\n */\nexport interface DbBranchTimings {\n /** When the resolve began, ISO. */\n startedAt: string\n /** Resolving the project, plus its retention and region reads. */\n projectResolveMs?: number\n /** Creating the branch, through its provider operations reaching terminal. */\n branchCreateMs?: number\n /** Resolving the connection URI. 0 when the provider returns one inline. */\n connectionUriMs?: number\n /** The compute accepting a connection. */\n computeConnectMs?: number\n /** The branch answering a readiness query. */\n baseProbeMs?: number\n /** Your warm-up SQL. Absent when you supplied none. */\n warmupMs?: number\n /** The whole resolve, or time-to-failure when it threw. */\n totalMs: number\n}\n\n/**\n * Wire shape of the caller's `ReplayOptions.dbBranch`, sent to\n * `/api/sdk/replay/start` and applied per lease.\n */\nexport interface DbBranchSettings {\n minCu?: number\n maxCu?: number\n warmupSql?: string\n}\n\n/**\n * Pre-built lookup table of historical span outputs.\n * Keys are `${traceFunctionKey}:${spanName}:${callIndex}` so that repeated\n * calls with the same (key, name) are matched by call order, but spans\n * sharing only the traceFunctionKey (different name) do not collide.\n */\nexport interface MockTree {\n spans: Map<string, MockSpan>\n}\n\nexport interface ReplayContext {\n testRunId: string\n traceId?: string\n inputSourceSpanId?: string\n /**\n * External trace ID from `external_traces.id`. Used for span-chain\n * lookup against the source platform's trace tree (Braintrust, etc.).\n * NOT the same as the Bitfab `traceId` - see `sourceBitfabTraceId`.\n */\n inputSourceTraceId?: string\n /**\n * The Bitfab `traces.id` of the historical trace that produced this\n * replay item's input. This is what customer-facing surfaces (e.g.\n * `ReplayBranch.traceId`) should expose, since it's the ID the\n * customer sees in the Bitfab dashboard.\n */\n sourceBitfabTraceId?: string\n replayAttempt?: number\n mockTree?: MockTree\n callCounters?: Map<string, number>\n mockStrategy?: \"none\" | \"all\" | \"marked\"\n /**\n * Resolved override chain for this replay, per-call overrides first then\n * registered ones (first matcher wins). Empty/absent when no overrides apply.\n */\n mockOverrides?: MockOverride[]\n /**\n * Memoized lazy fetch of a span's recorded output (deserialized), keyed by\n * `externalSpanId`. Present ONLY on a non-`all` path that needs a tree\n * (`marked`, or `none` with overrides); absent under `mock: \"all\"`, where\n * outputs are inline even when overrides are present. Its presence is the\n * signal that outputs must be fetched rather than read inline.\n */\n fetchSpanOutput?: (externalSpanId: string) => Promise<unknown>\n dbBranchLease?: DbBranchLease\n /**\n * Server-measured provisioning timings for this item's branch, echoed back\n * on the trace completion so the trace records what it cost to set up. Kept\n * off `ReplayBranch`: customer code reads that mid-replay to reach the\n * branch, and provisioning latency is a property of the run, not of the\n * connection.\n */\n dbBranchTimings?: DbBranchTimings\n /**\n * Set to true by `ReplayBranch` the first time customer code actually\n * obtains `databaseUrl` for this item. Reported on the trace completion inside\n * `db_snapshot_usage` so the server can distinguish \"branch was\n * provisioned and exposed\" from \"branch URL was actually consumed\".\n * Only an explicit `databaseUrl` read may set it. A path that hands the URL\n * over by other means (e.g. a process-isolated runner writing an env\n * overlay) must leave it alone: setting it there would make every such\n * replay report `accessed` for free, and the flag would stop separating\n * \"branch was used\" from \"branch was offered\".\n */\n dbSnapshotAccessed?: boolean\n}\n\nlet replayContextStorage: AsyncLocalStorageLike<ReplayContext | null> | null =\n null\nconst REPLAY_CONTEXT_STORAGE_SYMBOL = Symbol.for(\"bitfab.replayContextStorage\")\n\nexport const replayContextReady: Promise<void> = asyncStorageReady.then(() => {\n const shared = globalThis as typeof globalThis & Record<symbol, unknown>\n const existing = shared[REPLAY_CONTEXT_STORAGE_SYMBOL] as\n | AsyncLocalStorageLike<ReplayContext | null>\n | undefined\n if (existing) {\n replayContextStorage = existing\n return\n }\n const created = createAsyncLocalStorage<ReplayContext | null>()\n if (created) {\n shared[REPLAY_CONTEXT_STORAGE_SYMBOL] = created\n replayContextStorage = created\n }\n})\n\n/** Get the current replay context, if any. */\nexport function getReplayContext(): ReplayContext | null {\n return replayContextStorage?.getStore() ?? null\n}\n\n/** Run a function within a replay context. */\nexport function runWithReplayContext<T>(ctx: ReplayContext, fn: () => T): T {\n if (replayContextStorage) {\n return replayContextStorage.run(ctx, fn)\n }\n return fn()\n}\n","/**\n * The ceiling on a span's encoded carrier, and the trimming that enforces it.\n *\n * A span's whole payload (input, output, contexts, prompt, metadata) ships as\n * a single `bitfab.payload` string attribute, and the exporter drops any\n * carrier that exceeds the per-request byte ceiling outright rather than\n * trimming it. Capping each value on its own cannot prevent that: two values\n * that each fit can still add up to an undeliverable span. So the budget is\n * enforced on the whole span, and an oversized one ships with its largest\n * fields stubbed instead of vanishing.\n *\n * The budget is measured on the *carrier* (the payload re-escaped into the\n * OTLP attribute), not on the payload body, because the carrier is what the\n * exporter weighs. Bounding the body instead leaves escape-heavy content to\n * blow the request ceiling anyway: a body of escaped JSON, Windows paths, or\n * regexes is nearly all backslashes, and every one of them doubles. Measured\n * on a body sized exactly to a 2.4 MB cap, prose produced a 2.4 MB carrier but\n * backslash-dense content produced 4.8 MB, which the exporter dropped.\n *\n * The normal 2.8 MB fallback leaves room beneath the 3 MB wire target. Trace\n * transport may first preserve a carrier up to 7.8 MB when its single-span\n * request compresses below that wire target and remains below ingress's 8 MB\n * decompressed ceiling.\n */\nexport const MAX_SPAN_CARRIER_BYTES = 2_800_000\n\n/**\n * A larger carrier may still fit when its single-span request is compressed.\n * This leaves 200 kB beneath ingress's 8 MB decompressed-body ceiling for the\n * OTLP span and request envelopes.\n */\nexport const MAX_COMPRESSIBLE_SPAN_CARRIER_BYTES = 7_800_000\n\nconst textEncoder =\n typeof TextEncoder !== \"undefined\" ? new TextEncoder() : null\n\nexport function byteLength(value: string): number {\n return textEncoder ? textEncoder.encode(value).length : value.length\n}\n\n/**\n * The byte length `body` occupies once re-escaped as a JSON string value.\n *\n * `body` is itself JSON text, so the first encode already replaced every\n * control character with a `\\uXXXX` sequence, leaving only `\"` and `\\` to\n * escape at one extra byte each.\n *\n * Counts UTF-8 width and escapes in the same pass and allocates nothing.\n * `TextEncoder.encode().length` would be the obvious way to get the byte count,\n * but it copies the entire body into a fresh array just to read its length,\n * which on a multi-megabyte span costs more than producing the body did.\n */\nexport function carrierByteLength(body: string): number {\n return carrierBytesOf(textEncoder ? textEncoder.encode(body) : null, body)\n}\n\n/**\n * Counts escapes over the UTF-8 bytes rather than the UTF-16 string. Bytes\n * `0x22` and `0x5c` are unambiguous there (a multi-byte sequence never uses a\n * byte below `0x80`), so a flat byte scan is exact, and it reuses the array the\n * byte count already had to produce instead of walking the string a second\n * time. Measured ~2x faster than the equivalent `charCodeAt` loop.\n */\nfunction carrierBytesOf(encoded: Uint8Array | null, body: string): number {\n if (!encoded) {\n // No TextEncoder (a browser old enough to lack it). Fall back to the string,\n // where `length` is the best available byte estimate.\n return body.length + 2\n }\n let extra = 2 // the quotes wrapping the attribute value\n for (let i = 0; i < encoded.length; i++) {\n const byte = encoded[i]\n if (byte === 34 || byte === 92) {\n extra += 1 // `\"` and `\\` take a leading backslash\n } else if (byte < 0x20) {\n extra +=\n byte === 8 || byte === 9 || byte === 10 || byte === 12 || byte === 13\n ? 1 // \\b \\f \\n \\r \\t\n : 5 // \\uXXXX\n }\n }\n return encoded.length + extra\n}\n\n/**\n * The most carrier bytes one UTF-16 code unit of a *JSON body* can become.\n *\n * A unit is at most 3 UTF-8 bytes, and the only characters that grow under\n * escaping are `\"` and `\\`, which are one byte and become two. A unit cannot be\n * both, so 3 is the ceiling. This holds because every caller passes the output\n * of a JSON encoder, which by specification never emits a raw control character\n * (the case that would otherwise expand to a 6-byte `\\uXXXX`); the invariant is\n * pinned by a test so a future caller that broke it would fail loudly rather\n * than silently ship an oversized carrier.\n */\nconst MAX_BYTES_PER_UNIT = 3\n\n/**\n * Whether `body` fits the carrier budget, escalating only as far as it must.\n *\n * `body.length` is O(1) and brackets the answer for both ordinary spans (far\n * under the budget) and hopeless ones (already past it on raw length alone),\n * which is every span in normal traffic: neither case touches the string. Only\n * a body near the budget is measured exactly, and that costs one encode plus\n * one byte scan.\n */\nexport function fitsCarrierBudget(\n body: string,\n maxBytes: number = MAX_SPAN_CARRIER_BYTES,\n): boolean {\n const units = body.length\n if (units * MAX_BYTES_PER_UNIT + 2 <= maxBytes) {\n return true\n }\n if (units + 2 > maxBytes) {\n return false\n }\n return carrierByteLength(body) <= maxBytes\n}\n\n/**\n * Span fields that identify the span rather than carry user data. Trimming one\n * would leave a span that no longer says what it is, so they stay whatever the\n * payload costs.\n */\nconst STRUCTURAL_SPAN_KEYS = new Set([\n \"name\",\n \"type\",\n \"function_name\",\n \"error_source\",\n])\n\nfunction asRecord(value: unknown): Record<string, unknown> | undefined {\n return typeof value === \"object\" && value !== null && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : undefined\n}\n\ninterface Candidate {\n container: Record<string, unknown>\n key: string\n size: number\n}\n\n/**\n * The records holding user data, cloned so trimming never mutates the caller's\n * objects. Returns the payload copy to encode plus the containers to trim.\n */\nfunction cloneTrimmable(payload: Record<string, unknown>): {\n copy: Record<string, unknown>\n containers: Record<string, unknown>[]\n} {\n const copy = { ...payload }\n const containers: Record<string, unknown>[] = []\n\n const spanData = asRecord(copy.span_data)\n if (spanData) {\n const clone = { ...spanData }\n copy.span_data = clone\n containers.push(clone)\n }\n\n const rawSpan = asRecord(copy.rawSpan)\n const rawSpanData = rawSpan && asRecord(rawSpan.span_data)\n if (rawSpan && rawSpanData) {\n const clone = { ...rawSpanData }\n copy.rawSpan = { ...rawSpan, span_data: clone }\n containers.push(clone)\n }\n\n // No span_data anywhere: a trace-level or otherwise unfamiliar payload. Trim\n // its own fields rather than give up, so an oversized body still ships.\n if (containers.length === 0) {\n containers.push(copy)\n }\n\n return { copy, containers }\n}\n\nfunction collectCandidates(containers: Record<string, unknown>[]): Candidate[] {\n const candidates: Candidate[] = []\n for (const container of containers) {\n for (const [key, value] of Object.entries(container)) {\n if (STRUCTURAL_SPAN_KEYS.has(key) || value == null) {\n continue\n }\n let size: number\n try {\n size = byteLength(JSON.stringify(value) ?? \"\")\n } catch {\n continue\n }\n candidates.push({ container, key, size })\n }\n }\n return candidates.sort((a, b) => b.size - a.size)\n}\n\n/**\n * Stub the largest payload fields until the encoded body fits the budget.\n *\n * Returns the trimmed payload and the names of the fields that were stubbed, or\n * `undefined` when nothing could be trimmed (the caller then ships the\n * oversized body and lets the exporter report the drop, which is still better\n * than silently emptying a span).\n */\nexport function trimPayloadToBudget(\n payload: Record<string, unknown>,\n encode: (value: Record<string, unknown>) => string,\n maxBytes: number = MAX_SPAN_CARRIER_BYTES,\n): { value: Record<string, unknown>; trimmed: string[] } | undefined {\n const { copy, containers } = cloneTrimmable(payload)\n const candidates = collectCandidates(containers)\n if (candidates.length === 0) {\n return undefined\n }\n\n const trimmed: string[] = []\n for (const candidate of candidates) {\n candidate.container[candidate.key] =\n `<unserializable: too_large_${candidate.size}_bytes>`\n trimmed.push(candidate.key)\n let body: string\n try {\n body = encode(copy)\n } catch {\n return undefined\n }\n if (fitsCarrierBudget(body, maxBytes)) {\n return { value: copy, trimmed }\n }\n }\n return undefined\n}\n\n/**\n * Record a trim in the payload's own `errors`, which is what the server reads\n * to flag a trace as incomplete.\n */\nexport function markPayloadTrimmed(\n value: Record<string, unknown>,\n trimmed: string[],\n maxBytes: number = MAX_SPAN_CARRIER_BYTES,\n): void {\n const existing = Array.isArray(value.errors) ? value.errors : []\n value.errors = [\n ...existing,\n {\n source: \"sdk\",\n step: \"payload_budget\",\n error: `trimmed oversized field(s) to fit the ${maxBytes}-byte span carrier budget: ${[\n ...new Set(trimmed),\n ].join(\", \")}`,\n },\n ]\n}\n","/**\n * Emit a `console.warn` at most once per distinct `key` for the life of the\n * process.\n *\n * The SDK must NEVER crash a host app, so every failure on the user's path\n * degrades silently (a span is dropped, a call runs untraced, a payload is\n * stubbed). Silent is safe but undebuggable: a user who suddenly has no traces,\n * or sees `<unserializable>` in a span, has no signal as to why. A one-time\n * warning per distinct issue restores that signal without spamming the console\n * from a hot path.\n *\n * Keys should identify the specific degradation (e.g. include the traced\n * function key) so each distinct issue warns once, not just the first one seen.\n */\nconst warned = new Set<string>()\n\nexport function warnOnce(key: string, message: string): void {\n if (warned.has(key)) {\n return\n }\n warned.add(key)\n try {\n console.warn(`[bitfab] ${message}`)\n } catch {\n // Logging must never crash the host app (e.g. a closed/replaced console).\n }\n}\n\n/** Test-only: clear the dedup set so a warning can fire again. */\nexport function _resetWarnOnce(): void {\n warned.clear()\n}\n","/**\n * Defensive payload encoding, shared by the HTTP path and the OTel carrier\n * path. Lives in its own module because `otel.ts` needs it and importing it\n * from `http.ts` would close an http -> transport -> otel -> http cycle.\n */\n\nimport {\n fitsCarrierBudget,\n MAX_SPAN_CARRIER_BYTES,\n markPayloadTrimmed,\n trimPayloadToBudget,\n} from \"./payloadBudget.js\"\nimport { warnOnce } from \"./warnOnce.js\"\n\n/**\n * JSON-encode a request body without ever throwing on a stray value, and\n * within the per-span byte budget.\n *\n * Upstream serialization (`serializeValue` / the LangGraph handler's\n * `safeSerialize`) should already have flattened user data. This is the\n * boundary backstop: if anything non-serializable still slips through\n * (BigInt, function, symbol, circular ref), it is stubbed in place instead of\n * letting `JSON.stringify` throw and drop the whole span/trace silently.\n *\n * The fast path is a plain `JSON.stringify`; the sanitizing replacer only runs\n * when that throws, so happy-path payloads (and shared non-circular refs) are\n * untouched. Returns `dropped` (the stubbed type names) so the caller can warn\n * loudly rather than ship a degraded payload in silence.\n */\nexport function serializePayloadBody(payload: Record<string, unknown>): {\n body: string\n dropped: string[]\n}\nexport function serializePayloadBody(\n payload: Record<string, unknown>,\n maxCarrierBytes: number,\n): { body: string; dropped: string[] }\nexport function serializePayloadBody(\n payload: Record<string, unknown>,\n maxCarrierBytes: number = MAX_SPAN_CARRIER_BYTES,\n): { body: string; dropped: string[] } {\n const encoded = encodePayloadBody(payload)\n if (fitsCarrierBudget(encoded.body, maxCarrierBytes)) {\n return { body: encoded.body, dropped: encoded.dropped }\n }\n return applyPayloadBudget(encoded, maxCarrierBytes)\n}\n\n/**\n * Trim an over-budget payload, preferring its largest fields, so the span\n * ships degraded rather than being dropped whole by the exporter.\n *\n * Trims the value that was actually encoded, not the caller's original: a\n * cyclic or otherwise non-encodable field cannot be sized (`JSON.stringify`\n * throws on it), so on the original graph the biggest field is skipped as a\n * trim candidate and the oversized body ships anyway. The sanitized copy has\n * those values already replaced with stubs, so every field is sizeable.\n */\nfunction applyPayloadBudget(\n encoded: EncodedPayload,\n maxCarrierBytes: number,\n): {\n body: string\n dropped: string[]\n} {\n const result = encoded.value\n ? trimPayloadToBudget(\n encoded.value,\n (value) => encodePayloadBody(value).body,\n maxCarrierBytes,\n )\n : undefined\n if (!result) {\n return { body: encoded.body, dropped: encoded.dropped }\n }\n warnOnce(\n \"payload:over-budget\",\n `a span payload exceeded the ${maxCarrierBytes}-byte carrier budget; its largest field(s) (${[\n ...new Set(result.trimmed),\n ].join(\n \", \",\n )}) were replaced with placeholders so the span still ships. The span is incomplete and may not be replayable.`,\n )\n markPayloadTrimmed(result.value, result.trimmed, maxCarrierBytes)\n // `dropped` names values that could not be encoded, which drives the\n // \"non-serializable value(s)\" warning. A budget trim is a size decision, not\n // an encoding failure, and already has its own warning and `payload_budget`\n // error entry, so it must not be reported as one.\n return {\n body: encodePayloadBody(result.value).body,\n dropped: encoded.dropped,\n }\n}\n\ninterface EncodedPayload {\n body: string\n dropped: string[]\n /**\n * The value the body was encoded from: the payload itself, or its sanitized\n * copy. Undefined when the encoded value isn't an object, which leaves\n * nothing with named fields to trim.\n */\n value: Record<string, unknown> | undefined\n}\n\nfunction encodePayloadBody(payload: Record<string, unknown>): EncodedPayload {\n try {\n return { body: JSON.stringify(payload), dropped: [], value: payload }\n } catch {\n const dropped: string[] = []\n // An explicit backtracking walk, not a JSON.stringify replacer: a replacer\n // gets no subtree-exit signal, so a single WeakSet would mis-tag a shared\n // (DAG) reference under sibling keys as a cycle. Tracking only the\n // current-path ancestors stubs real cycles while serializing DAGs in full.\n const sanitize = (value: unknown, seen: WeakSet<object>): unknown => {\n const t = typeof value\n if (\n value === null ||\n t === \"string\" ||\n t === \"number\" ||\n t === \"boolean\"\n ) {\n return value\n }\n if (t === \"bigint\") {\n dropped.push(\"BigInt\")\n return \"<unserializable: BigInt>\"\n }\n if (t === \"function\") {\n const name = (value as { name?: string }).name || \"Function\"\n dropped.push(name)\n return `<unserializable: ${name}>`\n }\n if (t === \"symbol\") {\n dropped.push(\"Symbol\")\n return \"<unserializable: Symbol>\"\n }\n if (t !== \"object\") {\n return undefined // e.g. undefined; JSON omits/normalizes it\n }\n const obj = value as object\n const className =\n (obj as { constructor?: { name?: string } }).constructor?.name ||\n \"object\"\n if (seen.has(obj)) {\n dropped.push(className)\n return `<cycle: ${className}>`\n }\n seen.add(obj)\n let result: unknown\n if (Array.isArray(obj)) {\n result = obj.map((item) => sanitize(item, seen))\n } else if (typeof (obj as { toJSON?: unknown }).toJSON === \"function\") {\n try {\n result = sanitize((obj as { toJSON(): unknown }).toJSON(), seen)\n } catch {\n dropped.push(className)\n result = `<unserializable: ${className}>`\n }\n } else {\n try {\n const out: Record<string, unknown> = {}\n for (const [k, v] of Object.entries(obj)) {\n out[k] = sanitize(v, seen)\n }\n result = out\n } catch {\n // A throwing getter or Proxy on `obj` can make `Object.entries`\n // throw. Stub just this object instead of failing the whole payload\n // (which would drop every span field). Mirrors the toJSON branch.\n warnOnce(\n \"payload:field-getter-threw\",\n \"a value with a throwing getter/proxy could not be serialized into a span payload; it was replaced with a placeholder. The span still ships with its other fields intact.\",\n )\n dropped.push(className)\n result = `<unserializable: ${className}>`\n }\n }\n seen.delete(obj) // backtrack: only ancestors stay tracked\n return result\n }\n let sanitized: unknown\n try {\n sanitized = sanitize(payload, new WeakSet())\n } catch (error) {\n // Truly pathological. Still never drop silently: send a marker body.\n const message = error instanceof Error ? error.message : String(error)\n const marker = { error: `payload_serialize_failed: ${message}` }\n return { body: JSON.stringify(marker), dropped, value: marker }\n }\n // Keep the server-side signal that the SDK had to stub values, so the\n // trace can be flagged as possibly incomplete / not replayable, while the\n // span content (everything that did serialize) is preserved.\n const isRecord =\n typeof sanitized === \"object\" &&\n sanitized !== null &&\n !Array.isArray(sanitized)\n if (dropped.length > 0 && isRecord) {\n const obj = sanitized as Record<string, unknown>\n const existing = Array.isArray(obj.errors) ? obj.errors : []\n obj.errors = [\n ...existing,\n {\n source: \"sdk\",\n step: \"json_serialize\",\n error: `stubbed non-serializable value(s): ${[\n ...new Set(dropped),\n ].join(\", \")}`,\n },\n ]\n }\n return {\n body: JSON.stringify(sanitized),\n dropped,\n value: isRecord ? (sanitized as Record<string, unknown>) : undefined,\n }\n }\n}\n","/**\n * The boundary every instrumentation path crosses to hand a Bitfab payload to\n * the network. Kept in its own module, free of both `http.ts` and `otel.ts`,\n * so the HTTP client can depend on the transport contract without importing\n * the OpenTelemetry implementation (and vice versa).\n */\n\nimport type { EncodedRequestBody } from \"./compress.js\"\n\n/** Which Bitfab payload a carrier span holds. */\nexport type TraceOperation =\n | \"external_span\"\n | \"external_trace\"\n | \"internal_trace\"\n\n/**\n * Posts one fully-encoded request body and resolves once the server has\n * accepted it whole. Supplied by `HttpClient`, which owns the endpoint, the\n * auth, and what the server's answer means: a rejection arrives here as a\n * {@link DeliveryError}, so the transport decides whether to retry without ever\n * reading a response.\n *\n * The request arrives already encoded, carrying its own content encoding and\n * byte counts: the exporter assembles it from per-span encodes it has to\n * produce anyway to size a request, so handing over an object here would make\n * the client encode the same batch a second time.\n */\nexport type DirectBatchSender = (\n request: EncodedRequestBody,\n timeoutMs: number,\n) => Promise<void>\n\n/**\n * Why a delivery failed, in the only two terms the transport acts on. A sender\n * classifies everything it can see, including a network fault carrying no\n * verdict; anything else reaching the transport is a fault in the sender and is\n * not retried.\n */\nexport class DeliveryError extends Error {\n readonly retryable: boolean\n readonly oversized: boolean\n /** How long the server asked us to wait, when it said so. */\n readonly retryAfterMs?: number\n\n constructor(\n message: string,\n options: {\n retryable?: boolean\n oversized?: boolean\n retryAfterMs?: number\n } = {},\n ) {\n super(message)\n this.name = \"DeliveryError\"\n this.retryable = options.retryable ?? false\n this.oversized = options.oversized ?? false\n this.retryAfterMs = options.retryAfterMs\n }\n}\n\n/**\n * Which carrier a payload is, for delivery accounting only. Supplied by the\n * caller that built the payload: the transport never reads inside one.\n *\n * `spanId` is omitted for the carrier that closes a trace, which is what tells\n * the transport the trace's expected set has stopped growing.\n */\nexport interface CarrierRef {\n traceId: string\n spanId?: string\n}\n\n/**\n * Everything the transport needs to know ABOUT a payload without reading one.\n * Supplied by the caller that built it; each field falls back to something the\n * transport can decide without looking inside.\n */\nexport interface CarrierMeta {\n /** Delivery identity. Omitted for carriers nobody accounts for. */\n ref?: CarrierRef\n /** Carrier span name. Defaults to `bitfab.<operation>`. */\n name?: string\n /** Epoch ms. Omitted lets OTel stamp the carrier as it is created. */\n startTime?: number\n endTime?: number\n /** Marks the carrier span errored. */\n errored?: boolean\n}\n\nexport interface TraceTransport {\n /** Queue a payload. Never throws; delivery failures degrade silently. */\n submit(\n operation: TraceOperation,\n payload: Record<string, unknown>,\n meta?: CarrierMeta,\n ): void\n /** Drain the queue within `timeoutMs`. False on export failure or timeout. */\n flush(timeoutMs?: number): Promise<boolean>\n /** Flush, then permanently stop this transport. */\n shutdown(timeoutMs?: number): Promise<boolean>\n}\n","/**\n * Best-effort `unref()` on a timer handle so a pending timeout never keeps the\n * Node.js event loop alive on its own. An un-unref'd timeout would delay\n * process exit, prolong a serverless function's billed lifetime, and hang test\n * runners until it fires.\n *\n * In the browser `setTimeout` returns a number with no `unref`, so this is a\n * no-op there. Callers should still `clearTimeout` the handle once the work it\n * guards has settled.\n */\nexport function unrefTimer(timer: ReturnType<typeof setTimeout>): void {\n const handle = timer as { unref?: () => void }\n if (typeof handle.unref === \"function\") {\n handle.unref()\n }\n}\n","/**\n * OpenTelemetry transport for Bitfab spans and trace completions.\n *\n * OTel is used here as a queueing, batching, and delivery engine only. Bitfab\n * keeps ownership of logical trace identity: every payload travels inside an\n * internal *carrier* span whose `bitfab.payload` attribute holds the encoded\n * Bitfab body, and the server reconstructs the stored tree from that payload\n * rather than from the carrier's OTel topology. The provider and processor are\n * private to each client, so an application's own OTel traces are never mixed\n * into Bitfab traces and the global provider is never replaced.\n */\n\nimport { type Span, SpanStatusCode, type Tracer } from \"@opentelemetry/api\"\nimport {\n type ExportResult,\n ExportResultCode,\n type InstrumentationScope,\n} from \"@opentelemetry/core\"\nimport { resourceFromAttributes } from \"@opentelemetry/resources\"\nimport {\n AlwaysOnSampler,\n BasicTracerProvider,\n BatchSpanProcessor,\n type ReadableSpan,\n type SpanExporter,\n} from \"@opentelemetry/sdk-trace-base\"\nimport { type EncodedRequestBody, encodeRequestBody } from \"./compress.js\"\nimport { __version__ } from \"./constants.js\"\nimport { BitfabError } from \"./errors.js\"\nimport {\n byteLength,\n MAX_COMPRESSIBLE_SPAN_CARRIER_BYTES,\n MAX_SPAN_CARRIER_BYTES,\n} from \"./payloadBudget.js\"\nimport { readEnv } from \"./readEnv.js\"\nimport { serializePayloadBody } from \"./serializePayload.js\"\nimport type {\n CarrierMeta,\n CarrierRef,\n DirectBatchSender,\n TraceOperation,\n TraceTransport,\n} from \"./transportTypes.js\"\nimport { DeliveryError } from \"./transportTypes.js\"\nimport { unrefTimer } from \"./unrefTimer.js\"\nimport { warnOnce } from \"./warnOnce.js\"\n\nconst OPERATION_ATTRIBUTE = \"bitfab.operation\"\nconst PAYLOAD_ATTRIBUTE = \"bitfab.payload\"\nconst MAX_EXPORT_REQUEST_BYTES = 3_000_000\nconst MAX_DECOMPRESSED_REQUEST_BYTES = 8_000_000\nconst MAX_REQUEST_BYTES_ENV = \"BITFAB_OTEL_MAX_REQUEST_BYTES\"\nconst EXPORT_CONCURRENCY_ENV = \"BITFAB_OTEL_EXPORT_CONCURRENCY\"\nconst MAX_QUEUE_SIZE = 8_192\nconst DIRECT_MAX_EXPORT_BATCH_SIZE = 512\nconst DIRECT_MAX_REQUEST_BATCH_SIZE = 128\nconst DEFAULT_EXPORT_CONCURRENCY = 32\nconst MAX_EXPORT_CONCURRENCY = 64\nconst SCHEDULE_DELAY_MILLIS = 5_000\nconst EXPORT_TIMEOUT_MILLIS = 30_000\nconst RETRY_BASE_DELAY_MILLIS = 100\n// Ceiling on the exponential growth of our OWN backoff. It does not bound a\n// wait the server asked for: OTLP says to honor Retry-After, and warns that a\n// delay big enough to make the client drop data is the server's mistake to\n// avoid, not the client's cue to discard. What bounds an honored wait is the\n// export budget below, since a wait outliving the export cannot be served.\nconst RETRY_BACKOFF_CEILING_MILLIS = 5_000\nconst MAX_SEND_ATTEMPTS = 3\nconst DEFAULT_LIFECYCLE_TIMEOUT_MS = 30_000\n\nconst liveTransports = new Set<OtelBatchTransport>()\n\n// Keyed by the carrier span object so a dropped span needs no cleanup. The ref\n// cannot ride on the span as an attribute: `spanLimits` caps carriers at two,\n// and `bitfab.operation` and `bitfab.payload` hold both.\nconst carrierRefs = new WeakMap<object, CarrierRef>()\n\nfunction readBoundedIntEnv(\n name: string,\n max: number,\n fallback: number,\n warnKey: string,\n): number {\n const raw = readEnv(name)\n if (raw === undefined) {\n return fallback\n }\n const value = Number(raw)\n if (Number.isInteger(value) && value > 0 && value <= max) {\n return value\n }\n warnOnce(\n warnKey,\n `${name} must be a positive integer no greater than ${max}; using ${fallback}`,\n )\n return fallback\n}\n\nfunction logError(message: string, error?: unknown): void {\n try {\n if (error === undefined) {\n console.error(`[bitfab] ${message}`)\n } else {\n console.error(`[bitfab] ${message}`, error)\n }\n } catch {\n // Logging must never crash the host app.\n }\n}\n\nfunction otlpValue(value: unknown): Record<string, unknown> {\n if (typeof value === \"boolean\") {\n return { boolValue: value }\n }\n if (typeof value === \"number\") {\n return Number.isInteger(value)\n ? { intValue: String(value) }\n : { doubleValue: value }\n }\n if (typeof value === \"string\") {\n return { stringValue: value }\n }\n if (Array.isArray(value)) {\n return { arrayValue: { values: value.map(otlpValue) } }\n }\n return { stringValue: String(value) }\n}\n\nfunction otlpAttributes(\n attributes: Record<string, unknown> | undefined,\n): Record<string, unknown>[] {\n if (!attributes) {\n return []\n }\n return Object.entries(attributes)\n .filter(([, value]) => value !== undefined)\n .map(([key, value]) => ({ key, value: otlpValue(value) }))\n}\n\n/**\n * Nanoseconds since the epoch as a decimal string. Built by concatenation\n * rather than arithmetic because the value exceeds `Number.MAX_SAFE_INTEGER`,\n * so multiplying seconds out would silently lose the low digits.\n */\nfunction hrTimeToNanoString(time: [number, number] | undefined): string {\n if (!time) {\n return \"0\"\n }\n return `${time[0]}${String(time[1]).padStart(9, \"0\")}`\n}\n\nfunction spanToOtlp(span: ReadableSpan): Record<string, unknown> {\n const spanContext = span.spanContext()\n const result: Record<string, unknown> = {\n traceId: spanContext.traceId,\n spanId: spanContext.spanId,\n name: span.name,\n kind: span.kind + 1,\n startTimeUnixNano: hrTimeToNanoString(span.startTime),\n endTimeUnixNano: hrTimeToNanoString(span.endTime),\n attributes: otlpAttributes(span.attributes as Record<string, unknown>),\n droppedAttributesCount: span.droppedAttributesCount,\n droppedEventsCount: span.droppedEventsCount,\n droppedLinksCount: span.droppedLinksCount,\n status: {\n code: span.status.code,\n ...(span.status.message ? { message: span.status.message } : {}),\n },\n flags: spanContext.traceFlags,\n }\n const parentSpanId = span.parentSpanContext?.spanId\n if (parentSpanId) {\n result.parentSpanId = parentSpanId\n }\n if (spanContext.traceState) {\n result.traceState = spanContext.traceState.serialize()\n }\n return result\n}\n\n/**\n * A span encoded exactly as it will appear on the wire, carrying its own byte\n * count. Encoding once and remembering the size is what keeps request packing\n * linear: sizing a candidate batch by re-encoding the whole request re-escapes\n * every carrier's `bitfab.payload` string on every span considered.\n */\ninterface EncodedSpan {\n json: string\n size: number\n ref?: CarrierRef\n}\n\ninterface RequestBatch {\n spans: EncodedSpan[]\n size: number\n}\n\n/**\n * The invariant head and tail of an OTLP request for one export window. Key\n * order matches what `JSON.stringify` emits for the equivalent object, so a\n * body assembled by concatenation is byte-identical to encoding that object.\n */\ninterface RequestEnvelope {\n head: string\n tail: string\n size: number\n}\n\n/** The comma `join` puts between adjacent spans in the request's span list. */\nconst SPAN_SEPARATOR_BYTES = 1\n\nfunction encodeSpan(span: ReadableSpan): EncodedSpan {\n const json = JSON.stringify(spanToOtlp(span))\n return {\n json,\n size: byteLength(json),\n ref: carrierRefs.get(span),\n }\n}\n\nfunction trimEncodedSpan(span: EncodedSpan): EncodedSpan | undefined {\n try {\n const carrier = JSON.parse(span.json) as {\n attributes?: Array<{\n key?: string\n value?: { stringValue?: string }\n }>\n }\n const attribute = carrier.attributes?.find(\n (entry) => entry.key === PAYLOAD_ATTRIBUTE,\n )\n const payloadBody = attribute?.value?.stringValue\n if (!attribute?.value || payloadBody === undefined) {\n return undefined\n }\n const payload = JSON.parse(payloadBody) as Record<string, unknown>\n attribute.value.stringValue = serializePayloadBody(\n payload,\n MAX_SPAN_CARRIER_BYTES,\n ).body\n const json = JSON.stringify(carrier)\n return { json, size: byteLength(json) }\n } catch {\n return undefined\n }\n}\n\nasync function prepareRequest(body: string): Promise<EncodedRequestBody> {\n const prepared = encodeRequestBody(body)\n return prepared instanceof Promise ? await prepared : prepared\n}\n\nfunction requestEnvelope(first: ReadableSpan): RequestEnvelope {\n const scope = first.instrumentationScope as InstrumentationScope\n const resource = JSON.stringify({\n attributes: otlpAttributes(\n first.resource.attributes as Record<string, unknown>,\n ),\n })\n const scopeJson = JSON.stringify({\n name: scope.name,\n version: scope.version ?? \"\",\n })\n const head = `{\"resourceSpans\":[{\"resource\":${resource},\"scopeSpans\":[{\"scope\":${scopeJson},\"spans\":[`\n const tail = \"]}]}]}\"\n return { head, tail, size: byteLength(head) + byteLength(tail) }\n}\n\nfunction encodeRequest(\n envelope: RequestEnvelope,\n spans: EncodedSpan[],\n): string {\n return (\n envelope.head + spans.map((span) => span.json).join(\",\") + envelope.tail\n )\n}\n\nfunction delay(ms: number): Promise<void> {\n return new Promise((resolve) => {\n const timer = setTimeout(resolve, ms)\n unrefTimer(timer)\n })\n}\n\n/**\n * Race `work` against `timeoutMs`. Resolves `false` when the deadline wins, so\n * a wedged export can never hold a flush or shutdown open past its budget.\n */\nasync function withDeadline(\n work: Promise<boolean>,\n timeoutMs: number,\n): Promise<boolean> {\n let timer: ReturnType<typeof setTimeout> | undefined\n try {\n return await Promise.race([\n work,\n new Promise<boolean>((resolve) => {\n timer = setTimeout(() => resolve(false), Math.max(0, timeoutMs))\n unrefTimer(timer)\n }),\n ])\n } finally {\n if (timer) {\n clearTimeout(timer)\n }\n }\n}\n\n/** Run `task` over `items` with at most `limit` in flight at any moment. */\nasync function mapWithConcurrency<T, R>(\n items: T[],\n limit: number,\n task: (item: T) => Promise<R>,\n): Promise<R[]> {\n const results = new Array<R>(items.length)\n let next = 0\n const workers = Array.from(\n { length: Math.min(Math.max(limit, 1), items.length) },\n async () => {\n while (next < items.length) {\n const index = next\n next += 1\n results[index] = await task(items[index])\n }\n },\n )\n await Promise.all(workers)\n return results\n}\n\n/**\n * Only what the sender classified. Anything else reaching here is a fault in\n * the sender itself, and retrying a deterministic bug just delays it.\n */\nfunction isRetryable(error: unknown): boolean {\n return error instanceof DeliveryError && error.retryable\n}\n\nfunction isOversized(error: unknown): boolean {\n return error instanceof DeliveryError && error.oversized\n}\n\n/**\n * How long to wait before the next send attempt, or `null` to stop trying.\n *\n * A server that sent `Retry-After` has told us when it wants us back, so that\n * wait is honored exactly. Clamping it would return early, which is the single\n * thing the server asked us not to do; when the wait is longer than we are\n * willing to hold a batch, the honest answer is to give up rather than come\n * back sooner and add load to something already struggling.\n *\n * Absent an instruction, back off exponentially so a struggling server is not\n * hit on a fixed cadence, and jitter it so every client in a fleet does not\n * return in lockstep.\n */\n/**\n * How long to wait before the next attempt, or null when the wait cannot be\n * served inside `remainingMillis` and the batch has to be given up.\n *\n * A server that sent Retry-After told us when it wants us back, so that wait is\n * honored whole rather than shortened: coming back early is the one thing it\n * asked us not to do. It is refused only when it outlasts the export budget,\n * where waiting would mean being killed mid-wait and losing the batch anyway.\n *\n * Absent an instruction, back off exponentially so a struggling server is not\n * hit on a fixed cadence, and jitter it so a fleet does not return in lockstep.\n */\nfunction retryWaitMillis(\n error: unknown,\n attempt: number,\n remainingMillis: number,\n): number | null {\n const requested =\n error instanceof DeliveryError ? error.retryAfterMs : undefined\n // Half the remaining budget, not all of it: a wait is only worth taking if\n // what is left afterwards can still carry the request. Spending the whole\n // budget waiting means being killed mid-wait, which loses the batch AND holds\n // an export slot for the duration.\n const affordable = remainingMillis / 2\n if (requested !== undefined) {\n return requested < affordable ? requested : null\n }\n const backoff = Math.min(\n RETRY_BASE_DELAY_MILLIS * 2 ** attempt,\n RETRY_BACKOFF_CEILING_MILLIS,\n )\n const jittered = backoff / 2 + Math.random() * (backoff / 2)\n return jittered < affordable ? jittered : null\n}\n\n/**\n * Direct delivery to Bitfab's OTLP/JSON ingress.\n *\n * OTel hands this exporter one batch as a candidate window. The window is\n * repacked into requests bounded by both a carrier count and the exact encoded\n * request size, and those complete requests are sent concurrently. That keeps\n * OTel's queue, scheduling, force-flush and shutdown while restoring the small\n * independent requests Bitfab's serverless ingress is built to scale.\n */\nexport class BitfabSpanExporter implements SpanExporter {\n constructor(\n private readonly directSender: DirectBatchSender,\n private readonly maxRequestBytes: number,\n private readonly maxRequestBatchSize: number,\n private readonly exportConcurrency: number,\n private readonly onDelivered?: (refs: CarrierRef[]) => void,\n // The same budget the processor enforces around this export. Waits are\n // measured against it, so a configured timeout and the deadline a wait is\n // judged by can never drift apart.\n private readonly exportTimeoutMillis: number = EXPORT_TIMEOUT_MILLIS,\n ) {}\n\n /** Epoch ms until which the server has asked this exporter to stay away. */\n private throttledUntil = 0\n\n export(\n spans: ReadableSpan[],\n resultCallback: (result: ExportResult) => void,\n ): void {\n void this.exportAsync(spans).then(\n (succeeded) => {\n resultCallback({\n code: succeeded ? ExportResultCode.SUCCESS : ExportResultCode.FAILED,\n })\n },\n (error) => {\n resultCallback({ code: ExportResultCode.FAILED, error })\n },\n )\n }\n\n private async exportAsync(spans: ReadableSpan[]): Promise<boolean> {\n if (spans.length === 0) {\n return true\n }\n let encoded: EncodedSpan[]\n let envelope: RequestEnvelope\n try {\n encoded = spans.map(encodeSpan)\n envelope = requestEnvelope(spans[0])\n } catch (error) {\n logError(\"failed to encode an OpenTelemetry span batch\", error)\n return false\n }\n\n const batches = this.buildRequestBatches(envelope, encoded)\n const results = await mapWithConcurrency(\n batches,\n this.exportConcurrency,\n (batch) => this.send(envelope, batch),\n )\n return results.every(Boolean)\n }\n\n private buildRequestBatches(\n envelope: RequestEnvelope,\n spans: EncodedSpan[],\n ): RequestBatch[] {\n const batches: RequestBatch[] = []\n let current: EncodedSpan[] = []\n let size = envelope.size\n\n for (const span of spans) {\n const addition =\n span.size + (current.length > 0 ? SPAN_SEPARATOR_BYTES : 0)\n if (\n current.length > 0 &&\n (current.length >= this.maxRequestBatchSize ||\n size + addition > this.maxRequestBytes)\n ) {\n batches.push({ spans: current, size })\n current = []\n size = envelope.size\n }\n current.push(span)\n size += span.size + (current.length > 1 ? SPAN_SEPARATOR_BYTES : 0)\n }\n\n if (current.length > 0) {\n batches.push({ spans: current, size })\n }\n return batches\n }\n\n private async send(\n envelope: RequestEnvelope,\n batch: RequestBatch,\n ): Promise<boolean> {\n try {\n let requestSpans = batch.spans\n let requestRawBytes = batch.size\n let alreadyTrimmed = false\n while (true) {\n if (requestRawBytes <= MAX_DECOMPRESSED_REQUEST_BYTES) {\n const prepared = await prepareRequest(\n encodeRequest(envelope, requestSpans),\n )\n if (prepared.wireBytes <= this.maxRequestBytes) {\n await this.sendWithRetries(prepared)\n // Refs come from the batch, not the possibly-trimmed request:\n // trimming rebuilds a span without its ref, and a trimmed carrier\n // still reached the server under its original identity.\n this.reportDelivered(batch.spans)\n return true\n }\n }\n\n if (batch.spans.length !== 1) {\n logError(\n \"an OpenTelemetry span batch exceeded the configured request-size target and could not be exported\",\n )\n return false\n }\n if (alreadyTrimmed) {\n logError(\n \"a single OpenTelemetry span exceeded the configured request-size target after trimming\",\n )\n return false\n }\n const trimmed = trimEncodedSpan(batch.spans[0])\n if (!trimmed) {\n logError(\n \"a single OpenTelemetry span exceeded the configured request-size target and could not be trimmed\",\n )\n return false\n }\n requestSpans = [trimmed]\n requestRawBytes = envelope.size + trimmed.size\n alreadyTrimmed = true\n }\n } catch (error) {\n if (isOversized(error)) {\n logError(\n batch.spans.length === 1\n ? \"a single OpenTelemetry span exceeded the ingestion request limit and could not be exported\"\n : \"an OpenTelemetry span batch exceeded the ingestion request limit and could not be exported\",\n )\n return false\n }\n logError(\"failed to export an OpenTelemetry span batch\", error)\n return false\n }\n }\n\n /**\n * Retries transient failures. Span and trace-completion carriers are safe to\n * retry: the server keys them idempotently on `sourceSpanId`/`sourceTraceId`,\n * so a duplicate delivery cannot create a duplicate row.\n *\n * KNOWN LIMITATION: an `internal_trace` (a `call()` BAML trace) carries no\n * such key, so retrying a batch that holds one can create a duplicate trace -\n * including when a request times out client-side but the server goes on to\n * persist it. Accepted deliberately for now, matching the other SDKs, rather\n * than skipping retries for a whole batch or inventing an idempotency scheme\n * the server does not yet understand. The fix is a client-supplied\n * idempotency key that ingestion dedupes on.\n */\n /**\n * Remember a throttle the server asked for, so the requests fanned out\n * alongside this one respect it too. Delaying only the request that was\n * refused leaves the other seven in the window hitting a server that just\n * asked for room.\n */\n private recordThrottle(error: unknown): void {\n const requested =\n error instanceof DeliveryError ? error.retryAfterMs : undefined\n if (requested !== undefined) {\n this.throttledUntil = Math.max(\n this.throttledUntil,\n Date.now() + requested,\n )\n }\n }\n\n /**\n * Waits out an active throttle, or reports the batch undeliverable when the\n * throttle outlasts what we are willing to hold it for. Either way nothing is\n * sent while the server has asked us to stay away.\n */\n private async awaitThrottle(deadline: number): Promise<void> {\n const remaining = this.throttledUntil - Date.now()\n if (remaining <= 0) {\n return\n }\n // Waited out, not refused: OTLP asks the client to hold off until the\n // window passes, and treats data dropped while throttled as the outcome to\n // avoid. Only a throttle outliving the export budget is refused, because\n // the processor would kill the wait before it could send anyway.\n if (remaining >= (deadline - Date.now()) / 2) {\n throw new DeliveryError(\n `OTLP ingestion is throttled for another ${remaining}ms, longer than the export budget`,\n )\n }\n await delay(remaining)\n }\n\n private async sendWithRetries(request: EncodedRequestBody): Promise<void> {\n // One budget for the whole exchange, waits included: the processor kills\n // the export at this deadline, so a wait past it cannot be served.\n const deadline = Date.now() + this.exportTimeoutMillis\n for (let attempt = 0; attempt < MAX_SEND_ATTEMPTS; attempt += 1) {\n try {\n await this.awaitThrottle(deadline)\n await this.directSender(request, Math.max(0, deadline - Date.now()))\n return\n } catch (error) {\n if (isOversized(error)) {\n throw error\n }\n this.recordThrottle(error)\n if (attempt === MAX_SEND_ATTEMPTS - 1 || !isRetryable(error)) {\n throw error\n }\n const wait = retryWaitMillis(error, attempt, deadline - Date.now())\n if (wait === null) {\n throw error\n }\n await delay(wait)\n }\n }\n }\n\n /**\n * Announce the carriers a request delivered. Wrapped because a listener that\n * throws must never turn a delivered batch into a failed export.\n */\n private reportDelivered(spans: EncodedSpan[]): void {\n if (this.onDelivered === undefined) {\n return\n }\n const refs = spans\n .map((span) => span.ref)\n .filter((ref): ref is CarrierRef => ref !== undefined)\n if (refs.length === 0) {\n return\n }\n try {\n this.onDelivered(refs)\n } catch (error) {\n logError(\"a delivery listener threw\", error)\n }\n }\n\n async shutdown(): Promise<void> {}\n\n async forceFlush(): Promise<void> {}\n}\n\n/**\n * Counts export failures so `flush` can answer \"was this delivered?\" instead of\n * only \"did the processor queue drain?\". Without it a flush would report\n * success for a batch the exporter dropped, and replay would finalize a run\n * whose traces never landed.\n */\nclass DeliveryTrackingExporter implements SpanExporter {\n // Deliberately unscoped, matching the Python SDK. An export can outlive\n // OTel's export timeout and report failure after the flush that was waiting\n // on it already returned, so that failure surfaces on the NEXT flush instead.\n // That over-reports: a good flush can inherit an older failure. The\n // alternative - discarding failures from completed flush windows - under-\n // reports, and `BatchSpanProcessor` also runs scheduled exports that belong\n // to no flush at all, so their failures would vanish entirely. For a\n // telemetry SDK a false \"flush failed\" is investigable; a false \"flush\n // succeeded\" silently loses traces. We take the noisy direction on purpose.\n private failedExports = 0\n\n constructor(private readonly exporter: SpanExporter) {}\n\n export(\n spans: ReadableSpan[],\n resultCallback: (result: ExportResult) => void,\n ): void {\n try {\n this.exporter.export(spans, (result) => {\n if (result.code !== ExportResultCode.SUCCESS) {\n this.failedExports += 1\n }\n resultCallback(result)\n })\n } catch (error) {\n this.failedExports += 1\n resultCallback({ code: ExportResultCode.FAILED, error: error as Error })\n }\n }\n\n takeFailedExports(): number {\n const failed = this.failedExports\n this.failedExports = 0\n return failed\n }\n\n shutdown(): Promise<void> {\n return this.exporter.shutdown()\n }\n\n forceFlush(): Promise<void> {\n return this.exporter.forceFlush?.() ?? Promise.resolve()\n }\n}\n\nexport interface OtelBatchTransportOptions {\n directSender: DirectBatchSender\n /** Called with the refs of every carrier a request delivered. */\n onDelivered?: (refs: CarrierRef[]) => void\n maxExportBatchSize?: number\n maxRequestBatchSize?: number\n maxQueueSize?: number\n exportConcurrency?: number\n maxRequestBytes?: number\n /** Overridable so tests can drive OTel's export-timeout path in ms, not 30s. */\n exportTimeoutMillis?: number\n}\n\nexport class OtelBatchTransport implements TraceTransport {\n private readonly provider: BasicTracerProvider\n private readonly processor: BatchSpanProcessor\n private readonly deliveryTracker: DeliveryTrackingExporter\n private readonly tracer: Tracer\n private closed = false\n private pendingFlush: Promise<boolean> | undefined\n\n constructor(options: OtelBatchTransportOptions) {\n const maxRequestBytes = options.maxRequestBytes ?? MAX_EXPORT_REQUEST_BYTES\n const maxRequestBatchSize =\n options.maxRequestBatchSize ?? DIRECT_MAX_REQUEST_BATCH_SIZE\n if (maxRequestBatchSize <= 0) {\n throw new BitfabError(\"maxRequestBatchSize must be a positive integer\")\n }\n\n this.deliveryTracker = new DeliveryTrackingExporter(\n new BitfabSpanExporter(\n options.directSender,\n maxRequestBytes,\n maxRequestBatchSize,\n options.exportConcurrency ?? DEFAULT_EXPORT_CONCURRENCY,\n options.onDelivered,\n options.exportTimeoutMillis ?? EXPORT_TIMEOUT_MILLIS,\n ),\n )\n\n this.processor = new BatchSpanProcessor(this.deliveryTracker, {\n maxQueueSize: options.maxQueueSize ?? MAX_QUEUE_SIZE,\n maxExportBatchSize:\n options.maxExportBatchSize ?? DIRECT_MAX_EXPORT_BATCH_SIZE,\n scheduledDelayMillis: SCHEDULE_DELAY_MILLIS,\n exportTimeoutMillis: options.exportTimeoutMillis ?? EXPORT_TIMEOUT_MILLIS,\n })\n\n // Every option is passed explicitly: `BasicTracerProvider` otherwise reads\n // OTEL_* defaults, so a host application's sampler or attribute-length\n // limit would silently drop or truncate Bitfab payloads.\n this.provider = new BasicTracerProvider({\n sampler: new AlwaysOnSampler(),\n resource: resourceFromAttributes({\n \"service.name\": \"bitfab-typescript-sdk\",\n \"service.version\": __version__,\n }),\n spanLimits: {\n attributeCountLimit: 2,\n attributeValueLengthLimit: Number.POSITIVE_INFINITY,\n },\n spanProcessors: [this.processor],\n })\n this.tracer = this.provider.getTracer(\"bitfab\", __version__)\n liveTransports.add(this)\n }\n\n submit(\n operation: TraceOperation,\n payload: Record<string, unknown>,\n meta: CarrierMeta = {},\n ): void {\n if (this.closed) {\n warnOnce(\n \"otel-submit-after-shutdown\",\n \"OpenTelemetry transport is shut down; dropping spans\",\n )\n return\n }\n try {\n // Not a bare JSON.stringify: contexts, metadata and `call()` inputs\n // never pass through `serializeValue`, so one stray value here would\n // throw and drop the whole span rather than being stubbed. This is the\n // same backstop the pre-transport HTTP path applied.\n const { body, dropped } = serializePayloadBody(\n payload,\n MAX_COMPRESSIBLE_SPAN_CARRIER_BYTES,\n )\n if (dropped.length > 0) {\n warnOnce(\n \"otel-carrier-payload-stubbed\",\n `a span payload held non-serializable value(s) (${[\n ...new Set(dropped),\n ].join(\", \")}); they were stubbed so the span still ships, but the ` +\n \"trace may be incomplete or not replayable.\",\n )\n }\n const span = this.tracer.startSpan(meta.name ?? `bitfab.${operation}`, {\n attributes: {\n [OPERATION_ATTRIBUTE]: operation,\n [PAYLOAD_ATTRIBUTE]: body,\n },\n startTime: meta.startTime,\n })\n if (meta.ref !== undefined) {\n carrierRefs.set(span, meta.ref)\n }\n if (meta.errored === true) {\n span.setStatus({ code: SpanStatusCode.ERROR })\n }\n endSpan(span, meta.endTime)\n } catch (error) {\n logError(\"failed to queue an OpenTelemetry span\", error)\n }\n }\n\n async flush(\n timeoutMs: number = DEFAULT_LIFECYCLE_TIMEOUT_MS,\n ): Promise<boolean> {\n // Serialized: two concurrent force-flushes would race for the same\n // delivery counter and one would report the other's failures as success.\n const pending = (this.pendingFlush ?? Promise.resolve(true)).then(() =>\n this.forceFlushOnce(),\n )\n this.pendingFlush = pending.catch(() => false)\n return withDeadline(pending, timeoutMs)\n }\n\n private async forceFlushOnce(): Promise<boolean> {\n try {\n await this.processor.forceFlush()\n } catch (error) {\n logError(\"failed to flush OpenTelemetry spans\", error)\n this.deliveryTracker.takeFailedExports()\n return false\n }\n return this.deliveryTracker.takeFailedExports() === 0\n }\n\n async shutdown(\n timeoutMs: number = DEFAULT_LIFECYCLE_TIMEOUT_MS,\n ): Promise<boolean> {\n const deadline = Date.now() + Math.max(timeoutMs, 0)\n this.closed = true\n const flushed = await this.flush(Math.max(0, deadline - Date.now()))\n liveTransports.delete(this)\n const shutdownCompleted = await withDeadline(\n this.provider\n .shutdown()\n .then(() => true)\n .catch((error) => {\n logError(\"failed to shut down the OpenTelemetry transport\", error)\n return false\n }),\n Math.max(0, deadline - Date.now()),\n )\n return flushed && shutdownCompleted\n }\n}\n\nfunction endSpan(span: Span, endTime: number | undefined): void {\n span.end(endTime)\n}\n\nexport function createOtelTransport(options: {\n directSender: DirectBatchSender\n onDelivered?: (refs: CarrierRef[]) => void\n}): OtelBatchTransport {\n return new OtelBatchTransport({\n ...options,\n exportConcurrency: readBoundedIntEnv(\n EXPORT_CONCURRENCY_ENV,\n MAX_EXPORT_CONCURRENCY,\n DEFAULT_EXPORT_CONCURRENCY,\n \"otel-export-concurrency-invalid\",\n ),\n maxRequestBytes: readBoundedIntEnv(\n MAX_REQUEST_BYTES_ENV,\n MAX_EXPORT_REQUEST_BYTES,\n MAX_EXPORT_REQUEST_BYTES,\n \"otel-max-request-bytes-invalid\",\n ),\n })\n}\n\nasync function forEachLiveTransport(\n timeoutMs: number,\n run: (transport: OtelBatchTransport, remainingMs: number) => Promise<boolean>,\n): Promise<boolean> {\n const deadline = Date.now() + Math.max(timeoutMs, 0)\n let succeeded = true\n for (const transport of [...liveTransports]) {\n succeeded =\n (await run(transport, Math.max(0, deadline - Date.now()))) && succeeded\n }\n return succeeded\n}\n\nexport function flushOtelTransports(\n timeoutMs: number = DEFAULT_LIFECYCLE_TIMEOUT_MS,\n): Promise<boolean> {\n return forEachLiveTransport(timeoutMs, (transport, remaining) =>\n transport.flush(remaining),\n )\n}\n\nexport function shutdownOtelTransports(\n timeoutMs: number = DEFAULT_LIFECYCLE_TIMEOUT_MS,\n): Promise<boolean> {\n return forEachLiveTransport(timeoutMs, (transport, remaining) =>\n transport.shutdown(remaining),\n )\n}\n","/**\n * The single seam between the HTTP client and whichever transport implements\n * span delivery. Keeping the factory here (rather than importing `otel.ts`\n * from `http.ts` directly) is what lets the OpenTelemetry implementation\n * depend on `HttpClient`'s request path without an import cycle.\n */\n\nimport {\n createOtelTransport,\n flushOtelTransports,\n shutdownOtelTransports,\n} from \"./otel.js\"\nimport type {\n CarrierRef,\n DirectBatchSender,\n TraceTransport,\n} from \"./transportTypes.js\"\n\nexport function createTraceTransport(options: {\n directSender: DirectBatchSender\n onDelivered?: (refs: CarrierRef[]) => void\n}): TraceTransport {\n return createOtelTransport(options)\n}\n\nexport function flushTraceTransports(timeoutMs?: number): Promise<boolean> {\n return flushOtelTransports(timeoutMs)\n}\n\nexport function shutdownTraceTransports(timeoutMs?: number): Promise<boolean> {\n return shutdownOtelTransports(timeoutMs)\n}\n","/**\n * HTTP client utilities for Bitfab API requests.\n *\n * This module provides:\n * - HttpClient class for making API requests\n * - awaitOnExit helper so deferred span work still gates process exit\n */\n\nimport { type EncodedRequestBody, encodeRequestBody } from \"./compress.js\"\nimport { __packageName__, __version__ } from \"./constants.js\"\nimport type { DbSnapshotRef } from \"./dbSnapshot.js\"\nimport { BitfabError } from \"./errors.js\"\nimport {\n type DbBranchLease,\n type DbBranchSettings,\n type DbBranchTimings,\n replayContextReady,\n} from \"./replayContext.js\"\nimport { serializePayloadBody } from \"./serializePayload.js\"\nimport {\n createTraceTransport,\n flushTraceTransports,\n shutdownTraceTransports,\n} from \"./transport.js\"\nimport {\n type CarrierMeta,\n type CarrierRef,\n DeliveryError,\n type TraceOperation,\n type TraceTransport,\n} from \"./transportTypes.js\"\nimport { unrefTimer } from \"./unrefTimer.js\"\nimport { warnOnce } from \"./warnOnce.js\"\n\n// BitfabError lives in `errors.ts` to break the http ↔ dbSnapshot import\n// cycle. Re-exported here for backwards compatibility with existing\n// callers that import it from \"./http.js\".\nexport { BitfabError }\nexport { serializePayloadBody }\n\nconst REPLAY_DB_BRANCH_REQUEST_TIMEOUT_MS = 300_000\nconst REPLAY_COMPLETE_REQUEST_TIMEOUT_MS = 120_000\nconst OTLP_TRACES_ENDPOINT = \"/api/sdk/otel/v1/traces\"\n// OTLP's retryable set, plus 500. Every other 4xx is the server's verdict on\n// the payload and will be the same next time.\n//\n// 500 is a deliberate deviation: OTLP treats it as the app being broken, which\n// assumes a collector that fails deterministically. Bitfab ingestion answers\n// every unhandled error with 500, so a connection blip or a cold start arrives\n// here indistinguishable from a real fault, and giving up on the first one\n// drops spans that a second attempt would have delivered.\nconst RETRYABLE_STATUSES = new Set([429, 500, 502, 503, 504])\nconst EXIT_FLUSH_TIMEOUT_MS = 5_000\nconst DEFAULT_LIFECYCLE_TIMEOUT_MS = 30_000\n\n// Global set to track pending trace creation promises\n// This prevents promises from being garbage collected before they complete\nconst pendingTracePromises = new Set<Promise<unknown>>()\n\n/**\n * Track a promise so `flushTraces()` and the exit hook wait for it.\n *\n * Exactly one caller remains: the deferred `finalize` chain, which hands its\n * span to the transport only after finalize settles. Everything else submits\n * synchronously, so the transport's own queue is the complete picture. Python\n * has no equivalent because its finalize runs inline.\n *\n * @param promise - The promise to track\n * @returns The same promise (for chaining)\n */\nexport function awaitOnExit<T>(promise: Promise<T>): Promise<T> {\n pendingTracePromises.add(promise)\n // Use void to prevent unhandled rejection warnings from the .finally() chain\n // The actual error handling is done by the caller's .catch() on the returned promise\n void promise\n .finally(() => {\n pendingTracePromises.delete(promise)\n })\n .catch(() => {\n // Swallow rejection in this chain - the caller handles errors via their own .catch()\n })\n return promise\n}\n\n/**\n * Wait for pending fire-and-forget requests AND every live span transport to\n * deliver, within one total deadline. Useful in tests and scripts to ensure all\n * data has been sent before asserting or exiting.\n *\n * Returns `false` when delivery failed or the deadline expired, so a caller\n * that depends on persistence (replay does) can react instead of assuming a\n * drained queue means the server has the data.\n *\n * @param timeoutMs - Maximum total time to wait in milliseconds (default: 5000)\n */\nexport async function flushTraces(timeoutMs: number = 5000): Promise<boolean> {\n const deadline = Date.now() + Math.max(timeoutMs, 0)\n const requestsFlushed = await awaitPendingRequests(timeoutMs)\n const transportsFlushed = await flushTraceTransports(\n Math.max(0, deadline - Date.now()),\n )\n return requestsFlushed && transportsFlushed\n}\n\n/**\n * Wait for in-flight fire-and-forget requests and deferred span work, WITHOUT\n * flushing the transports.\n *\n * Replay needs this half on its own: a `finalize` span reaches the transport\n * only after its deferred chain settles, so the expected-span tally has to be\n * read after that work lands but before a flush is issued (which would be\n * wasted, and would emit a request, when the run submitted nothing).\n */\nexport async function awaitPendingRequests(\n timeoutMs: number = DEFAULT_LIFECYCLE_TIMEOUT_MS,\n): Promise<boolean> {\n // Async-context storage loads asynchronously, and spans traced before it\n // resolves have their recording deferred behind it. Without this, a script\n // that traces and immediately flushes or closes races its own first spans.\n await replayContextReady.catch(() => {})\n return waitForPromises(Array.from(pendingTracePromises), timeoutMs)\n}\n\n/**\n * Await `promises` within `timeoutMs`, reporting whether they all settled in\n * time rather than throwing. Rejections count as settled: a failed span upload\n * is already reported by its own catch handler, and the caller is asking about\n * completion, not success.\n */\nasync function waitForPromises(\n promises: Promise<unknown>[],\n timeoutMs: number,\n): Promise<boolean> {\n if (promises.length === 0) {\n return true\n }\n // Clear and unref the timeout so the loser of the race never leaves a\n // dangling timer holding the event loop open after flush resolves.\n let timer: ReturnType<typeof setTimeout> | undefined\n try {\n return await Promise.race([\n Promise.allSettled(promises).then(() => true),\n new Promise<boolean>((resolve) => {\n timer = setTimeout(() => resolve(false), timeoutMs)\n unrefTimer(timer)\n }),\n ])\n } finally {\n if (timer) {\n clearTimeout(timer)\n }\n }\n}\n\n// Register beforeExit handler to wait for pending traces (Node.js only)\n// This ensures traces are sent before the process exits (for scripts).\n// The transport is included: its batch worker sits on an unref'd timer, so a\n// script that ends without an explicit flush would otherwise exit with a queue\n// of spans still waiting on the scheduled delay.\nif (\n typeof process !== \"undefined\" &&\n process.versions != null &&\n process.versions.node != null\n) {\n let isFlushing = false\n process.on(\"beforeExit\", () => {\n if (isFlushing) {\n return\n }\n isFlushing = true\n // Awaiting here keeps the event loop alive until delivery settles.\n void Promise.allSettled([\n ...Array.from(pendingTracePromises).map((p) => p.catch(() => {})),\n shutdownTraceTransports(EXIT_FLUSH_TIMEOUT_MS).catch(() => false),\n ]).then(() => {\n isFlushing = false\n })\n })\n}\n\n/**\n * How the API key is supplied internally: either a literal string or a\n * function resolved each time the key is needed (at request/send time). The\n * function form is what defers key resolution past module-load construction\n * so an env var loaded after the client is built (the ESM dotenv-hoisting\n * case) is still picked up.\n */\nexport type ApiKeyInput = string | (() => string | undefined)\n\nexport interface HttpClientConfig {\n apiKey?: ApiKeyInput\n serviceUrl: string\n timeout?: number\n}\n\nexport type SpanOccurrence = \"first\" | \"last\" | number\n\nexport type SpanLookup =\n | { id: string; name?: never; occurrence?: never }\n | { name: string; id?: never; occurrence?: SpanOccurrence }\n\nexport interface CapturedSpan {\n id: string\n traceId: string\n parentSpanId: string | null\n name: string | null\n type: string\n input: unknown\n output: unknown\n contexts: Record<string, unknown>[]\n prompt: string | null\n metadata: Record<string, unknown>\n metrics: Record<string, unknown> | null\n errors: unknown\n startedAt: string | null\n endedAt: string | null\n}\n\n/**\n * HTTP client for Bitfab API requests.\n *\n * Provides methods for different API endpoints with proper error handling,\n * timeouts, and authentication.\n */\n/**\n * `Retry-After` as milliseconds. The header is either a delay in seconds or an\n * HTTP date; both forms appear in the wild, so both are read. Anything else, or\n * a date already in the past, yields `undefined` so the caller falls back to\n * its own backoff.\n */\n/**\n * Read one response header without letting it break delivery. `Response.headers`\n * is always present from a real `fetch`, but polyfills and doubles are looser,\n * and an optional header must never be the reason a batch fails to send.\n */\nfunction readHeader(response: Response, name: string): string | null {\n try {\n return response.headers?.get(name) ?? null\n } catch {\n return null\n }\n}\n\nexport function parseRetryAfterMs(header: string | null): number | undefined {\n // Trimmed and emptiness-checked before Number(), which reads \"\" and \" \" as\n // 0 and would turn a blank header into \"retry immediately\", skipping the\n // backoff entirely. The other SDKs treat a blank header as no instruction.\n const value = header?.trim()\n if (!value) {\n return undefined\n }\n const seconds = Number(value)\n if (Number.isFinite(seconds)) {\n return seconds >= 0 ? seconds * 1_000 : undefined\n }\n const at = Date.parse(value)\n if (Number.isNaN(at)) {\n return undefined\n }\n return Math.max(0, at - Date.now())\n}\n\n/**\n * The delivery identity of a carrier, read from the payload here because this\n * is where the payload shape is owned. The transport is handed the result and\n * never looks inside a payload itself.\n */\n/**\n * Everything the transport needs to know about a carrier, derived here because\n * this is where the payload shape is owned. The transport applies these and\n * never looks inside a payload itself.\n */\nfunction carrierMeta(\n operation: TraceOperation,\n payload: Record<string, unknown>,\n ref: CarrierRef | undefined,\n): CarrierMeta {\n return {\n ref,\n name: carrierName(operation, payload),\n startTime: payloadTimestamp(payload, \"started_at\"),\n endTime: payloadTimestamp(payload, \"ended_at\"),\n errored: payloadHasError(payload),\n }\n}\n\nfunction carrierName(\n operation: TraceOperation,\n payload: Record<string, unknown>,\n): string {\n if (operation === \"external_span\") {\n const spanData = asPayloadRecord(\n asPayloadRecord(payload.rawSpan)?.span_data,\n )\n if (typeof spanData?.name === \"string\") {\n return spanData.name\n }\n }\n if (typeof payload.traceFunctionKey === \"string\") {\n return payload.traceFunctionKey\n }\n return `bitfab.${operation}`\n}\n\n/**\n * Milliseconds since the epoch for a payload timestamp, or `undefined` to let\n * OTel stamp the carrier with the current time.\n */\nfunction payloadTimestamp(\n payload: Record<string, unknown>,\n field: string,\n): number | undefined {\n const rawSpan = asPayloadRecord(payload.rawSpan)\n const rawTrace =\n asPayloadRecord(payload.externalTrace) ?? asPayloadRecord(payload.rawTrace)\n const raw = rawSpan?.[field] ?? rawTrace?.[field]\n if (typeof raw !== \"string\") {\n return undefined\n }\n const parsed = Date.parse(raw)\n return Number.isNaN(parsed) ? undefined : parsed\n}\n\nfunction payloadHasError(payload: Record<string, unknown>): boolean {\n const spanData = asPayloadRecord(asPayloadRecord(payload.rawSpan)?.span_data)\n if (spanData?.error != null) {\n return true\n }\n const errors = payload.errors\n return Array.isArray(errors) ? errors.length > 0 : Boolean(errors)\n}\n\nfunction asPayloadRecord(value: unknown): Record<string, unknown> | undefined {\n return typeof value === \"object\" && value !== null && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : undefined\n}\n\n/** What a caller learns about one tracked trace once it takes it back. */\nexport interface DeliveryReport {\n spanCount: number\n /** A closing carrier was submitted, so the expected set is final. */\n closed: boolean\n /** Every carrier submitted under this trace came back accepted. */\n delivered: boolean\n /**\n * The server's assigned `traces.id`, read back from the OTLP ingest response.\n * Absent when talking to a server that predates this field, or before any\n * carrier for the trace has been acked.\n */\n serverTraceId?: string\n}\n\ninterface TraceDelivery {\n submittedSpanIds: Set<string>\n ackedSpanIds: Set<string>\n closed: boolean\n closingAcked: boolean\n serverTraceId?: string\n}\n\nfunction carrierRef(payload: Record<string, unknown>): CarrierRef | undefined {\n const traceId = sourceTraceIdOf(payload)\n if (traceId === undefined) {\n return undefined\n }\n const rawSpan = payload.rawSpan\n if (rawSpan === undefined) {\n return { traceId }\n }\n const spanId = (rawSpan as Record<string, unknown>)?.id\n return {\n traceId,\n spanId: typeof spanId === \"string\" ? spanId : `submission-${++carrierSeq}`,\n }\n}\n\nfunction sourceTraceIdOf(payload: Record<string, unknown>): string | undefined {\n if (typeof payload.sourceTraceId === \"string\") {\n return payload.sourceTraceId\n }\n const rawTrace = (payload.externalTrace ?? payload.rawTrace) as\n | Record<string, unknown>\n | undefined\n const id = rawTrace?.id\n return typeof id === \"string\" ? id : undefined\n}\n\nlet carrierSeq = 0\n\nexport class HttpClient {\n private readonly apiKey: ApiKeyInput | undefined\n private readonly serviceUrl: string\n private readonly timeout: number\n private traceTransport: TraceTransport | undefined\n // Only traces a caller asked about are tracked, so ordinary tracing stores\n // nothing here.\n private readonly traceDeliveries = new Map<string, TraceDelivery>()\n // Deferred span work owned by THIS client. The module-global set backs the\n // process-wide `flushTraces()` and the exit hook, but per-client lifecycle\n // must not wait on another client's slow finalize: a false `close()` failure\n // caused by unrelated work is worse than no signal at all.\n private readonly deferredWork = new Set<Promise<unknown>>()\n private closed = false\n private closing: Promise<boolean> | undefined\n\n constructor(config: HttpClientConfig) {\n this.apiKey = config.apiKey\n this.serviceUrl = config.serviceUrl\n this.timeout = config.timeout ?? 120000\n }\n\n /**\n * Resolve the API key at the moment it is needed (request time), invoking\n * the function form if one was supplied. Never read at construction.\n */\n private resolveApiKey(): string | undefined {\n return typeof this.apiKey === \"function\" ? this.apiKey() : this.apiKey\n }\n\n /**\n * This client's span transport, built on first use.\n *\n * Lazy on purpose: a client that never sends a span must never start a batch\n * worker. Every framework integration created from a `Bitfab` client shares\n * the owning client's `HttpClient`, so handlers reuse this one worker instead\n * of each spinning up their own.\n */\n private getTraceTransport(): TraceTransport | undefined {\n if (this.closed) {\n warnOnce(\n \"http-client-closed\",\n \"the Bitfab client is closed; dropping spans\",\n )\n return undefined\n }\n if (!this.traceTransport) {\n this.traceTransport = createTraceTransport({\n directSender: (request, timeoutMs) =>\n this.deliverCarriers(request, timeoutMs),\n onDelivered: (refs) => this.recordDeliveredCarriers(refs),\n })\n }\n return this.traceTransport\n }\n\n /**\n * Post one encoded batch and decide what the server's answer means, so the\n * transport never reads a response. Rejections and permanent statuses come\n * back as a non-retryable {@link DeliveryError}; anything the server might\n * still accept on a second try comes back retryable.\n */\n private async deliverCarriers(\n request: EncodedRequestBody,\n timeoutMs: number,\n ): Promise<void> {\n let response: Record<string, unknown>\n try {\n // sendPrepared, not sendEncoded: the exporter already encoded this batch\n // to size the request, and re-encoding here would do that work twice.\n response = await this.sendPrepared<Record<string, unknown>>(\n OTLP_TRACES_ENDPOINT,\n request,\n { timeout: timeoutMs },\n )\n } catch (error) {\n const status = error instanceof BitfabError ? error.status : undefined\n if (status === undefined) {\n // No verdict from the server (a network fault): worth another attempt.\n throw new DeliveryError(`OTLP ingestion failed: ${String(error)}`, {\n retryable: true,\n })\n }\n throw new DeliveryError(`OTLP ingestion failed with HTTP ${status}`, {\n retryable: RETRYABLE_STATUSES.has(status),\n oversized: status === 413,\n ...(error instanceof BitfabError && error.retryAfterMs !== undefined\n ? { retryAfterMs: error.retryAfterMs }\n : {}),\n })\n }\n\n const serverTraceIds = asPayloadRecord(response?.traceIds)\n if (serverTraceIds !== undefined) {\n this.recordServerTraceIds(serverTraceIds)\n }\n\n const partialSuccess = asPayloadRecord(response?.partialSuccess)\n const rejected = partialSuccess?.rejectedSpans\n if (rejected !== undefined && rejected !== \"0\" && rejected !== 0) {\n // The server's verdict on the payload, not a transient fault.\n throw new DeliveryError(\n `OTLP ingestion rejected ${rejected} span(s): ${\n partialSuccess?.errorMessage ?? \"no reason provided\"\n }`,\n )\n }\n }\n\n /**\n * Start tracking delivery for `traceIds`. Nothing is recorded for a trace\n * that was never tracked, so ordinary tracing costs no bookkeeping at all.\n */\n trackTraceDeliveries(traceIds: string[]): void {\n for (const traceId of traceIds) {\n if (!this.traceDeliveries.has(traceId)) {\n this.traceDeliveries.set(traceId, {\n submittedSpanIds: new Set(),\n ackedSpanIds: new Set(),\n closed: false,\n closingAcked: false,\n })\n }\n }\n }\n\n /**\n * The server's assigned `traces.id` for a tracked trace if it has already\n * been read back off an ingest response, without stopping tracking. Lets a\n * replay surface the id mid-run for items whose spans already landed.\n */\n peekServerTraceId(traceId: string): string | undefined {\n return this.traceDeliveries.get(traceId)?.serverTraceId\n }\n\n /** Whether any tracked trace has had its closing carrier submitted. */\n hasClosedDeliveries(traceIds: string[]): boolean {\n return traceIds.some((traceId) => this.traceDeliveries.get(traceId)?.closed)\n }\n\n /**\n * Report what each tracked trace submitted and whether the server confirmed\n * it, and stop tracking them. Every id passed is freed, so a caller cannot\n * leak a record for a trace that never closed.\n *\n * `delivered` is only meaningful once a flush has settled: acks land before\n * an export resolves, so a flush that reported success has already collected\n * every ack it is going to collect.\n */\n takeTraceDeliveries(traceIds: string[]): Record<string, DeliveryReport> {\n const reports: Record<string, DeliveryReport> = {}\n for (const traceId of traceIds) {\n const delivery = this.traceDeliveries.get(traceId)\n if (delivery === undefined) {\n continue\n }\n this.traceDeliveries.delete(traceId)\n reports[traceId] = {\n spanCount: delivery.submittedSpanIds.size,\n closed: delivery.closed,\n delivered:\n delivery.closingAcked &&\n [...delivery.submittedSpanIds].every((spanId) =>\n delivery.ackedSpanIds.has(spanId),\n ),\n serverTraceId: delivery.serverTraceId,\n }\n }\n return reports\n }\n\n /** Build a carrier's meta and record what it adds to its trace's expected set. */\n private recordedMeta(\n operation: TraceOperation,\n payload: Record<string, unknown>,\n ref: CarrierRef | undefined,\n ): CarrierMeta {\n this.recordSubmittedCarrier(ref)\n return carrierMeta(operation, payload, ref)\n }\n\n private recordSubmittedCarrier(ref: CarrierRef | undefined): void {\n if (ref === undefined) {\n return\n }\n const delivery = this.traceDeliveries.get(ref.traceId)\n if (delivery === undefined) {\n return\n }\n if (ref.spanId === undefined) {\n delivery.closed = true\n } else {\n delivery.submittedSpanIds.add(ref.spanId)\n }\n }\n\n /**\n * Ingestion commits every carrier in a request before it answers, so a\n * delivered ref is proof its row exists: the same fact the replay status\n * endpoint would report, already in hand.\n */\n /**\n * Record the server's assigned `traces.id` for each tracked source trace,\n * read back from the OTLP ingest response. Keyed by source trace id, the same\n * key the delivery ledger uses. Untracked ids are ignored.\n */\n private recordServerTraceIds(map: Record<string, unknown>): void {\n for (const [sourceTraceId, serverTraceId] of Object.entries(map)) {\n if (typeof serverTraceId !== \"string\") {\n continue\n }\n const delivery = this.traceDeliveries.get(sourceTraceId)\n if (delivery === undefined) {\n continue\n }\n delivery.serverTraceId = serverTraceId\n }\n }\n\n private recordDeliveredCarriers(refs: CarrierRef[]): void {\n for (const ref of refs) {\n const delivery = this.traceDeliveries.get(ref.traceId)\n if (delivery === undefined) {\n continue\n }\n if (ref.spanId === undefined) {\n delivery.closingAcked = true\n } else {\n delivery.ackedSpanIds.add(ref.spanId)\n }\n }\n }\n\n /**\n * Track deferred span work so this client's own lifecycle waits for it, and\n * so the process-wide flush and exit hook do too.\n */\n trackDeferred<T>(promise: Promise<T>): Promise<T> {\n this.deferredWork.add(promise)\n void promise\n .finally(() => this.deferredWork.delete(promise))\n .catch(() => {})\n return awaitOnExit(promise)\n }\n\n /**\n * Settle only THIS client's deferred span work. Scoped deliberately: the\n * global set can contain another client's long-running finalize, and\n * attributing its timeout here would fail a client whose own work succeeded.\n */\n async settleDeferredWork(\n timeoutMs: number = DEFAULT_LIFECYCLE_TIMEOUT_MS,\n ): Promise<boolean> {\n await replayContextReady.catch(() => {})\n return waitForPromises(Array.from(this.deferredWork), timeoutMs)\n }\n\n /**\n * Wait for spans queued by this client to be delivered, within one deadline.\n * Returns false on delivery failure or timeout.\n */\n async waitForPendingRequests(\n timeoutMs: number = DEFAULT_LIFECYCLE_TIMEOUT_MS,\n ): Promise<boolean> {\n const deadline = Date.now() + Math.max(timeoutMs, 0)\n const settled = await this.settleDeferredWork(timeoutMs)\n const flushed =\n (await this.traceTransport?.flush(Math.max(0, deadline - Date.now()))) ??\n true\n return settled && flushed\n }\n\n /**\n * Flush and permanently close this client's tracing transport. Idempotent:\n * a second call joins the first rather than tearing down a pipeline the\n * first call already owns.\n */\n close(timeoutMs: number = DEFAULT_LIFECYCLE_TIMEOUT_MS): Promise<boolean> {\n if (this.closing) {\n return this.closing\n }\n const deadline = Date.now() + Math.max(timeoutMs, 0)\n this.closing = (async () => {\n // Settle deferred span work BEFORE refusing submissions. A span whose\n // recording is still queued (the `finalize` chain, or any call made\n // before async-context storage finished loading) has not reached the\n // transport yet; flipping `closed` first would reject it on arrival and\n // silently drop a span the caller had every reason to think was captured.\n const settled = await this.settleDeferredWork(\n Math.max(0, deadline - Date.now()),\n )\n this.closed = true\n const transport = this.traceTransport\n this.traceTransport = undefined\n const shutdownOk =\n (await transport?.shutdown(Math.max(0, deadline - Date.now()))) ?? true\n // Deferred work that outran the deadline will submit into a closed\n // client and be dropped, so close cannot report success for it.\n return settled && shutdownOk\n })()\n return this.closing\n }\n\n /**\n * Make an HTTP request to the Bitfab API. Defaults to POST; pass\n * `options.method` to use a different verb (e.g. \"PATCH\").\n *\n * @param endpoint - The API endpoint (without base URL)\n * @param payload - The request body\n * @param options - Optional request options\n * @returns The parsed JSON response\n * @throws {BitfabError} If the request fails\n */\n async request<T>(\n endpoint: string,\n payload: Record<string, unknown>,\n options?: { timeout?: number; method?: \"POST\" | \"PATCH\" | \"PUT\" },\n ): Promise<T> {\n // Serialize the payload so a stray non-serializable value (BigInt,\n // function, circular ref, a class instance that slipped past upstream\n // serialization) can never abort the send and silently drop the span.\n // Strays are stubbed in place, preserving span content, and a degraded\n // payload warns loudly.\n const { body, dropped } = serializePayloadBody(payload)\n if (dropped.length > 0) {\n try {\n console.warn(\n `Bitfab: request body to ${endpoint} held ${dropped.length} ` +\n `non-serializable value(s) (${[...new Set(dropped)].join(\", \")}); ` +\n \"they were stubbed so the span still sends, but the trace may be \" +\n \"incomplete or not replayable. Capture a JSON-safe projection of \" +\n \"this input to make it replayable.\",\n )\n } catch {}\n }\n return this.sendEncoded<T>(endpoint, body, options)\n }\n\n /**\n * POST an already-encoded body. The span transport encodes its own batches,\n * so routing them back through {@link HttpClient.request} would encode the\n * same data twice.\n */\n async sendEncoded<T>(\n endpoint: string,\n body: string,\n options?: { timeout?: number; method?: \"POST\" | \"PATCH\" | \"PUT\" },\n ): Promise<T> {\n // Awaited only when compression actually runs, so an uncompressed request\n // still calls `fetch` synchronously the way it did before compression.\n const prepared = encodeRequestBody(body)\n const encoded = prepared instanceof Promise ? await prepared : prepared\n return this.sendPrepared<T>(endpoint, encoded, options)\n }\n\n private async sendPrepared<T>(\n endpoint: string,\n encoded: EncodedRequestBody,\n options?: { timeout?: number; method?: \"POST\" | \"PATCH\" | \"PUT\" },\n ): Promise<T> {\n const url = `${this.serviceUrl}${endpoint}`\n const timeout = options?.timeout ?? this.timeout\n const method = options?.method ?? \"POST\"\n\n const controller = new AbortController()\n const timeoutId = setTimeout(() => controller.abort(), timeout)\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${this.resolveApiKey() ?? \"\"}`,\n }\n if (encoded.contentEncoding) {\n headers[\"Content-Encoding\"] = encoded.contentEncoding\n }\n\n try {\n const response = await fetch(url, {\n method,\n headers,\n body: encoded.body,\n signal: controller.signal,\n })\n\n if (!response.ok) {\n const errorText = await response.text()\n throw new BitfabError(\n `HTTP ${response.status}: ${errorText.slice(0, 500)}`,\n undefined,\n response.status,\n parseRetryAfterMs(readHeader(response, \"retry-after\")),\n )\n }\n\n const result = await response.json()\n\n // Check for errors in the response\n if (result.error) {\n if (result.url) {\n throw new BitfabError(\n `${result.error} Configure it at: ${this.serviceUrl}${result.url}`,\n result.url,\n )\n }\n throw new BitfabError(result.error)\n }\n\n return result as T\n } catch (error) {\n if (error instanceof BitfabError) {\n throw error\n }\n if (error instanceof Error) {\n if (error.name === \"AbortError\") {\n throw new BitfabError(`Request timed out after ${timeout}ms`)\n }\n throw new BitfabError(error.message)\n }\n throw new BitfabError(\"Unknown error occurred\")\n } finally {\n clearTimeout(timeoutId)\n }\n }\n\n /**\n * Look up a function by name.\n * Blocks until complete - needed for function execution.\n */\n async lookupFunction<T>(name: string): Promise<T> {\n return this.request<T>(\"/api/sdk/functions/lookup\", { name })\n }\n\n async getAutoTracePolicy<T>(\n traceFunctionKey: string,\n protocol: string,\n ): Promise<T> {\n return this.request<T>(\"/api/sdk/auto-trace/policy\", {\n traceFunctionKey,\n protocol,\n })\n }\n\n async getTraceSpan(\n traceId: string,\n lookup: SpanLookup,\n ): Promise<CapturedSpan | null> {\n const searchParams = new URLSearchParams()\n if (lookup.id !== undefined) {\n searchParams.set(\"id\", lookup.id)\n } else {\n searchParams.set(\"name\", lookup.name)\n searchParams.set(\"occurrence\", String(lookup.occurrence ?? \"last\"))\n }\n\n const endpoint = `/api/sdk/traces/${encodeURIComponent(traceId)}/span?${searchParams.toString()}`\n const response = await this.get<{ span: CapturedSpan | null }>(endpoint)\n return response.span\n }\n\n /**\n * GET a JSON endpoint on the service with the client's API key. Throws a\n * `BitfabError` carrying the status text for any non-2xx response.\n */\n async get<T>(endpoint: string): Promise<T> {\n const url = `${this.serviceUrl}${endpoint}`\n const controller = new AbortController()\n const timeoutId = setTimeout(() => controller.abort(), this.timeout)\n\n try {\n const response = await fetch(url, {\n method: \"GET\",\n headers: { Authorization: `Bearer ${this.resolveApiKey() ?? \"\"}` },\n signal: controller.signal,\n })\n if (!response.ok) {\n const errorText = await response.text()\n throw new BitfabError(\n `HTTP ${response.status}: ${errorText.slice(0, 500)}`,\n undefined,\n response.status,\n parseRetryAfterMs(readHeader(response, \"retry-after\")),\n )\n }\n return (await response.json()) as T\n } catch (error) {\n if (error instanceof BitfabError) {\n throw error\n }\n if (error instanceof Error) {\n if (error.name === \"AbortError\") {\n throw new BitfabError(`Request timed out after ${this.timeout}ms`)\n }\n throw new BitfabError(error.message)\n }\n throw new BitfabError(\"Unknown error occurred\")\n } finally {\n clearTimeout(timeoutId)\n }\n }\n\n /**\n * Queue an internal trace (from local BAML execution via `call()`) onto this\n * client's batching transport. `functionId` moves into the payload because\n * the OTLP carrier has no path to carry it.\n */\n sendInternalTrace(\n functionId: string,\n payload: Record<string, unknown>,\n ): void {\n const body = {\n ...payload,\n functionId,\n sdkPackage: __packageName__,\n sdkVersion: __version__,\n }\n this.getTraceTransport()?.submit(\n \"internal_trace\",\n body,\n carrierMeta(\"internal_trace\", body, undefined),\n )\n }\n\n /**\n * Queue an external span (from withSpan wrapper or OpenAI tracing) onto this\n * client's batching transport. Fire-and-forget: the transport owns delivery,\n * so callers await `flushTraces()` or `close()` rather than a per-span\n * promise.\n */\n sendExternalSpan(payload: Record<string, unknown>): void {\n this.getTraceTransport()?.submit(\n \"external_span\",\n { ...payload, sdkVersion: __version__ },\n this.recordedMeta(\"external_span\", payload, carrierRef(payload)),\n )\n }\n\n /**\n * Queue an external trace completion (from OpenAI tracing) onto this\n * client's batching transport. Fire-and-forget for the same reason as\n * {@link HttpClient.sendExternalSpan}; replay confirms persistence with the\n * server-authoritative barrier in `replay.ts`, not by awaiting this call.\n */\n sendExternalTrace(payload: Record<string, unknown>): void {\n this.getTraceTransport()?.submit(\n \"external_trace\",\n {\n ...payload,\n sdkPackage: __packageName__,\n sdkVersion: __version__,\n },\n this.recordedMeta(\n \"external_trace\",\n payload,\n payload.completed === true ? carrierRef(payload) : undefined,\n ),\n )\n }\n\n /**\n * Partial update of an existing trace identified by its Bitfab trace ID.\n * Used by the detached `client.getTrace(id)` handle.\n *\n * Blocking, like the other trace-API calls: it resolves once the server has\n * applied the change and rejects if the server refused it. A patch targets a\n * trace that is already closed, so there is no batch for it to ride along\n * with and no later signal that would reveal a silent failure.\n */\n async patchTrace(\n traceId: string,\n payload: {\n appendContexts?: Record<string, unknown>[]\n mergeMetadata?: Record<string, unknown>\n setSessionId?: string\n setName?: string\n },\n ): Promise<void> {\n const endpoint = `/api/sdk/traces/${encodeURIComponent(traceId)}`\n await this.request(endpoint, payload, { method: \"PATCH\" })\n }\n\n /**\n * Start a replay session by fetching historical traces.\n * Blocking call - creates a test run and returns lightweight item references.\n */\n async startReplay(\n traceFunctionKey: string,\n limit: number | undefined,\n traceIds?: string[],\n name?: string,\n codeChangeDescription?: string | null,\n codeChangeFiles?: CodeChangeFile[] | null,\n includeDbBranchLease?: boolean,\n experimentGroupId?: string,\n datasetId?: string,\n graderIds?: string[],\n dbBranchSettings?: DbBranchSettings,\n attempts?: number,\n includeOriginalMetadata?: boolean,\n ): Promise<StartReplayResponse> {\n // limit is only meaningful without traceIds (an explicit ID list\n // already determines the count), so it's omitted when undefined.\n const payload: Record<string, unknown> = { traceFunctionKey }\n if (limit !== undefined) {\n payload.limit = limit\n }\n if (traceIds) {\n payload.traceIds = traceIds\n }\n if (name !== undefined) {\n payload.name = name\n }\n if (codeChangeDescription !== undefined) {\n payload.codeChangeDescription = codeChangeDescription\n }\n if (codeChangeFiles !== undefined) {\n payload.codeChangeFiles = codeChangeFiles\n }\n if (includeDbBranchLease) {\n payload.includeDbBranchLease = true\n payload.lazyDbBranchLease = true\n }\n if (experimentGroupId !== undefined) {\n payload.experimentGroupId = experimentGroupId\n }\n if (datasetId !== undefined) {\n payload.datasetId = datasetId\n }\n if (graderIds !== undefined) {\n payload.graderIds = graderIds\n }\n if (dbBranchSettings !== undefined) {\n payload.dbBranchSettings = dbBranchSettings\n }\n if (attempts !== undefined && attempts > 1) {\n payload.attempts = attempts\n }\n if (includeOriginalMetadata) {\n payload.includeOriginalMetadata = true\n }\n // When DB branching is on, the server resolves a Neon preview branch\n // per item (snapshot + restore + poll), which can run ~5-10s each, and\n // runs any `warmupSql` against each branch on a 240s budget of its own.\n // The server gives up at 280s and answers, so this is a backstop for a\n // reply that never comes rather than the thing that normally fires; it\n // sits above the server's own ceiling so the server's error is the one\n // callers see. Not raisable in practice either: undici's default\n // `headersTimeout` is also 300s and `fetch` cannot override it per\n // request.\n const timeout = includeDbBranchLease\n ? REPLAY_DB_BRANCH_REQUEST_TIMEOUT_MS\n : 30_000\n return this.request<StartReplayResponse>(\"/api/sdk/replay/start\", payload, {\n timeout,\n })\n }\n\n /**\n * Fetch an external span by ID.\n * Blocking GET request.\n * The replay view limits rawData to input/output serialization fields.\n */\n async getExternalSpan(\n spanId: string,\n options?: { view?: \"full\" | \"replay\" },\n ): Promise<ExternalSpanResponse> {\n const query = options?.view === \"replay\" ? \"?view=replay\" : \"\"\n const url = `${this.serviceUrl}/api/sdk/externalSpans/${spanId}${query}`\n const controller = new AbortController()\n const timeoutId = setTimeout(() => controller.abort(), 30_000)\n\n try {\n const response = await fetch(url, {\n method: \"GET\",\n headers: { Authorization: `Bearer ${this.resolveApiKey() ?? \"\"}` },\n signal: controller.signal,\n })\n\n if (!response.ok) {\n const errorText = await response.text()\n throw new BitfabError(\n `HTTP ${response.status}: ${errorText.slice(0, 500)}`,\n )\n }\n\n return (await response.json()) as ExternalSpanResponse\n } catch (error) {\n if (error instanceof BitfabError) {\n throw error\n }\n if (error instanceof Error) {\n if (error.name === \"AbortError\") {\n throw new BitfabError(\"Request timed out after 30000ms\")\n }\n throw new BitfabError(error.message)\n }\n throw new BitfabError(\"Unknown error occurred\")\n } finally {\n clearTimeout(timeoutId)\n }\n }\n\n /**\n * Fetch the span tree for a root span.\n * Blocking GET request.\n *\n * Pass `includeOutputs: false` for a payload-free tree (structure +\n * `externalSpanId` only), so recorded outputs are fetched lazily per mocked\n * span instead of all up front. Omit it (default eager) for `mock: \"all\"`.\n * Pass `includeRootOutput: false` when the root was already fetched.\n */\n async getSpanTree(\n externalSpanId: string,\n options?: { includeOutputs?: boolean; includeRootOutput?: boolean },\n ): Promise<SpanTreeResponse> {\n const searchParams = new URLSearchParams()\n if (options?.includeOutputs === false) {\n searchParams.set(\"includeOutputs\", \"false\")\n }\n if (options?.includeRootOutput === false) {\n searchParams.set(\"includeRootOutput\", \"false\")\n }\n const encodedQuery = searchParams.toString()\n const query = encodedQuery ? `?${encodedQuery}` : \"\"\n const url = `${this.serviceUrl}/api/sdk/replay/spanTree/${externalSpanId}${query}`\n const controller = new AbortController()\n const timeoutId = setTimeout(() => controller.abort(), 30_000)\n\n try {\n const response = await fetch(url, {\n method: \"GET\",\n headers: { Authorization: `Bearer ${this.resolveApiKey() ?? \"\"}` },\n signal: controller.signal,\n })\n\n if (!response.ok) {\n const errorText = await response.text()\n throw new BitfabError(\n `HTTP ${response.status}: ${errorText.slice(0, 500)}`,\n )\n }\n\n return (await response.json()) as SpanTreeResponse\n } catch (error) {\n if (error instanceof BitfabError) {\n throw error\n }\n if (error instanceof Error) {\n if (error.name === \"AbortError\") {\n throw new BitfabError(\"Request timed out after 30000ms\")\n }\n throw new BitfabError(error.message)\n }\n throw new BitfabError(\"Unknown error occurred\")\n } finally {\n clearTimeout(timeoutId)\n }\n }\n\n /**\n * Read which of a replay run's traces the server has fully persisted.\n *\n * With `expectedSpanCounts`, a trace appears in the response only once it\n * has a final status AND at least that many persisted spans, which is what\n * makes this a real barrier rather than a \"the row exists\" check.\n */\n async getReplayStatus(\n testRunId: string,\n expectedSpanCounts: Record<string, number>,\n ): Promise<ReplayStatusResponse> {\n return this.request<ReplayStatusResponse>(\n \"/api/sdk/replay/status\",\n { testRunId, expectedSpanCounts },\n { timeout: 30_000 },\n )\n }\n\n /**\n * Mark a replay test run as completed.\n * Blocking call.\n */\n async completeReplay(testRunId: string): Promise<CompleteReplayResponse> {\n return this.request<CompleteReplayResponse>(\n \"/api/sdk/replay/complete\",\n { testRunId },\n { timeout: REPLAY_COMPLETE_REQUEST_TIMEOUT_MS },\n )\n }\n\n /**\n * Ask the server to materialize a per-trace DB branch lease from a\n * captured `dbSnapshotRef`. Blocking - the resolver creates a Neon\n * snapshot + preview branch and polls operations to readiness, which\n * can take seconds.\n */\n async resolveDbBranchLease(\n testRunId: string,\n traceId: string,\n dbBranchSettings?: DbBranchSettings,\n attempt?: number,\n ): Promise<{\n dbSnapshotRef: DbSnapshotRef | null\n lease: DbBranchLease | null\n leaseError: { code: string; message: string } | null\n timings: DbBranchTimings | null\n }> {\n return this.request<{\n dbSnapshotRef: DbSnapshotRef | null\n lease: DbBranchLease | null\n leaseError: { code: string; message: string } | null\n timings: DbBranchTimings | null\n }>(\n \"/api/sdk/replay/resolveDbBranchLease\",\n {\n testRunId,\n traceId,\n dbBranchSettings,\n ...(attempt !== undefined && attempt > 0 ? { attempt } : {}),\n },\n { timeout: REPLAY_DB_BRANCH_REQUEST_TIMEOUT_MS },\n )\n }\n\n /** Release a previously-resolved DB branch by deleting its Neon branch. Idempotent server-side. */\n async releaseDbBranchLease(neonBranchId: string): Promise<void> {\n await this.request<{ released: true }>(\n \"/api/sdk/replay/releaseDbBranchLease\",\n { neonBranchId },\n { timeout: 30_000 },\n )\n }\n}\n\nexport interface TokenUsage {\n input: number | null\n output: number | null\n cached: number | null\n total: number | null\n}\n\n/**\n * Describes a single file edited as part of a code change.\n *\n * - `path`: file path (relative to the repo root, or any consistent root)\n * - `before`: file contents before the change (\"\" for newly created files)\n * - `after`: file contents after the change (\"\" for deleted files)\n */\nexport interface CodeChangeFile {\n path: string\n before: string\n after: string\n}\n\nexport interface StartReplayResponse {\n testRunId: string\n testRunUrl: string\n attempts?: number\n items: Array<{\n /** Bitfab trace ID of the original (historical) trace being replayed. */\n originalTraceId?: string\n /** External span ID the recorded inputs were read from (the original root span). */\n originalSpanId?: string\n /** @deprecated alias for `originalTraceId`; the only key emitted by servers that predate the rename. */\n sourceTraceId: string\n /** @deprecated alias for `originalSpanId`; the only key emitted by servers that predate the rename. */\n sourceSpanId: string\n durationMs: number | null\n tokens: TokenUsage | null\n model: string | null\n /**\n * The DB snapshot ref captured by the SDK at trace open. Surfaced so\n * the SDK can pass it to the lease-resolver step (or report when no\n * snapshot was captured for this trace).\n */\n dbSnapshotRef?: DbSnapshotRef\n /**\n * Populated once the server-side resolver has materialized a per-item\n * branch from `dbSnapshotRef`. The SDK exposes this to customer code\n * via `getCurrentReplayBranch()`. Absent until the resolver lands.\n */\n dbBranchLease?: DbBranchLease\n /**\n * Why the branch could not be resolved, when one was requested and the\n * attempt failed. Distinct from both fields being absent, which means the\n * trace carried no snapshot ref so nothing was attempted.\n */\n dbBranchLeaseError?: { code: string; message: string }\n /**\n * How long provisioning took, per phase. Sits beside the two fields above\n * rather than inside either: it is reported on both outcomes, complete on\n * success and partial up to the failing phase on error. Absent from\n * servers that predate it.\n */\n dbBranchTimings?: DbBranchTimings\n originalMetadata?: Record<string, unknown>\n }>\n}\n\nexport interface ExternalSpanResponse {\n id: string\n externalTraceId: string\n rawData: {\n span_data: {\n input: unknown\n output: unknown\n input_meta?: unknown\n output_meta?: unknown\n input_serialized?: { json: unknown; meta: unknown }\n output_serialized?: { json: unknown; meta: unknown }\n }\n }\n}\n\nexport interface ReplayStatusResponse {\n /**\n * Local replay trace id -> server trace row id, for the traces the server\n * considers fully persisted. Traces still short of their expected span count\n * are simply absent.\n */\n traceIds?: Record<string, string>\n}\n\nexport interface CompleteReplayResponse {\n id: string\n status: string\n traceIds?: Record<string, string>\n /**\n * Per-replay-trace token usage, keyed by the server trace id (the values of\n * `traceIds`). Aggregated server-side from the freshly-uploaded replay spans,\n * so it's the REPLAYED run's tokens (the same source Studio reads), not the\n * original trace's. The SDK maps each item onto this to set\n * `ReplayItem.tokens`. Absent on servers that predate this field.\n */\n tokens?: Record<string, TokenUsage | null>\n /**\n * Number of traces the server has persisted for this test run at\n * completion time. Lets the SDK distinguish \"uploads failed\" from\n * \"server never saw them\" when the trace-ID mapping is incomplete.\n */\n traceCount?: number\n}\n\nexport interface SpanTreeNode {\n /** Upstream platform span id. Stable structural identity; NOT the row id. */\n sourceSpanId: string\n /**\n * The `externalSpans` row id, accepted by {@link HttpClient.getExternalSpan}.\n * Distinct from `sourceSpanId`; used to lazily fetch this node's output when\n * the tree was fetched with `includeOutputs: false`. Optional so trees from\n * older servers (which omit it) still deserialize.\n */\n externalSpanId?: string\n traceFunctionKey: string\n spanName: string\n type: string\n /** Omitted when the tree was fetched payload-free (`includeOutputs: false`). */\n output?: unknown\n outputMeta?: unknown\n children: SpanTreeNode[]\n}\n\nexport interface SpanTreeResponse {\n root: SpanTreeNode\n}\n","/**\n * Serialization utilities for Bitfab SDK.\n *\n * This module provides serialization with type metadata preservation,\n * using superjson for handling special JavaScript types like Date, Map,\n * Set, BigInt, undefined, etc.\n */\n\nimport superjson from \"superjson\"\nimport { MAX_COMPRESSIBLE_SPAN_CARRIER_BYTES } from \"./payloadBudget.js\"\nimport { warnOnce } from \"./warnOnce.js\"\n\n/**\n * Serialized value with JSON data and optional superjson meta for type preservation.\n *\n * The json field contains the JSON-serializable data.\n * The meta field (if present) contains superjson type information for deserializing\n * special types like Date, Map, Set, BigInt, etc.\n */\nexport interface SerializedValue {\n json: unknown\n meta?: unknown\n}\n\n// Cap on a single serialized value. superjson can succeed on values like SDK\n// client instances (OpenAI, etc.) and produce hundreds of KB to MB of useless\n// internal state, so this is the cheap early-out that stops the walk before a\n// pathological object is carried any further. It is deliberately the same\n// number as the whole-span budget: one legitimately large value may use the\n// entire budget, and `serializePayloadBody` is what enforces the total once\n// every field is in. Anything past it is replaced with a stub so the span\n// still ships and the trace isn't dropped server-side.\nconst MAX_SERIALIZED_BYTES = MAX_COMPRESSIBLE_SPAN_CARRIER_BYTES\n\n// The framework-capture path (toJsonSafe) shares that ceiling. Agent/graph\n// states (LangGraph, Claude Agent SDK) are legitimately larger than a single\n// function's args/return, and capping them lower than ordinary values only\n// discarded detail the span had room for.\nconst MAX_FRAMEWORK_SERIALIZED_BYTES = MAX_COMPRESSIBLE_SPAN_CARRIER_BYTES\n\nfunction describeValue(value: unknown): string {\n try {\n const ctorName = (value as { constructor?: { name?: string } })?.constructor\n ?.name\n if (ctorName && ctorName !== \"Object\") {\n return ctorName\n }\n } catch {\n // Property access on `value` can throw (Proxy, poisoned getter).\n }\n return typeof value\n}\n\nfunction unserializableStub(value: unknown, reason: string): SerializedValue {\n // Normalize the byte count out of the key so a too_large warning dedups\n // across differently-sized payloads instead of warning once per size.\n warnOnce(\n `serialize:${reason.replace(/\\d+/g, \"N\")}`,\n `a value could not be fully serialized for a span (${reason}); it was replaced with a placeholder. The span still ships, but its captured input/output is incomplete.`,\n )\n let summary: string\n try {\n summary = `<unserializable: ${describeValue(value)} (${reason})>`\n } catch {\n summary = `<unserializable (${reason})>`\n }\n return { json: summary }\n}\n\n/**\n * Serialize a value using superjson for trace storage.\n *\n * Handles arbitrary JavaScript values including:\n * - Date, RegExp, Error\n * - Map, Set\n * - BigInt\n * - undefined (in objects/arrays)\n * - Circular references\n *\n * Guarantees:\n * - Never throws. Pathological inputs (SDK clients, proxies, poisoned\n * getters, circular graphs that defeat superjson) return a stub string.\n * - Never returns a payload larger than MAX_SERIALIZED_BYTES; oversized\n * inputs are replaced with a stub. Without this the wire-side\n * `JSON.stringify` in http.ts can produce a request that times out or\n * gets rejected, leaving a trace with zero spans.\n *\n * @param value - Any JavaScript value to serialize\n * @returns SerializedValue with 'json' field containing the data.\n * If type metadata is needed for reconstruction, includes 'meta' field.\n *\n * @example\n * ```typescript\n * const result = serializeValue(new Date('2024-01-15T10:30:00Z'))\n * // result.json contains the ISO string\n * // result.meta contains type info for Date reconstruction\n * ```\n */\nexport function serializeValue(value: unknown): SerializedValue {\n try {\n const { json, meta } = superjson.serialize(value)\n\n let size: number\n try {\n size = JSON.stringify(json).length\n } catch {\n return unserializableStub(value, \"stringify_failed_after_superjson\")\n }\n if (size > MAX_SERIALIZED_BYTES) {\n return unserializableStub(value, `too_large_${size}_bytes`)\n }\n\n return meta ? { json, meta } : { json }\n } catch {\n try {\n return { json: JSON.parse(JSON.stringify(value)) }\n } catch {\n return unserializableStub(value, \"json_stringify_failed\")\n }\n }\n}\n\n/**\n * Deserialize a value that was serialized with serializeValue.\n *\n * @param serialized - A SerializedValue object with 'json' and optional 'meta'\n * @returns The reconstructed JavaScript value\n *\n * @example\n * ```typescript\n * const serialized = serializeValue(new Date('2024-01-15'))\n * const date = deserializeValue(serialized)\n * // date is a Date object\n * ```\n */\nexport function deserializeValue(serialized: SerializedValue): unknown {\n if (serialized.meta === undefined) {\n // No metadata, return as-is\n return serialized.json\n }\n\n // Use superjson to deserialize with type reconstruction\n // Cast json to the expected superjson type\n type SuperJSONResult = Parameters<typeof superjson.deserialize>[0]\n return superjson.deserialize({\n json: serialized.json as SuperJSONResult[\"json\"],\n meta: serialized.meta as SuperJSONResult[\"meta\"],\n })\n}\n\nconst MAX_SAFE_DEPTH = 6\n\n/**\n * Convert any value to JSON-safe primitives, never throwing.\n *\n * Produces plain objects/arrays/scalars, recursing through `toJSON()` and\n * own-enumerable properties so no raw non-serializable value (a class, a\n * BigInt-bearing object) survives into a span payload. Cycles collapse to a\n * `<cycle ...>` marker; depth is capped.\n *\n * This is the single shared \"safe serialize\" used by the framework\n * integrations that capture raw objects (LangGraph, Claude Agent SDK). Keeping\n * the recurse-the-dump logic here, in one place, is what stops a new\n * integration from reintroducing the \"dump without recursing\" bug - see\n * `serializationInvariant.test.ts`.\n */\nexport function toJsonSafe(value: unknown): unknown {\n return toJsonSafeReport(value).safe\n}\n\n/**\n * Like {@link toJsonSafe}, but also reports what could not be faithfully\n * captured.\n *\n * Returns `{ safe, dropped }` where `dropped` lists the type name behind every\n * placeholder the walker had to emit: a cycle, a max-depth cut, an oversized\n * payload, or a value that could only be stringified (a function/symbol) or\n * stubbed after a throw. A non-empty `dropped` means the captured input/output\n * is lossy. Framework handlers carry it to the send boundary so a degraded\n * capture is marked non-replayable (`serialization_degraded`) instead of being\n * shipped as if it round-trips - mirrors the Python SDK's `to_json_safe_report`\n * + `finalize_span_payload`.\n */\nexport function toJsonSafeReport(value: unknown): {\n safe: unknown\n dropped: string[]\n} {\n const dropped: string[] = []\n const safe = toJsonSafeInner(value, 0, new WeakSet(), dropped)\n // Cap output size for parity with serializeValue. A multi-MB framework\n // payload (a large LangGraph state, a long message history) would otherwise\n // be JSON.stringify'd synchronously on the user's thread in http.ts and may\n // be rejected server-side, leaving a trace with zero spans. Stub it instead\n // so the span still ships. toJsonSafeInner produces only plain\n // objects/arrays/scalars/strings, so JSON.stringify here cannot throw; the\n // try is belt-and-suspenders.\n try {\n const size = JSON.stringify(safe)?.length ?? 0\n if (size > MAX_FRAMEWORK_SERIALIZED_BYTES) {\n warnOnce(\n \"toJsonSafe:too_large\",\n `a framework payload exceeded ${MAX_FRAMEWORK_SERIALIZED_BYTES} bytes and was replaced with a placeholder so the span still ships. The captured state for this span is incomplete.`,\n )\n // Keep any drops already accumulated by the walk (cycles, functions,\n // depth cuts); a payload can be both lossy AND oversized, and the\n // non-replayable marking needs the real types, not just the size stub.\n return {\n safe: `<unserializable: too_large_${size}_bytes>`,\n dropped: [...dropped, `too_large_${size}_bytes`],\n }\n }\n } catch {\n // Keep the recursed value; the http-layer sanitizer is the final backstop.\n }\n return { safe, dropped }\n}\n\nfunction toJsonSafeInner(\n value: unknown,\n depth: number,\n seen: WeakSet<object>,\n dropped: string[],\n): unknown {\n if (value === null || value === undefined) {\n return value\n }\n if (\n typeof value === \"string\" ||\n typeof value === \"number\" ||\n typeof value === \"boolean\"\n ) {\n return value\n }\n\n const className =\n (value as { constructor?: { name?: string } })?.constructor?.name ??\n typeof value\n if (depth > MAX_SAFE_DEPTH) {\n dropped.push(className)\n return `<${className}>`\n }\n\n // Non-object composites (bigint, function, symbol) stringify directly. A\n // bigint stringifies faithfully; a function/symbol becomes a lossy summary,\n // so those are reported as dropped.\n if (typeof value !== \"object\") {\n if (typeof value === \"function\" || typeof value === \"symbol\") {\n dropped.push(className)\n }\n try {\n return String(value)\n } catch {\n dropped.push(className)\n return `<${className}>`\n }\n }\n\n if (seen.has(value as object)) {\n dropped.push(className)\n return `<cycle ${className}>`\n }\n seen.add(value as object)\n\n let result: unknown\n if (Array.isArray(value)) {\n result = value.map((item) =>\n toJsonSafeInner(item, depth + 1, seen, dropped),\n )\n } else if (typeof (value as Record<string, unknown>).toJSON === \"function\") {\n // Recurse toJSON() output: it can still hold non-serializable values (e.g.\n // a LangChain tool whose schema is a class) that would otherwise survive\n // into the span payload and crash the wire-side JSON.stringify.\n try {\n result = toJsonSafeInner(\n (value as { toJSON(): unknown }).toJSON(),\n depth + 1,\n seen,\n dropped,\n )\n } catch {\n dropped.push(className)\n result = `<${className}>`\n }\n } else {\n try {\n const obj: Record<string, unknown> = {}\n for (const [k, v] of Object.entries(value)) {\n if (!k.startsWith(\"_\")) {\n obj[k] = toJsonSafeInner(v, depth + 1, seen, dropped)\n }\n }\n result = obj\n } catch {\n dropped.push(className)\n result = `<${className}>`\n }\n }\n\n // Backtrack: keep only ancestors on the current path in `seen`, so a shared\n // (DAG) reference under sibling keys is serialized again rather than stubbed\n // as a false cycle. Real cycles (an ancestor referencing itself) are still\n // caught above.\n seen.delete(value as object)\n return result\n}\n","/**\n * Generate a UUID v4 without assuming a global `crypto`.\n *\n * `crypto.randomUUID()` is the fast path and exists in every mainstream modern\n * runtime (Node >= 19, all browsers, Deno, Vercel edge, Cloudflare Workers).\n * But the SDK must NEVER crash a host app, and a few runtimes it can legitimately\n * run in lack a global `crypto` or `crypto.randomUUID` (Node < 19 without a\n * polyfill, older React Native, some sandboxes). There, an unguarded\n * `crypto.randomUUID()` throws on the user's call path. This helper falls back\n * to a `Math.random()`-based v4 string instead.\n *\n * The fallback is NOT cryptographically secure. That is fine: trace and span\n * IDs only need to be unique enough to correlate the spans of one trace; they\n * are never security-sensitive.\n */\nimport { warnOnce } from \"./warnOnce.js\"\n\nexport function randomUuid(): string {\n const globalCrypto = (\n globalThis as { crypto?: { randomUUID?: () => string } }\n ).crypto\n if (typeof globalCrypto?.randomUUID === \"function\") {\n try {\n return globalCrypto.randomUUID()\n } catch {\n // Fall through to the manual generator below.\n }\n }\n warnOnce(\n \"crypto-unavailable\",\n \"global crypto.randomUUID is unavailable; using a non-cryptographic fallback for trace/span ids. Tracing works normally (ids are correlation-only, not security-sensitive).\",\n )\n return fallbackUuidV4()\n}\n\n/**\n * RFC 4122 version 4 layout filled from `Math.random()`. Used only when a usable\n * global `crypto.randomUUID` is unavailable.\n */\nfunction fallbackUuidV4(): string {\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, (char) => {\n const rand = (Math.random() * 16) | 0\n const value = char === \"x\" ? rand : (rand & 0x3) | 0x8\n return value.toString(16)\n })\n}\n","/**\n * Selective mock overrides for replay.\n *\n * A mock override injects a custom value into a specific span (node) during\n * replay: the matched span short-circuits its real execution and returns the\n * value you supply, so downstream real code runs against the substituted\n * output. This is a third mock mode alongside \"run real code\" and \"replay\n * recorded output\" (see {@link MockStrategy}).\n *\n * The matcher and value are deliberately separate so matching stays cheap\n * (structural metadata only, no output fetch) and the recorded output is\n * fetched lazily - and only if the value function actually asks for it via\n * {@link MockOverrideCtx.getOriginalOutput}.\n */\n\n/**\n * Structural identity of a span during replay, passed to a {@link NodeMatcher}.\n * Carries no output payload - matching must not depend on the recorded output,\n * so the output fetch stays lazy and gated.\n */\nexport interface SpanNodeMeta {\n /** The `withSpan` key of the executing span (its code-side identity). */\n traceFunctionKey: string\n /** Resolved span name: `options.name ?? fn.name ?? traceFunctionKey`. */\n spanName: string\n /** Span type, e.g. \"llm\", \"agent\", \"tool\", \"custom\". */\n type: string\n /**\n * The id of this span in the original (replayed) trace, when it exists in\n * that trace's tree. Undefined when the live span has no recorded\n * counterpart (e.g. a span the changed code newly introduced).\n */\n originalSpanId?: string\n}\n\n/** Context passed to a {@link MockValue} function for a matched span. */\nexport interface MockOverrideCtx {\n /** The matched span's structural metadata. */\n node: SpanNodeMeta\n /** The live replay args passed to the wrapped function this run. */\n inputs: unknown[]\n /**\n * Lazily fetch this span's ORIGINAL recorded output (deserialized). The fetch\n * happens only when called and is memoized per replay item, so a purely flat\n * override that never calls it triggers zero output round trips. Rejects if\n * the span has no recorded counterpart. Being async, it is only usable for\n * spans wrapping async functions.\n */\n getOriginalOutput: () => Promise<unknown>\n}\n\n/**\n * Return this from a mock override resolver to decline the override for the\n * current span. Resolution continues with the next override, then the replay's\n * base mock strategy.\n */\nexport const NO_MOCK_OVERRIDE = Symbol(\"bitfab.noMockOverride\")\n\n/** Selects which spans an override applies to. Runs on structural metadata. */\nexport type NodeMatcher = (node: SpanNodeMeta) => boolean\n\n/** The function form of {@link MockValue}, receiving the override context. */\nexport type MockValueFn = (ctx: MockOverrideCtx) => unknown | Promise<unknown>\n\n/**\n * A client-wide, keyed, or per-replay resolver. A global resolver can route on\n * `ctx.node.traceFunctionKey`; a keyed resolver is only invoked for spans with\n * its registered key. Return {@link NO_MOCK_OVERRIDE} for spans the resolver\n * does not want to override.\n */\nexport type MockOverrideResolver = (\n ctx: MockOverrideCtx,\n) => unknown | Promise<unknown>\n\n/**\n * The value injected for a matched span: either a flat value used as-is, or a\n * function of the {@link MockOverrideCtx} that returns one (or a Promise of\n * one). Full replacement - the value IS the span's output, no merge with the\n * recorded output.\n *\n * The flat side is spelled out (rather than `unknown`) so an inline function\n * still gets a typed `ctx`: `unknown | Fn` would collapse to `unknown` and drop\n * the contextual type. To inject a value that is itself a function, wrap it:\n * `value: () => theFunction`.\n */\nexport type MockValue =\n | MockValueFn\n | string\n | number\n | boolean\n | bigint\n | symbol\n | object\n | null\n | undefined\n\n/** One (match, value) pair. */\nexport interface MockOverride {\n match: NodeMatcher\n value: MockValue\n}\n\n/** Accepted shape for one mock override declaration. */\nexport type MockOverrideInput = MockOverride | MockOverrideResolver\n\n/**\n * Resolve an override's `value`: call it with `ctx` when it's a function, else\n * use it as-is (a flat value).\n */\nexport function resolveMockValue(\n value: MockValue,\n ctx: MockOverrideCtx,\n): unknown | Promise<unknown> {\n return typeof value === \"function\"\n ? (value as (c: MockOverrideCtx) => unknown | Promise<unknown>)(ctx)\n : value\n}\n\n/**\n * Normalize the per-call `mockOverride` option (an override pair, a global\n * resolver, an array, or nothing) into an ordered internal override array.\n */\nexport function normalizeMockOverrides(\n mockOverride?: MockOverrideInput | MockOverrideInput[],\n): MockOverride[] {\n if (mockOverride === undefined) {\n return []\n }\n const overrides = Array.isArray(mockOverride) ? mockOverride : [mockOverride]\n return overrides.map((override) =>\n typeof override === \"function\"\n ? { match: () => true, value: override }\n : override,\n )\n}\n\n/**\n * What a replay mock replaced on a span, and where the replacement came from.\n * Reported alongside `mocked` so a trace can say how a span was produced rather\n * than only that it was not re-run.\n *\n * `target` is `\"output\"` for every mock today: both the recorded-output path\n * and an override short-circuit the call. `\"input\"` is reserved for\n * substituting a span's arguments and letting the real code run.\n */\nexport type MockTarget = \"output\" | \"input\"\n\n/**\n * `recorded` is the original trace's own value; `override` is one the caller\n * supplied via `mockOverride` / `registerMockOverride`. Deliberately not\n * \"dynamic\": an override value may be a flat constant.\n */\nexport type MockSource = \"recorded\" | \"override\"\n","import type { CodeChangeFile } from \"./http\"\n\n/**\n * Auto-capture the code change to attach to a replay, when the caller passed\n * none explicitly.\n *\n * This lives in the SDK (not a wrapper) on purpose: `replay()` is the only point\n * guaranteed to run on every replay, so capturing here works no matter how the\n * replay was launched (plugin wrapper, a hand-run script, CI). Precedence:\n *\n * 1. `BITFAB_CODE_CHANGE_PATH` file — an override a caller/tool can inject.\n * 2. `git diff` vs trunk — the default fallback.\n *\n * Both are best-effort and browser-safe: any failure (no git, no fs, not a repo,\n * bad JSON) yields `null` and the replay proceeds with no code change. The diff\n * is cumulative (whole branch vs trunk), not per-experiment; an explicit\n * `codeChangeFiles` on `replay()` always wins over this and is what carries a\n * precise per-experiment before/after.\n */\n\nexport interface ResolvedCodeChange {\n description?: string\n files?: CodeChangeFile[]\n}\n\n// Bounds so a large delta never bloats the experiment payload.\nconst MAX_FILES = 60\nconst MAX_FILE_BYTES = 500_000\nconst MAX_TOTAL_BYTES = 2_000_000\n\n// Candidate trunk refs, tried in order, when no explicit base is supplied.\nconst TRUNK_CANDIDATES = [\n \"origin/HEAD\",\n \"origin/main\",\n \"origin/master\",\n \"main\",\n \"master\",\n]\n\nconst NUL = String.fromCharCode(0)\n\n/**\n * Resolve an auto code change: the `BITFAB_CODE_CHANGE_PATH` override first,\n * then the git-vs-trunk diff. Returns null when neither yields anything.\n */\nexport async function resolveAutoCodeChange(\n label?: string,\n): Promise<ResolvedCodeChange | null> {\n if (typeof process === \"undefined\") {\n return null\n }\n if (process.env?.BITFAB_DISABLE_CODE_CHANGE_CAPTURE) {\n return null\n }\n const fromEnv = await readCodeChangeFile()\n if (fromEnv) {\n return fromEnv\n }\n return captureCodeChangeFromGit(process.cwd?.() ?? \".\", label)\n}\n\nasync function readCodeChangeFile(): Promise<ResolvedCodeChange | null> {\n const path = process.env?.BITFAB_CODE_CHANGE_PATH\n if (!path) {\n return null\n }\n try {\n const { readFile } = await import(\"node:fs/promises\")\n const parsed = JSON.parse(await readFile(path, \"utf8\"))\n // A malformed payload (non-array, or entries that aren't objects) must yield\n // no code change, never forward a bad shape to the start-replay request.\n const files =\n Array.isArray(parsed?.files) &&\n parsed.files.every(\n (f: unknown) =>\n typeof f === \"object\" && f !== null && !Array.isArray(f),\n )\n ? parsed.files\n : undefined\n const description =\n typeof parsed?.description === \"string\" ? parsed.description : undefined\n if (!files && description === undefined) {\n return null\n }\n return { description, files }\n } catch {\n return null\n }\n}\n\nasync function captureCodeChangeFromGit(\n cwd: string,\n label?: string,\n): Promise<ResolvedCodeChange | null> {\n let execFile: typeof import(\"node:child_process\").execFile\n let readFile: typeof import(\"node:fs/promises\").readFile\n try {\n ;({ execFile } = await import(\"node:child_process\"))\n ;({ readFile } = await import(\"node:fs/promises\"))\n } catch {\n // No child_process / fs (e.g. a browser bundle): capture is a no-op.\n return null\n }\n\n const git = (dir: string, args: string[]): Promise<string | null> =>\n new Promise((resolve) => {\n execFile(\n \"git\",\n args,\n // 30s timeout so a hung git (e.g. a network-touching ref op) can't\n // block the whole replay indefinitely.\n { cwd: dir, maxBuffer: 64 * 1024 * 1024, timeout: 30_000 },\n (err, stdout) => resolve(err ? null : stdout),\n )\n })\n\n try {\n const root = (await git(cwd, [\"rev-parse\", \"--show-toplevel\"]))?.trim()\n if (!root) {\n return null\n }\n\n const resolved = await resolveBase(git, root)\n if (!resolved) {\n return null\n }\n const { base, fromTrunk } = resolved\n\n // Size of a path on either side WITHOUT reading its contents: the git blob\n // size for `before`, a stat for the working `after`. Lets us skip an\n // oversized file before loading it into memory.\n const blobBytes = async (ref: string, path: string): Promise<number> => {\n const out = await git(root, [\"cat-file\", \"-s\", `${ref}:${path}`])\n const n = out ? Number.parseInt(out.trim(), 10) : Number.NaN\n return Number.isFinite(n) ? n : 0\n }\n const workingBytes = async (path: string): Promise<number> => {\n try {\n const { stat } = await import(\"node:fs/promises\")\n const { join } = await import(\"node:path\")\n return (await stat(join(root, path))).size\n } catch {\n return 0\n }\n }\n\n // Tracked changes vs base. `:!.bitfab` keeps replay artifacts out.\n const tracked = await git(root, [\n \"diff\",\n \"--name-status\",\n \"--find-renames\",\n \"-z\",\n base,\n \"--\",\n \":!.bitfab\",\n ])\n // Untracked-but-not-ignored files (the diff above omits these).\n const untracked = await git(root, [\n \"ls-files\",\n \"--others\",\n \"--exclude-standard\",\n \"-z\",\n \"--\",\n \":!.bitfab\",\n ])\n\n const entries: GitChange[] = [\n ...parseNameStatusZ(tracked ?? \"\"),\n ...(untracked ?? \"\")\n .split(NUL)\n .filter((p) => p.length > 0)\n .map((path) => ({ status: \"A\", beforePath: path, path })),\n ]\n if (entries.length === 0) {\n return null\n }\n\n const files: CodeChangeFile[] = []\n let totalBytes = 0\n for (const { status, beforePath, path } of entries) {\n if (files.length >= MAX_FILES) {\n break\n }\n // Skip oversized files by size BEFORE reading their full contents, so a\n // huge changed file can't OOM/stall the replay just to be discarded.\n const beforeBytes = status === \"A\" ? 0 : await blobBytes(base, beforePath)\n const afterBytes = status === \"D\" ? 0 : await workingBytes(path)\n if (beforeBytes > MAX_FILE_BYTES || afterBytes > MAX_FILE_BYTES) {\n continue\n }\n // Normalize CRLF -> LF on both sides: git's blob is already LF-normalized\n // (autocrlf clean), so a raw CRLF working file would otherwise skew every\n // line as changed. Comparing/storing LF keeps the diff meaningful.\n const before = (\n status === \"A\"\n ? \"\"\n : ((await git(root, [\"show\", `${base}:${beforePath}`])) ?? \"\")\n ).replace(/\\r\\n/g, \"\\n\")\n const after = (\n status === \"D\" ? \"\" : await readWorkingFile(readFile, root, path)\n ).replace(/\\r\\n/g, \"\\n\")\n if (before === after) {\n continue\n }\n // Bytes, not chars: a multi-byte source file must count against the byte\n // cap the same way Ruby's `bytesize` does.\n const size =\n Buffer.byteLength(before, \"utf8\") + Buffer.byteLength(after, \"utf8\")\n if (\n totalBytes + size > MAX_TOTAL_BYTES ||\n looksBinary(before) ||\n looksBinary(after)\n ) {\n continue\n }\n totalBytes += size\n files.push({ path, before, after })\n }\n\n if (files.length === 0) {\n return null\n }\n\n const subject = (\n await git(root, [\"log\", \"-1\", \"--format=%s\", \"HEAD\"])\n )?.trim()\n const fileWord = files.length === 1 ? \"file\" : \"files\"\n const head = label?.trim() || subject || \"Working-tree change\"\n // \"vs trunk\" only when we actually diffed against a trunk merge-base; the\n // HEAD fallback captures uncommitted work only, so label it honestly.\n const against = fromTrunk ? \"vs trunk\" : \"uncommitted (vs HEAD)\"\n return {\n description: `${head} (${files.length} ${fileWord} changed ${against})`,\n files,\n }\n } catch {\n return null\n }\n}\n\nasync function resolveBase(\n git: (dir: string, args: string[]) => Promise<string | null>,\n root: string,\n): Promise<{ base: string; fromTrunk: boolean } | null> {\n const forced = process.env?.BITFAB_CODE_CHANGE_BASE\n if (forced && (await refExists(git, root, forced))) {\n const base =\n (await git(root, [\"merge-base\", \"HEAD\", forced]))?.trim() ||\n (await git(root, [\"rev-parse\", \"--verify\", forced]))?.trim() ||\n null\n return base ? { base, fromTrunk: true } : null\n }\n for (const candidate of TRUNK_CANDIDATES) {\n if (!(await refExists(git, root, candidate))) {\n continue\n }\n const mb = (await git(root, [\"merge-base\", \"HEAD\", candidate]))?.trim()\n if (mb) {\n return { base: mb, fromTrunk: true }\n }\n }\n return (await refExists(git, root, \"HEAD\"))\n ? { base: \"HEAD\", fromTrunk: false }\n : null\n}\n\nasync function refExists(\n git: (dir: string, args: string[]) => Promise<string | null>,\n root: string,\n ref: string,\n): Promise<boolean> {\n return (\n (await git(root, [\"rev-parse\", \"--verify\", `${ref}^{object}`])) !== null\n )\n}\n\nasync function readWorkingFile(\n readFile: typeof import(\"node:fs/promises\").readFile,\n root: string,\n path: string,\n): Promise<string> {\n try {\n const { join } = await import(\"node:path\")\n return await readFile(join(root, path), \"utf8\")\n } catch {\n return \"\"\n }\n}\n\ninterface GitChange {\n status: string\n beforePath: string\n path: string\n}\n\nfunction parseNameStatusZ(raw: string): GitChange[] {\n const parts = raw.split(NUL).filter((p) => p.length > 0)\n const out: GitChange[] = []\n let i = 0\n while (i + 1 < parts.length) {\n const status = parts[i].charAt(0)\n i += 1\n const beforePath = parts[i]\n i += 1\n if ((status === \"R\" || status === \"C\") && i < parts.length) {\n out.push({ status, beforePath, path: parts[i] })\n i += 1\n } else {\n out.push({ status, beforePath, path: beforePath })\n }\n }\n return out\n}\n\nfunction looksBinary(s: string): boolean {\n return s.slice(0, 8000).includes(NUL)\n}\n","/**\n * Replay historical traces through a function and create a test run.\n *\n * The replay flow has three phases:\n * 1. Start: fetches historical traces from the server and creates a test run\n * 2. Execute: re-runs each trace's inputs through the provided function locally\n * 3. Complete: marks the test run as completed on the server\n */\n\nimport { resolveAutoCodeChange } from \"./codeChange.js\"\nimport type { DbSnapshotRef } from \"./dbSnapshot.js\"\nimport { BitfabError } from \"./errors.js\"\nimport {\n type CodeChangeFile,\n flushTraces,\n type HttpClient,\n type SpanTreeNode,\n type TokenUsage,\n} from \"./http.js\"\nimport type { MockOverride, MockOverrideInput } from \"./mockOverride.js\"\nimport { normalizeMockOverrides } from \"./mockOverride.js\"\nimport { randomUuid } from \"./randomUuid.js\"\nimport type {\n DbBranchLease,\n DbBranchSettings,\n DbBranchTimings,\n MockSpan,\n MockTree,\n} from \"./replayContext.js\"\nimport { replayContextReady, runWithReplayContext } from \"./replayContext.js\"\nimport { deserializeValue } from \"./serialize.js\"\n\nexport type MockStrategy = \"none\" | \"all\" | \"marked\"\n\nexport type TraceIngestionType = \"captured\" | \"seeded\"\n\nconst REPLAY_PERSISTENCE_TIMEOUT_MS = 30_000\nconst MAX_REPLAY_ATTEMPTS = 100\n\nfunction expandReplayWork<T>(\n serverItems: T[],\n attempts: number,\n): Array<{ serverItem: T; attempt: number }> {\n return Array.from({ length: attempts }, (_, attempt) =>\n serverItems.map((serverItem) => ({ serverItem, attempt })),\n ).flat()\n}\n\nfunction resolveAttempts(attempts: number | undefined): number {\n if (attempts === undefined) {\n return 1\n }\n if (\n !Number.isInteger(attempts) ||\n attempts < 1 ||\n attempts > MAX_REPLAY_ATTEMPTS\n ) {\n throw new BitfabError(\n `attempts must be an integer from 1 to ${MAX_REPLAY_ATTEMPTS} (got ${attempts}).`,\n )\n }\n return attempts\n}\n\n/**\n * How the DB-snapshot branch each replay item runs against is sized and warmed.\n *\n * Every field is optional, so this object is only worth passing when you want\n * to override the mirror project's own sizing. To branch with those defaults,\n * pass `dbBranch: true` instead of an empty object.\n */\nexport interface DbBranchOptions {\n /**\n * Autoscaling floor for the branch's compute, in Neon Compute Units (0.25 to\n * 56). Omit to keep the mirror project's own default. Raise it when the\n * mirror is provisioned smaller than the database it stands in for, so\n * replay latency reflects your code rather than a cold, undersized branch.\n */\n minCu?: number\n /**\n * Autoscaling ceiling for the branch's compute, in Neon Compute Units.\n * Setting it equal to `minCu` pins the size, which keeps items comparable:\n * otherwise a later item can run against an endpoint that has already\n * scaled up and post a better number for the same code.\n */\n maxCu?: number\n /**\n * SQL that warms the branch's cache. The server appends it to the branch's\n * readiness check, so it runs BEFORE your function sees the branch and its\n * time is not charged to the replayed call. Invalid SQL fails the branch\n * rather than silently leaving it cold.\n */\n warmupSql?: string\n}\n\n/**\n * Whether the caller asked for database branching. `true` and a settings object\n * both turn it on; `false` and omission leave it off. Kept separate from\n * `resolveDbBranchSettings` because `dbBranch: true` enables branching while\n * contributing no settings, so presence of settings can't stand in for the\n * switch.\n */\nfunction dbBranchEnabled(\n dbBranch: DbBranchOptions | boolean | undefined,\n): boolean {\n return dbBranch !== undefined && dbBranch !== false\n}\n\n/**\n * Narrow the caller's branch options to the wire shape, dropping the object\n * entirely when nothing was set so the request stays byte-identical to what\n * older SDKs send. Booleans carry no settings: they only move the switch.\n */\nfunction resolveDbBranchSettings(\n dbBranch: DbBranchOptions | boolean | undefined,\n): DbBranchSettings | undefined {\n if (!dbBranch || dbBranch === true) {\n return undefined\n }\n const { minCu, maxCu, warmupSql } = dbBranch\n const settings: DbBranchSettings = {\n ...(minCu === undefined ? {} : { minCu }),\n ...(maxCu === undefined ? {} : { maxCu }),\n ...(warmupSql === undefined ? {} : { warmupSql }),\n }\n return Object.keys(settings).length === 0 ? undefined : settings\n}\n\nexport interface ReplayOptions {\n /**\n * Maximum number of traces to replay (1-5,000, default 5). Ignored when\n * `traceIds` is passed (with a warning), or when `datasetId` is passed,\n * because either source already determines how many traces replay.\n */\n limit?: number\n attempts?: number\n /** Optional list of specific trace IDs to replay (max 100). Mutually exclusive with `datasetId`. */\n traceIds?: string[]\n /** Optional display name for the resulting experiment/test run. */\n name?: string\n /** Maximum number of items to process in parallel. Set to 1 for sequential. Default 10. */\n maxConcurrency?: number\n /**\n * Description of the code change being tested in this replay. Stored on\n * the resulting experiment so the change can be reviewed alongside results.\n * Supplying a description without `codeChangeFiles` preserves this text\n * while the SDK automatically captures the files.\n * Pass `null` when the replay should have no description; use\n * `codeChangeFiles: null` to suppress automatic file capture.\n */\n codeChangeDescription?: string | null\n /**\n * Files edited as part of this code change. Each entry holds the file path\n * and the full `before`/`after` contents. The agent reads each file before\n * and after editing and passes the two strings. Use `\"\"` for newly created\n * files (`before`) or deleted files (`after`). Omit this field to capture\n * automatically, or pass `null` to suppress file capture for this replay.\n */\n codeChangeFiles?: CodeChangeFile[] | null\n /**\n * Mock strategy for child spans during replay.\n * - \"marked\": only spans tagged with { mockOnReplay: true } in SpanOptions are mocked (default)\n * - \"none\": everything runs real code\n * - \"all\": every matched recorded child withSpan returns historical output;\n * a missing occurrence fails the replay item closed\n */\n mock?: MockStrategy\n /**\n * Selective mock overrides: inject custom values into specific spans during\n * replay, so downstream real code runs against the substituted output. Each\n * Pass `{ match, value }` pairs, or one resolver invoked for every child span.\n * A resolver can route on `ctx.node.traceFunctionKey` and return\n * `NO_MOCK_OVERRIDE` to continue to the next override and base strategy.\n * Per-call overrides take precedence over registrations on the client.\n */\n mockOverride?: MockOverrideInput | MockOverrideInput[]\n /**\n * Run each item against a database branch restored to the state its source\n * trace saw. Pass `true` to branch with the mirror project's own sizing, or a\n * {@link DbBranchOptions} object to tune how each branch is sized and warmed.\n * `false` and omission leave branching off. Inside `fn`, read the resolved\n * branch with `getCurrentReplayBranch()`.\n *\n * Items whose source trace carried no DB snapshot reference get no branch and\n * use the app's normal database path. Unsafe calls on that path still require\n * replay mocking. An item whose branch was requested but could not be resolved\n * fails instead of running, so replay never silently reports a result that did\n * not use the historical data you asked for.\n */\n dbBranch?: DbBranchOptions | boolean\n /** Group ID to associate this replay with an experiment group for live streaming in Studio. */\n experimentGroupId?: string\n /**\n * Dataset this replay runs against. Mutually exclusive with `traceIds`. When\n * set, the resulting experiment is\n * durably attributed to the dataset (stored on the test run), so it appears\n * under the dataset's experiments even if the trace lineage can't be\n * reconstructed. Validated server-side against the org.\n */\n datasetId?: string\n /**\n * Graders to attach directly to this experiment (test run), independent of any\n * graders already on the dataset. The resulting experiment is graded by the\n * union of these and the dataset's runnable graders at completion, so use this\n * to grade a single run with a check you don't want to add to the dataset\n * permanently. Each id must be an active/live grader belonging to the same\n * organization and trace function, otherwise the server rejects the replay.\n */\n graderIds?: string[]\n /**\n * Reshape recorded inputs before they are spread into `fn`.\n *\n * Replay pulls each trace's inputs exactly as they were captured against the\n * function's signature AT TRACE TIME. When the function's shape has since\n * changed (params renamed, reordered, collapsed into an options object, etc.),\n * the recorded inputs no longer line up and `fn(...inputs)` throws. This hook\n * lets a caller map the recorded inputs onto the current signature so replay\n * can still run.\n *\n * Receives the deserialized recorded inputs and a per-trace {@link AdaptContext}\n * (so a table-driven adapter can look up the adapted inputs by `traceId`), and\n * returns the array actually spread into `fn`. The returned array is also what\n * `ReplayItem.input` reports, so the experiment shows what was really run.\n *\n * Runs per item, inside the same try/catch as `fn`: if the adapter throws, the\n * failure is surfaced on that item's `error` rather than crashing the run.\n * Omit it to spread the recorded inputs unchanged.\n */\n adaptInputs?: (inputs: unknown[], ctx: AdaptContext) => unknown[]\n /**\n * Resolve every item's inputs and stop, without calling the function.\n *\n * Selection, span fetch, deserialization, and `adaptInputs` all run, so each\n * item reports the exact arguments the function would have received. Nothing\n * executes and no replay traces are produced, which is the cheap way to check\n * that recorded inputs still fit the current signature.\n */\n dryRun?: boolean\n /**\n * Called once per item as it finishes, in completion order (not input\n * order), with running totals for the whole run. Use it to render replay\n * progress, for example a terminal progress bar. Replay does not know\n * pass/fail at this point (verdicts are assigned later), so the totals only\n * distinguish items whose function ran (`succeeded`) from items that threw\n * (`errored`).\n *\n * Invoked synchronously right after each item finishes, so keep it cheap. A\n * throwing callback never crashes the run: the error is swallowed so progress\n * UI can't break replay.\n */\n onItemFinish?: (progress: ReplayItemFinishProgress) => void\n /**\n * @deprecated Use {@link onItemFinish}. This compatibility callback receives\n * the same per-item finish events plus the legacy whole-run `\"complete\"`\n * event. It is ignored when `onItemFinish` is also provided.\n */\n onProgress?: (progress: ReplayProgress) => void\n /**\n * Called once when each replay item begins processing, before input loading,\n * mock preparation, database branching, or the customer function runs. Use\n * it with {@link onItemFinish} to distinguish queued items from items that\n * are still in flight. A throwing callback never crashes the run.\n */\n onItemStart?: (progress: ReplayItemStartProgress) => void\n}\n\n/** Emitted through {@link ReplayOptions.onItemStart} when a worker starts an item. */\nexport interface ReplayItemStartProgress {\n type: \"started\"\n /** Test run ID created for this replay. */\n testRunId: string\n /** Items whose processing has started so far. */\n started: number\n /** Items that have finished so far, whether they succeeded or errored. */\n completed: number\n /** Total number of items in this replay run. */\n total: number\n /** Of the completed items, how many finished without a code or replay error. */\n succeeded: number\n /** Of the completed items, how many finished with an error. */\n errored: number\n /** The historical trace and span whose replay processing just started. */\n item: {\n originalTraceId: string\n originalSpanId: string\n /** @deprecated alias for `originalTraceId`. */\n sourceTraceId: string\n /** @deprecated alias for `originalSpanId`. */\n sourceSpanId: string\n attempt: number\n }\n}\n\n/** Running totals reported to {@link ReplayOptions.onItemFinish} as replay proceeds. */\nexport interface ReplayItemFinishProgress {\n /** Event kind, omitted for backward-compatible per-item events. */\n type?: \"item\"\n /** Test run ID created for this replay. */\n testRunId: string\n /** Items that have finished so far, whether they succeeded or errored. */\n completed: number\n /** Total number of items in this replay run. */\n total: number\n /** Of the completed items, how many finished without a code or replay error. */\n succeeded: number\n /** Of the completed items, how many have `item.error` set. */\n errored: number\n /**\n * The single item that just finished to produce this event. Field-for-field\n * the same shape and meaning as {@link ReplayItem}, so a progress UI and a\n * final-result UI read one contract. `traceId` is null at this stage (the\n * server replay id arrives at completion), and `tokens` is null for the same\n * reason: the replayed run's usage is aggregated server-side by\n * completeReplay. `durationMs` is how long this item took to replay; the\n * `original*` fields describe the trace it replayed.\n */\n item: ReplayProgressItem\n}\n\n/** See {@link ReplayItemFinishProgress.item}. Mirrors {@link ReplayItem}. */\nexport interface ReplayProgressItem {\n /** Trace ID of the new replay trace (null during the run; the server id arrives at completion). */\n traceId?: string | null\n /** Bitfab trace ID of the original (historical) trace being replayed. */\n originalTraceId: string | null\n /** External span ID the recorded inputs were read from (the original root span). */\n originalSpanId?: string | null\n /** @deprecated alias for `originalTraceId`. */\n sourceTraceId: string | null\n /** @deprecated alias for `originalSpanId`. */\n sourceSpanId?: string | null\n attempt: number\n /** Deserialized inputs from the original trace. */\n input?: unknown[]\n /** The result returned by the replayed function, or undefined on error. */\n result?: unknown\n /** The original output from the historical trace. */\n originalOutput?: unknown\n /** Backward-compatible message for either error kind. */\n error: string | null\n /** The actual value thrown by the replayed customer function. */\n traceError?: unknown | null\n /** The actual value thrown while Bitfab prepared this replay item. */\n replayError?: unknown | null\n /** How long the replayed function took on this run. */\n durationMs?: number | null\n /** The original trace's duration, tokens, and model. */\n originalDurationMs?: number | null\n originalTokens?: TokenUsage | null\n originalModel?: string | null\n /** Always null here: the replayed run's usage is only known at completion. */\n tokens?: TokenUsage | null\n /** @deprecated renamed to `originalModel`. */\n model?: string | null\n dbSnapshotRef?: DbSnapshotRef | null\n dbBranchTimings?: DbBranchTimings | null\n}\n\n/**\n * @deprecated Use {@link ReplayItemFinishProgress}. This legacy shape also\n * represents the item-less terminal `\"complete\"` event emitted by\n * {@link ReplayOptions.onProgress}.\n */\nexport interface ReplayProgress {\n type?: \"item\" | \"complete\"\n result?: ReplayResult<unknown>\n testRunId?: string\n completed: number\n total: number\n succeeded: number\n errored: number\n item?: ReplayItemFinishProgress[\"item\"]\n}\n\n/**\n * Wire prefix the Bitfab plugin scans for. Each line {@link reportReplayProgress}\n * writes is this prefix followed by the JSON of the running totals (plus the\n * finished `item`). The plugin polls these lines to report live progress while a\n * replay runs in the background; keep the SDK emitter and the plugin parser in\n * sync.\n */\nexport const BITFAB_PROGRESS_PREFIX = \"@@bitfab:progress \"\n\n/**\n * A ready-made replay lifecycle callback for replay scripts.\n * Pass it straight in:\n *\n * ```ts\n * await bitfab.replay(\"my-fn\", fn, {\n * limit,\n * onItemStart: reportReplayProgress,\n * onItemFinish: reportReplayProgress,\n * })\n * ```\n *\n * It writes `@@bitfab:progress` lines to stderr, which the Bitfab plugin polls\n * to report in-flight and finished items while replay runs in the background,\n * so scripts never hand-format the wire protocol.\n * stdout is left untouched for direct-run ReplayResult JSON. Outside Node (no\n * `process.stderr`, e.g. a browser) it is a no-op, and a write failure is\n * swallowed so progress can never crash a run.\n */\nexport function reportReplayProgress(\n progress: ReplayItemFinishProgress | ReplayItemStartProgress | ReplayProgress,\n): void {\n const stderr = typeof process !== \"undefined\" ? process.stderr : undefined\n if (!stderr) {\n return\n }\n try {\n stderr.write(\n `${BITFAB_PROGRESS_PREFIX}${JSON.stringify(progress, replayJsonReplacer)}\\n`,\n )\n } catch {\n // A progress reporter must never crash the replay run.\n }\n}\n\n/** Per-trace context passed to {@link ReplayOptions.adaptInputs}. */\nexport interface AdaptContext {\n /** Bitfab trace ID of the original (historical) trace being replayed. */\n originalTraceId: string\n /** External span ID the recorded inputs were read from. */\n originalSpanId: string\n /** @deprecated alias for {@link AdaptContext.originalTraceId}. */\n sourceTraceId: string\n /** @deprecated alias for {@link AdaptContext.originalSpanId}. */\n sourceSpanId: string\n metadata: Record<string, unknown>\n}\n\n/**\n * The shape an adapter module must export as `adaptInputs`.\n *\n * Author an adapter in its own file (e.g. `scripts/replay-adapters/<name>.ts`),\n * import it in your replay script, and pass it to `replay({ adaptInputs })`:\n *\n * ```ts\n * import type { AdaptInputsFn } from \"@bitfab/sdk\"\n * export const adaptInputs: AdaptInputsFn = (inputs, ctx) => [reshape(inputs)]\n * ```\n */\nexport type AdaptInputsFn = (inputs: unknown[], ctx: AdaptContext) => unknown[]\n\nexport interface ReplayItem<T> {\n /**\n * Server trace ID of the new replay trace this item produced. Written in by\n * `replay()` from the complete-replay response once the server has minted the\n * trace row; the client-side id used to correlate spans during the run is\n * never surfaced here. Null until completion, on older servers that omit the\n * mapping, or if the item produced no trace. Not the verdict-persistence key:\n * that is the original-trace lineage (`originalTraceId` + `testRunId`).\n */\n traceId: string | null\n /** Bitfab trace ID of the original (historical) trace being replayed. */\n originalTraceId: string\n /** External span ID the recorded inputs were read from (the original root span). */\n originalSpanId: string\n /** @deprecated alias for {@link ReplayItem.originalTraceId}. */\n sourceTraceId: string\n /** @deprecated alias for {@link ReplayItem.originalSpanId}. */\n sourceSpanId: string\n attempt: number\n /** Deserialized inputs from the original trace. */\n input: unknown[]\n /** The result returned by the function during replay, or undefined on error. */\n result: T | undefined\n originalOutput: unknown\n /**\n * How the source trace came to exist. Absent on servers that predate the\n * field, which only ever served captured traces.\n */\n ingestionType?: TraceIngestionType\n /**\n * Backward-compatible message for either error kind. Prefer `traceError` and\n * `replayError` when callers need the original exception and its source.\n */\n error: string | null\n /** The actual value thrown by the replayed customer function. */\n traceError: unknown | null\n /**\n * The actual value thrown by replay setup before the customer function ran,\n * such as database warmup, input hydration, or mock preparation.\n */\n replayError: unknown | null\n /**\n * How long the replayed function took on this run, in ms. Null if the item\n * failed before it ran. Compare against\n * {@link ReplayItem.originalDurationMs} for the before/after.\n */\n durationMs: number | null\n /** The original trace's duration in ms, or null if its timestamps are missing. */\n originalDurationMs: number | null\n /**\n * Token usage recorded on the original trace, or null if it captured none.\n * The \"old\" side of a token delta; {@link ReplayItem.tokens} is the new one.\n */\n originalTokens: TokenUsage | null\n /** Model name from the original trace, or null if not captured. */\n originalModel: string | null\n /**\n * Token usage from the REPLAYED run (this item's new execution), aggregated\n * server-side from the spans it produced, or null if the run captured no\n * token data. Compare against {@link ReplayItem.originalTokens} to see how\n * the code change moved cost. Matches what Studio's experiments view shows.\n *\n * Unprefixed because the replay is this item's subject: anything describing\n * the trace being replayed carries `original`.\n */\n tokens: TokenUsage | null\n /** @deprecated renamed to {@link ReplayItem.originalModel}. */\n model: string | null\n /**\n * The DB snapshot ref the SDK captured at trace open. Useful for debugging\n * (\"what state was this trace pinned to?\") and for customers building\n * their own resolvers. Undefined when the source trace was captured\n * without `dbSnapshot` configured.\n */\n dbSnapshotRef: DbSnapshotRef | null\n /**\n * How long this item's DB branch took to provision, per phase, measured\n * server-side. Present whenever a branch was attempted, on both outcomes:\n * complete on success, partial up to the failing phase when the resolve\n * failed. Null when no branch was asked for, when the source trace carried\n * no snapshot ref, or against a server that predates timings.\n */\n dbBranchTimings: DbBranchTimings | null\n}\n\nexport type { CodeChangeFile, TokenUsage }\n\nexport interface ReplayResult<T> {\n /** Individual replay items with inputs, results, and comparison data. */\n items: ReplayItem<T>[]\n /** The test run ID created on the server. */\n testRunId: string\n /** Full URL to view the test run in the dashboard. */\n testRunUrl: string\n attempts: number\n}\n\n/**\n * Whole-run replay failure that preserves every item collected before the run\n * failed. The original whole-run exception is available as `cause`.\n */\nexport class ReplayError<T = unknown> extends BitfabError {\n constructor(\n message: string,\n public readonly items: ReplayItem<T>[],\n public readonly testRunId: string,\n public readonly testRunUrl: string,\n public readonly cause: unknown,\n ) {\n super(message, testRunUrl)\n this.name = \"ReplayError\"\n }\n}\n\n/**\n * A database branch requested for one replay item could not be resolved.\n *\n * The server's resolver code and message are retained as structured fields so\n * callers can handle failures such as `branch_create_failed` and\n * `snapshot_from_replaced_origin` without parsing the compatible `item.error`\n * string.\n */\nexport class DbBranchReplayError extends BitfabError {\n constructor(\n public readonly code: string,\n message: string,\n public readonly originalTraceId: string,\n public readonly cause?: unknown,\n ) {\n super(message)\n this.name = \"DbBranchReplayError\"\n }\n}\n\nfunction isPlainRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value)\n}\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error)\n}\n\nfunction replayItemErrorMessage(error: unknown): string {\n if (error instanceof DbBranchReplayError) {\n return `Replay requested a database branch for trace ${error.originalTraceId} but it could not be resolved (${error.code}): ${error.message}. The function was not run, because replaying it against the live database would produce a result that looks valid but did not use the historical data you asked for.`\n }\n return errorMessage(error)\n}\n\nfunction replayJsonReplacer(_key: string, value: unknown): unknown {\n if (value instanceof Error) {\n const serialized: Record<string, unknown> = {\n name: value.name,\n message: value.message,\n stack: value.stack,\n }\n if (value instanceof DbBranchReplayError) {\n serialized.code = value.code\n serialized.originalTraceId = value.originalTraceId\n if (value.cause !== undefined) {\n serialized.cause = value.cause\n }\n }\n return serialized\n }\n return value\n}\n\n/**\n * Serialize a replay result as JSON while retaining structured trace and replay\n * errors. Use this for direct-run stdout instead of raw `JSON.stringify`, which\n * drops the useful fields on JavaScript `Error` objects.\n */\nexport function serializeReplayResult<T>(result: ReplayResult<T>): string {\n return JSON.stringify(result, replayJsonReplacer, 2)\n}\n\nasync function preserveReplayFailure<T, TItem>(\n operation: () => Promise<T>,\n items: ReplayItem<TItem>[],\n testRunId: string,\n testRunUrl: string,\n): Promise<T> {\n try {\n return await operation()\n } catch (cause) {\n if (cause instanceof ReplayError) {\n throw cause\n }\n throw new ReplayError(\n errorMessage(cause),\n items,\n testRunId,\n testRunUrl,\n cause,\n )\n }\n}\n\n/**\n * Deserialize inputs from a historical span's rawData.\n *\n * Prefers superjson-serialized `input_meta` for type preservation,\n * falls back to the raw `input` field.\n */\nfunction deserializeInputs(spanData: Record<string, unknown>): unknown[] {\n const inputMeta = spanData.input_meta as unknown\n const rawInput = spanData.input\n\n // If superjson meta is available, deserialize with type reconstruction\n if (inputMeta !== undefined && inputMeta !== null) {\n const deserialized = deserializeValue({ json: rawInput, meta: inputMeta })\n if (Array.isArray(deserialized)) {\n return deserialized\n }\n return deserialized !== undefined && deserialized !== null\n ? [deserialized]\n : []\n }\n\n // Fall back to raw input\n if (Array.isArray(rawInput)) {\n return rawInput\n }\n return rawInput !== undefined && rawInput !== null ? [rawInput] : []\n}\n\n/**\n * Deserialize the original output from a historical span's rawData.\n */\nfunction deserializeOutput(spanData: Record<string, unknown>): unknown {\n const outputMeta = spanData.output_meta as unknown\n const rawOutput = spanData.output\n\n if (outputMeta !== undefined && outputMeta !== null) {\n return deserializeValue({ json: rawOutput, meta: outputMeta })\n }\n\n return rawOutput\n}\n\n/**\n * Walk the children of a root span tree node in depth-first order and build\n * a MockTree keyed by `${traceFunctionKey}:${spanName}:${callIndex}`.\n *\n * The historical root itself is NOT walked. At replay time the runtime root\n * span has `isRootSpan === true` and never queries the mockTree (mock\n * interception is skipped for root spans by design), so the root has nothing\n * to look up. Walking it would just leave an unreachable entry in the table.\n *\n * The (key, name) compound match is what disambiguates same-key spans:\n * - A wrapped function's children commonly share its traceFunctionKey via\n * the fluent `getFunction(key).withSpan({ name }, ...)` pattern. They\n * disambiguate by `name`, never colliding with each other.\n * - Recursion: same (key, name) at every depth. callIndex per (key, name)\n * orders them correctly without leaking the historical root into the\n * nested call's slot.\n * - Outer-wrapper replay scripts: the outer wrapper's `name` is distinct\n * from anything in the historical tree (it only exists at replay), so\n * its presence never disturbs counters or lookups for spans that do\n * exist in the historical tree.\n */\nfunction buildMockTree(rootNode: SpanTreeNode): MockTree {\n const spans = new Map<string, MockSpan>()\n const counters = new Map<string, number>()\n\n function walk(node: SpanTreeNode): void {\n const key = node.traceFunctionKey\n if (key) {\n const name = node.spanName || key\n const counterKey = `${key}:${name}`\n const index = counters.get(counterKey) ?? 0\n counters.set(counterKey, index + 1)\n // `output`/`outputMeta` are undefined on a payload-free (lazy) tree;\n // `externalSpanId` is what the lazy path fetches them by. Both are copied\n // verbatim so eager and lazy trees build through the same walk.\n spans.set(`${counterKey}:${index}`, {\n sourceSpanId: node.sourceSpanId,\n externalSpanId: node.externalSpanId,\n output: node.output,\n outputMeta: node.outputMeta,\n })\n }\n for (const child of node.children) {\n walk(child)\n }\n }\n\n for (const child of rootNode.children) {\n walk(child)\n }\n\n return { spans }\n}\n\n/**\n * Execute a single replay item: fetch span data, deserialize inputs, call\n * the function within a replay context that injects testRunId into new spans.\n */\nasync function processItem<TReturn>(\n httpClient: HttpClient,\n serverItem: {\n originalTraceId?: string\n originalSpanId?: string\n /** @deprecated alias emitted by servers that predate the originalTraceId rename. */\n sourceTraceId: string\n /** @deprecated alias emitted by servers that predate the originalSpanId rename. */\n sourceSpanId: string\n originalDurationMs?: number | null\n originalTokens?: TokenUsage | null\n originalModel?: string | null\n originalMetadata?: Record<string, unknown>\n ingestionType?: TraceIngestionType\n /** @deprecated unprefixed aliases emitted by servers that predate the rename.\n * `tokens` here is the ORIGINAL trace's usage: the start item has never\n * carried the replay's, which only exists after completeReplay. */\n durationMs: number | null\n tokens?: TokenUsage | null\n model: string | null\n dbSnapshotRef?: DbSnapshotRef\n dbBranchLease?: DbBranchLease\n dbBranchLeaseError?: { code: string; message: string }\n dbBranchTimings?: DbBranchTimings\n },\n // biome-ignore lint/suspicious/noExplicitAny: replay deserializes inputs from historical data\n fn: (...args: any[]) => TReturn | Promise<TReturn>,\n testRunId: string,\n mockStrategy: MockStrategy,\n resolvedOverrides: MockOverride[],\n replayedTraceId: string,\n attempt: number,\n includeDbBranchLease: boolean,\n dbBranchSettings: DbBranchSettings | undefined,\n adaptInputs:\n | ((inputs: unknown[], ctx: AdaptContext) => unknown[])\n | undefined,\n dryRun: boolean,\n): Promise<ReplayItem<TReturn>> {\n // The server-side resolver materializes a Neon preview branch per item\n // during `/api/sdk/replay/start` (when the customer passed `dbBranch`,\n // which triggers `includeDbBranchLease: true`). The lease arrives on the\n // server item; we just attach it to the replay context and release the\n // branch in `finally` so any throw (in fetch, mock-tree build, or the\n // customer fn) frees the Neon resource. Items whose source trace had no\n // snapshot ref arrive without a lease; `getCurrentReplayBranch()` returns\n // null for those, and the app uses its normal DB path. Unsafe calls on that\n // path still require replay mocking.\n let lease = includeDbBranchLease ? serverItem.dbBranchLease : undefined\n // A resolve that was attempted and FAILED is different: the caller asked for\n // a branch, so running their function against live data would produce a\n // result that looks valid and isn't. Fail this item instead, loudly.\n let leaseError = includeDbBranchLease\n ? serverItem.dbBranchLeaseError\n : undefined\n let dbSnapshotRef = serverItem.dbSnapshotRef\n // Reported whichever way the resolve went, so it is tracked separately from\n // both the lease and the error rather than hanging off either.\n let dbBranchTimings = includeDbBranchLease\n ? serverItem.dbBranchTimings\n : undefined\n\n let inputs: unknown[] = []\n let originalOutput: unknown\n let result: TReturn | undefined\n let error: string | null = null\n let traceError: unknown | null = null\n let replayError: unknown | null = null\n // Timed around the replayed function only, so it is comparable to\n // originalDurationMs (that same function's wall time on the original run)\n // rather than to the span fetches and persistence around it.\n let replayDurationMs: number | null = null\n // Null until the replayed function actually starts, so an item that fails in\n // the span fetch or mock-tree build reports no replay duration rather than\n // timing work that was not the function.\n let replayStarted: number | null = null\n\n // The ORIGINAL (historical) trace/span this item replays. Canonical server\n // keys are originalTraceId/originalSpanId; older servers only send the\n // deprecated sourceTraceId/sourceSpanId aliases.\n const originalTraceId = serverItem.originalTraceId ?? serverItem.sourceTraceId\n const originalSpanId = serverItem.originalSpanId ?? serverItem.sourceSpanId\n\n try {\n if (includeDbBranchLease && !lease && !leaseError) {\n let resolved: Awaited<ReturnType<HttpClient[\"resolveDbBranchLease\"]>>\n try {\n resolved = await httpClient.resolveDbBranchLease(\n testRunId,\n originalTraceId,\n dbBranchSettings,\n attempt,\n )\n } catch (cause) {\n throw new DbBranchReplayError(\n \"lease_request_failed\",\n `Bitfab could not request the database branch: ${errorMessage(cause)}`,\n originalTraceId,\n cause,\n )\n }\n lease = resolved.lease ?? undefined\n leaseError = resolved.leaseError ?? undefined\n dbSnapshotRef = resolved.dbSnapshotRef ?? dbSnapshotRef\n dbBranchTimings = resolved.timings ?? dbBranchTimings\n }\n\n if (leaseError) {\n throw new DbBranchReplayError(\n leaseError.code,\n leaseError.message,\n originalTraceId,\n )\n }\n\n const span = await httpClient.getExternalSpan(originalSpanId, {\n view: \"replay\",\n })\n const spanData = (span.rawData?.span_data ?? {}) as Record<string, unknown>\n\n inputs = deserializeInputs(spanData)\n originalOutput = deserializeOutput(spanData)\n\n // Reshape the recorded inputs onto the current signature when an adapter\n // is supplied. Runs before the mock tree / fn call so the adapted array is\n // what fn receives and what `item.input` reports.\n if (adaptInputs) {\n const originalMetadata = serverItem.originalMetadata\n inputs = adaptInputs(inputs, {\n originalTraceId,\n originalSpanId,\n // Deprecated aliases for originalTraceId/originalSpanId.\n sourceTraceId: originalTraceId,\n sourceSpanId: originalSpanId,\n metadata: isPlainRecord(originalMetadata)\n ? { ...originalMetadata }\n : {},\n })\n }\n\n // Build the mock tree whenever mocking could apply: any non-\"none\" strategy,\n // OR overrides are present (overrides substitute even under \"none\" - the\n // \"run real code but replace node X\" case). Only \"all\" needs outputs inline;\n // Non-\"all\" runs that need a tree (\"marked\", or \"none\" with overrides)\n // keep it payload-free and pull outputs lazily, so we never drag down every\n // span's recorded output when only a few get mocked.\n const hasOverrides = resolvedOverrides.length > 0\n const needTree =\n mockStrategy === \"all\" || mockStrategy === \"marked\" || hasOverrides\n const includeOutputs = mockStrategy === \"all\"\n\n let mockTree: MockTree | undefined\n if (needTree) {\n try {\n const treeResponse = await httpClient.getSpanTree(originalSpanId, {\n includeOutputs,\n includeRootOutput: false,\n })\n if (!treeResponse.root) {\n throw new BitfabError(\n `Replay mock strategy \"${mockStrategy}\"${hasOverrides ? \" with overrides\" : \"\"} requires a span tree root for original span ${originalSpanId}.`,\n )\n }\n mockTree = buildMockTree(treeResponse.root)\n } catch (error) {\n if (mockStrategy !== \"marked\" || hasOverrides) {\n throw error\n }\n // The root still runs under \"marked\". An empty active tree lets an\n // unmarked-only root proceed, while any selected child fails closed at\n // its call site instead of executing the real span.\n mockTree = { spans: new Map() }\n }\n }\n\n // Lazy per-span output fetch, memoized per item so a span read twice (once\n // as a marked mock, once via an override's getOriginalOutput) fetches once.\n // Present only when outputs were NOT fetched inline (not the eager \"all\"\n // path); its presence signals the mock path to fetch on demand.\n const outputCache = new Map<string, Promise<unknown>>()\n const fetchSpanOutput =\n mockTree && !includeOutputs\n ? (externalSpanId: string): Promise<unknown> => {\n let pending = outputCache.get(externalSpanId)\n if (!pending) {\n pending = httpClient\n .getExternalSpan(externalSpanId, { view: \"replay\" })\n .then((s) =>\n deserializeOutput(\n (s.rawData?.span_data ?? {}) as Record<string, unknown>,\n ),\n )\n outputCache.set(externalSpanId, pending)\n }\n return pending\n }\n : undefined\n\n if (dryRun) {\n return {\n traceId: null,\n originalTraceId,\n originalSpanId,\n sourceTraceId: originalTraceId,\n sourceSpanId: originalSpanId,\n attempt,\n input: inputs,\n result: undefined,\n originalOutput,\n ...(serverItem.ingestionType && {\n ingestionType: serverItem.ingestionType,\n }),\n error: null,\n traceError: null,\n replayError: null,\n durationMs: null,\n originalDurationMs:\n serverItem.originalDurationMs ?? serverItem.durationMs ?? null,\n originalTokens: serverItem.originalTokens ?? serverItem.tokens ?? null,\n originalModel: serverItem.originalModel ?? serverItem.model ?? null,\n tokens: null,\n model: serverItem.originalModel ?? serverItem.model ?? null,\n dbSnapshotRef: dbSnapshotRef ?? null,\n dbBranchTimings: dbBranchTimings ?? null,\n }\n }\n\n try {\n replayStarted = performance.now()\n const maybePromise = runWithReplayContext(\n {\n testRunId,\n traceId: replayedTraceId,\n inputSourceSpanId: span.id,\n inputSourceTraceId: span.externalTraceId,\n sourceBitfabTraceId: originalTraceId,\n replayAttempt: attempt,\n mockTree,\n callCounters: mockTree ? new Map() : undefined,\n mockStrategy,\n mockOverrides: hasOverrides ? resolvedOverrides : undefined,\n fetchSpanOutput,\n dbBranchLease: lease,\n dbBranchTimings,\n },\n () => fn(...inputs),\n )\n result =\n maybePromise instanceof Promise ? await maybePromise : maybePromise\n replayDurationMs = Math.round(performance.now() - replayStarted)\n } catch (e) {\n // The function ran and threw, so it still has a duration worth reporting.\n if (replayStarted !== null) {\n replayDurationMs = Math.round(performance.now() - replayStarted)\n }\n traceError = e\n error = errorMessage(e)\n }\n } catch (e) {\n // Replay setup failed. replayStarted is null unless the customer function\n // had already begun, so this leaves durationMs null for a genuine\n // setup failure rather than timing work that was not the function.\n if (replayStarted !== null) {\n replayDurationMs = Math.round(performance.now() - replayStarted)\n }\n replayError = e\n error = replayItemErrorMessage(e)\n } finally {\n if (lease) {\n try {\n await httpClient.releaseDbBranchLease(lease.neonBranchId)\n } catch (e) {\n try {\n console.warn(\n `Bitfab: failed to release DB branch ${lease.neonBranchId} (TTL janitor will catch it): ${\n e instanceof Error ? e.message : String(e)\n }`,\n )\n } catch {\n // Never crash the host\n }\n }\n }\n }\n\n // Canonical names first, falling back to the unprefixed ones a server that\n // predates the rename sends.\n const originalDurationMs =\n serverItem.originalDurationMs ?? serverItem.durationMs ?? null\n const originalModel = serverItem.originalModel ?? serverItem.model ?? null\n return {\n // Written in by replay() from the complete-replay response once the server\n // has minted this replay trace's row. Null until then: the client-side\n // correlation id (replayedTraceId) is never surfaced as the item's traceId.\n traceId: null,\n originalTraceId,\n originalSpanId,\n // Deprecated aliases for originalTraceId/originalSpanId.\n sourceTraceId: originalTraceId,\n sourceSpanId: originalSpanId,\n attempt,\n input: inputs,\n result,\n originalOutput,\n ...(serverItem.ingestionType && {\n ingestionType: serverItem.ingestionType,\n }),\n error,\n traceError,\n replayError,\n durationMs: replayDurationMs,\n originalDurationMs,\n originalTokens: serverItem.originalTokens ?? serverItem.tokens ?? null,\n originalModel,\n // Filled in by replay() from the complete-replay response once the\n // replay traces are persisted and their spans aggregated server-side.\n // Null here (and on older servers) means \"replay tokens not known\".\n tokens: null,\n model: originalModel,\n dbSnapshotRef: dbSnapshotRef ?? null,\n dbBranchTimings: dbBranchTimings ?? null,\n }\n}\n\n/**\n * Block until the server has fully persisted every replay trace this run\n * submitted, or fail loudly.\n *\n * `completeReplay` reads at a single instant: it mints the trace-ID mapping and\n * aggregates each trace's tokens from its spans. Run it while spans are still\n * in flight and `item.traceId` comes back null with undercounted tokens.\n *\n * In the normal case the verdict is local: ingestion commits a request's\n * carriers before it answers, so a flush that delivered every carrier has\n * already proven the traces are whole and polling only asked the server to\n * repeat itself. Acks cannot settle a request that timed out client-side after\n * the server committed, so anything short of fully delivered falls through to\n * the server poll, which stays the authority there.\n *\n * Returns the server-assigned `traces.id` for each replay trace, read back off\n * the OTLP ingest response during the flush and keyed by the client-side replay\n * trace id. Empty when the server predates that field or nothing was delivered.\n */\nexport async function waitForReplayPersistence(\n httpClient: HttpClient,\n testRunId: string,\n replayedTraceIds: string[],\n): Promise<Record<string, string>> {\n // Settle deferred submissions before counting. A `finalize` root span only\n // reaches the transport once its finalize chain resolves, so tallying first\n // would under-count and let the barrier pass on a trace that is still short.\n // This waits for that work WITHOUT flushing: a run that submitted nothing\n // must not emit an export request just to discover it has nothing to wait on.\n const deferredSettled = await httpClient.settleDeferredWork(\n REPLAY_PERSISTENCE_TIMEOUT_MS,\n )\n\n // Checked BEFORE the tally: deferred work that never landed means no\n // completion may have registered at all, and an empty tally would then look\n // like \"nothing to wait for\" and finalize the run with root spans pending.\n if (!deferredSettled) {\n // Freed before throwing: every other exit releases these, and a retained\n // record would carry this run's submitted-but-unacked spans into the next\n // replay of the same trace ids.\n httpClient.takeTraceDeliveries(replayedTraceIds)\n throw new BitfabError(\n `Replay could not settle deferred span work before the deadline, so the ` +\n `expected span counts are incomplete (testRunId ${testRunId}).`,\n )\n }\n\n // Peeked before flushing: a run whose traces never closed submitted nothing\n // to wait on, and must not emit an export request just to discover that.\n if (!httpClient.hasClosedDeliveries(replayedTraceIds)) {\n httpClient.takeTraceDeliveries(replayedTraceIds)\n return {}\n }\n\n // A failed flush is a hint, not a verdict. It means delivery was not\n // CONFIRMED within the deadline, which is not the same as lost: the export\n // timeout can fire while requests are still in flight and the server goes on\n // to persist every one of them. Throwing here failed runs whose data had\n // fully landed.\n const flushed = await flushTraces(REPLAY_PERSISTENCE_TIMEOUT_MS)\n\n const deliveries = httpClient.takeTraceDeliveries(replayedTraceIds)\n const expectedSpanCounts: Record<string, number> = {}\n const readBackTraceIds: Record<string, string> = {}\n let allDelivered = true\n for (const [traceId, delivery] of Object.entries(deliveries)) {\n if (delivery.serverTraceId !== undefined) {\n readBackTraceIds[traceId] = delivery.serverTraceId\n }\n if (!delivery.closed) {\n continue\n }\n expectedSpanCounts[traceId] = delivery.spanCount\n allDelivered = allDelivered && delivery.delivered\n }\n if (allDelivered) {\n return readBackTraceIds\n }\n\n // Unacked is not unpersisted: a request that timed out client-side may have\n // committed anyway, and an export the flush deadline abandoned may still be\n // in flight. Neither is knowable here, so from this point the server is the\n // only authority and the run polls it until it answers or the budget ends.\n //\n // The poll gets its own budget. Sharing one deadline with the flush meant a\n // flush that used it all left zero polling window, so the barrier failed\n // after a single not-ready answer - exactly the case where the export is\n // still in flight and about to persist.\n const deadline = Date.now() + REPLAY_PERSISTENCE_TIMEOUT_MS\n\n let missing = Object.keys(expectedSpanCounts).length\n while (true) {\n const status = await httpClient.getReplayStatus(\n testRunId,\n expectedSpanCounts,\n )\n const ready = status.traceIds ?? {}\n missing = Object.keys(expectedSpanCounts).filter(\n (traceId) => ready[traceId] === undefined,\n ).length\n if (missing === 0) {\n return readBackTraceIds\n }\n if (Date.now() >= deadline) {\n break\n }\n await sleepForReplayPersistence(\n Math.min(100, Math.max(0, deadline - Date.now())),\n )\n }\n\n // Only now is it a real failure: the server itself never confirmed these.\n // Surface the flush result as the likely cause rather than as the verdict.\n const cause = flushed\n ? \"\"\n : \" Delivery was also not confirmed before the flush deadline, so the \" +\n \"spans likely never reached the server.\"\n throw new BitfabError(\n `Replay traces were not fully persisted before the delivery deadline ` +\n `(testRunId ${testRunId}, missing ${missing} of ` +\n `${Object.keys(expectedSpanCounts).length} trace(s)).${cause}`,\n )\n}\n\n/** @internal Wait between replay persistence polls without releasing Node. */\nexport function sleepForReplayPersistence(ms: number): Promise<void> {\n return new Promise((resolve) => {\n // This timer is part of an awaited persistence barrier. It must keep a CLI\n // process alive until the server confirms the replay or the deadline fires.\n setTimeout(resolve, ms)\n })\n}\n\n/**\n * Run async tasks with a concurrency limit.\n * Each task factory is called when a slot opens; results preserve input order.\n */\nasync function mapWithConcurrency<T>(\n tasks: Array<() => Promise<T>>,\n maxConcurrency: number,\n onSettled?: (result: T, index: number) => void | Promise<void>,\n onStarted?: (index: number) => void,\n): Promise<T[]> {\n const results: T[] = new Array(tasks.length)\n let nextIndex = 0\n\n async function worker(): Promise<void> {\n while (nextIndex < tasks.length) {\n const index = nextIndex++\n onStarted?.(index)\n const result = await tasks[index]()\n results[index] = result\n await onSettled?.(result, index)\n }\n }\n\n const workers = Array.from(\n { length: Math.min(maxConcurrency, tasks.length) },\n () => worker(),\n )\n await Promise.all(workers)\n return results\n}\n\n/**\n * Replay historical traces through a function and create a test run.\n *\n * @internal Called by Bitfab.replay, not part of the public API.\n */\nexport async function replay<TReturn>(\n httpClient: HttpClient,\n serviceUrl: string,\n traceFunctionKey: string,\n // biome-ignore lint/suspicious/noExplicitAny: replay deserializes inputs from historical data\n fn: (...args: any[]) => TReturn | Promise<TReturn>,\n options?: ReplayOptions,\n registeredOverrides: MockOverride[] = [],\n): Promise<ReplayResult<TReturn>> {\n if (options?.traceIds !== undefined) {\n if (options.traceIds.length === 0) {\n throw new BitfabError(\"traceIds must contain at least one trace ID.\")\n }\n if (options.traceIds.length > 100) {\n throw new BitfabError(\n `traceIds supports at most 100 trace IDs per replay (got ${options.traceIds.length}).`,\n )\n }\n }\n if (options?.traceIds !== undefined && options?.datasetId !== undefined) {\n throw new BitfabError(\n \"traceIds and datasetId select different replay sources and cannot be used together.\",\n )\n }\n if (options?.limit !== undefined && options?.traceIds !== undefined) {\n try {\n console.warn(\n \"Bitfab: limit is ignored when traceIds is passed: the explicit trace ID list already determines how many traces replay.\",\n )\n } catch {\n // Never crash the host app\n }\n }\n const attempts = resolveAttempts(options?.attempts)\n await replayContextReady\n\n // Resolve the code change to attach to this experiment. codeChangeFiles is\n // the capture control: omitted auto-captures, an array wins, and null opts\n // out. A caller-supplied description is preserved when files are captured.\n let codeChangeDescription = options?.codeChangeDescription\n let codeChangeFiles = options?.codeChangeFiles\n if (codeChangeFiles === undefined) {\n const captured = await resolveAutoCodeChange(options?.name)\n if (captured) {\n codeChangeFiles = captured.files\n if (codeChangeDescription === undefined) {\n codeChangeDescription = captured.description\n }\n }\n }\n\n const {\n testRunId,\n testRunUrl,\n items: serverItems,\n } = await httpClient.startReplay(\n traceFunctionKey,\n // limit is meaningless with explicit traceIds (the ID list determines\n // the count), so it's omitted from the request entirely.\n options?.traceIds ? undefined : (options?.limit ?? 5),\n options?.traceIds,\n options?.name,\n codeChangeDescription,\n codeChangeFiles,\n // A dry run executes nothing, so a branch would be provisioned (and billed)\n // for code that never runs, and a seeded source's refusal would fail the item\n // before it could report its resolved inputs.\n dbBranchEnabled(options?.dbBranch) && options?.dryRun !== true,\n options?.experimentGroupId,\n options?.datasetId,\n options?.graderIds,\n resolveDbBranchSettings(options?.dbBranch),\n attempts,\n options?.adaptInputs !== undefined,\n )\n\n // An empty selection is the common shape of \"the corpus was never seeded\".\n // The result still reports it faithfully (zero items), but a caller reading\n // only the exit path would otherwise see a clean run that did nothing.\n if (serverItems.length === 0) {\n try {\n console.warn(\n `Bitfab: no traces matched \"${traceFunctionKey}\", so this replay ran nothing. Capture a trace, or seed one with seedTrace, before replaying.`,\n )\n } catch {\n // Never crash the host app\n }\n }\n\n const mockStrategy: MockStrategy = options?.mock ?? \"marked\"\n const maxConcurrency = options?.maxConcurrency ?? 10\n const fullTestRunUrl = `${serviceUrl}${testRunUrl}`\n\n // Per-call overrides take precedence over registered ones: concatenating them\n // first means the first-match-wins scan hits per-call overrides before the\n // client-registered chain, and both before the base mock strategy.\n const resolvedOverrides = [\n ...normalizeMockOverrides(options?.mockOverride),\n ...registeredOverrides,\n ]\n\n // One client-side replay trace id per item. It tags that item's replay spans\n // during the run so the server can echo back the row id it minted for them\n // (resolved in the complete-replay mapping below). Kept out of the public\n // ReplayItem: it's a correlation handle, never an id callers use.\n const workItems = expandReplayWork(serverItems, attempts)\n const replayedTraceIds = workItems.map(() => randomUuid())\n // Declared before the first span is submitted: the transport records delivery\n // only for traces someone asked about, so anything submitted before this\n // would go untracked.\n httpClient.trackTraceDeliveries(replayedTraceIds)\n const tasks = workItems.map(\n ({ serverItem, attempt }, index) =>\n () =>\n processItem(\n httpClient,\n serverItem,\n fn,\n testRunId,\n mockStrategy,\n resolvedOverrides,\n replayedTraceIds[index],\n attempt,\n dbBranchEnabled(options?.dbBranch) && options?.dryRun !== true,\n resolveDbBranchSettings(options?.dbBranch),\n options?.adaptInputs,\n options?.dryRun === true,\n ),\n )\n const total = tasks.length\n const onItemFinish = options?.onItemFinish ?? options?.onProgress\n let completed = 0\n let started = 0\n let succeeded = 0\n let errored = 0\n\n // Flush an item's trace the moment it finishes, so its server traces.id is\n // read back off the ingest response and surfaced on the item as it settles,\n // instead of waiting for the end-of-run barrier. Waiting until the end is\n // worst at low concurrency: each trace is closed and ready when its item\n // finishes, but nothing fills a batch to force an export, so ready ids sit in\n // the queue for the whole run.\n //\n // Coalesced so a burst of concurrent finishes shares one flush: while a flush\n // runs, later finishers mark `pending` and await the same promise, which loops\n // once more to cover them. Every caller therefore waits for a flush that ran\n // after it asked, and low concurrency degrades to a clean flush per item.\n let flushInFlight: Promise<void> | null = null\n let flushPending = false\n const flushFinishedItemTrace = (): Promise<void> => {\n // Mark work waiting first, so a finisher that arrives mid-flush is always\n // picked up by another loop iteration. The runner clears `flushInFlight`\n // synchronously with the loop exit (no await between the `while` check and\n // the reset), so no caller can observe a stale in-flight promise.\n flushPending = true\n if (!flushInFlight) {\n flushInFlight = (async () => {\n try {\n while (flushPending) {\n flushPending = false\n await httpClient.settleDeferredWork(REPLAY_PERSISTENCE_TIMEOUT_MS)\n await flushTraces(REPLAY_PERSISTENCE_TIMEOUT_MS)\n }\n } finally {\n flushInFlight = null\n }\n })()\n }\n return flushInFlight\n }\n\n const resultItems = await mapWithConcurrency(\n tasks,\n maxConcurrency,\n async (item, index) => {\n // Deliver this item's trace now, then read its server id back off the\n // ingest response. A flush failure never crashes the run: the id degrades\n // to null and the end-of-run barrier stays the authority on persistence.\n // Done BEFORE touching the counters so the increment and emit below carry\n // no await between them: with items flushing concurrently, that keeps each\n // event's running totals a consistent snapshot.\n let serverTraceId: string | null = null\n try {\n await flushFinishedItemTrace()\n serverTraceId =\n httpClient.peekServerTraceId(replayedTraceIds[index]) ?? null\n } catch {\n // Best-effort: fall through with null; the barrier settles persistence.\n }\n item.traceId = serverTraceId\n completed += 1\n if (item.error === null) {\n succeeded += 1\n } else {\n errored += 1\n }\n try {\n onItemFinish?.({\n testRunId,\n completed,\n total,\n succeeded,\n errored,\n item: {\n // The server's assigned traces.id, read back off the ingest\n // response and surfaced as this item finishes. Null only if the\n // per-item flush could not confirm delivery in time; the end-of-run\n // barrier then fills the returned ReplayItem. The client-side\n // placeholder is never surfaced.\n traceId: serverTraceId,\n originalTraceId: item.originalTraceId ?? null,\n originalSpanId: item.originalSpanId ?? null,\n // Deprecated aliases for originalTraceId/originalSpanId.\n sourceTraceId: item.originalTraceId ?? null,\n sourceSpanId: item.originalSpanId ?? null,\n attempt: item.attempt,\n input: item.input,\n result: item.result,\n originalOutput: item.originalOutput,\n error: item.error,\n traceError: item.traceError,\n replayError: item.replayError,\n durationMs: item.durationMs,\n originalDurationMs: item.originalDurationMs,\n originalTokens: item.originalTokens,\n originalModel: item.originalModel,\n tokens: item.tokens,\n model: item.model,\n dbSnapshotRef: item.dbSnapshotRef,\n dbBranchTimings: item.dbBranchTimings,\n },\n })\n } catch {\n // Progress UI must never crash the replay run.\n }\n },\n options?.onItemStart\n ? (index) => {\n started += 1\n const { serverItem, attempt } = workItems[index]\n const originalTraceId =\n serverItem.originalTraceId ?? serverItem.sourceTraceId\n const originalSpanId =\n serverItem.originalSpanId ?? serverItem.sourceSpanId\n try {\n options.onItemStart?.({\n type: \"started\",\n testRunId,\n started,\n completed,\n total,\n succeeded,\n errored,\n item: {\n originalTraceId,\n originalSpanId,\n sourceTraceId: originalTraceId,\n sourceSpanId: originalSpanId,\n attempt,\n },\n })\n } catch {\n // Progress UI must never crash the replay run.\n }\n }\n : undefined,\n )\n\n // Items submit their spans through the same batching transport live traffic\n // uses, so nothing here has waited on the network yet. Flush the transports,\n // then let the SERVER confirm each trace reached a final status with all of\n // its spans before finalizing: a drained queue is not proof that Bitfab\n // committed the data.\n // A dry run executed nothing, so it produced no spans and no traces. The\n // persistence barrier asserts the opposite (every completed item has a\n // persisted trace) and would fail the whole run, so it is skipped along with\n // the trace-id mapping it feeds. The test run is still finalized so it does\n // not sit unfinished in the experiments list.\n if (options?.dryRun === true) {\n await httpClient.completeReplay(testRunId).catch(() => undefined)\n const dryResult: ReplayResult<TReturn> = {\n items: resultItems,\n testRunId,\n testRunUrl: fullTestRunUrl,\n attempts,\n }\n await writeReplayResultFile(dryResult)\n return dryResult\n }\n\n const deliveredTraceIds = await preserveReplayFailure(\n () => waitForReplayPersistence(httpClient, testRunId, replayedTraceIds),\n resultItems,\n testRunId,\n fullTestRunUrl,\n )\n\n // Primary source for item.traceId: the server's assigned traces.id, read back\n // per trace off the ingest response during the flush above (server-sourced, no\n // polling, already in hand before completeReplay). The completeReplay map below\n // remains the fallback for servers that don't return ids on ingest.\n for (let index = 0; index < resultItems.length; index += 1) {\n const localId = replayedTraceIds[index]\n const readBack = localId ? deliveredTraceIds[localId] : undefined\n if (readBack !== undefined) {\n resultItems[index].traceId = readBack\n }\n }\n\n // completeReplay finalizes the test run and returns the token/diagnostic\n // mapping; its failures propagate loudly because a run that never completed\n // can't be finalized and callers must hear about it.\n const completeResult = await preserveReplayFailure(\n () => httpClient.completeReplay(testRunId),\n resultItems,\n testRunId,\n fullTestRunUrl,\n )\n const serverTraceIds = completeResult.traceIds\n // Per-replay-trace token usage, keyed by server trace id. The REPLAYED run's\n // tokens (span-aggregated server-side), used below to fill each item.tokens.\n const replayTokens = completeResult.tokens\n\n // `serverTraceIds` maps each item's client-side replay trace id (its entry in\n // `replayedTraceIds`, which tagged that item's spans during the run) to the\n // server's trace row id. We use it to (a) write the real server replay trace\n // id into `item.traceId` now that the row exists, (b) attach each item's\n // server-aggregated token usage, and (c) detect a systemic upload failure\n // early. Verdict persistence does NOT use this map: it is keyed by the\n // original-trace lineage (`originalTraceId` + `testRunId`), which needs no\n // client-held server id. Older servers that omit the map yield no replay\n // tokens and leave `item.traceId` null.\n if (serverTraceIds !== undefined) {\n const missing: string[] = []\n let completedCount = 0\n for (let index = 0; index < resultItems.length; index += 1) {\n const item = resultItems[index]\n const localId = replayedTraceIds[index]\n const mapped = localId ? serverTraceIds[localId] : undefined\n // Fallback fill for servers that did not return ids on the ingest\n // response; the read-back loop above already set it when they did, so\n // never overwrite a resolved id with null here.\n item.traceId = item.traceId ?? mapped ?? null\n if (item.error === null) {\n completedCount += 1\n if (mapped === undefined) {\n missing.push(localId ?? item.originalTraceId)\n }\n }\n if (mapped !== undefined) {\n item.tokens = replayTokens?.[mapped] ?? null\n }\n }\n // ALL completed items missing → systemic (the replayed function isn't\n // wrapped with withSpan, or uploads are wholesale broken). Throw; the run's\n // traces never persisted, so nothing can be labeled and silence here is the\n // exact bug this guarantee exists to prevent.\n if (completedCount > 0 && missing.length === completedCount) {\n const serverCount =\n completeResult.traceCount !== undefined\n ? ` The server persisted ${completeResult.traceCount} trace(s) for this run.`\n : \"\"\n const cause = new BitfabError(\n `Replay completed but the server has no persisted trace for any of the ${completedCount} completed item(s) (testRunId ${testRunId}).${serverCount} ` +\n `Trace uploads were awaited, so either the uploads failed (check for \"Bitfab: Failed to create\" errors above) or the replayed function is not wrapped with withSpan.`,\n )\n throw new ReplayError(\n cause.message,\n resultItems,\n testRunId,\n fullTestRunUrl,\n cause,\n )\n }\n // SOME completed items missing → per-item upload failure (transient blip,\n // one oversized payload). Log it, but return the run; the items that landed\n // can still be labeled via their lineage.\n if (missing.length > 0) {\n try {\n console.error(\n `Bitfab: server has no persisted trace for ${missing.length} of ${completedCount} completed replay item(s) (testRunId ${testRunId}). Their replay token usage is unavailable and they cannot be labeled.`,\n )\n } catch {\n // Never crash the host app\n }\n }\n }\n\n const result: ReplayResult<TReturn> = {\n items: resultItems,\n testRunId,\n testRunUrl: fullTestRunUrl,\n attempts,\n }\n // Persist the enriched result so the Bitfab plugin never has to parse the\n // replay's stdout, which a dependency's logging can corrupt.\n await writeReplayResultFile(result)\n // Preserve the legacy terminal event only for onProgress. onItemFinish is\n // strictly item-scoped, so every invocation always includes an item.\n if (!options?.onItemFinish) {\n try {\n options?.onProgress?.({\n type: \"complete\",\n testRunId,\n completed: total,\n total,\n succeeded,\n errored,\n result,\n })\n } catch {\n // A progress reporter must never crash the replay run.\n }\n }\n return result\n}\n\nasync function writeReplayResultFile(\n result: ReplayResult<unknown>,\n): Promise<void> {\n const resultPath =\n typeof process !== \"undefined\"\n ? process.env?.BITFAB_REPLAY_RESULT_PATH\n : undefined\n if (!resultPath) {\n return\n }\n\n try {\n const [{ dirname }, { mkdir, writeFile }] = await Promise.all([\n import(\"node:path\"),\n import(\"node:fs/promises\"),\n ])\n await mkdir(dirname(resultPath), { recursive: true })\n await writeFile(resultPath, `${serializeReplayResult(result)}\\n`)\n } catch (err) {\n try {\n console.warn(\n `Bitfab: failed to write replay result to BITFAB_REPLAY_RESULT_PATH (${resultPath}): ${\n err instanceof Error ? err.message : String(err)\n }`,\n )\n } catch {\n // Never crash the host app.\n }\n }\n}\n","/**\n * Node.js-specific entry point for the Bitfab SDK.\n *\n * Selected automatically via package.json `exports` conditions when the\n * consumer's runtime or bundler supports the \"node\" condition (Node.js,\n * most server-side bundlers).\n *\n * This entry point differs from the default (`index.ts`) in one way:\n * it synchronously registers Node.js's `AsyncLocalStorage` before any\n * other SDK code evaluates. This eliminates the async initialization\n * gap that the default entry point has (where the first span might\n * execute before the dynamic import of `node:async_hooks` resolves).\n *\n * The default entry point (`index.ts`) is used for browsers and other\n * environments where `node:async_hooks` is unavailable. There, span\n * nesting degrades gracefully to a shared stack (correct for sequential\n * async, but not for concurrent Promise.all patterns).\n */\n\n// ⚠️ IMPORT ORDER MATTERS\n// asyncStorageNode MUST be imported before index.js.\n// It registers the AsyncLocalStorage class synchronously during module\n// evaluation. index.js (via client.ts) reads from that registration at\n// span creation time. If this import is moved after index.js or removed,\n// span nesting silently degrades to the browser fallback (flat spans).\nimport \"./asyncStorageNode.js\"\n\nexport * from \"./index.js\"\n\n// Verify registration succeeded. This turns a silent degradation into a\n// loud error if someone reorders the imports above or if asyncStorageNode.ts\n// fails to register for any reason. Only runs in the Node.js entry point\n// where we know node:async_hooks must be available.\nimport { assertAsyncStorageRegistered } from \"./asyncStorage.js\"\n\nassertAsyncStorageRegistered()\n","/**\n * Synchronous AsyncLocalStorage registration for Node.js.\n *\n * This module is a side-effect-only import: it registers the Node.js\n * AsyncLocalStorage class into the shared registry so span nesting\n * works immediately - no async gap, no microtask delay.\n *\n * It is imported by `node.ts` (the Node.js-specific entry point) as\n * the FIRST import, before `index.ts` or `client.ts` are evaluated.\n *\n * This file must ONLY be imported in Node.js environments (not browsers).\n * It uses a static `import` of `node:async_hooks`, which will fail in\n * browser bundlers. The `node.ts` entry point is conditionally selected\n * via package.json `exports` conditions, so browsers never see this file.\n */\n\nimport { AsyncLocalStorage } from \"node:async_hooks\"\nimport type { AsyncLocalStorageLike } from \"./asyncStorage.js\"\nimport { registerAsyncLocalStorageClass } from \"./asyncStorage.js\"\n\nregisterAsyncLocalStorageClass(\n AsyncLocalStorage as unknown as new () => AsyncLocalStorageLike<unknown>,\n)\n","/**\n * Claude Agent SDK handler for Bitfab tracing.\n *\n * Hooks into the Claude Agent SDK's lifecycle to capture LLM turns,\n * tool invocations, and subagent execution as Bitfab spans.\n *\n * Uses two integration surfaces:\n * 1. SDK hooks (PreToolUse, PostToolUse, etc.) for tool/subagent lifecycle\n * 2. Stream wrapping for LLM turn capture from the message stream\n */\n\nimport { DEFAULT_SERVICE_URL } from \"./constants.js\"\nimport { type ApiKeyInput, HttpClient } from \"./http.js\"\nimport {\n finalizeSpanPayload,\n finalizeTracePayload,\n} from \"./processorPayload.js\"\nimport { randomUuid } from \"./randomUuid.js\"\nimport { toJsonSafe, toJsonSafeReport } from \"./serialize.js\"\nimport { nowIsoTimestamp } from \"./timestamp.js\"\n\nexport interface ActiveSpanContext {\n traceId: string\n spanId: string\n}\n\ninterface SpanInfo {\n id: string\n spanId: string\n traceId: string\n parentId: string | null\n startedAt: string\n endedAt?: string\n name: string\n type: string\n input?: unknown\n output?: unknown\n error?: string\n contexts: Array<Record<string, unknown>>\n // Type names of input/output values that could only be captured as\n // placeholders (serialized at capture time to snapshot a mutable value).\n // Carried to the send boundary so finalizeSpanPayload can mark the span.\n dropped?: string[]\n}\n\nfunction nowIso(): string {\n return nowIsoTimestamp()\n}\n\n// Delegates to the shared toJsonSafe so the recurse-the-dump logic lives in\n// exactly one place (see serialize.ts).\nconst safeSerialize = toJsonSafe\n\nfunction extractContentBlocks(\n content: unknown,\n): Array<Record<string, unknown>> {\n if (!Array.isArray(content)) {\n return []\n }\n return content.map((block) => safeSerialize(block) as Record<string, unknown>)\n}\n\nfunction asTokenCount(val: unknown): number | null {\n return typeof val === \"number\" && Number.isFinite(val) ? val : null\n}\n\nfunction extractUsage(\n message: Record<string, unknown>,\n): Record<string, unknown> {\n const usageInfo: Record<string, unknown> = {}\n const usage = message.usage as Record<string, unknown> | undefined\n if (!usage) {\n return usageInfo\n }\n\n // Anthropic reports `input_tokens` as the NON-cached prompt tokens, with\n // cache reads and cache writes counted separately. Bitfab's `inputTokens`\n // is the full prompt size (matching the LangGraph integration), so fold the\n // cache buckets in. `cacheReadTokens` stays the cached SUBSET, which the read\n // side uses to back out the uncached portion (`?tokenType=uncached`).\n const baseInput = asTokenCount(usage.input_tokens)\n const cacheRead = asTokenCount(usage.cache_read_input_tokens)\n const cacheCreation = asTokenCount(usage.cache_creation_input_tokens)\n if (baseInput !== null || cacheRead !== null || cacheCreation !== null) {\n usageInfo.inputTokens =\n (baseInput ?? 0) + (cacheRead ?? 0) + (cacheCreation ?? 0)\n }\n\n const output = asTokenCount(usage.output_tokens)\n if (output !== null) {\n usageInfo.outputTokens = output\n }\n if (cacheRead !== null) {\n usageInfo.cacheReadTokens = cacheRead\n }\n if (cacheCreation !== null) {\n usageInfo.cacheCreationTokens = cacheCreation\n }\n\n return usageInfo\n}\n\ntype HookCallback = (\n // biome-ignore lint/suspicious/noExplicitAny: Hook callback signatures from Claude Agent SDK use untyped dicts\n inputData: Record<string, any>,\n toolUseId: string | null,\n context: unknown,\n) => Promise<Record<string, unknown>>\n\n/**\n * Claude Agent SDK handler that sends traces to Bitfab.\n *\n * Captures LLM turns, tool invocations, and subagent execution as\n * Bitfab spans with proper parent-child hierarchy.\n *\n * The TypeScript Claude Agent SDK exposes a single `query()` entry point (there\n * is no `ClaudeSDKClient` class - that exists only in the Python SDK). Wrap the\n * `query()` async iterator with `wrapQuery`; tool and subagent spans come from\n * the hooks injected by `instrumentOptions`.\n *\n * ```typescript\n * import { Bitfab } from \"@bitfab/sdk\";\n * import { query } from \"@anthropic-ai/claude-agent-sdk\";\n *\n * const bitfab = new Bitfab({ apiKey: \"...\" });\n * const handler = bitfab.getClaudeAgentHandler(\"my-agent\");\n *\n * const options = handler.instrumentOptions({\n * model: \"claude-sonnet-4-5-...\",\n * });\n *\n * for await (const message of handler.wrapQuery(\n * query({ prompt: \"Do something\", options })\n * )) {\n * // process messages normally\n * }\n * ```\n */\nexport class BitfabClaudeAgentHandler {\n private readonly httpClient: HttpClient\n private readonly ownsHttpClient: boolean\n private readonly traceFunctionKey: string\n private readonly getActiveSpanContext: (() => ActiveSpanContext | null) | null\n\n // Span tracking\n private runToSpan: Map<string, SpanInfo> = new Map()\n private traceId: string | null = null\n private rootSpanId: string | null = null\n private activeContext: ActiveSpanContext | null = null\n private traceStartedAt: string | null = null\n\n // LLM turn tracking\n private conversationHistory: Array<Record<string, unknown>> = []\n private pendingMessages: Array<Record<string, unknown>> = []\n private currentLlmSpanId: string | null = null\n private currentLlmMessageId: string | null = null\n private currentLlmContent: Array<Record<string, unknown>> = []\n private currentLlmModel: string | null = null\n private currentLlmUsage: Record<string, unknown> = {}\n private currentLlmStartedAt: string | null = null\n private currentLlmHistorySnapshot: Array<Record<string, unknown>> = []\n\n // Subagent tracking\n private activeSubagentSpans: Map<string, string> = new Map()\n\n // Synthetic root span (handler-only replay). When an `input` is supplied to\n // wrapQuery/wrapResponse, the handler emits a root `agent` span carrying that\n // input, so a handler-instrumented run is replayable WITHOUT an enclosing\n // withSpan - matching the LangGraph handler, which records the graph input as\n // its root. The prompt is not present anywhere in the message stream, so it\n // must be handed in explicitly.\n private hasRootInput = false\n private rootInput: unknown\n private rootOutput: unknown\n\n constructor(config: {\n apiKey?: ApiKeyInput\n traceFunctionKey: string\n serviceUrl?: string\n timeout?: number\n getActiveSpanContext?: () => ActiveSpanContext | null\n /**\n * The owning `Bitfab` client's HTTP client. Supplied by\n * `getClaudeAgentHandler()` so this handler shares that client's single\n * span-transport worker instead of starting a second one.\n * @internal\n */\n _httpClient?: HttpClient\n }) {\n this.ownsHttpClient = config._httpClient === undefined\n this.httpClient =\n config._httpClient ??\n new HttpClient({\n apiKey: config.apiKey,\n serviceUrl: config.serviceUrl ?? DEFAULT_SERVICE_URL,\n timeout: config.timeout ?? 10000,\n })\n this.traceFunctionKey = config.traceFunctionKey\n this.getActiveSpanContext = config.getActiveSpanContext ?? null\n\n // Bind hook callbacks so they can be passed as standalone functions\n this.preToolUseHook = this.preToolUseHook.bind(this)\n this.postToolUseHook = this.postToolUseHook.bind(this)\n this.postToolUseFailureHook = this.postToolUseFailureHook.bind(this)\n this.subagentStartHook = this.subagentStartHook.bind(this)\n this.subagentStopHook = this.subagentStopHook.bind(this)\n }\n\n /**\n * Flush and release the span transport this handler started. A no-op when\n * the handler borrowed a `Bitfab` client's HTTP client: that client's\n * `close()` owns the worker's lifetime.\n */\n async close(timeoutMs?: number): Promise<boolean> {\n return this.ownsHttpClient ? this.httpClient.close(timeoutMs) : true\n }\n\n // ── trace lifecycle ──────────────────────────────────────────\n\n private ensureTrace(): string {\n if (this.traceId !== null) {\n return this.traceId\n }\n\n this.activeContext = this.getActiveSpanContext?.() ?? null\n\n if (this.activeContext) {\n this.traceId = this.activeContext.traceId\n } else {\n this.traceId = randomUuid()\n }\n\n this.traceStartedAt = nowIso()\n return this.traceId\n }\n\n private getParentId(agentId?: string): string | null {\n if (agentId) {\n const subagentSpanId = this.activeSubagentSpans.get(agentId)\n if (subagentSpanId) {\n return subagentSpanId\n }\n }\n // Prefer the synthetic root (handler-only mode) so every span nests under\n // it; fall back to the enclosing withSpan context. The two are never both\n // set - the synthetic root is only created when there is no active context.\n return this.rootSpanId ?? this.activeContext?.spanId ?? null\n }\n\n // Emit the synthetic root `agent` span once, before any child spans. No-op\n // unless an `input` was supplied AND there is no enclosing withSpan (in which\n // case that outer span is already the replayable root).\n private maybeStartRootSpan(): void {\n if (!this.hasRootInput || this.rootSpanId !== null) {\n return\n }\n this.ensureTrace()\n if (this.activeContext !== null) {\n return\n }\n const spanId = randomUuid()\n this.startSpan(spanId, this.traceFunctionKey, \"agent\", this.rootInput, null)\n this.rootSpanId = spanId\n }\n\n private completeRootSpan(): void {\n if (this.rootSpanId === null) {\n return\n }\n const spanId = this.rootSpanId\n this.rootSpanId = null\n this.completeSpan(spanId, this.rootOutput)\n }\n\n // ── span helpers ─────────────────────────────────────────────\n\n private startSpan(\n spanId: string,\n name: string,\n spanType: string,\n inputData?: unknown,\n parentId?: string | null,\n ): SpanInfo {\n const traceId = this.ensureTrace()\n\n // Serialize input now to snapshot it (tool input can mutate between\n // PreToolUse and PostToolUse), but keep the report so a lossy input is\n // still marked non-replayable at the send boundary.\n const { safe: safeInput, dropped: inputDropped } =\n toJsonSafeReport(inputData)\n\n const spanInfo: SpanInfo = {\n id: randomUuid(),\n spanId,\n traceId,\n parentId: parentId ?? null,\n startedAt: nowIso(),\n name,\n type: spanType,\n input: safeInput,\n contexts: [],\n }\n if (inputDropped.length > 0) {\n spanInfo.dropped = [...inputDropped]\n }\n this.runToSpan.set(spanId, spanInfo)\n return spanInfo\n }\n\n private completeSpan(\n spanId: string,\n output?: unknown,\n error?: string,\n extraContexts?: Record<string, unknown>,\n ): void {\n const spanInfo = this.runToSpan.get(spanId)\n if (!spanInfo) {\n return\n }\n this.runToSpan.delete(spanId)\n\n spanInfo.endedAt = nowIso()\n const { safe: safeOutput, dropped: outputDropped } =\n toJsonSafeReport(output)\n spanInfo.output = safeOutput\n if (outputDropped.length > 0) {\n spanInfo.dropped = [...(spanInfo.dropped ?? []), ...outputDropped]\n }\n if (error !== undefined) {\n spanInfo.error = error\n }\n\n if (extraContexts) {\n spanInfo.contexts.push(extraContexts)\n }\n\n this.sendSpan(spanInfo)\n }\n\n private sendSpan(spanInfo: SpanInfo): void {\n const spanData: Record<string, unknown> = {\n name: spanInfo.name,\n type: spanInfo.type,\n }\n if (spanInfo.input !== undefined) {\n spanData.input = spanInfo.input\n }\n if (spanInfo.output !== undefined) {\n spanData.output = spanInfo.output\n }\n if (spanInfo.error !== undefined) {\n spanData.error = spanInfo.error\n }\n if (spanInfo.contexts.length > 0) {\n spanData.contexts = spanInfo.contexts\n }\n\n const rawSpan: Record<string, unknown> = {\n id: spanInfo.spanId,\n trace_id: spanInfo.traceId,\n started_at: spanInfo.startedAt,\n ended_at: spanInfo.endedAt ?? nowIso(),\n span_data: spanData,\n }\n if (spanInfo.parentId !== null) {\n rawSpan.parent_id = spanInfo.parentId\n }\n\n const payload: Record<string, unknown> = {\n id: spanInfo.id,\n traceId: spanInfo.traceId,\n type: \"sdk-function\",\n source: \"typescript-sdk-claude-agent-sdk\",\n traceFunctionKey: this.traceFunctionKey,\n sourceTraceId: spanInfo.traceId,\n rawSpan,\n }\n\n // Sanitize the whole span (a non-serializable value in any field is\n // dumped/stubbed, a lossy capture is marked) instead of shipping it raw.\n // spanInfo.dropped carries losses from the capture-time input/output\n // snapshot above.\n const finalized = finalizeSpanPayload(payload, spanInfo.dropped)\n\n try {\n this.httpClient.sendExternalSpan(finalized)\n } catch {\n // Silently ignore - never crash the host app\n }\n }\n\n private sendTraceCompletion(\n endedAt?: string,\n metadata?: Record<string, unknown>,\n ): void {\n if (this.traceId === null) {\n return\n }\n\n const completed = this.activeContext === null\n const traceId = this.traceId\n\n // Mark as sent so the finally block doesn't re-send\n this.traceId = null\n\n const externalTrace: Record<string, unknown> = {\n id: traceId,\n started_at: this.traceStartedAt ?? nowIso(),\n ended_at: endedAt ?? nowIso(),\n }\n\n if (metadata) {\n externalTrace.metadata = metadata\n }\n\n const traceData: Record<string, unknown> = {\n id: traceId,\n type: \"sdk-function\",\n source: \"typescript-sdk-claude-agent-sdk\",\n traceFunctionKey: this.traceFunctionKey,\n externalTrace,\n completed,\n }\n\n // Sanitize the whole trace (warning when the capture was lossy) instead of\n // shipping it raw and risking a wire-side JSON.stringify failure.\n const finalized = finalizeTracePayload(traceData)\n\n try {\n this.httpClient.sendExternalTrace(finalized)\n } catch {\n // Silently ignore - never crash the host app\n }\n }\n\n // ── hook callbacks ───────────────────────────────────────────\n\n private async preToolUseHook(\n // biome-ignore lint/suspicious/noExplicitAny: Hook input from Claude Agent SDK is untyped\n inputData: Record<string, any>,\n toolUseId: string | null,\n _context: unknown,\n ): Promise<Record<string, unknown>> {\n try {\n const sid = (inputData.tool_use_id as string) ?? toolUseId ?? randomUuid()\n const toolName = (inputData.tool_name as string) ?? \"tool\"\n const toolInput = inputData.tool_input ?? {}\n const agentId = inputData.agent_id as string | undefined\n const parentId = this.getParentId(agentId)\n\n this.startSpan(sid, toolName, \"function\", toolInput, parentId)\n } catch {\n // Never crash the host app\n }\n return {}\n }\n\n private async postToolUseHook(\n // biome-ignore lint/suspicious/noExplicitAny: Hook input from Claude Agent SDK is untyped\n inputData: Record<string, any>,\n toolUseId: string | null,\n _context: unknown,\n ): Promise<Record<string, unknown>> {\n try {\n const sid = (inputData.tool_use_id as string) ?? toolUseId ?? \"\"\n const toolResponse = inputData.tool_response\n this.completeSpan(sid, toolResponse)\n } catch {\n // Never crash the host app\n }\n return {}\n }\n\n private async postToolUseFailureHook(\n // biome-ignore lint/suspicious/noExplicitAny: Hook input from Claude Agent SDK is untyped\n inputData: Record<string, any>,\n toolUseId: string | null,\n _context: unknown,\n ): Promise<Record<string, unknown>> {\n try {\n const sid = (inputData.tool_use_id as string) ?? toolUseId ?? \"\"\n const error = String(inputData.error ?? \"Unknown error\")\n this.completeSpan(sid, undefined, error)\n } catch {\n // Never crash the host app\n }\n return {}\n }\n\n private async subagentStartHook(\n // biome-ignore lint/suspicious/noExplicitAny: Hook input from Claude Agent SDK is untyped\n inputData: Record<string, any>,\n _toolUseId: string | null,\n _context: unknown,\n ): Promise<Record<string, unknown>> {\n try {\n const agentId = (inputData.agent_id as string) ?? randomUuid()\n const agentType = (inputData.agent_type as string) ?? \"subagent\"\n const parentId = this.getParentId()\n\n const spanId = randomUuid()\n this.activeSubagentSpans.set(agentId, spanId)\n\n this.startSpan(\n spanId,\n `Agent: ${agentType}`,\n \"agent\",\n undefined,\n parentId,\n )\n } catch {\n // Never crash the host app\n }\n return {}\n }\n\n private async subagentStopHook(\n // biome-ignore lint/suspicious/noExplicitAny: Hook input from Claude Agent SDK is untyped\n inputData: Record<string, any>,\n _toolUseId: string | null,\n _context: unknown,\n ): Promise<Record<string, unknown>> {\n try {\n const agentId = (inputData.agent_id as string) ?? \"\"\n const spanId = this.activeSubagentSpans.get(agentId)\n if (spanId) {\n this.activeSubagentSpans.delete(agentId)\n this.completeSpan(spanId)\n }\n } catch {\n // Never crash the host app\n }\n return {}\n }\n\n // ── public API ───────────────────────────────────────────────\n\n /**\n * Inject Bitfab tracing hooks into Claude Agent SDK options.\n *\n * Modifies the options object and returns it for convenience.\n * The SDK's `HookMatcher` is constructed as a plain object\n * (`{ matcher: null, hooks: [callback] }`) to avoid requiring\n * `@anthropic-ai/claude-agent-sdk` as a dependency.\n *\n * @param options - Options object with a `hooks` property\n * @returns The modified options object with Bitfab hooks injected\n */\n instrumentOptions<T extends Record<string, unknown>>(options: T): T {\n type HookEntry = { matcher: null; hooks: HookCallback[] }\n type HooksDict = Record<string, HookEntry[]>\n\n const hooks: HooksDict = (options.hooks as HooksDict) ?? {}\n if (!options.hooks) {\n ;(options as Record<string, unknown>).hooks = hooks\n }\n\n const hookConfig: Array<[string, HookCallback]> = [\n [\"PreToolUse\", this.preToolUseHook],\n [\"PostToolUse\", this.postToolUseHook],\n [\"PostToolUseFailure\", this.postToolUseFailureHook],\n [\"SubagentStart\", this.subagentStartHook],\n [\"SubagentStop\", this.subagentStopHook],\n ]\n\n for (const [event, callback] of hookConfig) {\n if (!hooks[event]) {\n hooks[event] = []\n }\n hooks[event].push({ matcher: null, hooks: [callback] })\n }\n\n return options\n }\n\n /**\n * Wrap any Claude Agent SDK message stream to capture LLM turns.\n *\n * Yields every message unchanged while capturing assistant message\n * content as LLM turn spans. Kept for naming symmetry with the Python\n * SDK's `wrapResponse` (which wraps `ClaudeSDKClient.receiveResponse()`);\n * in TypeScript, prefer `wrapQuery` around `query()`.\n *\n * Pass `{ input }` (the prompt) to record a replayable root span - see\n * `wrapQuery`.\n */\n async *wrapResponse(\n stream: AsyncIterable<unknown>,\n opts?: { input?: unknown },\n ): AsyncIterable<unknown> {\n this.setRootInput(opts)\n yield* this.processStream(stream)\n }\n\n /**\n * Wrap a `query()` async iterator to capture LLM turns.\n *\n * Tool and subagent spans are captured separately via the hooks injected\n * by `instrumentOptions` into the `options` passed to `query()`.\n *\n * Pass `{ input }` - the prompt (or the serializable args that produced it)\n * - to make a handler-only run replayable: the handler records a root `agent`\n * span with that input, so `replay(key, fn)` can re-feed it. Omit it only\n * when an enclosing `withSpan` already supplies the replayable root.\n *\n * ```typescript\n * handler.wrapQuery(query({ prompt, options }), { input: prompt })\n * ```\n */\n async *wrapQuery(\n stream: AsyncIterable<unknown>,\n opts?: { input?: unknown },\n ): AsyncIterable<unknown> {\n this.setRootInput(opts)\n yield* this.processStream(stream)\n }\n\n private setRootInput(opts?: { input?: unknown }): void {\n // Set deterministically on every wrap call so a prior call's input can\n // never leak into a later input-less run on a reused handler (e.g. if the\n // earlier stream's iterator was abandoned mid-iteration, so resetState\n // never ran).\n if (opts && opts.input !== undefined) {\n this.hasRootInput = true\n this.rootInput = opts.input\n } else {\n this.hasRootInput = false\n this.rootInput = undefined\n }\n this.rootOutput = undefined\n }\n\n // ── stream processing ────────────────────────────────────────\n\n private async *processStream(\n stream: AsyncIterable<unknown>,\n ): AsyncIterable<unknown> {\n try {\n this.maybeStartRootSpan()\n for await (const message of stream) {\n try {\n this.processMessage(message as Record<string, unknown>)\n } catch {\n // Never crash the host app\n }\n yield message\n }\n } finally {\n try {\n this.flushLlmTurn()\n this.completeRootSpan()\n this.sendTraceCompletion()\n } catch {\n // Never crash the host app\n }\n this.resetState()\n }\n }\n\n private processMessage(message: Record<string, unknown>): void {\n // The TypeScript Claude Agent SDK streams plain wire objects discriminated\n // by a `type` field (`{ type: \"assistant\", message: <BetaMessage>, ... }`),\n // NOT class instances. (The Python SDK, by contrast, yields AssistantMessage\n // / UserMessage / ResultMessage dataclasses - hence the different field\n // access here vs. claude_agent_sdk.py.) Routing on `constructor.name` would\n // always see \"Object\" and silently capture nothing.\n const typeName = message.type\n\n if (typeName === \"assistant\") {\n this.handleAssistantMessage(message)\n } else if (typeName === \"user\") {\n this.handleUserMessage(message)\n } else if (typeName === \"result\") {\n this.handleResultMessage(message)\n }\n }\n\n private handleAssistantMessage(message: Record<string, unknown>): void {\n this.ensureTrace()\n\n // Content, model, id, and usage live on the nested BetaMessage, not the\n // top-level SDK wire wrapper.\n const inner = (message.message as Record<string, unknown> | undefined) ?? {}\n\n const messageId =\n (inner.id as string | undefined) ?? (message.uuid as string | undefined)\n\n if (messageId !== this.currentLlmMessageId) {\n this.flushLlmTurn()\n\n // Drain pending user/tool messages into history before snapshot\n this.conversationHistory.push(...this.pendingMessages)\n this.pendingMessages = []\n\n this.currentLlmSpanId = randomUuid()\n this.currentLlmMessageId = messageId ?? null\n this.currentLlmContent = []\n this.currentLlmModel = (inner.model as string) ?? null\n this.currentLlmUsage = {}\n this.currentLlmStartedAt = nowIso()\n this.currentLlmHistorySnapshot = [...this.conversationHistory]\n }\n\n const content = inner.content\n if (Array.isArray(content)) {\n this.currentLlmContent.push(...extractContentBlocks(content))\n }\n\n const usage = extractUsage(inner)\n if (Object.keys(usage).length > 0) {\n Object.assign(this.currentLlmUsage, usage)\n }\n\n const model = inner.model as string | undefined\n if (model) {\n this.currentLlmModel = model\n }\n }\n\n private handleUserMessage(message: Record<string, unknown>): void {\n // User content lives on the nested MessageParam; tool_use_result is a\n // top-level field on the SDK wire wrapper.\n const inner = (message.message as Record<string, unknown> | undefined) ?? {}\n const content = inner.content\n const toolUseResult = message.tool_use_result\n\n if (toolUseResult !== undefined) {\n this.pendingMessages.push({\n role: \"tool\",\n content: safeSerialize(content),\n tool_result: safeSerialize(toolUseResult),\n })\n } else {\n this.pendingMessages.push({\n role: \"user\",\n content: safeSerialize(content),\n })\n }\n }\n\n private handleResultMessage(message: Record<string, unknown>): void {\n this.flushLlmTurn()\n\n // The final result text is the synthetic root span's output.\n if (message.result !== undefined) {\n this.rootOutput = message.result\n }\n this.completeRootSpan()\n\n const metadata: Record<string, unknown> = {}\n for (const attr of [\n \"num_turns\",\n \"total_cost_usd\",\n \"duration_ms\",\n \"duration_api_ms\",\n \"session_id\",\n ]) {\n const val = message[attr]\n if (val !== undefined && val !== null) {\n metadata[attr] = val\n }\n }\n\n const usage = message.usage\n if (usage && typeof usage === \"object\") {\n metadata.usage = safeSerialize(usage)\n }\n\n this.sendTraceCompletion(\n undefined,\n Object.keys(metadata).length > 0 ? metadata : undefined,\n )\n }\n\n private flushLlmTurn(): void {\n if (this.currentLlmSpanId === null) {\n return\n }\n\n const spanId = this.currentLlmSpanId\n const traceId = this.ensureTrace()\n const parentId = this.getParentId()\n\n const llmContext: Record<string, unknown> = {}\n if (this.currentLlmModel) {\n llmContext.model = this.currentLlmModel\n }\n Object.assign(llmContext, this.currentLlmUsage)\n\n const spanInfo: SpanInfo = {\n id: randomUuid(),\n spanId,\n traceId,\n parentId,\n startedAt: this.currentLlmStartedAt ?? nowIso(),\n endedAt: nowIso(),\n name: this.currentLlmModel ?? \"llm\",\n type: \"llm\",\n input: this.currentLlmHistorySnapshot,\n output: this.currentLlmContent,\n contexts: Object.keys(llmContext).length > 0 ? [llmContext] : [],\n }\n\n this.sendSpan(spanInfo)\n\n this.conversationHistory.push({\n role: \"assistant\",\n content: this.currentLlmContent,\n })\n\n this.currentLlmSpanId = null\n this.currentLlmMessageId = null\n this.currentLlmContent = []\n this.currentLlmModel = null\n this.currentLlmUsage = {}\n this.currentLlmStartedAt = null\n this.currentLlmHistorySnapshot = []\n }\n\n private resetState(): void {\n this.runToSpan.clear()\n this.traceId = null\n this.rootSpanId = null\n this.hasRootInput = false\n this.rootInput = undefined\n this.rootOutput = undefined\n this.activeContext = null\n this.traceStartedAt = null\n this.conversationHistory = []\n this.pendingMessages = []\n this.currentLlmSpanId = null\n this.currentLlmMessageId = null\n this.currentLlmContent = []\n this.currentLlmModel = null\n this.currentLlmUsage = {}\n this.currentLlmStartedAt = null\n this.currentLlmHistorySnapshot = []\n this.activeSubagentSpans.clear()\n }\n}\n","/**\n * Shared payload finalization for the framework tracing handlers.\n *\n * The OpenAI-Agents, LangGraph, and Claude Agent SDK handlers each build an\n * external span/trace payload that must be made JSON-safe before it is sent.\n *\n * Doing that silently with `toJsonSafe` hides a lossy capture. These helpers do\n * it in one place: sanitize via `toJsonSafeReport` and, when a value could only\n * be captured as a placeholder, mark the span (a `serialization_degraded`\n * error) or warn for the trace, so a degraded capture is surfaced as\n * non-replayable instead of being shipped silently. The HTTP boundary stays as\n * the final net. Mirrors the Python SDK's `processor_payload.py`.\n *\n * Note: this is only wired into the `toJsonSafe`-based framework surfaces. Core\n * `withSpan` / `@span` spans serialize via `serializeValue` (superjson, which\n * preserves the `meta` needed for typed replay); running this report serializer\n * there would strip that metadata, so the core path keeps its existing\n * http-layer sanitizer instead.\n */\n\nimport { toJsonSafeReport } from \"./serialize.js\"\nimport { warnOnce } from \"./warnOnce.js\"\n\nexport const SERIALIZATION_DEGRADED_STEP = \"serialization_degraded\"\n\ninterface DegradedError {\n source: \"sdk\"\n step: string\n error: string\n}\n\nfunction degradedError(dropped: string[]): DegradedError {\n const names = [...new Set(dropped)].sort().join(\", \")\n return {\n source: \"sdk\",\n step: SERIALIZATION_DEGRADED_STEP,\n error: `non-replayable: could not faithfully capture ${names}`,\n }\n}\n\n// Plain control fields carried through when the whole payload collapses to a\n// placeholder. Mirror of the Python SDK's `_rebuild_envelope` (plus\n// `traceFunctionKey`, which the TS payloads also carry): without them a\n// pathological top-level value would strip the routing fields the server needs,\n// not just the body. `completed` is span-irrelevant but harmless to copy.\nconst ENVELOPE_FIELDS = [\n \"type\",\n \"source\",\n \"traceFunctionKey\",\n \"sourceTraceId\",\n \"completed\",\n] as const\n\nfunction rebuildEnvelope(\n payload: Record<string, unknown>,\n bodyKey: string,\n placeholder: unknown,\n): Record<string, unknown> {\n const rebuilt: Record<string, unknown> = {}\n for (const k of ENVELOPE_FIELDS) {\n if (k in payload) {\n rebuilt[k] = payload[k]\n }\n }\n rebuilt[bodyKey] = { serialized: placeholder }\n return rebuilt\n}\n\n/**\n * Return a JSON-safe span payload, marking a lossy capture on its errors.\n *\n * The span body is preserved (never gutted). When a value could only be\n * captured as a placeholder, a `serialization_degraded` error is appended to\n * `payload.errors` so the lossy capture is recorded rather than shipped\n * silently.\n *\n * `extraDropped` carries losses detected by an earlier sanitization pass - e.g.\n * input/output that a handler serialized at capture time to snapshot a mutable\n * value. Without it, those fields reach this point as plain placeholder strings\n * and their loss would go unreported.\n */\nexport function finalizeSpanPayload(\n payload: Record<string, unknown>,\n extraDropped?: string[],\n): Record<string, unknown> {\n const { safe, dropped } = toJsonSafeReport(payload)\n const allDropped = [...(extraDropped ?? []), ...dropped]\n\n // toJsonSafeReport collapses to a non-object only for a pathological\n // top-level value; rebuild an envelope (carrying control fields) so the span\n // still ships and stays routable.\n const collapsed =\n safe === null || typeof safe !== \"object\" || Array.isArray(safe)\n const result: Record<string, unknown> = collapsed\n ? rebuildEnvelope(payload, \"rawSpan\", safe)\n : (safe as Record<string, unknown>)\n\n if (allDropped.length > 0) {\n const existing = result.errors\n const errors = Array.isArray(existing) ? existing : []\n errors.push(degradedError(allDropped))\n result.errors = errors\n }\n return result\n}\n\n/**\n * Return a JSON-safe trace payload, warning when the capture was lossy.\n *\n * The trace is preserved (never dropped). A trace payload has no errors field,\n * so a lossy capture is surfaced via `warnOnce` instead.\n */\nexport function finalizeTracePayload(\n payload: Record<string, unknown>,\n): Record<string, unknown> {\n const { safe, dropped } = toJsonSafeReport(payload)\n const collapsed =\n safe === null || typeof safe !== \"object\" || Array.isArray(safe)\n const result: Record<string, unknown> = collapsed\n ? rebuildEnvelope(payload, \"externalTrace\", safe)\n : (safe as Record<string, unknown>)\n\n if (dropped.length > 0 || collapsed) {\n const names =\n dropped.length > 0 ? [...new Set(dropped)].sort().join(\", \") : \"trace\"\n warnOnce(\n `finalizeTrace:${names.replace(/\\d+/g, \"N\")}`,\n `a trace held non-serializable value(s) (${names}); they were captured as placeholders, so the trace may not be replayable.`,\n )\n }\n return result\n}\n","let lastTimestampMicros = 0\n\nexport function nowIsoTimestamp(): string {\n const wallClockMicros = Date.now() * 1_000\n lastTimestampMicros = Math.max(wallClockMicros, lastTimestampMicros + 1)\n const milliseconds = Math.floor(lastTimestampMicros / 1_000)\n const remainingMicros = lastTimestampMicros % 1_000\n return new Date(milliseconds)\n .toISOString()\n .replace(\"Z\", `${remainingMicros.toString().padStart(3, \"0\")}Z`)\n}\n","/**\n * Bitfab client for provider-based API calls.\n */\n\nimport {\n type AsyncLocalStorageLike,\n asyncStorageReady,\n createAsyncLocalStorage,\n isAsyncStorageInitDone,\n} from \"./asyncStorage.js\"\nimport {\n __bitfabAutoTraceActive,\n __setBitfabAutoTraceCapturePolicy,\n type AutoTraceContext,\n type AutoTraceFunctionDefinition,\n type AutoTraceNodeConfiguration,\n getAutoTraceCapturePolicy,\n runWithAutoTraceContext,\n runWithAutoTraceNodeConfiguration,\n runWithAutoTraceRootContext,\n} from \"./autoTrace.js\"\nimport {\n type AllowedEnvVars,\n type ProviderDefinition,\n runFunctionWithBaml,\n} from \"./baml.js\"\nimport type { CaptureSurface, SurfaceRequest } from \"./captureSurface.js\"\nimport {\n assertSurfacesCompatible,\n DEFAULT_SURFACE,\n mixedTracingError,\n resolveSurface,\n} from \"./captureSurface.js\"\nimport { BitfabClaudeAgentHandler } from \"./claudeAgentSdk.js\"\nimport { DEFAULT_SERVICE_URL } from \"./constants.js\"\nimport { DatasetsClient } from \"./datasets.js\"\nimport type { DbSnapshotConfig, DbSnapshotRef } from \"./dbSnapshot.js\"\nimport { buildSnapshotRef, validateDbSnapshotConfig } from \"./dbSnapshot.js\"\nimport { MixedTracingError } from \"./errors.js\"\nimport {\n BitfabError,\n type CapturedSpan,\n HttpClient,\n type SpanLookup,\n} from \"./http.js\"\nimport { BitfabLangGraphCallbackHandler } from \"./langgraph.js\"\nimport {\n BitfabLangGraphIntegration,\n type LangGraphIntegrationOptions,\n} from \"./langgraphIntegration.js\"\nimport type {\n MockOverride,\n MockOverrideResolver,\n MockSource,\n MockTarget,\n MockValue,\n NodeMatcher,\n SpanNodeMeta,\n} from \"./mockOverride.js\"\nimport { NO_MOCK_OVERRIDE, resolveMockValue } from \"./mockOverride.js\"\nimport { BitfabOpenAIAgentHandler } from \"./openaiAgentSdk.js\"\nimport { importOptionalPeer } from \"./optionalPeer.js\"\nimport { randomUuid } from \"./randomUuid.js\"\nimport type {\n ReplayOptions,\n ReplayResult,\n TraceIngestionType,\n} from \"./replay.js\"\nimport { ReplayBranch } from \"./replayBranch.js\"\nimport type { DbBranchTimings } from \"./replayContext.js\"\nimport { getReplayContext } from \"./replayContext.js\"\nimport {\n getSeedContext,\n inSeedScope,\n runWithSeedContext,\n seedContextReady,\n} from \"./seedContext.js\"\nimport { deserializeValue, serializeValue } from \"./serialize.js\"\nimport { nowIsoTimestamp } from \"./timestamp.js\"\nimport { BitfabOpenAITracingProcessor } from \"./tracing.js\"\nimport { BitfabVercelAiHandler } from \"./vercelAiSdk.js\"\nimport { warnOnce } from \"./warnOnce.js\"\n\n// Context entry for addContext calls - each entry is an object with multiple key-value pairs\ntype ContextEntry = Record<string, unknown>\n\n// Trace state for tracking trace-level data\ninterface TraceState {\n traceId: string\n sessionId?: string\n name?: string\n metadata?: Record<string, unknown>\n contexts: ContextEntry[]\n startedAt: string\n testRunId?: string\n inputSourceTraceId?: string\n replayAttempt?: number\n dbSnapshotRef?: DbSnapshotRef\n // Set by getCurrentTrace().drop(); ridden out on trace completion so the\n // server scrubs and marks the trace `dropped` instead of `completed`.\n dropped?: boolean\n ingestionType?: TraceIngestionType\n}\n\nexport type { CaptureSurface } from \"./captureSurface.js\"\n\n// Span context for tracking nested spans\ninterface SpanContext {\n traceId: string\n spanId: string\n contexts: ContextEntry[]\n prompt?: string\n surface?: CaptureSurface\n}\n\n// Global map to track active trace states\nconst activeTraceStates = new Map<string, TraceState>()\n\nlet asyncLocalStorage: AsyncLocalStorageLike<SpanContext[]> | null = null\nconst SPAN_CONTEXT_STORAGE_SYMBOL = Symbol.for(\"bitfab.spanContextStorage\")\n\nconst initializeAsyncContext = () => {\n if (asyncLocalStorage) {\n return\n }\n const shared = globalThis as typeof globalThis & Record<symbol, unknown>\n const existing = shared[SPAN_CONTEXT_STORAGE_SYMBOL] as\n | AsyncLocalStorageLike<SpanContext[]>\n | undefined\n if (existing) {\n asyncLocalStorage = existing\n return\n }\n const created = createAsyncLocalStorage<SpanContext[]>()\n if (created) {\n shared[SPAN_CONTEXT_STORAGE_SYMBOL] = created\n asyncLocalStorage = created\n }\n}\n\nconst asyncLocalStorageReady: Promise<void> = asyncStorageReady.then(() => {\n initializeAsyncContext()\n})\n\n// Browser fallback: a single module-level stack shared across all async\n// execution chains. Works correctly for synchronous nesting and sequential\n// async nesting (the common browser cases), but breaks when multiple\n// independent spans are in-flight concurrently (e.g. Promise.all with\n// separate withSpan calls). In that scenario, whichever span resumes last\n// overwrites the shared stack, so inner spans may see the wrong parent.\n//\n// Node.js avoids this via AsyncLocalStorage, which gives each async chain\n// its own isolated copy of the stack.\n//\n// Potential future fixes:\n// - TC39 AsyncContext proposal (stage 2) would provide AsyncLocalStorage\n// semantics natively in all JS environments, including browsers.\n// https://github.com/tc39/proposal-async-context\n// - Zone.js could work today but is ~50KB, monkey-patches Promise/setTimeout/\n// fetch/etc., and can conflict with frameworks like React. Too invasive for\n// an SDK dependency.\nlet browserSpanStack: SpanContext[] = []\n\nfunction getSpanStack(): SpanContext[] {\n if (asyncLocalStorage) {\n return asyncLocalStorage.getStore() ?? []\n }\n return browserSpanStack\n}\n\nfunction enclosingSurface(): CaptureSurface | undefined {\n const stack = getSpanStack()\n return stack[stack.length - 1]?.surface\n}\n\nfunction runWithSpanStack<T>(stack: SpanContext[], fn: () => T): T {\n if (asyncLocalStorage) {\n return asyncLocalStorage.run(stack, fn)\n }\n // Browser fallback: save/restore the stack around the function call.\n // This is correct for sequential async but not for concurrent async -\n // see the browserSpanStack comment above for details.\n const previousStack = browserSpanStack\n browserSpanStack = stack\n try {\n const result = fn()\n if (result instanceof Promise) {\n return result.finally(() => {\n browserSpanStack = previousStack\n }) as T\n }\n browserSpanStack = previousStack\n return result\n } catch (error) {\n browserSpanStack = previousStack\n throw error\n }\n}\n\nfunction isAsyncGenerator(\n value: unknown,\n): value is AsyncGenerator<unknown, unknown, unknown> {\n if (value === null || typeof value !== \"object\") {\n return false\n }\n const candidate = value as Record<PropertyKey, unknown>\n return (\n typeof candidate.next === \"function\" &&\n typeof candidate.return === \"function\" &&\n typeof candidate.throw === \"function\" &&\n typeof candidate[Symbol.asyncIterator] === \"function\"\n )\n}\n\n// Wrap an async generator so that:\n// 1. Each .next()/.return()/.throw() resumes the generator body inside\n// the parent span's context, so nested withSpan calls nest correctly.\n// 2. The span is sent only after iteration completes (or errors), with\n// the yielded values plus any final return value as the result.\n//\n// Without this, async-generator functions returned from withSpan close their\n// span synchronously when the generator object is created - before any of\n// the body has run - and every child span becomes its own root trace.\nfunction wrapAsyncGenerator<TYield, TReturn>(\n source: AsyncGenerator<TYield, TReturn, unknown>,\n spanStack: SpanContext[],\n sendSpan: (params: { result: unknown; error?: string }) => Promise<void>,\n): AsyncGenerator<TYield, TReturn, unknown> {\n const yielded: TYield[] = []\n let returnValue: TReturn | undefined\n let finalized = false\n\n const finalize = (errorMsg?: string) => {\n if (finalized) {\n return\n }\n finalized = true\n void sendSpan({\n result: { yielded, return: returnValue },\n ...(errorMsg && { error: errorMsg }),\n })\n }\n\n const step = (\n method: \"next\" | \"return\" | \"throw\",\n arg: unknown,\n ): Promise<IteratorResult<TYield, TReturn>> =>\n runWithSpanStack(spanStack, () => {\n const op = source[method] as (\n a?: unknown,\n ) => Promise<IteratorResult<TYield, TReturn>>\n return op.call(source, arg)\n })\n\n const handle = async (\n method: \"next\" | \"return\" | \"throw\",\n arg: unknown,\n ): Promise<IteratorResult<TYield, TReturn>> => {\n try {\n const result = await step(method, arg)\n if (result.done) {\n returnValue = result.value\n finalize()\n } else {\n yielded.push(result.value)\n }\n return result\n } catch (error) {\n finalize(error instanceof Error ? error.message : String(error))\n throw error\n }\n }\n\n const wrapped = {\n next(arg?: unknown) {\n return handle(\"next\", arg)\n },\n return(value: TReturn | PromiseLike<TReturn>) {\n return handle(\"return\", value)\n },\n throw(err: unknown) {\n return handle(\"throw\", err)\n },\n [Symbol.asyncIterator]() {\n return wrapped\n },\n [Symbol.asyncDispose]() {\n return handle(\"return\", undefined).then(() => undefined)\n },\n } as AsyncGenerator<TYield, TReturn, unknown>\n\n return wrapped\n}\n\n// --- BAML Collector support for wrapBAML ---\n\ntype CollectorConstructor = new (name: string) => unknown\n\nlet cachedCollectorClass: CollectorConstructor | null | undefined\n\n/** @internal Reset the cached Collector class - for testing only. */\nexport function _resetCollectorCache(): void {\n cachedCollectorClass = undefined\n}\n\n/** @internal Inject a mock Collector class - for testing only. */\nexport function _setCollectorCache(cls: CollectorConstructor | null): void {\n cachedCollectorClass = cls\n}\n\n/** @internal Count of in-flight (registered, not yet completed) trace states - for testing only. */\nexport function _activeTraceStateCount(): number {\n return activeTraceStates.size\n}\n\nasync function loadCollectorClass(): Promise<CollectorConstructor | null> {\n if (cachedCollectorClass !== undefined) {\n return cachedCollectorClass\n }\n try {\n // Reconstructed specifier (see importOptionalPeer): a consumer's bundler\n // must not try to resolve `@boundaryml/baml` at build time when it is not\n // installed (optional peer, only needed for BAML execution / collectors).\n const baml = await importOptionalPeer<typeof import(\"@boundaryml/baml\")>([\n \"@boundaryml\",\n \"baml\",\n ])\n cachedCollectorClass = baml.Collector as CollectorConstructor\n return cachedCollectorClass\n } catch {\n cachedCollectorClass = null\n return null\n }\n}\n\n// Typed accessors for the BAML Collector's internal structure.\n// Uses defensive access since these are untyped objects from the BAML runtime.\n\ninterface CollectorCall {\n selected?: boolean\n clientName?: string\n provider?: string\n usage?: {\n inputTokens?: number\n outputTokens?: number\n cachedInputTokens?: number\n }\n httpRequest?: {\n url?: string\n body?: { json: () => Record<string, unknown> | null }\n }\n}\n\ninterface CollectorLog {\n calls?: CollectorCall[]\n timing?: { durationMs?: number }\n}\n\ninterface CollectorLike {\n last?: CollectorLog | null\n usage?: {\n inputTokens?: number\n outputTokens?: number\n cachedInputTokens?: number\n }\n}\n\nfunction extractPromptFromCollector(collector: unknown): string | null {\n try {\n const c = collector as CollectorLike\n const calls = c?.last?.calls ?? []\n const selectedCall = calls.find((call) => call.selected) ?? calls[0]\n if (!selectedCall?.httpRequest?.body) {\n return null\n }\n const body = selectedCall.httpRequest.body.json()\n if (!body || typeof body !== \"object\") {\n return null\n }\n const messages = body.messages\n if (!Array.isArray(messages) || messages.length === 0) {\n return null\n }\n const rendered = (messages as Record<string, unknown>[])\n .filter(\n (msg): msg is { role: string; content: unknown } =>\n typeof msg === \"object\" &&\n msg !== null &&\n \"role\" in msg &&\n typeof (msg as { role: unknown }).role === \"string\",\n )\n .map((msg) => ({\n role: msg.role,\n content:\n typeof msg.content === \"string\"\n ? msg.content\n : JSON.stringify(msg.content),\n }))\n if (rendered.length > 0) {\n return JSON.stringify(rendered)\n }\n return null\n } catch {\n return null\n }\n}\n\nfunction extractContextFromCollector(\n collector: unknown,\n): Record<string, unknown> | null {\n try {\n const c = collector as CollectorLike\n const calls = c?.last?.calls ?? []\n const selectedCall = calls.find((call) => call.selected) ?? calls[0]\n const usage = c?.usage\n\n const context: Record<string, unknown> = {}\n if (selectedCall?.provider) {\n context.provider = selectedCall.provider\n }\n\n // Extract model from HTTP request body (OpenAI/Anthropic) or URL (Vertex AI)\n const body = selectedCall?.httpRequest?.body?.json()\n if (body && typeof body === \"object\" && typeof body.model === \"string\") {\n context.model = body.model\n } else {\n const url = selectedCall?.httpRequest?.url\n if (url) {\n const match = url.match(/\\/models\\/([^/:]+)/)\n if (match?.[1]) {\n context.model = match[1]\n }\n }\n }\n\n const inputTokens =\n usage?.inputTokens ?? selectedCall?.usage?.inputTokens ?? null\n const outputTokens =\n usage?.outputTokens ?? selectedCall?.usage?.outputTokens ?? null\n if (inputTokens !== null) {\n context.inputTokens = inputTokens\n }\n if (outputTokens !== null) {\n context.outputTokens = outputTokens\n }\n\n const durationMs = c?.last?.timing?.durationMs ?? null\n if (durationMs !== null) {\n context.durationMs = durationMs\n }\n\n return Object.keys(context).length > 0 ? context : null\n } catch {\n return null\n }\n}\n\n/**\n * Options for wrapBAML.\n */\nexport interface WrapBAMLOptions {\n /** Called after each BAML invocation with the Collector instance. */\n onCollector?: (collector: unknown) => void\n}\n\n/**\n * A function returned by wrapBAML that exposes the BAML collector from the last call.\n */\nexport interface WrappedBamlFn<TArgs extends unknown[], TReturn> {\n (...args: TArgs): Promise<TReturn>\n /** The BAML Collector instance from the most recent call. `null` before the first call or if @boundaryml/baml is unavailable. */\n collector: unknown | null\n}\n\n/**\n * A handle to the current active span, allowing context to be added.\n */\nexport interface CurrentSpan {\n /** The Bitfab ID for the current span. */\n readonly id: string\n /** The trace ID for the current span. */\n readonly traceId: string\n /**\n * Add a context entry to this span. Each call appends to the contexts array.\n * Context entries are stored in span_data.contexts as [{key, value}, ...].\n */\n addContext(context: Record<string, unknown>): void\n /**\n * Set the prompt for this span. Stored in span_data.prompt.\n * Calling multiple times overwrites the previous value.\n */\n setPrompt(prompt: string): void\n}\n\n/**\n * A detached handle to a previously-created trace, looked up by its\n * canonical Bitfab trace ID.\n *\n * Unlike `getCurrentTrace()`, this handle is not tied to AsyncLocalStorage -\n * each method sends to the server immediately. Useful for adding context\n * to a trace from a different process, request, or thread (e.g. a forked\n * agent that wants to annotate the original conversation's trace).\n */\nexport interface DetachedTrace {\n /** The canonical Bitfab trace ID this handle resolves. */\n readonly traceId: string\n /**\n * Append a context entry to this trace. Each call adds one entry to the\n * server-side contexts array; existing entries are preserved.\n *\n * Resolves once the server has applied the change and REJECTS if the server\n * refused it. A detached patch targets an already-closed trace, so it rides\n * no batch and no later signal would reveal a silent failure - the caller is\n * the only one who can react.\n */\n addContext(context: Record<string, unknown>): Promise<void>\n /**\n * Merge metadata into this trace. Server-side shallow-merges the new keys\n * into the existing metadata object; existing keys are preserved unless\n * overwritten by the new values. Rejects if the server refused the update.\n */\n setMetadata(metadata: Record<string, unknown>): Promise<void>\n /**\n * Set the sessionId for this trace. Replaces any existing sessionId.\n * Rejects if the server refused the update.\n */\n setSessionId(sessionId: string): Promise<void>\n setName(name: string): Promise<void>\n}\n\nconst UUID_PATTERN =\n /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i\n\nfunction validateTraceId(traceId: string): void {\n if (typeof traceId !== \"string\" || !UUID_PATTERN.test(traceId)) {\n throw new BitfabError(\"traceId must be a valid Bitfab trace ID\")\n }\n}\n\nfunction validateSpanId(id: string): void {\n if (typeof id !== \"string\" || !UUID_PATTERN.test(id)) {\n throw new BitfabError(\"id must be a valid Bitfab span ID\")\n }\n}\n\n/**\n * A handle to the current active trace, allowing trace-level context to be set.\n */\nexport interface CurrentTrace {\n /**\n * Set the session ID for this trace. Stored in the database session_id column.\n */\n setSessionId(sessionId: string): void\n setName(name: string): void\n /**\n * Set metadata for this trace. Stored in rawData.metadata.\n * Subsequent calls merge with existing metadata, with later values taking precedence.\n */\n setMetadata(metadata: Record<string, unknown>): void\n /**\n * Add a context entry to this trace. Each call appends to the contexts array.\n * Context entries are stored in rawData.contexts as [{key, value}, ...].\n */\n addContext(context: Record<string, unknown>): void\n /**\n * Flag this trace to be dropped. Once flagged, spans that complete afterward\n * are not uploaded at all, and when the trace completes the server scrubs any\n * payloads that already raced out (trace, external trace, and sibling spans),\n * marking it `dropped` instead of `completed` and retaining only a skeleton\n * audit record. Use this to discard runs you never want stored (e.g. health\n * checks, or a run you know contains sensitive data). Takes effect\n * immediately for later spans; the server-side scrub takes effect at trace\n * completion, so a trace that is flagged but never completes is not scrubbed.\n */\n drop(): void\n}\n\n// No-op implementations for when called outside a span context\nconst noOpSpan: CurrentSpan = {\n id: \"\",\n traceId: \"\",\n addContext(): void {\n // No-op\n },\n setPrompt(): void {\n // No-op\n },\n}\n\nconst noOpTrace: CurrentTrace = {\n setSessionId(): void {\n // No-op\n },\n setName(): void {},\n setMetadata(): void {\n // No-op\n },\n addContext(): void {\n // No-op\n },\n drop(): void {\n // No-op\n },\n}\n\n/**\n * Get a handle to the current active span.\n *\n * Call this from inside a traced function (wrapped with `withSpan`) to get\n * a span handle that allows adding context at runtime.\n *\n * Returns a no-op object if called outside of a span context (methods do nothing).\n */\nexport function getCurrentSpan(): CurrentSpan {\n const stack = getSpanStack()\n const current = stack[stack.length - 1]\n if (!current) {\n return noOpSpan\n }\n return {\n id: current.spanId,\n traceId: current.traceId,\n addContext(context: Record<string, unknown>): void {\n try {\n if (typeof context !== \"object\" || context === null) {\n return\n }\n // Push the entire context object as one entry\n current.contexts.push(context)\n } catch {\n // Silently ignore - never crash the host app\n }\n },\n setPrompt(prompt: string): void {\n try {\n if (typeof prompt !== \"string\") {\n return\n }\n current.prompt = prompt\n } catch {\n // Silently ignore - never crash the host app\n }\n },\n }\n}\n\n/**\n * Get the database branch the current replay item is running against.\n *\n * Call this from inside a function being replayed with `replay({ dbBranch })`\n * and point your database client at `branch.databaseUrl` so the replay reads\n * the data as it was at trace time:\n *\n * ```ts\n * const branch = getCurrentReplayBranch()\n * const url = branch?.databaseUrl ?? process.env.DATABASE_URL\n * ```\n *\n * Returns null outside a replay item, and for an item whose source trace\n * carried no DB snapshot reference, so live request code takes the same path\n * it always did.\n */\nexport function getCurrentReplayBranch(): ReplayBranch | null {\n const ctx = getReplayContext()\n if (!ctx?.dbBranchLease) {\n return null\n }\n // Surface the Bitfab traceId (what the customer sees in the dashboard), not\n // the external_traces.id. Falling back to the external ID keeps replays from\n // external sources working until the source-system path is fully wired.\n const traceId = ctx.sourceBitfabTraceId ?? ctx.inputSourceTraceId\n if (!traceId) {\n return null\n }\n return new ReplayBranch(ctx.dbBranchLease, traceId, ctx)\n}\n\n/**\n * Get a handle to the current active trace.\n *\n * Call this from inside a traced function (wrapped with `withSpan`) to get\n * a trace handle that allows setting trace-level context at runtime.\n *\n * Returns a no-op object if called outside of a span context (methods do nothing).\n */\nexport function getCurrentTrace(): CurrentTrace {\n const stack = getSpanStack()\n const current = stack[stack.length - 1]\n if (!current) {\n return noOpTrace\n }\n\n const traceId = current.traceId\n\n const getOrCreateTraceState = (): TraceState => {\n let traceState = activeTraceStates.get(traceId)\n if (!traceState) {\n traceState = {\n traceId,\n startedAt: nowIsoTimestamp(),\n contexts: [],\n }\n activeTraceStates.set(traceId, traceState)\n }\n return traceState\n }\n\n return {\n setSessionId(sessionId: string): void {\n try {\n const traceState = getOrCreateTraceState()\n traceState.sessionId = sessionId\n } catch {\n // Silently ignore - never crash the host app\n }\n },\n setName(name: string): void {\n if (typeof name !== \"string\" || name.length === 0) {\n return\n }\n try {\n getOrCreateTraceState().name = name\n } catch {}\n },\n setMetadata(metadata: Record<string, unknown>): void {\n try {\n if (typeof metadata !== \"object\" || metadata === null) {\n return\n }\n const traceState = getOrCreateTraceState()\n traceState.metadata = { ...traceState.metadata, ...metadata }\n } catch {\n // Silently ignore - never crash the host app\n }\n },\n addContext(context: Record<string, unknown>): void {\n try {\n if (typeof context !== \"object\" || context === null) {\n return\n }\n const traceState = getOrCreateTraceState()\n // Push the entire context object as one entry\n traceState.contexts.push(context)\n } catch {\n // Silently ignore - never crash the host app\n }\n },\n drop(): void {\n try {\n getOrCreateTraceState().dropped = true\n } catch {\n // Silently ignore - never crash the host app\n }\n },\n }\n}\n\n/**\n * Read an environment variable without throwing in non-Node runtimes\n * (browsers, edge workers) where `process` is absent. The SDK ships to\n * browsers, so this must never assume `process` exists.\n */\nfunction readEnv(name: string): string | undefined {\n if (typeof process !== \"undefined\" && process.env) {\n return process.env[name]\n }\n return undefined\n}\n\nexport interface SeedCaseOptions {\n input: unknown[]\n expected?: unknown\n // biome-ignore lint/suspicious/noExplicitAny: matches the replay callable\n fn?: (...args: any[]) => unknown\n metadata?: Record<string, unknown>\n sessionId?: string\n name?: string\n spanName?: string\n spanType?: SpanType\n}\n\nexport interface SeedRunOptions<TArgs extends unknown[]> {\n args?: TArgs\n metadata?: Record<string, unknown>\n sessionId?: string\n name?: string\n}\n\nexport interface BitfabConfig {\n /**\n * The API key for Bitfab API authentication. Resolved lazily, the first\n * time a span actually needs it, not at construction. When it resolves\n * empty, tracing is disabled (a no-op, unless `strict` is set).\n *\n * Accepts either a string or a function returning the key. The function\n * form is resolved at first use, so it survives the ESM trap where a shim\n * built at module load runs before the script body's `dotenv.config()`:\n * `apiKey: () => process.env.BITFAB_API_KEY`. When omitted (or it resolves\n * empty), the SDK also falls back to reading `BITFAB_API_KEY` from the\n * environment itself, again at first use.\n */\n apiKey?: string | (() => string | null | undefined)\n /** The base URL for the Bitfab API (default: https://bitfab.ai) */\n serviceUrl?: string\n /** Request timeout in milliseconds (default: 120000) */\n timeout?: number\n /** Environment variables for LLM provider API keys (only OPENAI_API_KEY is supported) */\n envVars?: AllowedEnvVars\n captureEnabled?: boolean\n enabled?: boolean\n /**\n * Fail loud instead of degrading quietly. When true, the first traced call\n * with no resolvable API key throws a `BitfabError` rather than silently\n * disabling tracing. Off by default so a missing telemetry key never takes\n * down the host app; turn it on in standalone scripts where a run that\n * emits no traces is a failure you want surfaced immediately.\n */\n strict?: boolean\n /** The generated BAML client instance (e.g., `b` from your baml_client). Used by wrapBAML() when no explicit client is passed. */\n bamlClient?: unknown\n /**\n * Per-trace database snapshot config. When set, every root span captures\n * a wall-clock timestamp (and, if `captureRef` is provided, a provider-\n * specific point-in-time ref) so the trace can later be replayed against\n * a branch materialized from that point.\n */\n dbSnapshot?: DbSnapshotConfig\n}\n\n/**\n * Span types matching the backend enum.\n * - llm: LLM API calls\n * - agent: Autonomous orchestrators\n * - function: Tool implementations\n * - guardrail: Safety/validation checks\n * - handoff: Agent-to-agent transfers\n * - custom: Application-specific tracing (default)\n */\nexport type SpanType =\n | \"llm\"\n | \"agent\"\n | \"function\"\n | \"guardrail\"\n | \"handoff\"\n | \"custom\"\n\n/**\n * Controls when a span is captured.\n * - always: Capture the span even when it becomes the root of a new trace.\n * - nested: Capture the span only when another Bitfab span is already active.\n */\nexport type CaptureWhen = \"always\" | \"nested\"\n\n/**\n * Options for configuring span behavior.\n */\nexport interface SpanOptions {\n /**\n * The name of the span. Defaults to the function name if available,\n * otherwise falls back to the trace function key.\n */\n name?: string\n /**\n * The type of span. Defaults to \"custom\" if not specified.\n */\n type?: SpanType\n /**\n * Controls whether this span may start a new trace. Defaults to \"always\".\n *\n * Use \"nested\" for reusable helpers that should appear inside an existing\n * trace but should run untraced when called on their own.\n * Unknown values warn once and default to \"always\".\n */\n captureWhen?: CaptureWhen\n /**\n * When true, replay will reuse this span's historical output instead of\n * executing the wrapped function. Read by the \"marked\" replay strategy;\n * ignored outside replay and under the \"all\"/\"none\" strategies.\n *\n * Use this for child spans that are expensive (paid LLM/API calls),\n * slow, or non-deterministic - the root function still runs real code,\n * only the marked descendants return their recorded output. If a selected\n * occurrence is unavailable, replay fails the item without executing the\n * real child.\n */\n mockOnReplay?: boolean\n /** Optional test run ID included on the span and on the trace it starts. */\n testRunId?: string\n /**\n * Record a serializable view of a non-serializable result (e.g. a live\n * stream object) as the span output.\n *\n * When set, the wrapped function's raw return value is handed back to the\n * caller unchanged (so streaming and first-byte latency are untouched),\n * but instead of serializing that raw value, the span records\n * `await finalize(result)`. Use this to trace functions that return a live\n * stream consumed by the caller (Vercel AI SDK `streamText`, a\n * `ReadableStream`, an SSE response) while still capturing a serializable,\n * replayable output such as `{ text, usage, toolCalls }`.\n *\n * Reading from a multi-consumer stream result (like the AI SDK's, which\n * tees internally) does not disturb the caller's own consumption. For the\n * Vercel AI SDK shape, pass the prebuilt `finalizers.aiSdk` helper.\n *\n * Ignored for async-generator results, which are captured automatically.\n */\n // biome-ignore lint/suspicious/noExplicitAny: the result type is the wrapped fn's return; SpanOptions is not generic, so callers narrow it inside finalize\n finalize?: (result: any) => unknown | Promise<unknown>\n}\n\n/**\n * The standard method context passed to a decorator.\n *\n * Defined structurally instead of referencing TypeScript's built-in\n * `ClassMethodDecoratorContext`, which was added in TypeScript 5.0. This keeps\n * the SDK's non-decorator APIs consumable by projects on older compilers.\n */\nexport interface SpanMethodDecoratorContext<TThis, TValue> {\n readonly kind: \"method\"\n readonly name: string | symbol\n readonly static: boolean\n readonly private: boolean\n readonly access: {\n has(object: TThis): boolean\n get(object: TThis): TValue\n }\n addInitializer(initializer: (this: TThis) => void): void\n readonly metadata?: Record<PropertyKey, unknown>\n}\n\n/** A standard ECMAScript method decorator produced by {@link Bitfab.span}. */\nexport type SpanMethodDecorator = <TThis, TArgs extends unknown[], TReturn>(\n originalMethod: (this: TThis, ...args: TArgs) => TReturn,\n context: SpanMethodDecoratorContext<\n TThis,\n (this: TThis, ...args: TArgs) => TReturn\n >,\n) => (this: TThis, ...args: TArgs) => TReturn\n\n/** Trace-owned configuration for a function discovered beneath `trace()`. */\nexport interface NodeOptions extends Omit<SpanOptions, \"captureWhen\"> {\n /** Whether the enclosing trace captures this call. Defaults to true. */\n capture?: boolean\n}\n\ntype NodeConfigurationOptions = Omit<AutoTraceNodeConfiguration, \"functionName\">\n\ntype StandardNodeMethodDecorator = SpanMethodDecorator\n\ntype LegacyNodeMethodDecorator = <TThis, TArgs extends unknown[], TReturn>(\n target: object,\n propertyKey: string | symbol,\n descriptor: TypedPropertyDescriptor<(this: TThis, ...args: TArgs) => TReturn>,\n) => void\n\n/** A method decorator produced by {@link Bitfab.node}. */\nexport type NodeMethodDecorator = StandardNodeMethodDecorator &\n LegacyNodeMethodDecorator\n\n/** Options for experimental automatic subtree tracing. */\nexport interface TraceOptions {\n /** Root span name. Defaults to the decorated or wrapped function name. */\n name?: string\n /** Root span type. Descendants are always `function` spans. */\n type?: SpanType\n /**\n * Default replay-mocking policy for automatically captured descendants.\n * When true, those descendants are mocked by the default \"marked\" strategy\n * unless a node explicitly sets `mockOnReplay: false`. Defaults to false.\n */\n mockOnReplayDefault?: boolean\n /** Maximum number of recorded descendant levels. Defaults to 30. */\n maxDepth?: number\n /** Maximum descendant spans recorded per root invocation. Defaults to 500. */\n maxSpans?: number\n /** Qualified or simple function names to leave out of the subtree. */\n exclude?: readonly string[] | ReadonlySet<string>\n /** Record rest-argument wrapper functions. Defaults to false. */\n includeWrappers?: boolean\n}\n\ninterface InternalSpanOptions extends SpanOptions {\n functionId?: string\n captureContent?: boolean\n autoTraceDefinition?: AutoTraceFunctionDefinition\n surface?: SurfaceRequest\n}\n\ntype StandardTraceMethodDecorator = <This, TArgs extends unknown[], TReturn>(\n method: (this: This, ...args: TArgs) => TReturn,\n context: { kind: \"method\"; name: string | symbol },\n) => (this: This, ...args: TArgs) => TReturn\n\ntype LegacyTraceMethodDecorator = <This, TArgs extends unknown[], TReturn>(\n target: object,\n propertyKey: string | symbol,\n descriptor: TypedPropertyDescriptor<(this: This, ...args: TArgs) => TReturn>,\n) => void\n\ntype TraceMethodDecorator = StandardTraceMethodDecorator &\n LegacyTraceMethodDecorator\n\nconst DEFAULT_AUTO_TRACE_MAX_DEPTH = 30\nconst DEFAULT_AUTO_TRACE_MAX_SPANS = 500\nconst AUTO_TRACE_PROTOCOL = \"ts-auto-v1\"\nconst AUTO_TRACE_POLICY_REFRESH_MS = 60_000\nconst AUTO_TRACE_POLICY_RETRY_MS = 10_000\n\ninterface AutoTracePolicyResponse {\n protocol: typeof AUTO_TRACE_PROTOCOL\n functionIds: string[]\n revision: string | null\n}\n\ninterface AutoTracePolicyRefresh {\n refreshAfter: number\n inFlight?: Promise<void>\n}\n\nfunction autoTraceLimit(value: number | undefined, fallback: number): number {\n return value !== undefined && Number.isFinite(value) && value >= 0\n ? Math.floor(value)\n : fallback\n}\n\ninterface FunctionVersionResponse {\n id: string\n name: string\n versionId: string\n versionNumber: number | null\n prompt: string\n providers: ProviderDefinition[]\n}\n\nexport { MixedTracingError }\n\n// Re-export BitfabError for backwards compatibility\nexport { BitfabError }\n\n/**\n * Client for making provider-based API calls via BAML.\n */\nexport class Bitfab {\n private readonly apiKeyConfig:\n | string\n | (() => string | null | undefined)\n | undefined\n /** Cached only once a non-empty key is found, so an early resolve (before env loaded) can't poison a later one. */\n private resolvedApiKey: string | undefined\n /** Gate the empty-key warning to fire at most once. */\n private apiKeyWarned: boolean = false\n private readonly serviceUrl: string\n private readonly timeout: number\n private readonly envVars: AllowedEnvVars\n private readonly captureConfigured: boolean\n private readonly strict: boolean\n private readonly httpClient: HttpClient\n /** Dataset operations for the authenticated organization. */\n readonly datasets: DatasetsClient\n private readonly bamlClient: unknown\n private readonly dbSnapshot: DbSnapshotConfig | undefined\n private readonly autoTracePolicyRefreshes = new Map<\n string,\n AutoTracePolicyRefresh\n >()\n /**\n * Mock overrides registered via {@link Bitfab.registerMockOverride}, applied\n * to every `replay` on this client (after any per-call `mockOverride`). In\n * registration order; first matcher wins within this list.\n */\n private readonly mockOverrides: MockOverride[] = []\n\n /**\n * Initialize the Bitfab client.\n *\n * @param config - Configuration options for the client\n */\n constructor(config: BitfabConfig) {\n this.apiKeyConfig = config.apiKey\n this.serviceUrl = config.serviceUrl ?? DEFAULT_SERVICE_URL\n this.timeout = config.timeout ?? 120000\n this.envVars = config.envVars ?? {}\n if (config.enabled !== undefined) {\n warnOnce(\n \"deprecated-enabled-option\",\n \"Bitfab({ enabled }) is deprecated; pass captureEnabled instead.\",\n )\n }\n this.captureConfigured =\n (config.captureEnabled ?? true) && (config.enabled ?? true)\n this.strict = config.strict ?? false\n this.bamlClient = config.bamlClient ?? null\n if (config.dbSnapshot) {\n validateDbSnapshotConfig(config.dbSnapshot)\n }\n this.dbSnapshot = config.dbSnapshot\n // The key is NOT read here. HttpClient gets a thunk so the key is resolved\n // at send time, after any in-script dotenv.config() has run.\n this.httpClient = new HttpClient({\n apiKey: () => this.resolveApiKey(),\n serviceUrl: this.serviceUrl,\n timeout: this.timeout,\n })\n this.datasets = new DatasetsClient(this.httpClient)\n }\n\n /**\n * Decorate a class method as an automatically expanded trace root.\n *\n * Build instrumentation turns repository functions called beneath this\n * method into nested spans that capture inputs, outputs, and errors by\n * default. A confirmed capture policy can narrow rich capture to selected\n * function IDs.\n * Without a compatible build transform, this still records the decorated\n * method as a normal rich root span but cannot discover child calls.\n *\n * @param traceFunctionKey - Groups traces and their capture policy.\n * @param options - Root presentation, subtree bounds, and exclusions.\n * @experimental Automatic child-call instrumentation is experimental.\n */\n trace(\n traceFunctionKey: string,\n options: TraceOptions = {},\n ): TraceMethodDecorator {\n const decorator = (...args: unknown[]): unknown => {\n if (args.length === 3) {\n const propertyKey = args[1] as string | symbol\n const descriptor = args[2] as TypedPropertyDescriptor<\n (this: unknown, ...methodArgs: unknown[]) => unknown\n >\n if (!descriptor || typeof descriptor.value !== \"function\") {\n throw new BitfabError(\"@bitfab.trace can only decorate methods\")\n }\n descriptor.value = this.createAutoTraceRoot(\n traceFunctionKey,\n String(propertyKey),\n options,\n descriptor.value,\n )\n return\n }\n\n const method = args[0]\n const context = args[1] as\n | { kind?: string; name?: string | symbol }\n | undefined\n if (\n typeof method !== \"function\" ||\n context?.kind !== \"method\" ||\n context.name === undefined\n ) {\n throw new BitfabError(\"@bitfab.trace can only decorate methods\")\n }\n return this.createAutoTraceRoot(\n traceFunctionKey,\n String(context.name),\n options,\n method as (this: unknown, ...methodArgs: unknown[]) => unknown,\n )\n }\n\n return decorator as TraceMethodDecorator\n }\n\n /**\n * Wrap a function as an automatically expanded trace root.\n *\n * This is the function-oriented equivalent of {@link Bitfab.trace}. Build\n * instrumentation turns repository functions called beneath the wrapped\n * function into nested spans that capture inputs, outputs, and errors by\n * default. A confirmed capture policy can narrow rich capture to selected\n * function IDs. Without a compatible transform, this still records one\n * normal rich root span and runs the function unchanged.\n *\n * @param traceFunctionKey - Groups traces and their capture policy.\n * @param optionsOrFn - Options or the workflow entrypoint to wrap.\n * @param maybeFn - Workflow entrypoint when options are provided.\n * @experimental Automatic child-call instrumentation is experimental.\n */\n withTrace<This, TArgs extends unknown[], TReturn>(\n traceFunctionKey: string,\n fn: (this: This, ...args: TArgs) => TReturn,\n ): (this: This, ...args: TArgs) => TReturn\n withTrace<This, TArgs extends unknown[], TReturn>(\n traceFunctionKey: string,\n options: TraceOptions,\n fn: (this: This, ...args: TArgs) => TReturn,\n ): (this: This, ...args: TArgs) => TReturn\n withTrace<This, TArgs extends unknown[], TReturn>(\n traceFunctionKey: string,\n optionsOrFn: TraceOptions | ((this: This, ...args: TArgs) => TReturn),\n maybeFn?: (this: This, ...args: TArgs) => TReturn,\n ): (this: This, ...args: TArgs) => TReturn {\n const options = typeof optionsOrFn === \"function\" ? {} : optionsOrFn\n const fn = typeof optionsOrFn === \"function\" ? optionsOrFn : maybeFn\n if (!fn) {\n throw new BitfabError(\"bitfab.withTrace requires a function\")\n }\n const name = fn.name !== \"\" ? fn.name : traceFunctionKey\n return this.createAutoTraceRoot(traceFunctionKey, name, options, fn)\n }\n\n /**\n * Configure a transformed class method when it is discovered beneath a\n * {@link Bitfab.trace} root.\n *\n * The decorator creates no span or trace by itself. Beneath an active trace,\n * it can rename or retype the discovered call, capture its contents, mark it\n * for recorded-output replay, finalize its output, or omit it while leaving\n * captured descendants attached to the nearest captured parent.\n *\n * @param options - Trace-owned call configuration.\n * @experimental Automatic child-call instrumentation is experimental.\n */\n node(options: NodeOptions = {}): NodeMethodDecorator {\n const configuration = this.resolveNodeConfiguration(options)\n const decorator = (...args: unknown[]): unknown => {\n if (args.length === 3) {\n const descriptor = args[2] as TypedPropertyDescriptor<\n (this: unknown, ...methodArgs: unknown[]) => unknown\n >\n if (!descriptor || typeof descriptor.value !== \"function\") {\n throw new BitfabError(\"@bitfab.node can only decorate methods\")\n }\n descriptor.value = this.createAutoTraceNode(\n configuration,\n descriptor.value,\n String(args[1]),\n )\n return\n }\n\n const method = args[0]\n const context = args[1] as\n | { kind?: string; name?: string | symbol }\n | undefined\n if (typeof method !== \"function\" || context?.kind !== \"method\") {\n throw new BitfabError(\"@bitfab.node can only decorate methods\")\n }\n return this.createAutoTraceNode(\n configuration,\n method as (this: unknown, ...methodArgs: unknown[]) => unknown,\n String(context.name),\n )\n }\n\n return decorator as NodeMethodDecorator\n }\n\n /**\n * Configure a transformed standalone function when it is discovered beneath\n * a {@link Bitfab.trace} or {@link Bitfab.withTrace} root.\n *\n * This is the function-oriented equivalent of {@link Bitfab.node}. Without\n * an active automatic trace, the returned function runs normally and never\n * creates a span or trace. The function must be named so configuration can\n * be bound to its transformed definition without leaking to a descendant.\n *\n * @param optionsOrFn - Node options or the function to configure.\n * @param maybeFn - Function to configure when options are provided.\n * @experimental Automatic child-call instrumentation is experimental.\n */\n withNode<This, TArgs extends unknown[], TReturn>(\n fn: (this: This, ...args: TArgs) => TReturn,\n ): (this: This, ...args: TArgs) => TReturn\n withNode<This, TArgs extends unknown[], TReturn>(\n options: NodeOptions,\n fn: (this: This, ...args: TArgs) => TReturn,\n ): (this: This, ...args: TArgs) => TReturn\n withNode<This, TArgs extends unknown[], TReturn>(\n optionsOrFn: NodeOptions | ((this: This, ...args: TArgs) => TReturn),\n maybeFn?: (this: This, ...args: TArgs) => TReturn,\n internalFunctionName?: string,\n ): (this: This, ...args: TArgs) => TReturn {\n const options = typeof optionsOrFn === \"function\" ? {} : optionsOrFn\n const fn = typeof optionsOrFn === \"function\" ? optionsOrFn : maybeFn\n if (!fn) {\n throw new BitfabError(\"bitfab.withNode requires a function\")\n }\n const configuration = this.resolveNodeConfiguration(options)\n const functionName = internalFunctionName ?? fn.name\n if (functionName === \"\") {\n throw new BitfabError(\n \"bitfab.withNode requires a named function so the subtree transform can bind its configuration to the correct call.\",\n )\n }\n return this.createAutoTraceNode(configuration, fn, functionName)\n }\n\n private resolveNodeConfiguration(\n options: NodeOptions,\n ): NodeConfigurationOptions {\n const capture = options.capture ?? true\n if (!capture && options.mockOnReplay === true) {\n throw new BitfabError(\n \"bitfab.node({ capture: false }) cannot use mockOnReplay: true because an uncaptured node has no recorded output.\",\n )\n }\n return {\n capture,\n type: options.type ?? \"custom\",\n ...(options.name !== undefined && { name: options.name }),\n ...(options.testRunId !== undefined && {\n testRunId: options.testRunId,\n }),\n ...(options.mockOnReplay !== undefined && {\n mockOnReplay: options.mockOnReplay,\n }),\n ...(options.finalize !== undefined && { finalize: options.finalize }),\n }\n }\n\n private createAutoTraceNode<This, TArgs extends unknown[], TReturn>(\n configuration: NodeConfigurationOptions,\n fn: (this: This, ...args: TArgs) => TReturn,\n functionName: string,\n ): (this: This, ...args: TArgs) => TReturn {\n const nodeConfiguration = { ...configuration, functionName }\n return function (this: This, ...args: TArgs): TReturn {\n if (!__bitfabAutoTraceActive()) {\n if (enclosingSurface() === \"opt-in\") {\n throw mixedTracingError(\"node()\", \"opt-out\", \"opt-in\")\n }\n return fn.apply(this, args)\n }\n return runWithAutoTraceNodeConfiguration(nodeConfiguration, () =>\n fn.apply(this, args),\n )\n }\n }\n\n private createAutoTraceRoot<This, TArgs extends unknown[], TReturn>(\n traceFunctionKey: string,\n name: string,\n options: TraceOptions,\n fn: (this: This, ...args: TArgs) => TReturn,\n ): (this: This, ...args: TArgs) => TReturn {\n const self = this\n const maxDepth = autoTraceLimit(\n options.maxDepth,\n DEFAULT_AUTO_TRACE_MAX_DEPTH,\n )\n const maxSpans = autoTraceLimit(\n options.maxSpans,\n DEFAULT_AUTO_TRACE_MAX_SPANS,\n )\n const excluded = new Set(options.exclude ?? [])\n const includeWrappers = options.includeWrappers ?? false\n const rootOptions: InternalSpanOptions = {\n name: options.name ?? name,\n type: options.type ?? \"custom\",\n surface: \"opt-out\",\n }\n const tracedRoot = this.withSpan(\n traceFunctionKey,\n rootOptions,\n function (this: This, ...args: TArgs): TReturn {\n const capturePolicy = getAutoTraceCapturePolicy(self, traceFunctionKey)\n self.refreshAutoTraceCapturePolicy(traceFunctionKey)\n let spansUsed = 0\n let truncated = false\n const warnTruncated = (): void => {\n if (!truncated) {\n truncated = true\n getCurrentTrace().setMetadata({\n bitfabAutoTrace: {\n protocol: AUTO_TRACE_PROTOCOL,\n truncated: true,\n maxDepth,\n maxSpans,\n },\n })\n }\n warnOnce(\n `auto-trace-truncated:${traceFunctionKey}`,\n `\"${traceFunctionKey}\" hit an automatic subtree capture limit (maxDepth=${maxDepth}, maxSpans=${maxSpans}); its trace is incomplete. Raise the limits or narrow the subtree with exclude.`,\n )\n }\n const autoTraceContext: AutoTraceContext = {\n invoke<T>(\n definition: AutoTraceFunctionDefinition,\n inputs: unknown[],\n invokeFn: () => T,\n depth: number,\n nodeConfiguration?: AutoTraceNodeConfiguration,\n ): T {\n const nameParts = definition.name.split(\".\")\n const simpleName = nameParts[nameParts.length - 1]\n const invokeWithoutNode = (): T =>\n nodeConfiguration === undefined\n ? invokeFn()\n : runWithAutoTraceContext(autoTraceContext, invokeFn, depth)\n if (\n excluded.has(definition.name) ||\n (simpleName !== undefined && excluded.has(simpleName)) ||\n (nodeConfiguration === undefined &&\n definition.wrapper === true &&\n !includeWrappers)\n ) {\n return invokeWithoutNode()\n }\n if (nodeConfiguration?.capture === false) {\n return runWithAutoTraceContext(autoTraceContext, invokeFn, depth)\n }\n if (depth >= maxDepth || spansUsed >= maxSpans) {\n warnTruncated()\n return invokeWithoutNode()\n }\n spansUsed += 1\n const mockOnReplay =\n nodeConfiguration?.mockOnReplay ?? options.mockOnReplayDefault\n const childOptions: InternalSpanOptions = {\n name: nodeConfiguration?.name ?? definition.name,\n type: nodeConfiguration?.type ?? \"function\",\n captureWhen: \"nested\",\n surface: \"opt-out\",\n functionId: definition.id,\n captureContent:\n nodeConfiguration !== undefined ||\n capturePolicy === undefined ||\n capturePolicy.has(definition.id),\n autoTraceDefinition: definition,\n ...(nodeConfiguration?.testRunId !== undefined && {\n testRunId: nodeConfiguration.testRunId,\n }),\n ...(mockOnReplay !== undefined && {\n mockOnReplay,\n }),\n ...(nodeConfiguration?.finalize !== undefined && {\n finalize: nodeConfiguration.finalize,\n }),\n }\n const invokeWithAutoTraceContext = (): T =>\n runWithAutoTraceContext(autoTraceContext, invokeFn, depth + 1)\n if (definition.async === true) {\n const tracedAsyncChild = self.withSpan(\n traceFunctionKey,\n childOptions,\n async (..._inputs: unknown[]) =>\n await invokeWithAutoTraceContext(),\n )\n return tracedAsyncChild(...inputs) as T\n }\n const tracedChild = self.withSpan(\n traceFunctionKey,\n childOptions,\n (..._inputs: unknown[]): T => invokeWithAutoTraceContext(),\n )\n return tracedChild(...inputs)\n },\n }\n\n return runWithAutoTraceRootContext(autoTraceContext, () =>\n fn.apply(this, args),\n )\n },\n )\n const autoTraceRoot = function (this: This, ...args: TArgs): TReturn {\n if (!self.shouldRecord()) {\n return fn.apply(this, args)\n }\n return tracedRoot.apply(this, args)\n }\n Object.defineProperty(autoTraceRoot, \"_bitfabTraceFunctionKey\", {\n value: traceFunctionKey,\n })\n Object.defineProperty(autoTraceRoot, \"_bitfabWrappedFn\", { value: fn })\n return autoTraceRoot\n }\n\n private refreshAutoTraceCapturePolicy(traceFunctionKey: string): void {\n const now = Date.now()\n const state = this.autoTracePolicyRefreshes.get(traceFunctionKey) ?? {\n refreshAfter: 0,\n }\n if (state.inFlight || now < state.refreshAfter) {\n return\n }\n\n const request = this.httpClient\n .getAutoTracePolicy<AutoTracePolicyResponse>(\n traceFunctionKey,\n AUTO_TRACE_PROTOCOL,\n )\n .then((policy) => {\n if (policy.protocol !== AUTO_TRACE_PROTOCOL) {\n state.refreshAfter = Date.now() + AUTO_TRACE_POLICY_RETRY_MS\n return\n }\n const functionIds = Array.isArray(policy.functionIds)\n ? policy.functionIds\n .filter(\n (id): id is string =>\n typeof id === \"string\" &&\n id.startsWith(`${AUTO_TRACE_PROTOCOL}:`),\n )\n .slice(0, DEFAULT_AUTO_TRACE_MAX_SPANS)\n : []\n __setBitfabAutoTraceCapturePolicy(\n this,\n traceFunctionKey,\n policy.revision === null ? undefined : functionIds,\n )\n state.refreshAfter = Date.now() + AUTO_TRACE_POLICY_REFRESH_MS\n })\n .catch(() => {\n state.refreshAfter = Date.now() + AUTO_TRACE_POLICY_RETRY_MS\n })\n .finally(() => {\n state.inFlight = undefined\n })\n state.inFlight = request\n this.autoTracePolicyRefreshes.set(traceFunctionKey, state)\n }\n\n /**\n * Flush and permanently close this client's tracing resources: its pending\n * requests and the single span-transport worker shared by its decorators and\n * framework handlers.\n *\n * Resolves `false` when delivery failed or the deadline expired. Long-lived\n * processes never need this (the transport batches in the background and the\n * exit hook drains it); scripts and tests that want a hard guarantee should\n * await it.\n *\n * Deliberately not a `Symbol.asyncDispose` method: the SDK targets runtimes\n * where that symbol may be absent, and a computed key on a missing symbol\n * throws at class-definition time, taking the whole SDK down on load.\n */\n close(timeoutMs?: number): Promise<boolean> {\n return this.httpClient.close(timeoutMs)\n }\n\n /**\n * Resolve the API key lazily, the first time a span actually needs it.\n *\n * The key is intentionally NOT read at construction. In ESM, a shim that\n * does `new Bitfab({ apiKey: process.env.BITFAB_API_KEY })` is hoisted and\n * evaluated before the importing script's body runs `dotenv.config()`, so\n * the key would be empty at construction even though it is set moments\n * later. Resolving here (at first `withSpan` call / first request) reads\n * the key after env loading has run.\n *\n * Resolution order: the configured value (string, or function called each\n * time it is still unresolved), then a fallback read of `BITFAB_API_KEY`\n * from the environment. Once a non-empty key is found it is cached, so an\n * early resolve that found nothing never poisons a later one.\n */\n private resolveApiKey(): string | undefined {\n if (this.resolvedApiKey !== undefined) {\n return this.resolvedApiKey\n }\n const fromConfig =\n typeof this.apiKeyConfig === \"function\"\n ? this.apiKeyConfig()\n : this.apiKeyConfig\n const candidate =\n fromConfig && fromConfig.trim() !== \"\"\n ? fromConfig\n : readEnv(\"BITFAB_API_KEY\")\n const key = candidate && candidate.trim() !== \"\" ? candidate : undefined\n if (key) {\n this.resolvedApiKey = key\n return key\n }\n if (this.strict) {\n throw new BitfabError(\n \"Bitfab: no API key resolved. Set BITFAB_API_KEY or pass apiKey to \" +\n \"new Bitfab(). If a script loads env with dotenv, load it before the \" +\n \"module that constructs the client is imported (e.g. \" +\n \"`node --env-file=.env script.ts`), or pass \" +\n \"`apiKey: () => process.env.BITFAB_API_KEY`.\",\n )\n }\n if (this.captureConfigured && !this.apiKeyWarned) {\n this.apiKeyWarned = true\n console.warn(\n \"Bitfab: apiKey is empty - tracing is disabled. Provide a valid API key to enable tracing.\",\n )\n }\n return undefined\n }\n\n private isCaptureEnabled(): boolean {\n if (!this.captureConfigured) {\n return false\n }\n return this.resolveApiKey() !== undefined\n }\n\n private shouldRecord(): boolean {\n if (!this.captureConfigured && !getReplayContext() && !inSeedScope()) {\n return false\n }\n return this.resolveApiKey() !== undefined\n }\n\n get captureEnabled(): boolean {\n return this.isCaptureEnabled()\n }\n\n /**\n * Fetch the function with its current version and BAML prompt from the server.\n *\n * @param methodName - The name of the method to fetch\n * @returns The function with current version, BAML prompt, and provider definitions\n * @throws {BitfabError} If the function is not found or an error occurs\n */\n private async fetchFunctionVersion(\n methodName: string,\n ): Promise<FunctionVersionResponse> {\n const result =\n await this.httpClient.lookupFunction<FunctionVersionResponse>(methodName)\n\n // Check if function was not found\n if (result.id === null) {\n throw new BitfabError(\n `Function \"${methodName}\" not found. Create it at: ${this.serviceUrl}/functions`,\n \"/functions\",\n )\n }\n\n // Check if function has no prompt\n if (!result.prompt) {\n throw new BitfabError(\n `Function \"${methodName}\" has no prompt configured. Add one at: ${this.serviceUrl}/functions/${result.id}`,\n `/functions/${result.id}`,\n )\n }\n\n return result\n }\n\n /**\n * Call a method with the given named arguments via BAML execution.\n *\n * @param methodName - The name of the method to call\n * @param inputs - Named arguments to pass to the method\n * @returns The result of the BAML function execution\n * @throws {BitfabError} If service_url is not set, or if an error occurs\n */\n async call<T = unknown>(\n methodName: string,\n inputs: Record<string, unknown> = {},\n ): Promise<T> {\n try {\n const functionVersion = await this.fetchFunctionVersion(methodName)\n const executionResult = await runFunctionWithBaml(\n functionVersion.prompt,\n inputs,\n functionVersion.providers,\n this.envVars,\n )\n\n // Create trace for the local execution. A non-serializable result must\n // not throw into the user's `call()`: fall back to String() if\n // JSON.stringify throws or yields undefined (e.g. a function result).\n let resultStr: string\n if (typeof executionResult.result === \"string\") {\n resultStr = executionResult.result\n } else {\n try {\n resultStr =\n JSON.stringify(executionResult.result) ??\n String(executionResult.result)\n } catch {\n warnOnce(\n \"call-result-serialize\",\n \"a local execution result could not be JSON-serialized; storing its String() form instead. The call still returns its real value.\",\n )\n resultStr = String(executionResult.result)\n }\n }\n\n // Create trace in background so user doesn't have to wait\n this.httpClient.sendInternalTrace(functionVersion.id, {\n result: resultStr,\n source: \"typescript-sdk\",\n ...(Object.keys(inputs).length > 0 && { inputs }),\n ...(executionResult.rawCollector != null && {\n rawCollector: executionResult.rawCollector,\n }),\n })\n\n return executionResult.result as T\n } catch (error) {\n if (error instanceof BitfabError) {\n throw error\n }\n if (error instanceof Error) {\n throw new BitfabError(error.message)\n }\n throw new BitfabError(\"Unknown error occurred during local execution\")\n }\n }\n\n /**\n * Get a tracing processor for OpenAI Agents SDK integration.\n *\n * This processor automatically captures traces and spans from the OpenAI Agents SDK\n * and sends them to Bitfab for monitoring and analysis.\n *\n * Example usage:\n * ```typescript\n * import { addTraceProcessor } from '@openai/agents';\n *\n * const client = new Bitfab({ apiKey: 'your-api-key' });\n * const processor = client.getOpenAiTracingProcessor();\n * addTraceProcessor(processor);\n * ```\n *\n * @returns A BitfabOpenAITracingProcessor instance configured for this client\n */\n getOpenAiTracingProcessor() {\n return new BitfabOpenAITracingProcessor({\n // Resolved at getter-call time (framework handlers are set up after env\n // loads); the withSpan path stays lazy via the constructor HttpClient thunk.\n apiKey: this.resolveApiKey(),\n serviceUrl: this.serviceUrl,\n getActiveSpanContext: () => {\n const stack = getSpanStack()\n return stack[stack.length - 1] ?? null\n },\n _httpClient: this.httpClient,\n })\n }\n\n /**\n * Get an OpenAI Agents SDK handler that records a replayable root span.\n *\n * The processor from {@link getOpenAiTracingProcessor} captures everything\n * inside a run (LLM calls, tools, handoffs) but never sees the caller's\n * input, so a processor-only run records an empty-input root and is not\n * replayable. This handler's `wrapRun` is a drop-in for `run()` that opens a\n * `withSpan` root carrying the input and final output; the processor's spans\n * nest beneath it. Register the processor once at startup, then call\n * `handler.wrapRun(agent, input)` in place of `run(agent, input)`.\n *\n * ```typescript\n * import { addTraceProcessor, Agent, run } from \"@openai/agents\";\n *\n * addTraceProcessor(client.getOpenAiTracingProcessor());\n * const handler = client.getOpenAiAgentHandler(\"research-topic\");\n * const result = await handler.wrapRun(agent, \"Find X\");\n * ```\n *\n * @param traceFunctionKey - Groups traces under this key in Bitfab\n * @returns A BitfabOpenAIAgentHandler configured for this client\n */\n getOpenAiAgentHandler(traceFunctionKey: string) {\n return new BitfabOpenAIAgentHandler({\n traceFunctionKey,\n withSpan: this.withSpan.bind(this),\n getActiveSpanContext: () => {\n const stack = getSpanStack()\n return stack[stack.length - 1] ?? null\n },\n })\n }\n\n /**\n * Get a LangGraph/LangChain callback handler for tracing.\n *\n * The handler captures graph node execution, LLM calls, and tool\n * invocations as Bitfab spans with proper parent-child hierarchy.\n *\n * ```typescript\n * const handler = client.getLangGraphCallbackHandler(\"my-agent\");\n * const result = await agent.invoke(\n * { messages: [...] },\n * { callbacks: [handler] },\n * );\n * ```\n *\n * @param traceFunctionKey - Groups traces under this key in Bitfab\n * @returns A BitfabLangGraphCallbackHandler configured for this client\n */\n getLangGraphCallbackHandler(traceFunctionKey: string) {\n return new BitfabLangGraphCallbackHandler({\n apiKey: this.resolveApiKey(),\n traceFunctionKey,\n serviceUrl: this.serviceUrl,\n getActiveSpanContext: () => {\n const stack = getSpanStack()\n return stack[stack.length - 1] ?? null\n },\n _httpClient: this.httpClient,\n })\n }\n\n /**\n * Get a LangChain callback handler for tracing.\n *\n * Alias of {@link getLangGraphCallbackHandler}: LangChain chains and\n * LangGraph graphs share the same callback system, so one handler serves\n * both.\n *\n * ```typescript\n * const handler = client.getLangChainCallbackHandler(\"my-chain\");\n * const result = await chain.invoke(input, { callbacks: [handler] });\n * ```\n *\n * @param traceFunctionKey - Groups traces under this key in Bitfab\n * @returns A BitfabLangGraphCallbackHandler configured for this client\n */\n getLangChainCallbackHandler(traceFunctionKey: string) {\n return this.getLangGraphCallbackHandler(traceFunctionKey)\n }\n\n /**\n * Get the first-class LangGraph integration for tracing and replaying tools\n * executed by `ToolNode`.\n *\n * The integration combines `wrapTools()` for per-tool replay interception\n * with `createInvoker()` for a callback-configured replayable graph entry\n * point. Lower-level callback and root wrappers remain available.\n *\n * @param traceFunctionKey - Groups traces under this key in Bitfab\n * @param options - Controls which tools are marked for replay mocking\n * @experimental This API may change before it is stable.\n */\n getLangGraphIntegration(\n traceFunctionKey: string,\n options?: LangGraphIntegrationOptions,\n ): BitfabLangGraphIntegration {\n const callbackHandler = new BitfabLangGraphCallbackHandler({\n apiKey: this.resolveApiKey(),\n traceFunctionKey,\n serviceUrl: this.serviceUrl,\n getActiveSpanContext: () => {\n const stack = getSpanStack()\n return stack[stack.length - 1] ?? null\n },\n captureTools: false,\n _httpClient: this.httpClient,\n })\n return new BitfabLangGraphIntegration({\n client: this,\n traceFunctionKey,\n callbackHandler,\n options,\n })\n }\n\n /**\n * Get a Claude Agent SDK handler for tracing.\n *\n * The handler captures LLM turns, tool invocations, and subagent\n * execution as Bitfab spans with proper parent-child hierarchy.\n *\n * ```typescript\n * import { query } from \"@anthropic-ai/claude-agent-sdk\";\n *\n * const handler = client.getClaudeAgentHandler(\"my-agent\");\n * const options = handler.instrumentOptions({\n * model: \"claude-sonnet-4-5-...\",\n * });\n * for await (const msg of handler.wrapQuery(\n * query({ prompt: \"Do something\", options })\n * )) {\n * // process messages\n * }\n * ```\n *\n * @param traceFunctionKey - Groups traces under this key in Bitfab\n * @returns A BitfabClaudeAgentHandler configured for this client\n */\n getClaudeAgentHandler(traceFunctionKey: string) {\n return new BitfabClaudeAgentHandler({\n apiKey: this.resolveApiKey(),\n traceFunctionKey,\n serviceUrl: this.serviceUrl,\n getActiveSpanContext: () => {\n const stack = getSpanStack()\n return stack[stack.length - 1] ?? null\n },\n _httpClient: this.httpClient,\n })\n }\n\n /**\n * Get a Vercel AI SDK language-model middleware for tracing.\n *\n * Pass it to the AI SDK's `wrapLanguageModel` and use the wrapped model with\n * `generateText` / `streamText` / `generateObject` / `streamObject`. Every\n * call through that model is captured as a keyed `llm` span carrying the call\n * parameters (the prompt) as input and a serializable summary\n * (`{ text, toolCalls, usage, finishReason }`) as output. Streaming is\n * captured without disturbing the caller's live stream.\n *\n * ```typescript\n * import { wrapLanguageModel, streamText } from \"ai\";\n * import { openai } from \"@ai-sdk/openai\";\n *\n * const model = wrapLanguageModel({\n * model: openai(\"gpt-4o\"),\n * middleware: client.getVercelAiMiddleware(\"chat-turn\"),\n * });\n * const result = streamText({ model, messages });\n * ```\n *\n * @param traceFunctionKey - Groups traces under this key in Bitfab\n * @returns A Vercel AI SDK middleware configured for this client\n */\n getVercelAiMiddleware(traceFunctionKey: string) {\n return new BitfabVercelAiHandler({\n traceFunctionKey,\n withSpan: this.withSpan.bind(this),\n }).middleware\n }\n\n /**\n * Wrap a BAML client method to automatically capture prompt and LLM metadata.\n *\n * Creates a BAML Collector, calls the method through a tracked client,\n * then extracts rendered messages and token usage - calling setPrompt()\n * and addContext() on the current span automatically.\n *\n * The BAML client can be provided in the constructor or passed explicitly:\n *\n * ```typescript\n * // Option 1: bamlClient in constructor (use wrapBAML with just the method)\n * const client = new Bitfab({ apiKey: 'your-api-key', bamlClient: b });\n * const traced = client.withSpan('classify', { type: 'llm' },\n * client.wrapBAML(b.ClassifyText)\n * );\n *\n * // Option 2: pass bamlClient at call site\n * const client = new Bitfab({ apiKey: 'your-api-key' });\n * const traced = client.withSpan('classify', { type: 'llm' },\n * client.wrapBAML(b, b.ClassifyText)\n * );\n * ```\n *\n * @param methodOrClient - Either a BAML method (uses constructor bamlClient) or the BAML client instance\n * @param maybeMethodOrOptions - The BAML method when the first argument is a client, or WrapBAMLOptions when the first argument is the method\n * @param maybeOptions - WrapBAMLOptions when using the two-argument (client, method) form\n * @returns An async function with the same signature that instruments the BAML call\n */\n wrapBAML<TArgs extends unknown[], TReturn>(\n methodOrClient: unknown,\n maybeMethodOrOptions?:\n | ((...args: TArgs) => Promise<TReturn>)\n | WrapBAMLOptions,\n maybeOptions?: WrapBAMLOptions,\n ): WrappedBamlFn<TArgs, TReturn> {\n let bamlClient: unknown\n let method: (...args: TArgs) => Promise<TReturn>\n let options: WrapBAMLOptions | undefined\n\n if (typeof maybeMethodOrOptions === \"function\") {\n bamlClient = methodOrClient\n method = maybeMethodOrOptions\n options = maybeOptions\n } else {\n bamlClient = this.bamlClient\n method = methodOrClient as (...args: TArgs) => Promise<TReturn>\n options = maybeMethodOrOptions as WrapBAMLOptions | undefined\n if (!bamlClient) {\n throw new BitfabError(\n \"bamlClient is required for wrapBAML. Pass it in the constructor or as the first argument.\",\n )\n }\n }\n\n const methodName = method.name\n if (!methodName) {\n throw new BitfabError(\n \"wrapBAML requires a named function (e.g., b.ClassifyText).\",\n )\n }\n\n // Warm the Collector class cache so it's ready by the time the wrapper is called\n loadCollectorClass()\n\n const wrappedFn = async (...args: TArgs): Promise<TReturn> => {\n const CollectorClass = await loadCollectorClass()\n if (!CollectorClass) {\n // @boundaryml/baml not available - call method directly as fallback\n wrappedFn.collector = null\n return await (\n bamlClient as Record<string, (...a: TArgs) => Promise<TReturn>>\n )[methodName](...args)\n }\n\n const collector = new CollectorClass(\"bitfab-baml-tracing\")\n\n // Setting up the tracked client is a side-channel: a BAML version\n // mismatch, or a non-BAML object passed as `bamlClient`, must not stop\n // the user's call. If `withOptions` or the method lookup fails, fall back\n // to the untracked method so the call still runs (untraced).\n let trackedClient: Record<string, unknown>\n let trackedMethod: (...a: TArgs) => Promise<TReturn>\n try {\n trackedClient = (\n bamlClient as { withOptions: (opts: unknown) => unknown }\n ).withOptions({ collector }) as Record<string, unknown>\n const method = (\n trackedClient as Record<string, (...a: TArgs) => Promise<TReturn>>\n )[methodName]\n if (typeof method !== \"function\") {\n throw new BitfabError(\n \"bamlClient.withOptions did not return the wrapped method\",\n )\n }\n trackedMethod = method\n } catch {\n warnOnce(\n `wrapBAML-setup:${methodName}`,\n `BAML tracing setup failed for \"${methodName}\" (incompatible bamlClient or BAML version); calling it untraced. The call still runs; no span is recorded.`,\n )\n wrappedFn.collector = null\n return await (\n bamlClient as Record<string, (...a: TArgs) => Promise<TReturn>>\n )[methodName](...args)\n }\n\n const result = await trackedMethod.bind(trackedClient)(...args)\n\n wrappedFn.collector = collector\n\n try {\n const prompt = extractPromptFromCollector(collector)\n if (prompt) {\n getCurrentSpan().setPrompt(prompt)\n }\n const metadata = extractContextFromCollector(collector)\n if (metadata) {\n getCurrentSpan().addContext(metadata)\n }\n } catch {\n // Never crash the host app\n }\n\n try {\n options?.onCollector?.(collector)\n } catch {\n // Never crash the host app\n }\n\n return result\n }\n\n wrappedFn.collector = null as unknown | null\n\n return wrappedFn\n }\n\n /**\n * Wrap a function to automatically create a span for its inputs and outputs.\n *\n * The wrapped function behaves identically to the original, but sends\n * span data to Bitfab in the background after each call.\n *\n * Example usage:\n * ```typescript\n * const client = new Bitfab({ apiKey: 'your-api-key' });\n *\n * async function processOrder(orderId: string, items: string[]): Promise<{ total: number }> {\n * // ... process order\n * return { total: 100 };\n * }\n *\n * // Basic usage (defaults to \"custom\" span type)\n * const tracedProcessOrder = client.withSpan('order-processing', processOrder);\n *\n * // With explicit span type\n * const tracedProcessOrder = client.withSpan('order-processing', { type: 'function' }, processOrder);\n *\n * // Call the wrapped function normally\n * const result = await tracedProcessOrder('order-123', ['item-1', 'item-2']);\n * // Span is automatically sent to Bitfab\n * ```\n *\n * @param traceFunctionKey - A string identifier for grouping spans (e.g., 'order-processing', 'user-auth')\n * @param optionsOrFn - Either SpanOptions or the function to wrap\n * @param maybeFn - The function to wrap if options were provided\n * @returns A wrapped function with the same signature that creates spans for inputs and outputs\n */\n withSpan<TArgs extends unknown[], TReturn>(\n traceFunctionKey: string,\n optionsOrFn: SpanOptions | ((...args: TArgs) => TReturn),\n maybeFn?: (...args: TArgs) => TReturn,\n ): (...args: TArgs) => TReturn {\n // Handle overloaded signature\n const options: InternalSpanOptions =\n typeof optionsOrFn === \"function\" ? {} : optionsOrFn\n const fn: (...args: TArgs) => TReturn =\n typeof optionsOrFn === \"function\" ? optionsOrFn : maybeFn!\n const self = this\n\n // Detect Promise-returning fn at wrap time so the mock-fire path can\n // match the original return shape. `AsyncFunction` covers `async fn`\n // declarations; for plain functions that return a Promise we fall back\n // to a `fn.toString()` heuristic (looks for `Promise` or `await`).\n // Brittle for minified code, but mock-fire is the only consumer and a\n // sync fallback (returning a raw value) is the safe degradation.\n const fnIsAsyncFunction = fn.constructor.name === \"AsyncFunction\"\n const fnReturnsPromise =\n fnIsAsyncFunction ||\n (() => {\n try {\n const src = fn.toString()\n return /\\b(?:Promise|await)\\b/.test(src)\n } catch {\n return false\n }\n })()\n\n const wrappedFn = function (this: unknown, ...args: TArgs): TReturn {\n // Decide whether to trace at CALL time, not wrap time. The shim builds\n // this wrapper at module load, often before env (dotenv) has loaded, so\n // freezing the decision here would permanently disable tracing for a key\n // that is set moments later. Re-checking per call lets a late-resolved\n // key take effect; once a key is found the resolution is cached.\n if (!self.shouldRecord()) {\n return fn.apply(this, args)\n }\n\n // The Node-specific entry registers async_hooks synchronously, but ESM\n // chunk evaluation can load this module before that registration runs.\n // Re-check at call time so the first traced invocation gets native\n // context propagation instead of briefly using the browser fallback.\n initializeAsyncContext()\n\n // Defer until AsyncLocalStorage init completes. In Node.js, the\n // dynamic import resolves in one microtask; in browsers, the init\n // resolves immediately to a no-op. The `asyncLocalStorageInitDone`\n // flag prevents an infinite loop when AsyncLocalStorage is\n // unavailable (browsers).\n if (!asyncLocalStorage && !isAsyncStorageInitDone()) {\n return asyncLocalStorageReady.then(() =>\n wrappedFn.apply(this, args),\n ) as unknown as TReturn\n }\n\n const captureWhen: unknown =\n options.captureWhen === undefined ? \"always\" : options.captureWhen\n const resolvedCaptureWhen: CaptureWhen =\n captureWhen === \"always\" || captureWhen === \"nested\"\n ? captureWhen\n : \"always\"\n if (resolvedCaptureWhen !== captureWhen) {\n let invalidValue: string\n try {\n invalidValue = String(captureWhen)\n } catch {\n invalidValue = \"<unprintable>\"\n }\n warnOnce(\n `invalid-capture-when:${traceFunctionKey}`,\n `unknown captureWhen value \"${invalidValue}\"; defaulting to \"always\". Valid values: \"always\", \"nested\".`,\n )\n }\n\n if (resolvedCaptureWhen === \"nested\") {\n let hasParent = false\n try {\n hasParent = getSpanStack().length > 0\n } catch (setupError) {\n if (getReplayContext()) {\n throw setupError\n }\n warnOnce(\n `withSpan-setup:${traceFunctionKey}`,\n `tracing setup failed for \"${traceFunctionKey}\"; running it untraced. The function still runs and returns normally; no span is recorded.`,\n )\n return fn.apply(this, args) as TReturn\n }\n if (!hasParent) {\n return fn.apply(this, args) as TReturn\n }\n }\n\n // Tracing is a side-channel: building the span context must never stop\n // the user's function from running. If any of this setup throws (e.g. a\n // runtime without a usable `crypto`, or a context/snapshot edge), fall\n // back to running `fn` directly, untraced. The `!` definite-assignments\n // are sound because the catch always returns: reaching past the\n // try/catch means the try completed and both values were assigned.\n let newStack!: SpanContext[]\n let executeWithContext!: () => TReturn\n // Set only if THIS call registers root trace state below, so a setup\n // failure after registration can clean up the orphaned entry (see catch).\n let registeredTraceId: string | undefined\n try {\n // Get current span stack to determine trace context\n const currentStack = getSpanStack()\n const parentContext = currentStack[currentStack.length - 1]\n\n // Generate trace ID (replay override > parent > new)\n const replayCtxForTraceId = parentContext ? null : getReplayContext()\n const seedCtxForTraceId = parentContext ? null : getSeedContext()\n const traceId =\n parentContext?.traceId ??\n replayCtxForTraceId?.traceId ??\n seedCtxForTraceId?.traceId ??\n randomUuid()\n const spanId = randomUuid()\n const parentSpanId = parentContext?.spanId ?? null\n const isRootSpan = parentSpanId === null\n\n const requestedSurface: SurfaceRequest =\n options.surface ?? DEFAULT_SURFACE\n const surface = resolveSurface(requestedSurface, parentContext?.surface)\n assertSurfacesCompatible(\n requestedSurface,\n surface,\n parentContext?.surface,\n traceFunctionKey,\n )\n\n // Create new context for this span with empty contexts array\n const newContext: SpanContext = {\n traceId,\n spanId,\n contexts: [],\n ...(surface !== undefined && { surface }),\n }\n newStack = [...currentStack, newContext]\n\n // Capture inputs and start time\n const inputs = args\n const startedAt = nowIsoTimestamp()\n const replayCtxAtStart = getReplayContext()\n const testRunId = replayCtxAtStart?.testRunId ?? options.testRunId\n\n // Register trace state for root spans\n if (isRootSpan && !activeTraceStates.has(traceId)) {\n // Synchronously snapshot the wall clock the SDK sees right now,\n // before invoking the wrapped function. This timestamp is the Neon\n // snapshot pin used by the server-side resolver. It is captured on\n // every trace (no IO, harmless to store) so any trace can later be\n // replayed against a historical branch; the provider is attached\n // only when dbSnapshot is configured, otherwise resolved at replay.\n const dbSnapshotRef = buildSnapshotRef(self.dbSnapshot, startedAt)\n activeTraceStates.set(traceId, {\n traceId,\n startedAt,\n contexts: [],\n ...(testRunId !== undefined && { testRunId }),\n ...(replayCtxAtStart?.inputSourceTraceId && {\n inputSourceTraceId: replayCtxAtStart.inputSourceTraceId,\n }),\n ...(replayCtxAtStart?.replayAttempt !== undefined && {\n replayAttempt: replayCtxAtStart.replayAttempt,\n }),\n dbSnapshotRef,\n })\n registeredTraceId = traceId\n }\n\n // Shared span parameters\n const functionName = fn.name !== \"\" ? fn.name : undefined\n const baseSpanParams = {\n traceFunctionKey,\n functionName,\n spanName: options.name ?? functionName ?? traceFunctionKey,\n traceId,\n spanId,\n parentSpanId,\n inputs,\n startedAt,\n spanType: options.type ?? \"custom\",\n functionId: options.functionId,\n captureContent: options.captureContent ?? true,\n autoTraceDefinition: options.autoTraceDefinition,\n }\n\n // Helper to send the span and, for root spans, the trace completion\n // that follows it. Both are handed to the client's span transport,\n // which owns queueing, batching and delivery: nothing here waits on\n // the network, and replay confirms persistence with a server-side\n // barrier rather than by chaining upload promises.\n // Wrapped in try/catch so span errors never crash the host app.\n const sendSpan = async (params: {\n result: unknown\n error?: string\n mocked?: boolean\n mockTarget?: MockTarget\n mockSource?: MockSource\n }) => {\n const replayCtx = getReplayContext()\n try {\n const endedAt = nowIsoTimestamp()\n\n // If drop() was called on this trace, suppress the span PAYLOAD\n // upload for every span that completes after the flag was set.\n // The trace completion signal below still rides out with\n // `dropped: true`, so the server scrubs any sibling spans that\n // already raced out (fire-and-forget) before the flag was set.\n // Skipping the upload here is belt-and-suspenders on top of that\n // scrub: it avoids shipping payloads the server will only discard.\n const traceDropped =\n activeTraceStates.get(traceId)?.dropped === true\n\n // dbSnapshotRef is attached to the trace, not the span (see\n // sendTraceCompletion). A trace-level pin is what replay reads;\n // duplicating it on the root span would just leak the same\n // value into two places.\n if (!traceDropped) {\n self.sendWrapperSpan({\n ...baseSpanParams,\n ...params,\n contexts: newContext.contexts,\n prompt: newContext.prompt,\n endedAt,\n ...(testRunId !== undefined && { testRunId }),\n ...(replayCtx?.inputSourceSpanId && {\n inputSourceSpanId: replayCtx.inputSourceSpanId,\n }),\n })\n }\n\n // A root span closing its trace queues the completion right behind\n // its own span. No wait for the children first: the transport\n // preserves submission order and Bitfab's ingress keys spans and\n // traces idempotently, so completion never races ahead of content.\n if (isRootSpan) {\n const traceState = activeTraceStates.get(traceId)\n self.sendTraceCompletion({\n traceFunctionKey,\n traceId,\n startedAt: traceState?.startedAt ?? startedAt,\n endedAt,\n sessionId: traceState?.sessionId,\n name: traceState?.name,\n metadata: traceState?.metadata,\n contexts: traceState?.contexts ?? [],\n testRunId: traceState?.testRunId,\n inputSourceTraceId: traceState?.inputSourceTraceId,\n replayAttempt: traceState?.replayAttempt,\n dbSnapshotRef: traceState?.dbSnapshotRef,\n dropped: traceState?.dropped,\n ingestionType: traceState?.ingestionType,\n // Built AFTER the wrapped fn finished, so `accessed` reflects\n // whether customer code obtained the branch URL during this\n // item. Omitted entirely when no lease was attached, so the\n // server can distinguish \"no branch\" from \"branch ignored\".\n ...(replayCtx?.dbBranchLease && {\n dbSnapshotUsage: {\n neonBranchId: replayCtx.dbBranchLease.neonBranchId,\n snapshotTimestamp:\n replayCtx.dbBranchLease.snapshotTimestamp,\n region: replayCtx.dbBranchLease.region,\n originalTraceId: replayCtx.sourceBitfabTraceId,\n accessed: replayCtx.dbSnapshotAccessed === true,\n timings: replayCtx.dbBranchTimings,\n },\n }),\n })\n activeTraceStates.delete(traceId)\n }\n } catch {\n // Silently ignore - user's result/exception takes priority\n }\n }\n\n // Record the span output. With `finalize`, the raw result is handed\n // back to the caller untouched (streaming stays live) while a drained,\n // serializable view is recorded as the span output instead. finalize\n // runs in the background and never affects the caller's value; a\n // throwing finalize records an error rather than crashing the host.\n const recordSpan = (result: unknown): void => {\n if (options.finalize) {\n // Tracked on the OWNING client: the span reaches the transport\n // only once finalize settles, so a flush that merely drained the\n // transport would race a root span not yet queued - and in replay\n // that root's trace would miss the barrier. Scoped per client so\n // one client's slow finalize cannot fail another's close().\n void self.httpClient.trackDeferred(\n Promise.resolve()\n .then(() => options.finalize!(result))\n .then((output) => sendSpan({ result: output }))\n .catch((error: unknown) =>\n sendSpan({\n result: undefined,\n error:\n error instanceof Error\n ? `finalize failed: ${error.message}`\n : `finalize failed: ${String(error)}`,\n }),\n ),\n )\n } else {\n void sendSpan({ result })\n }\n }\n\n // Assign before mock interception because an asynchronous resolver can\n // decline after this setup block has already returned.\n executeWithContext = (): TReturn => {\n let result: TReturn\n try {\n result = fn.apply(this, args)\n } catch (error) {\n void sendSpan({\n result: undefined,\n error: error instanceof Error ? error.message : String(error),\n })\n throw error\n }\n\n if (result instanceof Promise) {\n return result\n .then((resolvedResult) => {\n recordSpan(resolvedResult)\n return resolvedResult\n })\n .catch((error: unknown) => {\n void sendSpan({\n result: undefined,\n error: error instanceof Error ? error.message : String(error),\n })\n throw error\n }) as TReturn\n }\n\n if (isAsyncGenerator(result)) {\n return wrapAsyncGenerator(result, newStack, sendSpan) as TReturn\n }\n\n recordSpan(result)\n return result\n }\n\n // Mock interception: for a non-root child span under an active mock\n // context, decide whether to substitute its output instead of running\n // real code. Precedence: a matching override wins (per-call before\n // registered, first matcher within each); otherwise the base strategy\n // (\"all\"/\"marked\") replays recorded output. The lookup key matches\n // buildMockTree: `${traceFunctionKey}:${spanName}:${idx}` with callIndex\n // scoped per (key, name) - see comment on buildMockTree.\n const replayCtxForMock = getReplayContext()\n if (replayCtxForMock?.mockTree && !isRootSpan) {\n const counters = replayCtxForMock.callCounters!\n const counterKey = `${traceFunctionKey}:${baseSpanParams.spanName}`\n const callIndex = counters.get(counterKey) ?? 0\n counters.set(counterKey, callIndex + 1)\n\n const mockKey = `${counterKey}:${callIndex}`\n const mockSpan = replayCtxForMock.mockTree.spans.get(mockKey)\n\n // Emit a mocked span (flagged so the trace view marks it), then return\n // the value in the wrapped fn's call shape. fnReturnsPromise keeps a\n // sync-but-Promise-returning fn's `.then()` consumers working.\n const emitMock = (\n output: unknown,\n mockSource: MockSource,\n ): TReturn => {\n void sendSpan({\n result: output,\n mocked: true,\n mockTarget: \"output\",\n mockSource,\n })\n if (fnReturnsPromise) {\n return Promise.resolve(output) as TReturn\n }\n return output as TReturn\n }\n // Same, when the value resolves asynchronously (lazy recorded-output\n // fetch, or an async value function). A synchronous wrapped fn cannot\n // return a Promise its caller can use, so surface it under replay\n // rather than silently mis-typing the result.\n const emitMockAsync = (\n pending: Promise<unknown>,\n mockSource: MockSource,\n ): TReturn => {\n if (!fnReturnsPromise) {\n throw new BitfabError(\n `Cannot mock synchronous span \"${traceFunctionKey}\" with an ` +\n \"asynchronously-resolved value (lazy recorded-output fetch or \" +\n \"an async value function). Make the wrapped function async, or \" +\n 'use mock: \"all\" so recorded outputs are fetched eagerly.',\n )\n }\n return (async () => {\n const output = await pending\n void sendSpan({\n result: output,\n mocked: true,\n mockTarget: \"output\",\n mockSource,\n })\n return output\n })() as TReturn\n }\n // Resolve this span's recorded output. Prefer an inline output when\n // the tree carried one (eager \"all\", or an older server that ignores\n // includeOutputs and returns outputs without an externalSpanId); only\n // lazily fetch when the payload-free tree omitted it. Returns a value\n // or a Promise.\n const resolveRecordedOutput = (): unknown | Promise<unknown> => {\n const hasInlineOutput =\n mockSpan?.output !== undefined ||\n mockSpan?.outputMeta !== undefined\n if (\n !hasInlineOutput &&\n replayCtxForMock.fetchSpanOutput &&\n mockSpan?.externalSpanId\n ) {\n return replayCtxForMock.fetchSpanOutput(mockSpan.externalSpanId)\n }\n if (!mockSpan) {\n // No recorded counterpart at all (e.g. getOriginalOutput on a span\n // the changed code newly introduced).\n return Promise.reject(\n new BitfabError(\n `No recorded span to source output for \"${traceFunctionKey}\".`,\n ),\n )\n }\n let output = mockSpan.output\n if (\n mockSpan.outputMeta !== undefined &&\n mockSpan.outputMeta !== null\n ) {\n output = deserializeValue({\n json: mockSpan.output,\n meta: mockSpan.outputMeta,\n })\n }\n return output\n }\n\n const shouldMockWithBaseStrategy =\n replayCtxForMock.mockStrategy === \"all\" ||\n (replayCtxForMock.mockStrategy === \"marked\" &&\n options.mockOnReplay === true)\n\n // 1) Overrides. A resolver can decline with NO_MOCK_OVERRIDE, which\n // continues to the next override and then the base strategy.\n if (replayCtxForMock.mockOverrides?.length) {\n const nodeMeta: SpanNodeMeta = {\n traceFunctionKey,\n spanName: baseSpanParams.spanName,\n type: options.type ?? \"custom\",\n originalSpanId: mockSpan?.sourceSpanId,\n }\n const overrideCtx = {\n node: nodeMeta,\n inputs: args,\n getOriginalOutput: () => Promise.resolve(resolveRecordedOutput()),\n }\n type OverrideResolution =\n | { matched: true; output: unknown }\n | { matched: false }\n const resolveOverrideFrom = (\n startIndex: number,\n ): OverrideResolution | Promise<OverrideResolution> => {\n for (\n let index = startIndex;\n index < replayCtxForMock.mockOverrides!.length;\n index += 1\n ) {\n const override = replayCtxForMock.mockOverrides![index]\n if (!override?.match(nodeMeta)) {\n continue\n }\n const injected = resolveMockValue(override.value, overrideCtx)\n if (injected instanceof Promise) {\n return injected.then((output) =>\n output === NO_MOCK_OVERRIDE\n ? resolveOverrideFrom(index + 1)\n : { matched: true, output },\n )\n }\n if (injected !== NO_MOCK_OVERRIDE) {\n return { matched: true, output: injected }\n }\n }\n return { matched: false }\n }\n\n const resolution = resolveOverrideFrom(0)\n if (resolution instanceof Promise) {\n if (!fnReturnsPromise) {\n throw new BitfabError(\n `Cannot resolve an asynchronous mock override for synchronous span \"${traceFunctionKey}\". ` +\n \"Make the wrapped function async or return NO_MOCK_OVERRIDE synchronously.\",\n )\n }\n return runWithSpanStack(newStack, async () => {\n const resolved = await resolution\n if (resolved.matched) {\n void sendSpan({\n result: resolved.output,\n mocked: true,\n mockTarget: \"output\",\n mockSource: \"override\",\n })\n return resolved.output\n }\n if (shouldMockWithBaseStrategy && !mockSpan) {\n throw new BitfabError(\n `Replay selected span \"${traceFunctionKey}:${baseSpanParams.spanName}\" for mocking, but recorded occurrence ${callIndex + 1} is unavailable. The real span was not executed.`,\n )\n }\n if (shouldMockWithBaseStrategy) {\n const output = await resolveRecordedOutput()\n void sendSpan({\n result: output,\n mocked: true,\n mockTarget: \"output\",\n mockSource: \"recorded\",\n })\n return output\n }\n return executeWithContext()\n }) as TReturn\n }\n if (resolution.matched) {\n return emitMock(resolution.output, \"override\")\n }\n }\n\n // 2) Base strategy: replay recorded output for mocked spans.\n if (shouldMockWithBaseStrategy && !mockSpan) {\n throw new BitfabError(\n `Replay selected span \"${traceFunctionKey}:${baseSpanParams.spanName}\" for mocking, but recorded occurrence ${callIndex + 1} is unavailable. The real span was not executed.`,\n )\n }\n if (shouldMockWithBaseStrategy) {\n const recorded = resolveRecordedOutput()\n if (recorded instanceof Promise) {\n return emitMockAsync(recorded, \"recorded\")\n }\n return emitMock(recorded, \"recorded\")\n }\n }\n } catch (setupError) {\n // If this call registered root trace state before failing, remove the\n // now-orphaned entry: no span or completion will follow, so leaving it\n // would leak the maps and block that trace id's completion forever.\n if (registeredTraceId) {\n activeTraceStates.delete(registeredTraceId)\n }\n if (setupError instanceof MixedTracingError) {\n throw setupError\n }\n // During replay (a controlled eval), a setup failure must surface, not\n // silently fall through. The setup region includes the mock\n // interception: if a matched mock can't build its output (e.g.\n // deserializeValue on bad outputMeta), swallowing it would run the real\n // function - real side effects, and a skewed mock call counter - which\n // defeats replay. Re-throw so the replay runner records it as that\n // item's error. The never-crash fallback below is for production hosts.\n if (getReplayContext() || inSeedScope()) {\n throw setupError\n }\n // Tracing setup failed; run the user's function untraced so a tracing\n // failure never crashes the host app while preserving its receiver.\n warnOnce(\n `withSpan-setup:${traceFunctionKey}`,\n `tracing setup failed for \"${traceFunctionKey}\"; running it untraced. The function still runs and returns normally; no span is recorded.`,\n )\n return fn.apply(this, args) as TReturn\n }\n\n // Run OUTSIDE the setup try: a throw from the user's own function must\n // propagate unchanged and never be mistaken for a tracing failure (which\n // would double-invoke `fn`).\n return runWithSpanStack(newStack, executeWithContext)\n }\n // Mark the wrapper with its key so replay() can tell wrapped functions\n // from plain callables (which it auto-wraps) and reject key mismatches.\n Object.defineProperty(wrappedFn, \"_bitfabTraceFunctionKey\", {\n value: traceFunctionKey,\n })\n // The wrapper takes rest parameters, so its own `length` is 0 and says\n // nothing about what the traced function requires. Keep the original so\n // seedTrace can check a case against the real signature, mirroring\n // `inspect.unwrap` on the Python side.\n Object.defineProperty(wrappedFn, \"_bitfabWrappedFn\", { value: fn })\n return wrappedFn\n }\n\n /**\n * Create a standard ECMAScript method decorator that records each invocation\n * as a span.\n *\n * It supports instance, static, and private methods; use\n * {@link Bitfab.withSpan} for standalone functions, class fields, and\n * accessors.\n *\n * @example\n * ```typescript\n * const bitfab = new Bitfab({ apiKey: process.env.BITFAB_API_KEY });\n *\n * class OrderService {\n * @bitfab.span(\"order-processing\", { type: \"agent\" })\n * async process(orderId: string) {\n * return { orderId };\n * }\n * }\n * ```\n *\n * @param traceFunctionKey - A string identifier for grouping spans\n * @param options - Span configuration applied to the decorated method\n * @returns A standard ECMAScript method decorator\n */\n span(\n traceFunctionKey: string,\n options: SpanOptions = {},\n ): SpanMethodDecorator {\n return (originalMethod, context) => {\n if (context.kind !== \"method\") {\n throw new BitfabError(\n `Bitfab span decorators can only decorate methods; ${String(context.name)} is a ${context.kind}`,\n )\n }\n\n return this.withSpan(traceFunctionKey, options, originalMethod)\n }\n }\n\n /**\n * Get a detached handle to a previously-created trace, looked up by the\n * canonical Bitfab trace ID.\n *\n * The returned handle is not tied to AsyncLocalStorage - each method sends\n * to the server immediately. Useful for adding context to a trace from a\n * different process or thread than the one that created it.\n *\n * Throws synchronously if `traceId` is not a valid Bitfab trace ID. The\n * server returns 404 if no trace exists with that ID in the org; the failure surfaces as a\n * logged warning (fire-and-forget) or via the awaited promise.\n *\n * Example:\n * ```typescript\n * const trace = client.getTrace(traceId);\n * await trace.addContext({ refund_status: \"approved\" });\n * await trace.setMetadata({ region: \"us-west\" });\n * ```\n */\n getTrace(traceId: string): DetachedTrace {\n validateTraceId(traceId)\n\n return {\n traceId,\n addContext: (context: Record<string, unknown>): Promise<void> => {\n if (!this.shouldRecord()) {\n return Promise.resolve()\n }\n if (typeof context !== \"object\" || context === null) {\n return Promise.resolve()\n }\n return this.httpClient.patchTrace(traceId, {\n appendContexts: [context],\n })\n },\n setMetadata: (metadata: Record<string, unknown>): Promise<void> => {\n if (!this.shouldRecord()) {\n return Promise.resolve()\n }\n if (typeof metadata !== \"object\" || metadata === null) {\n return Promise.resolve()\n }\n return this.httpClient.patchTrace(traceId, { mergeMetadata: metadata })\n },\n setSessionId: (sessionId: string): Promise<void> => {\n if (!this.shouldRecord()) {\n return Promise.resolve()\n }\n if (typeof sessionId !== \"string\" || sessionId.length === 0) {\n return Promise.resolve()\n }\n return this.httpClient.patchTrace(traceId, { setSessionId: sessionId })\n },\n setName: (name: string): Promise<void> => {\n if (!this.shouldRecord()) {\n return Promise.resolve()\n }\n if (typeof name !== \"string\" || name.length === 0) {\n return Promise.resolve()\n }\n return this.httpClient.patchTrace(traceId, { setName: name })\n },\n }\n }\n\n /**\n * Fetch one persisted span from a trace without loading the full trace.\n * Name lookups return the last matching span by default. Pass `occurrence`\n * as `\"first\"` or a zero-based index to select a different match.\n */\n async getTraceSpan(\n traceId: string,\n lookup: SpanLookup,\n ): Promise<CapturedSpan | null> {\n validateTraceId(traceId)\n const hasId = lookup.id !== undefined\n const hasName = lookup.name !== undefined\n if (hasId === hasName) {\n throw new BitfabError(\"Provide exactly one of id or name\")\n }\n if (hasId) {\n validateSpanId(lookup.id)\n } else {\n if (lookup.name.length === 0) {\n throw new BitfabError(\"name must be a non-empty string\")\n }\n const occurrence = lookup.occurrence ?? \"last\"\n if (\n occurrence !== \"first\" &&\n occurrence !== \"last\" &&\n (!Number.isInteger(occurrence) || occurrence < 0)\n ) {\n throw new BitfabError(\n 'occurrence must be \"first\", \"last\", or a non-negative integer',\n )\n }\n }\n return this.httpClient.getTraceSpan(traceId, lookup)\n }\n\n /**\n * Get a function wrapper for a specific trace function key.\n *\n * This provides a fluent API alternative to calling withSpan directly,\n * allowing you to bind the traceFunctionKey once and wrap multiple functions.\n *\n * Example usage:\n * ```typescript\n * const client = new Bitfab({ apiKey: 'your-api-key' });\n *\n * const orderFunc = client.getFunction('order-processing');\n * const tracedProcessOrder = orderFunc.withSpan(processOrder);\n * const tracedValidateOrder = orderFunc.withSpan(validateOrder);\n * ```\n *\n * @param traceFunctionKey - A string identifier for grouping spans\n * @returns A BitfabFunction instance for wrapping functions\n */\n getFunction(traceFunctionKey: string): BitfabFunction {\n return new BitfabFunction(this, traceFunctionKey)\n }\n\n /**\n * Send trace completion when a root span ends.\n * Internal method to record trace completion with end time.\n * Queued on the client's span transport; delivery is the transport's job.\n */\n private sendTraceCompletion(params: {\n traceFunctionKey: string\n traceId: string\n startedAt: string\n endedAt: string\n sessionId?: string\n name?: string\n metadata?: Record<string, unknown>\n contexts?: ContextEntry[]\n testRunId?: string\n inputSourceTraceId?: string\n replayAttempt?: number\n dbSnapshotRef?: DbSnapshotRef\n dropped?: boolean\n ingestionType?: TraceIngestionType\n /**\n * Replay DB branch usage record, present only when a lease was\n * attached to the replay item. Serialized as `db_snapshot_usage` so\n * the server can stamp the trace's metadata at ingest.\n */\n dbSnapshotUsage?: {\n neonBranchId: string\n snapshotTimestamp?: string\n /**\n * The branch's region. Recorded so a duration gap between items can be\n * attributed to a cross-region round trip rather than to the code.\n */\n region?: string\n /** Bitfab trace id of the original trace this replay item pinned to. */\n originalTraceId?: string\n accessed: boolean\n /** Server-measured provisioning timings, echoed back verbatim. */\n timings?: DbBranchTimings\n }\n }): void {\n // Build the raw trace object for the externalTraces endpoint\n const rawTrace: Record<string, unknown> = {\n id: params.traceId,\n started_at: params.startedAt,\n ended_at: params.endedAt,\n }\n\n // Add optional fields to rawData\n if (params.name) {\n rawTrace.name = params.name\n }\n if (params.metadata && Object.keys(params.metadata).length > 0) {\n rawTrace.metadata = params.metadata\n }\n if (params.contexts && params.contexts.length > 0) {\n rawTrace.contexts = params.contexts\n }\n if (params.inputSourceTraceId) {\n rawTrace.input_source_trace_id = params.inputSourceTraceId\n }\n if (params.replayAttempt !== undefined) {\n rawTrace.replay_attempt = params.replayAttempt\n }\n if (params.dbSnapshotRef) {\n rawTrace.db_snapshot_ref = params.dbSnapshotRef\n }\n if (params.ingestionType) {\n rawTrace.ingestion_type = params.ingestionType\n }\n if (params.dbSnapshotUsage) {\n rawTrace.db_snapshot_usage = {\n neon_branch_id: params.dbSnapshotUsage.neonBranchId,\n ...(params.dbSnapshotUsage.snapshotTimestamp && {\n snapshot_timestamp: params.dbSnapshotUsage.snapshotTimestamp,\n }),\n ...(params.dbSnapshotUsage.region && {\n region: params.dbSnapshotUsage.region,\n }),\n ...(params.dbSnapshotUsage.originalTraceId && {\n original_trace_id: params.dbSnapshotUsage.originalTraceId,\n // Deprecated wire alias, kept so this SDK still reports usage\n // against servers that predate the rename.\n source_trace_id: params.dbSnapshotUsage.originalTraceId,\n }),\n accessed: params.dbSnapshotUsage.accessed,\n // Echoed verbatim (camelCase inside) rather than re-cased into this\n // record's snake_case: it is the server's own object coming back, and\n // a translation layer here is one more thing to drift.\n ...(params.dbSnapshotUsage.timings && {\n timings: params.dbSnapshotUsage.timings,\n }),\n }\n }\n\n this.httpClient.sendExternalTrace({\n id: params.traceId,\n type: \"sdk-function\",\n source: \"typescript-sdk-function\",\n traceFunctionKey: params.traceFunctionKey,\n externalTrace: rawTrace,\n completed: true,\n ...(params.dropped && { dropped: true }),\n ...(params.sessionId && { sessionId: params.sessionId }),\n ...(params.testRunId && { testRunId: params.testRunId }),\n })\n }\n\n /**\n * Send a wrapper span from function execution.\n * Internal method to record spans when using withSpan.\n * Queued on the client's span transport; delivery is the transport's job.\n */\n private sendWrapperSpan(params: {\n traceFunctionKey: string\n functionName?: string\n spanName: string\n traceId: string\n spanId: string\n parentSpanId: string | null\n inputs?: unknown[]\n result: unknown\n error?: string\n startedAt: string\n endedAt: string\n spanType: SpanType\n contexts?: ContextEntry[]\n prompt?: string\n testRunId?: string\n inputSourceSpanId?: string\n mocked?: boolean\n mockTarget?: MockTarget\n mockSource?: MockSource\n functionId?: string\n captureContent: boolean\n autoTraceDefinition?: AutoTraceFunctionDefinition\n }): void {\n const serializedInputs = params.captureContent\n ? serializeValue(params.inputs)\n : undefined\n const serializedResult = params.captureContent\n ? serializeValue(params.result)\n : undefined\n\n // Format as an external span with the wrapper format\n const externalSpan: Record<string, unknown> = {\n id: params.spanId,\n trace_id: params.traceId,\n started_at: params.startedAt,\n ended_at: params.endedAt,\n span_data: {\n name: params.spanName,\n type: params.spanType,\n ...(params.functionId !== undefined && {\n function_id: params.functionId,\n content_captured: params.captureContent,\n }),\n ...(params.autoTraceDefinition !== undefined && {\n function_file: params.autoTraceDefinition.file,\n function_line: params.autoTraceDefinition.line,\n function_column: params.autoTraceDefinition.column,\n }),\n ...(serializedInputs !== undefined && {\n input: serializedInputs.json,\n ...(serializedInputs.meta !== undefined && {\n input_meta: serializedInputs.meta,\n }),\n }),\n ...(serializedResult !== undefined && {\n output: serializedResult.json,\n ...(serializedResult.meta !== undefined && {\n output_meta: serializedResult.meta,\n }),\n }),\n ...(params.functionName !== undefined && {\n function_name: params.functionName,\n }),\n ...(params.captureContent &&\n params.error !== undefined && {\n error: params.error,\n error_source: \"code\",\n }),\n ...(params.captureContent &&\n params.contexts &&\n params.contexts.length > 0 && {\n contexts: params.contexts,\n }),\n ...(params.captureContent &&\n params.prompt !== undefined && { prompt: params.prompt }),\n },\n }\n\n // Add parent_id for nested spans\n if (params.parentSpanId) {\n externalSpan.parent_id = params.parentSpanId\n }\n if (params.inputSourceSpanId) {\n externalSpan.input_source_span_id = params.inputSourceSpanId\n }\n\n this.httpClient.sendExternalSpan({\n id: params.spanId,\n traceId: params.traceId,\n type: \"sdk-function\",\n source: \"typescript-sdk-function\",\n sourceTraceId: params.traceId,\n traceFunctionKey: params.traceFunctionKey,\n rawSpan: externalSpan,\n ...(params.testRunId && { testRunId: params.testRunId }),\n ...(params.mocked && { mocked: true }),\n ...(params.mockTarget && { mockTarget: params.mockTarget }),\n ...(params.mockSource && { mockSource: params.mockSource }),\n })\n }\n\n /**\n * Replay historical traces through a function and create a test run.\n *\n * Fetches the last N traces for the given trace function key, re-runs each\n * through the provided function, and returns comparison data.\n *\n * Accepts either a `withSpan`-wrapped function (under the same key) or any\n * plain callable: plain callables are wrapped internally so each replayed\n * invocation records a trace tied to the test run. The plain-callable form\n * is how handler-instrumented workflows (LangGraph/LangChain, Claude Agent\n * SDK) replay - those record traces under a key with no `withSpan`-wrapped\n * root in the app.\n *\n * @param traceFunctionKey - The trace function key to replay\n * @param fn - The function to run recorded inputs through\n * @param options - Optional replay options. When `traceIds` is passed,\n * `limit` is ignored (with a warning): an explicit ID list already\n * determines how many traces replay.\n * @returns ReplayResult with items, testRunId, and testRunUrl\n */\n /**\n * Register a mock override applied to every subsequent `replay` on this\n * client, so downstream real code runs against a value you supply for the\n * matched span. Instance-scoped (no global state); call {@link clearMockOverrides}\n * to reset. Per-call `replay({ mockOverride })` overrides take precedence, and\n * both take precedence over the base `mock` strategy.\n *\n * ```ts\n * // Object form (value is a flat value here)\n * bitfab.registerMockOverride({\n * match: (node) => node.traceFunctionKey === \"classify-intent\",\n * value: { label: \"refund\" },\n * })\n * // Ordered form (equivalent); value may also be a function of the context\n * bitfab.registerMockOverride(\n * (node) => node.traceFunctionKey === \"classify-intent\",\n * ({ inputs }) => ({ label: \"refund\" }),\n * )\n * // Keyed form: the resolver only sees spans for this trace function key.\n * bitfab.registerMockOverride(\"classify-intent\", ({ inputs }) => ({\n * label: String(inputs[0]),\n * }))\n * // Or one resolver for every child span:\n * bitfab.registerMockOverride(({ node }) =>\n * node.traceFunctionKey === \"classify-intent\"\n * ? { label: \"refund\" }\n * : NO_MOCK_OVERRIDE,\n * )\n * ```\n */\n registerMockOverride(override: MockOverride): void\n registerMockOverride(resolver: MockOverrideResolver): void\n registerMockOverride(match: NodeMatcher, value: MockValue): void\n registerMockOverride(\n traceFunctionKey: string,\n override: MockOverride | MockOverrideResolver,\n ): void\n registerMockOverride(\n overrideOrResolverOrMatch:\n | string\n | MockOverride\n | MockOverrideResolver\n | NodeMatcher,\n ...values: [] | [MockValue | MockOverride | MockOverrideResolver]\n ): void {\n let override: MockOverride\n if (typeof overrideOrResolverOrMatch === \"string\") {\n const keyedOverride = values[0]\n if (values.length !== 1 || keyedOverride === undefined) {\n throw new BitfabError(\n \"registerMockOverride(traceFunctionKey, override) requires a resolver function or { match, value } override.\",\n )\n }\n if (typeof keyedOverride === \"function\") {\n override = {\n match: (node) => node.traceFunctionKey === overrideOrResolverOrMatch,\n value: keyedOverride,\n }\n } else if (\n typeof keyedOverride === \"object\" &&\n keyedOverride !== null &&\n \"match\" in keyedOverride &&\n \"value\" in keyedOverride\n ) {\n override = {\n match: (node) =>\n node.traceFunctionKey === overrideOrResolverOrMatch &&\n keyedOverride.match(node),\n value: keyedOverride.value,\n }\n } else {\n throw new BitfabError(\n \"registerMockOverride(traceFunctionKey, override) requires a resolver function or { match, value } override.\",\n )\n }\n } else if (typeof overrideOrResolverOrMatch !== \"function\") {\n override = overrideOrResolverOrMatch\n } else if (values.length === 0) {\n override = { match: () => true, value: overrideOrResolverOrMatch }\n } else {\n override = {\n match: overrideOrResolverOrMatch as NodeMatcher,\n value: values[0],\n }\n }\n this.mockOverrides.push(override)\n }\n\n /** Remove all overrides registered via {@link registerMockOverride}. */\n clearMockOverrides(): void {\n this.mockOverrides.length = 0\n }\n\n seedTrace(traceFunctionKey: string, options: SeedCaseOptions): string\n seedTrace<TArgs extends unknown[], TReturn>(\n traceFunctionKey: string,\n fn: (...args: TArgs) => TReturn,\n options?: SeedRunOptions<TArgs>,\n ): Promise<string>\n seedTrace(\n traceFunctionKey: string,\n optionsOrFn: SeedCaseOptions | ((...args: never[]) => unknown),\n runOptions?: SeedRunOptions<never[]>,\n ): string | Promise<string> {\n if (typeof optionsOrFn === \"function\") {\n return this.seedTraceByRunning(traceFunctionKey, optionsOrFn, runOptions)\n }\n return this.seedTraceFromCase(traceFunctionKey, optionsOrFn)\n }\n\n private seedTraceFromCase(\n traceFunctionKey: string,\n options: SeedCaseOptions,\n ): string {\n const { input } = options\n const fn =\n (options.fn as { _bitfabWrappedFn?: (...args: unknown[]) => unknown })\n ?._bitfabWrappedFn ?? options.fn\n if (fn && input.length < fn.length) {\n throw new BitfabError(\n `Seeded case supplies ${input.length} argument(s) but ${\n fn.name === \"\" ? \"the function\" : fn.name\n } requires ${fn.length}. Fix the case, or omit fn to seed it anyway.`,\n )\n }\n\n const traceId = randomUuid()\n const startedAt = nowIsoTimestamp()\n\n activeTraceStates.set(traceId, {\n traceId,\n startedAt,\n contexts: [],\n ingestionType: \"seeded\",\n ...(options.sessionId !== undefined && { sessionId: options.sessionId }),\n ...(options.name !== undefined && { name: options.name }),\n ...(options.metadata !== undefined && { metadata: options.metadata }),\n })\n\n try {\n this.sendWrapperSpan({\n traceFunctionKey,\n spanName: options.spanName ?? traceFunctionKey,\n traceId,\n spanId: randomUuid(),\n parentSpanId: null,\n inputs: input,\n result: options.expected,\n startedAt,\n endedAt: startedAt,\n spanType: options.spanType ?? \"agent\",\n captureContent: true,\n })\n this.sendTraceCompletion({\n traceFunctionKey,\n traceId,\n startedAt,\n endedAt: startedAt,\n sessionId: options.sessionId,\n name: options.name,\n metadata: options.metadata,\n contexts: [],\n ingestionType: \"seeded\",\n })\n } finally {\n activeTraceStates.delete(traceId)\n }\n\n return traceId\n }\n\n private async seedTraceByRunning(\n traceFunctionKey: string,\n fn: (...args: never[]) => unknown,\n options?: SeedRunOptions<never[]>,\n ): Promise<string> {\n const wrappedKey = (fn as { _bitfabTraceFunctionKey?: string })\n ._bitfabTraceFunctionKey\n let target = fn\n if (wrappedKey === undefined) {\n const seedRootOptions: InternalSpanOptions = {\n name: traceFunctionKey,\n type: \"agent\",\n surface: \"neutral\",\n }\n target = this.withSpan(\n traceFunctionKey,\n seedRootOptions,\n fn as (...args: unknown[]) => unknown,\n ) as (...args: never[]) => unknown\n } else if (wrappedKey !== traceFunctionKey) {\n throw new BitfabError(\n `Function is wrapped with trace function key '${wrappedKey}' but ` +\n `seedTrace was called with '${traceFunctionKey}'. Pass matching ` +\n \"keys, or pass the unwrapped function to seed it under the \" +\n \"explicit key.\",\n )\n }\n\n await seedContextReady\n\n const traceId = randomUuid()\n activeTraceStates.set(traceId, {\n traceId,\n startedAt: nowIsoTimestamp(),\n contexts: [],\n ingestionType: \"seeded\",\n ...(options?.sessionId !== undefined && { sessionId: options.sessionId }),\n ...(options?.name !== undefined && { name: options.name }),\n ...(options?.metadata !== undefined && { metadata: options.metadata }),\n })\n\n const args = (options?.args ?? []) as never[]\n let unrecorded = true\n try {\n await runWithSeedContext({ traceId }, async () => target(...args))\n } finally {\n try {\n const { flushTraces } = await import(\"./http.js\")\n await flushTraces(30_000)\n } finally {\n unrecorded = activeTraceStates.delete(traceId)\n }\n }\n if (unrecorded) {\n throw new BitfabError(\n `seedTrace recorded nothing for '${traceFunctionKey}': the call ` +\n \"finished without a root span. Check that an API key resolves \" +\n \"(BITFAB_API_KEY or apiKey), and that fn is a regular or async \" +\n \"function rather than a generator.\",\n )\n }\n return traceId\n }\n\n async replay<TReturn>(\n traceFunctionKey: string,\n // biome-ignore lint/suspicious/noExplicitAny: replay deserializes inputs from historical data, typed args would be incorrect\n fn: (...args: any[]) => TReturn | Promise<TReturn>,\n options?: ReplayOptions,\n ): Promise<ReplayResult<TReturn>> {\n const wrappedKey = (fn as { _bitfabTraceFunctionKey?: string })\n ._bitfabTraceFunctionKey\n let replayFn = fn\n if (wrappedKey === undefined) {\n // Name the root span after the key (not the callable's name) so it\n // matches the production root span: handler-instrumented roots (Claude\n // Agent SDK, OpenAI Agents) are named after the trace function key, so\n // naming the auto-wrap after fn.name would make the replayed root read\n // differently from the trace it replays.\n const replayRootOptions: InternalSpanOptions = {\n name: traceFunctionKey,\n type: \"agent\",\n surface: \"neutral\",\n }\n replayFn = this.withSpan(traceFunctionKey, replayRootOptions, fn)\n } else if (wrappedKey !== traceFunctionKey) {\n throw new BitfabError(\n `Function is wrapped with trace function key '${wrappedKey}' but ` +\n `replay was called with '${traceFunctionKey}'. Pass matching keys, ` +\n \"or pass the unwrapped function to replay it under the explicit key.\",\n )\n }\n const { replay: doReplay } = await import(\"./replay.js\")\n return doReplay(\n this.httpClient,\n this.serviceUrl,\n traceFunctionKey,\n replayFn,\n options,\n this.mockOverrides,\n )\n }\n}\n\n/**\n * Represents a Bitfab function that can wrap user functions for tracing.\n *\n * This provides a fluent API for binding a traceFunctionKey once and\n * then wrapping multiple functions with that key.\n *\n * Example usage:\n * ```typescript\n * const client = new Bitfab({ apiKey: 'your-api-key' });\n *\n * const orderFunc = client.getFunction('order-processing');\n * const tracedProcessOrder = orderFunc.withSpan(processOrder);\n * const tracedValidateOrder = orderFunc.withSpan(validateOrder);\n * ```\n */\nexport class BitfabFunction {\n constructor(\n private readonly client: Bitfab,\n private readonly traceFunctionKey: string,\n ) {}\n\n /**\n * Wrap a function to automatically create a span for its inputs and outputs.\n *\n * The wrapped function behaves identically to the original, but sends\n * span data to Bitfab in the background after each call.\n *\n * Example usage:\n * ```typescript\n * const orderFunc = client.getFunction('order-processing');\n *\n * // Basic usage (defaults to \"custom\" span type)\n * const tracedProcessOrder = orderFunc.withSpan(processOrder);\n *\n * // With explicit span type\n * const tracedProcessOrder = orderFunc.withSpan({ type: 'function' }, processOrder);\n * ```\n *\n * @param optionsOrFn - Either SpanOptions or the function to wrap\n * @param maybeFn - The function to wrap if options were provided\n * @returns A wrapped function with the same signature that creates spans\n */\n withSpan<TArgs extends unknown[], TReturn>(\n optionsOrFn: SpanOptions | ((...args: TArgs) => TReturn),\n maybeFn?: (...args: TArgs) => TReturn,\n ): (...args: TArgs) => TReturn {\n // Handle overloaded signature\n const options: SpanOptions =\n typeof optionsOrFn === \"function\" ? {} : optionsOrFn\n const fn: (...args: TArgs) => TReturn =\n typeof optionsOrFn === \"function\" ? optionsOrFn : maybeFn!\n\n return this.client.withSpan(this.traceFunctionKey, options, fn)\n }\n\n /**\n * Create a standard ECMAScript method decorator bound to this function key.\n *\n * @example\n * ```typescript\n * const orders = client.getFunction(\"order-processing\");\n *\n * class OrderService {\n * @orders.span({ type: \"agent\" })\n * async process(orderId: string) {\n * return { orderId };\n * }\n * }\n * ```\n *\n * @param options - Span configuration applied to the decorated method\n * @returns A standard ECMAScript method decorator\n */\n span(options: SpanOptions = {}): SpanMethodDecorator {\n return this.client.span(this.traceFunctionKey, options)\n }\n\n /**\n * Get a Vercel AI SDK language-model middleware bound to this function's key.\n *\n * Equivalent to `client.getVercelAiMiddleware(key)` but reuses the key bound\n * on this handle, so an outer `withSpan` root and the middleware-traced model\n * calls share one key without repeating the string. With a matching key, the\n * outer span is the replayable root and the model-call spans nest beneath it.\n *\n * Nesting is captured when the model is called, so keep the\n * `generateText` / `streamText` call inside this handle's `withSpan`; the\n * middleware object itself can be created anywhere.\n *\n * ```typescript\n * const chatTurn = client.getFunction(\"chat-turn\");\n * const runChatTurn = chatTurn.withSpan(\n * { type: \"agent\", finalize: finalizers.aiSdk },\n * (messages) => streamText({ model, messages }),\n * );\n * const model = wrapLanguageModel({\n * model: openai(\"gpt-4o\"),\n * middleware: chatTurn.getVercelAiMiddleware(),\n * });\n * ```\n *\n * @returns A Vercel AI SDK middleware configured for this client and key\n */\n getVercelAiMiddleware() {\n return this.client.getVercelAiMiddleware(this.traceFunctionKey)\n }\n\n /**\n * Get a Claude Agent SDK handler bound to this function's key.\n *\n * Equivalent to `client.getClaudeAgentHandler(key)` but reuses the key bound\n * on this handle, so an outer `withSpan` root and the handler share one key\n * without repeating the string. With a matching key, the outer span is the\n * replayable root and every handler span nests beneath it.\n *\n * Use the handler inside this handle's `withSpan` body so its spans capture\n * the enclosing root; framework calls made with no active span record their\n * own root instead.\n *\n * ```typescript\n * const pipeline = client.getFunction(\"my-agent\");\n * const tracedRun = pipeline.withSpan({ type: \"agent\" }, async (prompt) => {\n * const handler = pipeline.getClaudeAgentHandler();\n * const options = handler.instrumentOptions({ model: \"claude-sonnet-4-6\" });\n * for await (const msg of handler.wrapQuery(query({ prompt, options }))) { ... }\n * });\n * ```\n *\n * @returns A Claude Agent SDK handler configured for this client and key\n */\n getClaudeAgentHandler() {\n return this.client.getClaudeAgentHandler(this.traceFunctionKey)\n }\n\n /**\n * Get a LangGraph/LangChain callback handler bound to this function's key.\n *\n * Equivalent to `client.getLangGraphCallbackHandler(key)` but reuses the key\n * bound on this handle, so an outer `withSpan` root and the handler share one\n * key without repeating the string. With a matching key, the outer span is\n * the replayable root and the LangGraph spans nest beneath it.\n *\n * Use the handler inside this handle's `withSpan` body so its spans capture\n * the enclosing root; framework calls made with no active span record their\n * own root instead.\n *\n * ```typescript\n * const pipeline = client.getFunction(\"my-pipeline\");\n * const tracedRun = pipeline.withSpan({ type: \"agent\" }, async (query) => {\n * const handler = pipeline.getLangGraphCallbackHandler();\n * return agent.invoke({ messages: [...] }, { callbacks: [handler] });\n * });\n * ```\n *\n * @returns A LangGraph/LangChain callback handler for this client and key\n */\n getLangGraphCallbackHandler() {\n return this.client.getLangGraphCallbackHandler(this.traceFunctionKey)\n }\n\n /**\n * Alias of {@link getLangGraphCallbackHandler} - LangChain and LangGraph\n * share one callback system, so the same bound handler serves both.\n *\n * @returns A LangChain callback handler for this client and key\n */\n getLangChainCallbackHandler() {\n return this.client.getLangChainCallbackHandler(this.traceFunctionKey)\n }\n\n /**\n * Get the first-class LangGraph tool replay integration bound to this key.\n *\n * @experimental This API may change before it is stable.\n */\n getLangGraphIntegration(options?: LangGraphIntegrationOptions) {\n return this.client.getLangGraphIntegration(this.traceFunctionKey, options)\n }\n\n /**\n * Wrap a BAML client method to automatically capture prompt and LLM metadata.\n * Delegates to the parent client's wrapBAML method.\n *\n * Unlike the other methods on this handle, `wrapBAML` does NOT use the bound\n * key: it opens no span of its own. It enriches the *current* span (via\n * `getCurrentSpan().setPrompt()` / `addContext()`), so call it inside a\n * function wrapped by this handle's `withSpan` - the bound key keys that\n * wrapper, and the BAML prompt/metadata attach to it.\n *\n * @param methodOrClient - Either a BAML method (uses constructor bamlClient) or the BAML client instance\n * @param maybeMethodOrOptions - The BAML method when the first argument is a client, or WrapBAMLOptions when the first argument is the method\n * @param maybeOptions - WrapBAMLOptions when using the two-argument (client, method) form\n * @returns An async function with the same signature that instruments the BAML call\n */\n wrapBAML<TArgs extends unknown[], TReturn>(\n methodOrClient: unknown,\n maybeMethodOrOptions?:\n | ((...args: TArgs) => Promise<TReturn>)\n | WrapBAMLOptions,\n maybeOptions?: WrapBAMLOptions,\n ): WrappedBamlFn<TArgs, TReturn> {\n return this.client.wrapBAML(\n methodOrClient,\n maybeMethodOrOptions,\n maybeOptions,\n )\n }\n}\n","import {\n type AsyncLocalStorageLike,\n createAsyncLocalStorage,\n} from \"./asyncStorage.js\"\n\nexport interface AutoTraceFunctionDefinition {\n id: string\n name: string\n file: string\n line: number\n column: number\n async?: boolean\n wrapper?: boolean\n}\n\nexport interface AutoTraceNodeConfiguration {\n functionName: string\n name?: string\n type?: \"llm\" | \"agent\" | \"function\" | \"guardrail\" | \"handoff\" | \"custom\"\n capture: boolean\n testRunId?: string\n mockOnReplay?: boolean\n // biome-ignore lint/suspicious/noExplicitAny: node finalizers receive the configured function's result, whose type is owned by the caller\n finalize?: (result: any) => unknown | Promise<unknown>\n}\n\nexport interface AutoTraceContext {\n invoke<T>(\n definition: AutoTraceFunctionDefinition,\n inputs: unknown[],\n fn: () => T,\n depth: number,\n nodeConfiguration?: AutoTraceNodeConfiguration,\n ): T\n}\n\ninterface AutoTraceScope {\n context: AutoTraceContext\n depth: number\n nodeConfiguration?: AutoTraceNodeConfiguration\n}\n\ninterface AutoTraceState {\n storage: AsyncLocalStorageLike<AutoTraceScope> | null\n browserScope: AutoTraceScope | undefined\n capturePolicies: WeakMap<object, Map<string, ReadonlySet<string>>>\n activeRoots: number\n}\n\ninterface AutoTraceGlobal {\n __bitfabAutoTraceStateV3?: AutoTraceState\n}\n\ninterface AutoTraceAsyncGenerator {\n next(value?: unknown): Promise<IteratorResult<unknown, unknown>>\n return(value?: unknown): Promise<IteratorResult<unknown, unknown>>\n throw(error?: unknown): Promise<IteratorResult<unknown, unknown>>\n [Symbol.asyncIterator](): AutoTraceAsyncGenerator\n}\n\nconst autoTraceGlobal = globalThis as unknown as AutoTraceGlobal\nconst autoTraceState: AutoTraceState =\n autoTraceGlobal.__bitfabAutoTraceStateV3 ?? {\n storage: null,\n browserScope: undefined,\n capturePolicies: new WeakMap(),\n activeRoots: 0,\n }\nautoTraceGlobal.__bitfabAutoTraceStateV3 = autoTraceState\n\nfunction initializeAutoTraceStorage(): void {\n autoTraceState.storage ??= createAsyncLocalStorage<AutoTraceScope>()\n}\n\nexport function runWithAutoTraceContext<T>(\n context: AutoTraceContext,\n fn: () => T,\n depth = 0,\n): T {\n initializeAutoTraceStorage()\n const scope = { context, depth }\n if (autoTraceState.storage) {\n return autoTraceState.storage.run(scope, fn)\n }\n\n const previous = autoTraceState.browserScope\n autoTraceState.browserScope = scope\n try {\n return fn()\n } finally {\n autoTraceState.browserScope = previous\n }\n}\n\nexport function runWithAutoTraceNodeConfiguration<T>(\n nodeConfiguration: AutoTraceNodeConfiguration,\n fn: () => T,\n): T {\n const scope = currentAutoTraceScope()\n if (!scope) {\n return fn()\n }\n\n const configuredScope = { ...scope, nodeConfiguration }\n let result: T\n if (autoTraceState.storage) {\n result = autoTraceState.storage.run(configuredScope, fn)\n } else {\n const previous = autoTraceState.browserScope\n autoTraceState.browserScope = configuredScope\n try {\n result = fn()\n } finally {\n autoTraceState.browserScope = previous\n }\n }\n\n if (isAutoTraceAsyncGenerator(result)) {\n return wrapAutoTraceNodeAsyncGenerator(nodeConfiguration, result) as T\n }\n return result\n}\n\nexport function runWithAutoTraceRootContext<T>(\n context: AutoTraceContext,\n fn: () => T,\n): T {\n autoTraceState.activeRoots += 1\n let result: T\n try {\n result = runWithAutoTraceContext(context, fn)\n } catch (error) {\n autoTraceState.activeRoots -= 1\n throw error\n }\n\n if (isAutoTraceAsyncGenerator(result)) {\n autoTraceState.activeRoots -= 1\n return wrapAutoTraceAsyncGenerator(context, result) as T\n }\n\n if (result instanceof Promise) {\n return result.finally(() => {\n autoTraceState.activeRoots -= 1\n }) as T\n }\n\n autoTraceState.activeRoots -= 1\n return result\n}\n\nfunction isAutoTraceAsyncGenerator(\n value: unknown,\n): value is AutoTraceAsyncGenerator {\n if (value === null || typeof value !== \"object\") {\n return false\n }\n const candidate = value as Record<PropertyKey, unknown>\n return (\n typeof candidate.next === \"function\" &&\n typeof candidate.return === \"function\" &&\n typeof candidate.throw === \"function\" &&\n typeof candidate[Symbol.asyncIterator] === \"function\"\n )\n}\n\nfunction wrapAutoTraceAsyncGenerator(\n context: AutoTraceContext,\n source: AutoTraceAsyncGenerator,\n): AutoTraceAsyncGenerator {\n const step = (\n method: \"next\" | \"return\" | \"throw\",\n value?: unknown,\n ): Promise<IteratorResult<unknown, unknown>> =>\n runWithAutoTraceRootContext(context, () => source[method](value))\n const wrapped: AutoTraceAsyncGenerator = {\n next: (value) => step(\"next\", value),\n return: (value) => step(\"return\", value),\n throw: (error) => step(\"throw\", error),\n [Symbol.asyncIterator]: () => wrapped,\n }\n return wrapped\n}\n\nfunction wrapAutoTraceNodeAsyncGenerator(\n nodeConfiguration: AutoTraceNodeConfiguration,\n source: AutoTraceAsyncGenerator,\n): AutoTraceAsyncGenerator {\n const step = (\n method: \"next\" | \"return\" | \"throw\",\n value?: unknown,\n ): Promise<IteratorResult<unknown, unknown>> =>\n runWithAutoTraceNodeConfiguration(nodeConfiguration, () =>\n source[method](value),\n )\n const wrapped: AutoTraceAsyncGenerator = {\n next: (value) => step(\"next\", value),\n return: (value) => step(\"return\", value),\n throw: (error) => step(\"throw\", error),\n [Symbol.asyncIterator]: () => wrapped,\n }\n return wrapped\n}\n\nexport function __bitfabAutoSpan<T>(\n definition: AutoTraceFunctionDefinition,\n inputs: unknown[],\n fn: () => T,\n): T {\n const scope = currentAutoTraceScope()\n if (!scope) {\n return fn()\n }\n const nameParts = definition.name.split(\".\")\n const simpleName = nameParts[nameParts.length - 1]\n const nodeConfiguration =\n simpleName === scope.nodeConfiguration?.functionName\n ? scope.nodeConfiguration\n : undefined\n return scope.context.invoke(\n definition,\n inputs,\n fn,\n scope.depth,\n nodeConfiguration,\n )\n}\n\n/**\n * Preserve a function's original call arguments for transform cases where\n * parameter bindings discard them, such as destructured arrow parameters.\n *\n * This helper is internal transform/runtime protocol. The proxy preserves the\n * target's callability, arity, async identity, and non-constructibility while\n * only allocating a trace closure beneath an active automatic trace root.\n *\n * @experimental The automatic tracing protocol may change.\n */\nexport function __bitfabAutoWrap<T extends (...args: never[]) => unknown>(\n definition: AutoTraceFunctionDefinition,\n fn: T,\n): T {\n if (fn.name === \"\") {\n const nameParts = definition.name.split(\".\")\n const inferredName = nameParts[nameParts.length - 1]\n if (inferredName !== undefined) {\n Object.defineProperty(fn, \"name\", {\n configurable: true,\n value: inferredName,\n })\n }\n }\n\n const target = fn as unknown as (...args: unknown[]) => unknown\n return new Proxy(target, {\n apply(callTarget, thisArg, args) {\n if (!__bitfabAutoTraceActive()) {\n return Reflect.apply(callTarget, thisArg, args)\n }\n return __bitfabAutoSpan(definition, args, () =>\n Reflect.apply(callTarget, thisArg, args),\n )\n },\n }) as unknown as T\n}\n\n/**\n * Return whether the current call is inside an automatic trace root.\n *\n * Build transforms use this before allocating function metadata, captured\n * inputs, or an invocation closure. It is internal transform/runtime protocol,\n * not a supported application API.\n *\n * @experimental The automatic tracing protocol may change.\n */\nexport function __bitfabAutoTraceActive(): boolean {\n if (autoTraceState.activeRoots === 0) {\n return false\n }\n return currentAutoTraceScope() !== undefined\n}\n\nfunction currentAutoTraceScope(): AutoTraceScope | undefined {\n initializeAutoTraceStorage()\n return autoTraceState.storage?.getStore() ?? autoTraceState.browserScope\n}\n\nexport function __setBitfabAutoTraceCapturePolicy(\n client: object,\n traceFunctionKey: string,\n functionIds: Iterable<string> | undefined,\n): void {\n const policies = autoTraceState.capturePolicies.get(client) ?? new Map()\n if (functionIds === undefined) {\n policies.delete(traceFunctionKey)\n if (policies.size === 0) {\n autoTraceState.capturePolicies.delete(client)\n }\n return\n }\n policies.set(traceFunctionKey, new Set(functionIds))\n autoTraceState.capturePolicies.set(client, policies)\n}\n\nexport function getAutoTraceCapturePolicy(\n client: object,\n traceFunctionKey: string,\n): ReadonlySet<string> | undefined {\n return autoTraceState.capturePolicies.get(client)?.get(traceFunctionKey)\n}\n","/**\n * Import an OPTIONAL peer dependency without breaking a consumer's bundler.\n *\n * Optional peers (declared in this package's `peerDependenciesMeta` with\n * `optional: true` - e.g. `@openai/agents`, `@boundaryml/baml`) are absent by\n * design for most consumers: someone who only uses the Vercel AI integration\n * never installs `@openai/agents`, and someone who never calls `Bitfab.call()`\n * never installs `@boundaryml/baml`.\n *\n * A plain `import(\"@openai/agents\")` leaves a static, literal specifier in the\n * built SDK. A consumer's bundler (webpack, Turbopack, Vite, Rollup, esbuild)\n * statically analyses that specifier and tries to resolve it at *build* time,\n * failing the whole build with \"Module not found: Can't resolve\n * '@openai/agents'\" even though that code path never runs for that consumer.\n * Wrapping the import in try/catch is not enough: only webpack >= 5.90.2 treats\n * that as optional, and Turbopack/Vite/older webpack do not.\n *\n * The robust, bundler-agnostic fix is to keep the specifier out of static\n * analysis entirely. The caller passes the specifier as parts that are joined\n * at runtime, so no bundler can see a literal module name to resolve. The\n * `webpackIgnore` / `@vite-ignore` magic comments are belt-and-suspenders for\n * bundlers that still inspect the (now non-literal) request. This mirrors the\n * technique already used for `node:async_hooks` in `asyncStorage.ts`.\n *\n * The import stays a native runtime `import()`: it resolves from `node_modules`\n * when the peer IS installed, and throws an ordinary module-not-found error\n * only when the feature is actually used without its peer installed - which is\n * the correct behaviour (the caller opted into an integration whose peer they\n * chose not to install).\n *\n * @param specifierParts - The package specifier split so it is reconstructed at\n * runtime, never appearing as a literal (e.g. `[\"@openai\", \"agents\"]` ->\n * `\"@openai/agents\"`).\n */\nexport function importOptionalPeer<T = unknown>(\n specifierParts: readonly string[],\n): Promise<T> {\n // Reconstructed at runtime so no bundler sees a literal specifier to resolve.\n const specifier = specifierParts.join(\"/\")\n return import(\n /* webpackIgnore: true */ /* @vite-ignore */ specifier\n ) as Promise<T>\n}\n","/**\n * BAML execution utilities for the Bitfab TypeScript SDK.\n * This module provides functions to execute BAML prompts dynamically on the client side.\n */\n\nimport { importOptionalPeer } from \"./optionalPeer.js\"\n\ntype BamlModule = typeof import(\"@boundaryml/baml\")\n\nlet cachedBaml: BamlModule | null = null\n\nasync function loadBaml(): Promise<BamlModule> {\n if (cachedBaml) {\n return cachedBaml\n }\n try {\n // Reconstructed specifier (see importOptionalPeer): keeps a consumer's\n // bundler from trying to resolve `@boundaryml/baml` at build time when it\n // is not installed (it is an optional peer, only needed for Bitfab.call()).\n cachedBaml = await importOptionalPeer<BamlModule>([\"@boundaryml\", \"baml\"])\n return cachedBaml\n } catch {\n throw new Error(\n \"@boundaryml/baml is required for Bitfab.call(). Install it with: npm install @boundaryml/baml\",\n )\n }\n}\n\n/**\n * Provider definition from the server.\n */\nexport interface ProviderDefinition {\n provider: string\n apiKeyEnv: string\n models: Array<{\n model: string\n description: string\n }>\n}\n\n/**\n * Result of a BAML function execution with raw collector data.\n */\nexport interface BamlExecutionResult {\n /** The parsed result of the function */\n result: unknown\n /** Raw collector data for the server to parse */\n rawCollector: Record<string, unknown> | null\n}\n\n/**\n * Capitalize first letter of a string.\n */\nfunction capitalize(str: string): string {\n return str.charAt(0).toUpperCase() + str.slice(1)\n}\n\n/**\n * Convert provider name to PascalCase.\n * e.g., \"openai\" -> \"OpenAI\", \"anthropic\" -> \"Anthropic\"\n */\nfunction formatProvider(provider: string): string {\n const providerMap: Record<string, string> = {\n openai: \"OpenAI\",\n anthropic: \"Anthropic\",\n google: \"Google\",\n }\n return providerMap[provider] ?? capitalize(provider)\n}\n\n/**\n * Convert a model name to a valid BAML identifier part.\n * e.g., \"gpt-5-mini\" -> \"GPT5_mini\", \"gpt-4.1\" -> \"GPT4_1\"\n */\nfunction formatModel(model: string): string {\n return model\n .replace(/^gpt-/, \"GPT\") // gpt- prefix -> GPT\n .replace(/\\./g, \"_\") // dots -> underscore\n .replace(/-/g, \"_\") // hyphens -> underscore\n}\n\n/**\n * Generate the BAML client name from provider and model.\n * e.g., \"openai\" + \"gpt-4.1-mini\" -> \"OpenAI_GPT4_1_mini\"\n */\nexport function getClientName(provider: string, model: string): string {\n return `${formatProvider(provider)}_${formatModel(model)}`\n}\n\n/**\n * Generates BAML client definition strings.\n * BamlRuntime.fromFiles requires clients to be defined in source for parsing.\n */\nfunction generateClientDefinitions(providers: ProviderDefinition[]): string {\n const definitions: string[] = []\n\n for (const providerDef of providers) {\n for (const model of providerDef.models) {\n const clientName = getClientName(providerDef.provider, model.model)\n const temperatureOption = supportsTemperatureZero(\n providerDef.provider,\n model.model,\n )\n ? \"\\n temperature 0\"\n : \"\"\n definitions.push(`client<llm> ${clientName} {\n provider ${providerDef.provider}\n options {\n model \"${model.model}\"\n api_key env.${providerDef.apiKeyEnv}${temperatureOption}\n }\n}`)\n }\n }\n\n return definitions.join(\"\\n\\n\")\n}\n\nfunction supportsTemperatureZero(provider: string, model: string): boolean {\n return (\n provider === \"openai\" &&\n (model.startsWith(\"gpt-4.1\") || model.startsWith(\"gpt-4o\"))\n )\n}\n\n/**\n * Prepends the default client definitions to a BAML source if it doesn't already define them.\n */\nfunction withDefaultClients(\n bamlSource: string,\n providers: ProviderDefinition[],\n): string {\n const hasDefaultClient = bamlSource.includes(\"client<llm> OpenAI_\")\n if (hasDefaultClient) {\n return bamlSource\n }\n const defaultClients = generateClientDefinitions(providers)\n return `${defaultClients}\\n\\n${bamlSource}`\n}\n\n/**\n * Extracts the first function name from BAML source code.\n */\nfunction extractFunctionName(bamlSource: string): string | null {\n const match = bamlSource.match(/function\\s+(\\w+)\\s*\\(/)\n return match?.[1] ?? null\n}\n\n/**\n * Parameter type information extracted from BAML function signature.\n */\nexport interface BamlParameterType {\n name: string\n type: string\n isOptional: boolean\n}\n\n/**\n * Extracts function parameter names and types from BAML source code.\n * Used to properly coerce inputs based on expected types.\n */\nexport function extractFunctionParameters(\n bamlSource: string,\n): BamlParameterType[] {\n const functionMatch = bamlSource.match(/function\\s+\\w+\\s*\\(([^)]*)\\)\\s*->/)\n if (!functionMatch) {\n return []\n }\n\n const paramsString = functionMatch[1].trim()\n if (!paramsString) {\n return []\n }\n\n const params: BamlParameterType[] = []\n const paramParts = splitParameters(paramsString)\n\n for (const part of paramParts) {\n const trimmed = part.trim()\n if (!trimmed) {\n continue\n }\n\n const paramMatch = trimmed.match(/^(\\w+)\\s*:\\s*(.+)$/)\n if (paramMatch) {\n const name = paramMatch[1]\n let type = paramMatch[2].trim()\n const isOptional = type.endsWith(\"?\")\n if (isOptional) {\n type = type.slice(0, -1)\n }\n params.push({ name, type, isOptional })\n }\n }\n\n return params\n}\n\n/**\n * Split parameter string by commas, respecting nested angle brackets.\n */\nfunction splitParameters(paramsString: string): string[] {\n const parts: string[] = []\n let current = \"\"\n let depth = 0\n\n for (const char of paramsString) {\n if (char === \"<\") {\n depth++\n current += char\n } else if (char === \">\") {\n depth--\n current += char\n } else if (char === \",\" && depth === 0) {\n parts.push(current)\n current = \"\"\n } else {\n current += char\n }\n }\n\n if (current.trim()) {\n parts.push(current)\n }\n\n return parts\n}\n\n/**\n * Coerce a single string value to the expected BAML type.\n * Returns the coerced value, or the original string if coercion fails.\n */\nfunction coerceToType(value: string, expectedType: string): unknown {\n // String type - keep as is\n if (expectedType === \"string\") {\n return value\n }\n\n // Integer type\n if (expectedType === \"int\") {\n const parsed = Number.parseInt(value, 10)\n if (!Number.isNaN(parsed)) {\n return parsed\n }\n return value\n }\n\n // Float type\n if (expectedType === \"float\") {\n const parsed = Number.parseFloat(value)\n if (!Number.isNaN(parsed)) {\n return parsed\n }\n return value\n }\n\n // Boolean type\n if (expectedType === \"bool\") {\n const lower = value.toLowerCase()\n if (lower === \"true\") {\n return true\n }\n if (lower === \"false\") {\n return false\n }\n return value\n }\n\n // Array types (e.g., string[], int[])\n if (expectedType.endsWith(\"[]\")) {\n try {\n const parsed = JSON.parse(value)\n if (Array.isArray(parsed)) {\n return parsed\n }\n } catch {\n // Not valid JSON array\n }\n return value\n }\n\n // Complex types (objects, classes, maps) - try JSON parse\n try {\n return JSON.parse(value)\n } catch {\n return value\n }\n}\n\n/**\n * Coerces input values from strings to their appropriate types based on expected BAML types.\n * Actively coerces to the expected type (int, float, bool, etc.) rather than just avoiding\n * unintended conversions.\n */\nfunction coerceInputs(\n inputs: Record<string, unknown>,\n expectedTypes: Map<string, string>,\n): Record<string, unknown> {\n const coerced: Record<string, unknown> = {}\n\n for (const [key, value] of Object.entries(inputs)) {\n if (typeof value === \"string\") {\n const expectedType = expectedTypes.get(key)\n\n if (expectedType) {\n coerced[key] = coerceToType(value, expectedType)\n } else {\n // No expected type info - keep as string\n coerced[key] = value\n }\n } else {\n coerced[key] = value\n }\n }\n\n return coerced\n}\n\n/**\n * Recursively convert an object to a JSON-serializable structure.\n * Similar to Python's _obj_to_dict function.\n */\nfunction objToDict(obj: unknown, depth = 0, maxDepth = 5): unknown {\n if (depth > maxDepth) {\n return `<max depth reached: ${typeof obj}>`\n }\n\n // Handle primitives\n if (\n obj === null ||\n obj === undefined ||\n typeof obj === \"string\" ||\n typeof obj === \"number\" ||\n typeof obj === \"boolean\"\n ) {\n return obj\n }\n\n // Handle arrays\n if (Array.isArray(obj)) {\n return obj.map((item) => objToDict(item, depth + 1, maxDepth))\n }\n\n // Handle plain objects and class instances\n if (typeof obj === \"object\") {\n const result: Record<string, unknown> = {}\n\n // Add type information for non-plain objects\n if (obj.constructor && obj.constructor.name !== \"Object\") {\n result.__type__ = obj.constructor.name\n }\n\n // Extract all enumerable properties\n for (const key of Object.keys(obj)) {\n if (key.startsWith(\"_\")) {\n continue // Skip private properties\n }\n\n try {\n const value = (obj as Record<string, unknown>)[key]\n\n // Skip functions\n if (typeof value === \"function\") {\n continue\n }\n\n result[key] = objToDict(value, depth + 1, maxDepth)\n } catch (error) {\n result[key] =\n `<error: ${error instanceof Error ? error.message : String(error)}>`\n }\n }\n\n // Also try to get non-enumerable properties from the prototype\n // This helps capture getters and computed properties\n try {\n const proto = Object.getPrototypeOf(obj)\n if (proto && proto !== Object.prototype) {\n const descriptors = Object.getOwnPropertyDescriptors(proto)\n for (const [key, descriptor] of Object.entries(descriptors)) {\n if (key.startsWith(\"_\") || key === \"constructor\" || key in result) {\n continue\n }\n\n // Try to get the value if it has a getter\n if (descriptor.get) {\n try {\n const value = (obj as Record<string, unknown>)[key]\n if (typeof value !== \"function\") {\n result[key] = objToDict(value, depth + 1, maxDepth)\n }\n } catch {\n // Getter might throw or be inaccessible\n }\n }\n }\n }\n } catch {\n // Prototype inspection might fail\n }\n\n return result\n }\n\n // Fallback for other types\n return String(obj)\n}\n\n/**\n * Serialize the BAML Collector to a JSON-serializable structure.\n * Recursively extracts all properties from the Collector for server-side parsing.\n */\nfunction serializeCollector(\n collector: unknown,\n): Record<string, unknown> | null {\n try {\n return objToDict(collector, 0, 5) as Record<string, unknown>\n } catch (_error) {\n // Silently ignore serialization failures\n return null\n }\n}\n\n/**\n * Allowed environment variable keys for LLM providers.\n * Only these keys will be passed to the BAML runtime.\n */\nconst ALLOWED_ENV_KEYS = [\"OPENAI_API_KEY\"] as const\n\n/**\n * Type for allowed environment variables.\n * Only OPENAI_API_KEY is currently supported.\n */\nexport type AllowedEnvVars = {\n OPENAI_API_KEY?: string\n}\n\n/**\n * Filters environment variables to only include allowed keys.\n * This prevents accidentally passing sensitive environment variables to the BAML runtime.\n */\nfunction filterEnvVars(envVars: AllowedEnvVars): Record<string, string> {\n const filtered: Record<string, string> = {}\n for (const key of ALLOWED_ENV_KEYS) {\n const value = envVars[key]\n if (value) {\n filtered[key] = value\n }\n }\n return filtered\n}\n\n/**\n * Runs the BAML function with the given inputs using the BAML runtime directly.\n * No file generation or subprocess spawning needed.\n *\n * @param bamlSource - The BAML source code containing the function\n * @param inputs - Named arguments to pass to the function\n * @param providers - Available provider definitions\n * @param envVars - Environment variables for API keys (only OPENAI_API_KEY is allowed)\n * @returns The result and execution metadata of the BAML function call\n */\nexport async function runFunctionWithBaml(\n bamlSource: string,\n inputs: Record<string, unknown>,\n providers: ProviderDefinition[],\n envVars: AllowedEnvVars,\n): Promise<BamlExecutionResult> {\n const { BamlRuntime, Collector } = await loadBaml()\n\n // Extract function name from the BAML source\n const functionName = extractFunctionName(bamlSource)\n if (!functionName) {\n throw new Error(\"No function found in BAML source\")\n }\n\n // Add default client definitions (runtime needs them for parsing)\n const fullSource = withDefaultClients(bamlSource, providers)\n\n // Filter env vars to only allowed keys\n const filteredEnvVars = filterEnvVars(envVars)\n\n // Create runtime from source with env vars\n const runtime = BamlRuntime.fromFiles(\n \"/tmp/baml_runtime\",\n { \"source.baml\": fullSource },\n filteredEnvVars,\n )\n\n // Create context manager\n const ctx = runtime.createContextManager()\n\n // Create collector to capture execution metadata\n const collector = new Collector(\"bitfab-collector\")\n\n // Extract expected parameter types from BAML source\n const params = extractFunctionParameters(bamlSource)\n const expectedTypes = new Map(params.map((p) => [p.name, p.type]))\n\n // Coerce inputs from strings to proper types based on BAML signature\n const args = coerceInputs(inputs, expectedTypes)\n\n // Call the function with collector\n const functionResult = await runtime.callFunction(\n functionName,\n args,\n ctx,\n null, // TypeBuilder\n null, // ClientRegistry\n [collector], // Collectors - capture execution data\n {}, // Tags\n filteredEnvVars,\n )\n\n if (!functionResult.isOk()) {\n throw new Error(\"BAML function execution failed\")\n }\n\n // Serialize the collector to a dict for the server to parse\n const rawCollector = serializeCollector(collector)\n\n return {\n result: functionResult.parsed(false),\n rawCollector,\n }\n}\n","import { MixedTracingError } from \"./errors.js\"\n\nexport type CaptureSurface = \"opt-in\" | \"opt-out\"\n\nexport type SurfaceRequest = CaptureSurface | \"inherit\" | \"neutral\"\n\nexport const DEFAULT_SURFACE: CaptureSurface = \"opt-in\"\n\nconst SURFACE_API: Record<CaptureSurface, string> = {\n \"opt-in\": \"withSpan()\",\n \"opt-out\": \"withTrace()\",\n}\n\nconst MIXED_SURFACE_REMEDY: Record<CaptureSurface, string> = {\n \"opt-in\":\n \"Inside a withTrace/trace subtree, configure a discovered call with node()/withNode() instead, or trace this workflow with withSpan() only.\",\n \"opt-out\":\n \"Wrap the caller with withTrace()/trace() as well, or wrap this function with withSpan().\",\n}\n\nexport function resolveSurface(\n requested: SurfaceRequest,\n parentSurface: CaptureSurface | undefined,\n): CaptureSurface | undefined {\n if (requested === \"neutral\") {\n return undefined\n }\n if (requested === \"inherit\") {\n return parentSurface ?? DEFAULT_SURFACE\n }\n return requested\n}\n\nexport function mixedTracingError(\n enteredApi: string,\n entered: CaptureSurface,\n enclosing: CaptureSurface,\n traceFunctionKey?: string,\n): MixedTracingError {\n const subject =\n traceFunctionKey === undefined ? \"\" : ` for \"${traceFunctionKey}\"`\n return new MixedTracingError(\n `opt-in and opt-out tracing can't be mixed in one call stack: ${enteredApi} (${entered})${subject} was entered inside a ${SURFACE_API[enclosing]} call (${enclosing}). ${MIXED_SURFACE_REMEDY[entered]}`,\n )\n}\n\nexport function assertSurfacesCompatible(\n requested: SurfaceRequest,\n resolved: CaptureSurface | undefined,\n parentSurface: CaptureSurface | undefined,\n traceFunctionKey: string,\n): void {\n if (requested === \"inherit\" || requested === \"neutral\") {\n return\n }\n if (resolved === undefined || parentSurface === undefined) {\n return\n }\n if (parentSurface === resolved) {\n return\n }\n throw mixedTracingError(\n SURFACE_API[resolved],\n resolved,\n parentSurface,\n traceFunctionKey,\n )\n}\n","import type { HttpClient } from \"./http.js\"\n\nexport interface DatasetGraderRef {\n id: string\n name: string | null\n}\n\nexport interface Dataset {\n id: string\n traceFunctionKey: string\n name: string\n description: string | null\n traceCount: number\n graders: DatasetGraderRef[]\n createdAt: string\n updatedAt: string\n}\n\nexport interface SaveDatasetParams {\n traceFunctionKey: string\n name: string\n description?: string\n}\n\nexport interface SaveDatasetResult {\n dataset: Dataset\n created: boolean\n}\n\nexport interface ListDatasetsParams {\n traceFunctionKey?: string\n}\n\nexport interface DatasetTraceIds {\n datasetId: string\n traceIds: string[]\n}\n\nexport interface AddDatasetTracesResult {\n dataset: Dataset\n addedTraceIds: string[]\n alreadyPresentTraceIds: string[]\n skippedTraceIds: string[]\n}\n\nexport interface RemoveDatasetTracesResult {\n dataset: Dataset\n removedTraceIds: string[]\n notPresentTraceIds: string[]\n}\n\nexport interface AddDatasetGradersResult {\n dataset: Dataset\n addedGraderIds: string[]\n alreadyAssignedGraderIds: string[]\n skippedGraderIds: string[]\n}\n\nexport interface RemoveDatasetGradersResult {\n dataset: Dataset\n removedGraderIds: string[]\n notAssignedGraderIds: string[]\n}\n\nexport type GraderRerunStatus = \"pending\" | \"running\" | \"completed\" | \"errored\"\n\nexport interface GraderRerunProgress {\n completedTraces: number\n totalTraces: number\n graderCount: number\n}\n\nexport interface GraderRerunResult {\n tracesGraded: number\n gradersRun: number\n}\n\nexport interface GraderRerun {\n id: string\n status: GraderRerunStatus\n graderIds: string[]\n progress: GraderRerunProgress | null\n result: GraderRerunResult | null\n error: string | null\n createdAt: string\n updatedAt: string\n}\n\nexport interface RerunGradersOptions {\n graderIds?: string[]\n wait?: boolean\n timeoutMs?: number\n pollIntervalMs?: number\n}\n\nexport interface RerunGradersResult {\n run: GraderRerun\n joinedExisting: boolean\n}\n\nconst DEFAULT_RERUN_TIMEOUT_MS = 90_000\nconst DEFAULT_RERUN_POLL_INTERVAL_MS = 1_000\nconst TERMINAL_RERUN_STATUSES: ReadonlySet<GraderRerunStatus> = new Set([\n \"completed\",\n \"errored\",\n])\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\nfunction datasetPath(datasetId: string, suffix = \"\"): string {\n return `/api/sdk/datasets/${encodeURIComponent(datasetId)}${suffix}`\n}\n\n/**\n * Dataset operations for the authenticated organization, reached as\n * `client.datasets`. A dataset is a named bucket of traces scoped to one trace\n * function. Experiments replay against it and its graders score its members.\n */\nexport class DatasetsClient {\n constructor(private readonly httpClient: HttpClient) {}\n\n /**\n * Create a dataset, or update the one already named this way under the same\n * trace function. `created` reports which happened. An omitted description\n * leaves an existing one untouched.\n */\n async save(params: SaveDatasetParams): Promise<SaveDatasetResult> {\n return this.httpClient.request<SaveDatasetResult>(\"/api/sdk/datasets\", {\n traceFunctionKey: params.traceFunctionKey,\n name: params.name,\n ...(params.description === undefined\n ? {}\n : { description: params.description }),\n })\n }\n\n /**\n * List datasets, scoped to one trace function when `traceFunctionKey` is\n * given and organization-wide otherwise.\n */\n async list(params: ListDatasetsParams = {}): Promise<Dataset[]> {\n const query =\n params.traceFunctionKey === undefined\n ? \"\"\n : `?traceFunctionKey=${encodeURIComponent(params.traceFunctionKey)}`\n const response = await this.httpClient.get<{ datasets: Dataset[] }>(\n `/api/sdk/datasets${query}`,\n )\n return response.datasets\n }\n\n /** Fetch one dataset by id. Rejects with a 404 `BitfabError` when it is not in this organization. */\n async get(datasetId: string): Promise<Dataset> {\n const response = await this.httpClient.get<{ dataset: Dataset }>(\n datasetPath(datasetId),\n )\n return response.dataset\n }\n\n /** The ids of every trace in the dataset, the same membership a replay with `datasetId` selects. */\n async listTraces(datasetId: string): Promise<DatasetTraceIds> {\n return this.httpClient.get<DatasetTraceIds>(\n datasetPath(datasetId, \"/traces\"),\n )\n }\n\n /**\n * Add traces to the dataset (1 to 100 ids per call). Traces outside the\n * organization or under another trace function are reported in\n * `skippedTraceIds` rather than failing the call.\n */\n async addTraces(\n datasetId: string,\n traceIds: string[],\n ): Promise<AddDatasetTracesResult> {\n return this.httpClient.request<AddDatasetTracesResult>(\n datasetPath(datasetId, \"/traces\"),\n { traceIds },\n )\n }\n\n /** Remove traces from the dataset. The traces themselves are never deleted. */\n async removeTraces(\n datasetId: string,\n traceIds: string[],\n ): Promise<RemoveDatasetTracesResult> {\n return this.httpClient.request<RemoveDatasetTracesResult>(\n datasetPath(datasetId, \"/removeTraces\"),\n { traceIds },\n )\n }\n\n /**\n * Assign graders to the dataset (1 to 100 ids per call). Graders outside the\n * organization or under another trace function are reported in\n * `skippedGraderIds` rather than failing the call.\n */\n async addGraders(\n datasetId: string,\n graderIds: string[],\n ): Promise<AddDatasetGradersResult> {\n return this.httpClient.request<AddDatasetGradersResult>(\n datasetPath(datasetId, \"/graders\"),\n { graderIds },\n )\n }\n\n /** Unassign graders from the dataset. */\n async removeGraders(\n datasetId: string,\n graderIds: string[],\n ): Promise<RemoveDatasetGradersResult> {\n return this.httpClient.request<RemoveDatasetGradersResult>(\n datasetPath(datasetId, \"/removeGraders\"),\n { graderIds },\n )\n }\n\n /**\n * Re-run graders over every trace in the dataset. Defaults to every assigned\n * grader; an unassigned id is rejected. Waits for the run to finish (up to\n * `timeoutMs`, default 90s) unless `wait` is `false`, and returns the last\n * run state seen either way. A request matching an in-flight run joins it.\n */\n async rerunGraders(\n datasetId: string,\n options: RerunGradersOptions = {},\n ): Promise<RerunGradersResult> {\n const started = await this.httpClient.request<RerunGradersResult>(\n datasetPath(datasetId, \"/rerunGraders\"),\n options.graderIds === undefined ? {} : { graderIds: options.graderIds },\n )\n if (options.wait === false) {\n return started\n }\n\n const deadline =\n Date.now() + (options.timeoutMs ?? DEFAULT_RERUN_TIMEOUT_MS)\n const interval = options.pollIntervalMs ?? DEFAULT_RERUN_POLL_INTERVAL_MS\n let run = started.run\n while (!TERMINAL_RERUN_STATUSES.has(run.status) && Date.now() < deadline) {\n await sleep(interval)\n run = (await this.getGraderRerun(datasetId, run.id)) ?? run\n }\n return { run, joinedExisting: started.joinedExisting }\n }\n\n /**\n * The dataset's active grader re-run, or the run named by `runId`. Returns\n * `null` when nothing is active or the run does not belong to this dataset.\n */\n async getGraderRerun(\n datasetId: string,\n runId?: string,\n ): Promise<GraderRerun | null> {\n const query =\n runId === undefined ? \"\" : `?runId=${encodeURIComponent(runId)}`\n const response = await this.httpClient.get<{ run: GraderRerun | null }>(\n datasetPath(datasetId, `/rerunGraders${query}`),\n )\n return response.run\n }\n}\n","/**\n * Per-trace database snapshot ref capture.\n *\n * Every root span carries a `DbSnapshotRef` that pins the DB state at trace\n * open by wall-clock timestamp. Capturing the timestamp is free (no IO) and\n * harmless, so it happens on every trace regardless of configuration: that\n * lets any trace be replayed against a historical branch later. A `provider`\n * is attached only when the customer configured `dbSnapshot`; when absent it\n * is resolved at replay time. The Bitfab service uses the timestamp to\n * materialize an ephemeral branch from `customer-main`.\n */\n\nimport { BitfabError } from \"./errors.js\"\n\n// TODO: add more providers as resolvers are built (ardent, dolt, gfs, ...).\nexport const SUPPORTED_PROVIDERS = [\"neon\"] as const\n\nexport type DbSnapshotProvider = (typeof SUPPORTED_PROVIDERS)[number]\n\nexport interface DbSnapshotConfig {\n /** Discriminator for the server-side resolver. */\n provider: DbSnapshotProvider\n}\n\nexport interface DbSnapshotRef {\n /**\n * The wall-clock ISO timestamp the SDK observed immediately before\n * invoking the wrapped function. The name encodes its provenance:\n * SDK-observed, wall clock (not monotonic), captured before user code\n * began executing. Always present.\n */\n sdkWallClockBeforeFn: string\n /**\n * The configured provider for server-side branch resolution. Only set when\n * the customer configured `dbSnapshot`; otherwise the provider is resolved\n * at replay time.\n */\n provider?: DbSnapshotProvider\n}\n\nexport function validateDbSnapshotConfig(config: DbSnapshotConfig): void {\n if (!SUPPORTED_PROVIDERS.includes(config.provider)) {\n throw new BitfabError(\n `dbSnapshot.provider \"${config.provider}\" is not supported. Supported providers: ${SUPPORTED_PROVIDERS.join(\", \")}.`,\n )\n }\n}\n\n/**\n * Build a snapshot ref for one trace. Synchronous, no IO. Always stores the\n * wall clock the SDK observed immediately before invoking the wrapped\n * function; the resolver uses that as the Neon snapshot timestamp. The\n * `provider` is included only when `dbSnapshot` was configured (`config`\n * present); otherwise it is resolved at replay time.\n */\nexport function buildSnapshotRef(\n config: DbSnapshotConfig | undefined,\n sdkWallClockBeforeFn: string,\n): DbSnapshotRef {\n return {\n sdkWallClockBeforeFn,\n ...(config && { provider: config.provider }),\n }\n}\n","/**\n * LangGraph/LangChain callback handler for Bitfab tracing.\n *\n * Hooks into LangGraph's callback system to capture graph node execution,\n * LLM calls, and tool invocations as Bitfab spans, without requiring users\n * to wrap their functions with withSpan (which fails on non-serializable args).\n *\n * Duck-typed to match LangChain.js's BaseCallbackHandler interface.\n * No @langchain/core dependency required.\n */\n\nimport { DEFAULT_SERVICE_URL } from \"./constants.js\"\nimport { type ApiKeyInput, HttpClient } from \"./http.js\"\nimport {\n finalizeSpanPayload,\n finalizeTracePayload,\n} from \"./processorPayload.js\"\nimport { randomUuid } from \"./randomUuid.js\"\nimport { toJsonSafeReport } from \"./serialize.js\"\nimport { nowIsoTimestamp } from \"./timestamp.js\"\n\nexport interface ActiveSpanContext {\n traceId: string\n spanId: string\n}\n\ninterface SpanInfo {\n id: string\n spanId: string\n traceId: string\n rootRunId: string\n parentId: string | null\n startedAt: string\n endedAt?: string\n name: string\n type: string\n input?: unknown\n output?: unknown\n error?: string\n contexts: Array<Record<string, unknown>>\n model?: string\n hidden?: boolean\n // Type names of input/output values that could only be captured as\n // placeholders. Carried to the send boundary so finalizeSpanPayload can mark\n // the span non-replayable.\n dropped?: string[]\n}\n\ninterface InvocationState {\n traceId: string\n activeContext: ActiveSpanContext | null\n rootRunId: string\n}\n\nconst LANGSMITH_HIDDEN_TAG = \"langsmith:hidden\"\n\nconst CHAIN_RUN_TYPES = new Set([\"chain\", \"parser\", \"prompt\"])\n\nconst LANGGRAPH_METADATA_KEYS = [\n \"langgraph_step\",\n \"langgraph_node\",\n \"langgraph_triggers\",\n \"langgraph_path\",\n \"langgraph_checkpoint_ns\",\n] as const\n\nfunction nowIso(): string {\n return nowIsoTimestamp()\n}\n\nfunction normalizeChainStartArgs(\n parentRunIdOrRunType?: string,\n runTypeOrRunName?: string,\n runNameOrParentRunId?: string,\n): { parentRunId?: string; runName?: string } {\n if (parentRunIdOrRunType && CHAIN_RUN_TYPES.has(parentRunIdOrRunType)) {\n return {\n parentRunId: runNameOrParentRunId,\n runName: runTypeOrRunName,\n }\n }\n\n return {\n parentRunId: parentRunIdOrRunType,\n runName: runNameOrParentRunId,\n }\n}\n\nfunction convertMessage(message: unknown): Record<string, unknown> {\n if (typeof message !== \"object\" || message === null) {\n return { role: \"unknown\", content: String(message) }\n }\n\n const msg = message as Record<string, unknown>\n\n if (typeof msg.toDict === \"function\") {\n return (msg as { toDict(): Record<string, unknown> }).toDict()\n }\n\n const typeToRole: Record<string, string> = {\n human: \"user\",\n ai: \"assistant\",\n system: \"system\",\n tool: \"tool\",\n function: \"function\",\n }\n\n const result: Record<string, unknown> = {}\n\n const msgType = msg._getType\n ? String((msg as { _getType(): string })._getType())\n : (msg.type as string | undefined)\n\n result.role =\n (msgType ? typeToRole[msgType] : undefined) ?? msg.role ?? \"unknown\"\n result.content = msg.content ?? \"\"\n\n if (msg.tool_calls) {\n result.tool_calls = msg.tool_calls\n }\n if (msg.tool_call_id) {\n result.tool_call_id = msg.tool_call_id\n }\n if (msg.name) {\n result.name = msg.name\n }\n\n return result\n}\n\nfunction extractModelName(\n serialized: Record<string, unknown> | undefined,\n metadata: Record<string, unknown> | undefined,\n): string | undefined {\n if (serialized) {\n const kwargs = serialized.kwargs as Record<string, unknown> | undefined\n if (kwargs) {\n const model = kwargs.model_name ?? kwargs.model ?? kwargs.model_id\n if (model) {\n return String(model)\n }\n }\n }\n if (metadata) {\n const lsModel = metadata.ls_model_name\n if (lsModel) {\n return String(lsModel)\n }\n }\n return undefined\n}\n\ninterface NormalizedUsage {\n inputTokens: number | null\n outputTokens: number | null\n totalTokens: number | null\n cachedInputTokens: number | null\n}\n\nfunction asTokenCount(value: unknown): number | null {\n return typeof value === \"number\" && Number.isFinite(value) ? value : null\n}\n\n/**\n * Normalize a provider-reported token-usage dict into Bitfab's span fields.\n *\n * Handles, in priority order:\n * - Anthropic native (`input_tokens` EXCLUDES cache reads/creation, so they\n * are added back to get the true prompt size)\n * - OpenAI native (`prompt_tokens` / `completion_tokens`, snake or camel case)\n * - Google Gemini / Vertex native (`prompt_token_count` / `candidates_token_count`)\n * - LangChain normalized `usage_metadata` (`input_tokens` / `output_tokens` /\n * `total_tokens` with `input_token_details.cache_read`)\n *\n * Returns null when the value carries no recognizable token counts. Never\n * estimates: only provider-reported numbers are returned.\n */\nfunction normalizeTokenUsage(raw: unknown): NormalizedUsage | null {\n if (typeof raw !== \"object\" || raw === null || Array.isArray(raw)) {\n return null\n }\n const u = raw as Record<string, unknown>\n\n // Anthropic native: input_tokens excludes cached reads and cache writes.\n if (\"cache_read_input_tokens\" in u || \"cache_creation_input_tokens\" in u) {\n const cacheRead = asTokenCount(u.cache_read_input_tokens)\n const cacheCreation = asTokenCount(u.cache_creation_input_tokens)\n const baseInput = asTokenCount(u.input_tokens)\n const outputTokens = asTokenCount(u.output_tokens)\n if (\n cacheRead === null &&\n cacheCreation === null &&\n baseInput === null &&\n outputTokens === null\n ) {\n return null\n }\n const inputTokens =\n (baseInput ?? 0) + (cacheRead ?? 0) + (cacheCreation ?? 0)\n return {\n inputTokens,\n outputTokens,\n totalTokens: inputTokens + (outputTokens ?? 0),\n cachedInputTokens: cacheRead,\n }\n }\n\n // OpenAI native (snake_case) and LangChain.js legacy llmOutput (camelCase).\n if (\n \"prompt_tokens\" in u ||\n \"completion_tokens\" in u ||\n \"promptTokens\" in u ||\n \"completionTokens\" in u\n ) {\n const promptDetails = (u.prompt_tokens_details ?? {}) as Record<\n string,\n unknown\n >\n return withAnyTokenCount({\n inputTokens:\n asTokenCount(u.prompt_tokens) ?? asTokenCount(u.promptTokens),\n outputTokens:\n asTokenCount(u.completion_tokens) ?? asTokenCount(u.completionTokens),\n totalTokens: asTokenCount(u.total_tokens) ?? asTokenCount(u.totalTokens),\n cachedInputTokens: asTokenCount(promptDetails.cached_tokens),\n })\n }\n\n // Google Gemini / Vertex native.\n if (\"prompt_token_count\" in u || \"candidates_token_count\" in u) {\n return withAnyTokenCount({\n inputTokens: asTokenCount(u.prompt_token_count),\n outputTokens: asTokenCount(u.candidates_token_count),\n totalTokens: asTokenCount(u.total_token_count),\n cachedInputTokens: asTokenCount(u.cached_content_token_count),\n })\n }\n\n // LangChain normalized usage_metadata (also plain Anthropic without cache keys).\n if (\"input_tokens\" in u || \"output_tokens\" in u) {\n const inputDetails = (u.input_token_details ?? {}) as Record<\n string,\n unknown\n >\n const inputTokens = asTokenCount(u.input_tokens)\n const outputTokens = asTokenCount(u.output_tokens)\n let totalTokens = asTokenCount(u.total_tokens)\n if (totalTokens === null && inputTokens !== null && outputTokens !== null) {\n totalTokens = inputTokens + outputTokens\n }\n return withAnyTokenCount({\n inputTokens,\n outputTokens,\n totalTokens,\n cachedInputTokens: asTokenCount(inputDetails.cache_read),\n })\n }\n\n return null\n}\n\n/**\n * A recognizable usage shape whose values are all null/non-numeric carries no\n * usage. Returning null lets extraction fall through to the next source\n * (response_metadata, then legacy llm_output) instead of blocking it.\n */\nfunction withAnyTokenCount(usage: NormalizedUsage): NormalizedUsage | null {\n const hasCount =\n usage.inputTokens !== null ||\n usage.outputTokens !== null ||\n usage.totalTokens !== null ||\n usage.cachedInputTokens !== null\n return hasCount ? usage : null\n}\n\nfunction addUsage(totals: NormalizedUsage, usage: NormalizedUsage): void {\n for (const key of [\n \"inputTokens\",\n \"outputTokens\",\n \"totalTokens\",\n \"cachedInputTokens\",\n ] as const) {\n const value = usage[key]\n if (value !== null) {\n totals[key] = (totals[key] ?? 0) + value\n }\n }\n}\n\n/**\n * Extract usage from each generation's message: the standardized\n * `usage_metadata` (set by modern LangChain chat models, including the final\n * aggregated chunk of streaming runs), falling back to provider-native\n * `response_metadata`. Sums across generations when a result has several.\n */\nfunction usageFromGenerations(\n generations: unknown[][] | undefined,\n): NormalizedUsage | null {\n if (!generations?.length) {\n return null\n }\n const totals: NormalizedUsage = {\n inputTokens: null,\n outputTokens: null,\n totalTokens: null,\n cachedInputTokens: null,\n }\n let found = false\n for (const batch of generations) {\n if (!Array.isArray(batch)) {\n continue\n }\n for (const gen of batch) {\n const msg = (gen as Record<string, unknown> | null)?.message as\n | Record<string, unknown>\n | undefined\n if (!msg || typeof msg !== \"object\") {\n continue\n }\n const responseMetadata = msg.response_metadata as\n | Record<string, unknown>\n | undefined\n const usage =\n normalizeTokenUsage(msg.usage_metadata) ??\n normalizeTokenUsage(responseMetadata?.token_usage) ??\n normalizeTokenUsage(responseMetadata?.usage) ??\n normalizeTokenUsage(responseMetadata?.tokenUsage)\n if (!usage) {\n continue\n }\n found = true\n addUsage(totals, usage)\n }\n }\n return found ? totals : null\n}\n\n/**\n * Extract token usage from an LLM result.\n *\n * Resolution order: per-generation `message.usage_metadata` (normalized,\n * provider-agnostic), then `message.response_metadata` token usage, then the\n * legacy `llmOutput.tokenUsage` / `token_usage` / `usage` location. Fields\n * with no provider-reported value are omitted; nothing is ever estimated.\n */\nfunction extractUsage(\n output: Record<string, unknown>,\n): Record<string, unknown> {\n const generations = output.generations as unknown[][] | undefined\n const llmOutput = (output.llmOutput ?? output.llm_output) as\n | Record<string, unknown>\n | undefined\n\n const normalized =\n usageFromGenerations(generations) ??\n normalizeTokenUsage(llmOutput?.tokenUsage) ??\n normalizeTokenUsage(llmOutput?.token_usage) ??\n normalizeTokenUsage(llmOutput?.usage)\n\n const usage: Record<string, unknown> = {}\n if (!normalized) {\n return usage\n }\n if (normalized.inputTokens !== null) {\n usage.inputTokens = normalized.inputTokens\n }\n if (normalized.outputTokens !== null) {\n usage.outputTokens = normalized.outputTokens\n }\n if (normalized.totalTokens !== null) {\n usage.totalTokens = normalized.totalTokens\n }\n if (normalized.cachedInputTokens !== null) {\n usage.cachedInputTokens = normalized.cachedInputTokens\n }\n\n return usage\n}\n\nfunction extractLangGraphMetadata(\n metadata: Record<string, unknown> | undefined,\n): Record<string, unknown> {\n if (!metadata) {\n return {}\n }\n const result: Record<string, unknown> = {}\n for (const key of LANGGRAPH_METADATA_KEYS) {\n if (key in metadata) {\n result[key] = metadata[key]\n }\n }\n return result\n}\n\n/**\n * LangChain/LangGraph callback handler that sends traces to Bitfab.\n *\n * Duck-typed to match LangChain.js's BaseCallbackHandler, so no\n * `@langchain/core` dependency is required. Pass as a callback:\n *\n * ```typescript\n * const handler = bitfab.getLangGraphCallbackHandler(\"my-agent\");\n * const result = await agent.invoke(\n * { messages: [...] },\n * { callbacks: [handler] },\n * );\n * ```\n */\nexport class BitfabLangGraphCallbackHandler {\n name = \"BitfabLangGraphCallbackHandler\"\n\n ignoreRetry = true\n // Retriever callbacks ARE captured (retriever queries -> function spans).\n ignoreRetriever = false\n ignoreCustomEvent = true\n\n private readonly httpClient: HttpClient\n private readonly ownsHttpClient: boolean\n private readonly traceFunctionKey: string\n private readonly getActiveSpanContext: (() => ActiveSpanContext | null) | null\n private readonly captureTools: boolean\n\n private runToSpan: Map<string, SpanInfo> = new Map()\n private invocations: Map<string, InvocationState> = new Map()\n\n constructor(config: {\n apiKey?: ApiKeyInput\n traceFunctionKey: string\n serviceUrl?: string\n timeout?: number\n getActiveSpanContext?: () => ActiveSpanContext | null\n /** Whether callback tool events should emit spans. Defaults to true. */\n captureTools?: boolean\n /**\n * The owning `Bitfab` client's HTTP client. Supplied by\n * `getLangGraphCallbackHandler()` so this handler shares that client's\n * single span-transport worker instead of starting a second one.\n * @internal\n */\n _httpClient?: HttpClient\n }) {\n this.ownsHttpClient = config._httpClient === undefined\n this.httpClient =\n config._httpClient ??\n new HttpClient({\n apiKey: config.apiKey,\n serviceUrl: config.serviceUrl ?? DEFAULT_SERVICE_URL,\n timeout: config.timeout ?? 10000,\n })\n this.traceFunctionKey = config.traceFunctionKey\n this.getActiveSpanContext = config.getActiveSpanContext ?? null\n this.captureTools = config.captureTools ?? true\n }\n\n /**\n * Flush and release the span transport this handler started. A no-op when\n * the handler borrowed a `Bitfab` client's HTTP client: that client's\n * `close()` owns the worker's lifetime.\n */\n async close(timeoutMs?: number): Promise<boolean> {\n return this.ownsHttpClient ? this.httpClient.close(timeoutMs) : true\n }\n\n // ── lifecycle helpers ──────────────────────────────────────────\n\n private startSpan(\n runId: string,\n parentRunId: string | undefined,\n name: string,\n spanType: string,\n inputData?: unknown,\n metadata?: Record<string, unknown>,\n tags?: string[],\n ): SpanInfo {\n // If we have a tracked parent, inherit its invocation. Otherwise this\n // callback is the root of a fresh invocation: capture the outer Bitfab\n // span context now so concurrent invocations don't overwrite each other.\n const parentSpan = parentRunId ? this.runToSpan.get(parentRunId) : undefined\n const willHide = tags?.includes(LANGSMITH_HIDDEN_TAG) === true\n\n let invocation: InvocationState\n let effectiveParentId: string | null\n let isRootInvocation = false\n if (parentSpan) {\n const existing = this.invocations.get(parentSpan.rootRunId)\n if (existing) {\n invocation = existing\n } else {\n invocation = {\n traceId: parentSpan.traceId,\n activeContext: null,\n rootRunId: parentSpan.rootRunId,\n }\n this.invocations.set(invocation.rootRunId, invocation)\n }\n // Hidden callbacks stay local for parent resolution. Walk visible spans\n // to the nearest submitted ancestor so the stored tree has no orphan.\n if (!willHide) {\n let resolved: SpanInfo | undefined = parentSpan\n while (resolved?.hidden === true) {\n resolved = resolved.parentId\n ? this.runToSpan.get(resolved.parentId)\n : undefined\n }\n effectiveParentId = resolved\n ? resolved.spanId\n : (invocation.activeContext?.spanId ?? null)\n } else {\n effectiveParentId = parentRunId ?? null\n }\n } else {\n const activeContext = this.getActiveSpanContext?.() ?? null\n invocation = {\n traceId: activeContext ? activeContext.traceId : randomUuid(),\n activeContext,\n rootRunId: runId,\n }\n this.invocations.set(runId, invocation)\n effectiveParentId = activeContext?.spanId ?? null\n isRootInvocation = true\n }\n\n const lgMetadata = extractLangGraphMetadata(metadata)\n const contexts: Array<Record<string, unknown>> =\n Object.keys(lgMetadata).length > 0 ? [lgMetadata] : []\n\n const { safe: safeInput, dropped: inputDropped } =\n toJsonSafeReport(inputData)\n const spanInfo: SpanInfo = {\n id: randomUuid(),\n spanId: runId,\n traceId: invocation.traceId,\n rootRunId: invocation.rootRunId,\n parentId: effectiveParentId,\n startedAt: nowIso(),\n name,\n type: spanType,\n input: safeInput,\n contexts,\n }\n if (inputDropped.length > 0) {\n spanInfo.dropped = [...inputDropped]\n }\n if (willHide) {\n spanInfo.hidden = true\n }\n this.runToSpan.set(runId, spanInfo)\n if (isRootInvocation) {\n this.sendTraceStart(spanInfo)\n }\n return spanInfo\n }\n\n private completeSpan(\n runId: string,\n output?: unknown,\n error?: string,\n extraContexts?: Record<string, unknown>,\n ): void {\n const spanInfo = this.runToSpan.get(runId)\n if (!spanInfo) {\n return\n }\n this.runToSpan.delete(runId)\n\n spanInfo.endedAt = nowIso()\n const { safe: safeOutput, dropped: outputDropped } =\n toJsonSafeReport(output)\n spanInfo.output = safeOutput\n if (outputDropped.length > 0) {\n spanInfo.dropped = [...(spanInfo.dropped ?? []), ...outputDropped]\n }\n if (error !== undefined) {\n spanInfo.error = error\n }\n\n if (extraContexts && Object.keys(extraContexts).length > 0) {\n spanInfo.contexts.push(extraContexts)\n }\n\n if (spanInfo.hidden !== true) {\n this.sendSpan(spanInfo)\n }\n\n if (runId === spanInfo.rootRunId) {\n const invocation = this.invocations.get(runId)\n this.sendTraceCompletion(spanInfo, invocation?.activeContext ?? null)\n this.invocations.delete(runId)\n }\n }\n\n private sendSpan(spanInfo: SpanInfo): void {\n const spanData: Record<string, unknown> = {\n name: spanInfo.name,\n type: spanInfo.type,\n }\n if (spanInfo.input !== undefined) {\n spanData.input = spanInfo.input\n }\n if (spanInfo.output !== undefined) {\n spanData.output = spanInfo.output\n }\n if (spanInfo.error !== undefined) {\n spanData.error = spanInfo.error\n }\n if (spanInfo.contexts.length > 0) {\n spanData.contexts = spanInfo.contexts\n }\n const rawSpan: Record<string, unknown> = {\n id: spanInfo.spanId,\n trace_id: spanInfo.traceId,\n started_at: spanInfo.startedAt,\n ended_at: spanInfo.endedAt ?? nowIso(),\n span_data: spanData,\n }\n if (spanInfo.parentId !== null) {\n rawSpan.parent_id = spanInfo.parentId\n }\n\n const payload: Record<string, unknown> = {\n id: spanInfo.id,\n traceId: spanInfo.traceId,\n type: \"sdk-function\",\n source: \"typescript-sdk-langgraph\",\n traceFunctionKey: this.traceFunctionKey,\n sourceTraceId: spanInfo.traceId,\n rawSpan,\n }\n\n // Sanitize the whole span and mark a lossy capture non-replayable.\n // spanInfo.dropped carries losses from the capture-time input/output\n // snapshot above.\n const finalized = finalizeSpanPayload(payload, spanInfo.dropped)\n\n try {\n this.httpClient.sendExternalSpan(finalized)\n } catch {\n // Never crash the host app\n }\n }\n\n private sendTraceCompletion(\n rootSpan: SpanInfo,\n activeContext: ActiveSpanContext | null,\n ): void {\n const completed = activeContext === null\n\n const traceData: Record<string, unknown> = {\n id: rootSpan.traceId,\n type: \"sdk-function\",\n source: \"typescript-sdk-langgraph\",\n traceFunctionKey: this.traceFunctionKey,\n externalTrace: {\n id: rootSpan.traceId,\n started_at: rootSpan.startedAt,\n ended_at: rootSpan.endedAt ?? nowIso(),\n },\n completed,\n }\n\n const finalized = finalizeTracePayload(traceData)\n\n try {\n this.httpClient.sendExternalTrace(finalized)\n } catch {\n // Never crash the host app\n }\n }\n\n private sendTraceStart(rootSpan: SpanInfo): void {\n const traceData: Record<string, unknown> = {\n id: rootSpan.traceId,\n type: \"sdk-function\",\n source: \"typescript-sdk-langgraph\",\n traceFunctionKey: this.traceFunctionKey,\n externalTrace: {\n id: rootSpan.traceId,\n started_at: rootSpan.startedAt,\n },\n completed: false,\n }\n\n const finalized = finalizeTracePayload(traceData)\n\n try {\n this.httpClient.sendExternalTrace(finalized)\n } catch {\n // Never crash the host app\n }\n }\n\n // ── chain callbacks (graph nodes) ─────────────────────────────\n\n async handleChainStart(\n chain: Record<string, unknown> | null | undefined,\n inputs: Record<string, unknown>,\n runId: string,\n parentRunIdOrRunType?: string,\n tags?: string[],\n metadata?: Record<string, unknown>,\n runTypeOrRunName?: string,\n runNameOrParentRunId?: string,\n ): Promise<void> {\n try {\n const { parentRunId, runName } = normalizeChainStartArgs(\n parentRunIdOrRunType,\n runTypeOrRunName,\n runNameOrParentRunId,\n )\n const serialized = chain ?? {}\n const idArr = serialized.id as string[] | undefined\n const name =\n runName ??\n (serialized.name as string) ??\n idArr?.[idArr.length - 1] ??\n \"chain\"\n this.startSpan(\n runId,\n parentRunId,\n String(name),\n \"agent\",\n inputs,\n metadata,\n tags,\n )\n } catch {\n // Never crash the host app\n }\n }\n\n async handleChainEnd(\n outputs: Record<string, unknown>,\n runId: string,\n ): Promise<void> {\n try {\n this.completeSpan(runId, outputs)\n } catch {\n // Never crash the host app\n }\n }\n\n async handleChainError(error: unknown, runId: string): Promise<void> {\n try {\n const errorObj = error as { constructor?: { name?: string } }\n if (errorObj?.constructor?.name === \"GraphBubbleUp\") {\n this.completeSpan(runId, undefined, undefined)\n return\n }\n this.completeSpan(\n runId,\n undefined,\n error instanceof Error ? error.message : String(error),\n )\n } catch {\n // Never crash the host app\n }\n }\n\n // ── LLM callbacks ─────────────────────────────────────────────\n\n async handleChatModelStart(\n llm: Record<string, unknown> | null | undefined,\n messages: unknown[][],\n runId: string,\n parentRunId?: string,\n _extraParams?: Record<string, unknown>,\n tags?: string[],\n metadata?: Record<string, unknown>,\n runName?: string,\n ): Promise<void> {\n try {\n const serialized = llm ?? {}\n const model = extractModelName(serialized, metadata)\n const idArr = serialized.id as string[] | undefined\n const name = runName ?? model ?? idArr?.[idArr.length - 1] ?? \"llm\"\n const converted = messages.map((batch) => batch.map(convertMessage))\n\n const spanInfo = this.startSpan(\n runId,\n parentRunId,\n String(name),\n \"llm\",\n converted,\n metadata,\n tags,\n )\n spanInfo.model = model\n } catch {\n // Never crash the host app\n }\n }\n\n async handleLLMStart(\n llm: Record<string, unknown> | null | undefined,\n prompts: string[],\n runId: string,\n parentRunId?: string,\n _extraParams?: Record<string, unknown>,\n tags?: string[],\n metadata?: Record<string, unknown>,\n runName?: string,\n ): Promise<void> {\n try {\n const serialized = llm ?? {}\n const model = extractModelName(serialized, metadata)\n const idArr = serialized.id as string[] | undefined\n const name = runName ?? model ?? idArr?.[idArr.length - 1] ?? \"llm\"\n\n const spanInfo = this.startSpan(\n runId,\n parentRunId,\n String(name),\n \"llm\",\n prompts,\n metadata,\n tags,\n )\n spanInfo.model = model\n } catch {\n // Never crash the host app\n }\n }\n\n async handleLLMEnd(\n output: Record<string, unknown>,\n runId: string,\n ): Promise<void> {\n try {\n let llmOutput: unknown\n const generations = output.generations as unknown[][] | undefined\n if (generations?.length && generations[generations.length - 1]?.length) {\n const gen = generations[generations.length - 1][\n generations[generations.length - 1].length - 1\n ] as Record<string, unknown>\n const msg = gen.message as Record<string, unknown> | undefined\n llmOutput = msg ? convertMessage(msg) : (gen.text ?? String(gen))\n }\n\n const usage = extractUsage(output)\n const spanInfo = this.runToSpan.get(runId)\n const model = spanInfo?.model\n\n const llmContext: Record<string, unknown> = {}\n if (model) {\n llmContext.model = model\n }\n Object.assign(llmContext, usage)\n\n this.completeSpan(\n runId,\n llmOutput,\n undefined,\n Object.keys(llmContext).length > 0 ? llmContext : undefined,\n )\n } catch {\n // Never crash the host app\n }\n }\n\n async handleLLMError(error: unknown, runId: string): Promise<void> {\n try {\n this.completeSpan(\n runId,\n undefined,\n error instanceof Error ? error.message : String(error),\n )\n } catch {\n // Never crash the host app\n }\n }\n\n async handleLLMNewToken(): Promise<void> {\n // Intentionally empty: per-token events are not traced. Usage for\n // streaming runs is captured in handleLLMEnd from the final aggregated\n // chunk's usage_metadata / response_metadata.\n }\n\n // ── tool callbacks ────────────────────────────────────────────\n\n async handleToolStart(\n tool: Record<string, unknown> | null | undefined,\n input: string,\n runId: string,\n parentRunId?: string,\n tags?: string[],\n metadata?: Record<string, unknown>,\n runName?: string,\n ): Promise<void> {\n if (!this.captureTools) {\n return\n }\n try {\n const serialized = tool ?? {}\n const name = runName ?? (serialized.name as string) ?? \"tool\"\n this.startSpan(\n runId,\n parentRunId,\n String(name),\n \"function\",\n input,\n metadata,\n tags,\n )\n } catch {\n // Never crash the host app\n }\n }\n\n async handleToolEnd(output: unknown, runId: string): Promise<void> {\n if (!this.captureTools) {\n return\n }\n try {\n this.completeSpan(runId, output)\n } catch {\n // Never crash the host app\n }\n }\n\n async handleToolError(error: unknown, runId: string): Promise<void> {\n if (!this.captureTools) {\n return\n }\n try {\n this.completeSpan(\n runId,\n undefined,\n error instanceof Error ? error.message : String(error),\n )\n } catch {\n // Never crash the host app\n }\n }\n\n // ── retriever callbacks ───────────────────────────────────────\n\n async handleRetrieverStart(\n retriever: Record<string, unknown> | null | undefined,\n query: string,\n runId: string,\n parentRunId?: string,\n tags?: string[],\n metadata?: Record<string, unknown>,\n runName?: string,\n ): Promise<void> {\n try {\n const serialized = retriever ?? {}\n const name = runName ?? (serialized.name as string) ?? \"retriever\"\n this.startSpan(\n runId,\n parentRunId,\n String(name),\n \"function\",\n query,\n metadata,\n tags,\n )\n } catch {\n // Never crash the host app\n }\n }\n\n async handleRetrieverEnd(documents: unknown, runId: string): Promise<void> {\n try {\n this.completeSpan(runId, documents)\n } catch {\n // Never crash the host app\n }\n }\n\n async handleRetrieverError(error: unknown, runId: string): Promise<void> {\n try {\n this.completeSpan(\n runId,\n undefined,\n error instanceof Error ? error.message : String(error),\n )\n } catch {\n // Never crash the host app\n }\n }\n}\n","import { BitfabError } from \"./http.js\"\nimport type { BitfabLangGraphCallbackHandler } from \"./langgraph.js\"\nimport { importOptionalPeer } from \"./optionalPeer.js\"\nimport { getReplayContext } from \"./replayContext.js\"\n\nconst TOOL_RESULT_TAG = \"__bitfabLangGraphToolResult\"\n\ntype ToolMessageContent = string | Array<Record<string, unknown>>\n\ninterface ToolMessageFields {\n content: ToolMessageContent\n tool_call_id: string\n name?: string\n id?: string\n status?: \"success\" | \"error\"\n artifact?: unknown\n metadata?: Record<string, unknown>\n additional_kwargs?: Record<string, unknown>\n response_metadata?: Record<string, unknown>\n}\n\ninterface ToolMessageConstructor {\n new (fields: ToolMessageFields): unknown\n}\n\ninterface CommandConstructor {\n new (fields: {\n graph?: string\n update?: unknown\n resume?: unknown\n goto?: unknown\n }): unknown\n}\n\ninterface LangChainCoreRuntime {\n ToolMessage: ToolMessageConstructor\n}\n\ninterface LangGraphRuntime {\n Command: CommandConstructor\n}\n\ninterface SpanClient {\n withSpan<TArgs extends unknown[], TReturn>(\n traceFunctionKey: string,\n options: {\n name?: string\n type?: \"agent\" | \"function\"\n captureWhen?: \"always\" | \"nested\"\n mockOnReplay?: boolean\n finalize?: (result: unknown) => unknown | Promise<unknown>\n surface?: \"inherit\"\n },\n fn: (...args: TArgs) => TReturn,\n ): (...args: TArgs) => TReturn\n}\n\ninterface LangGraphTool {\n readonly name?: string\n invoke(input: unknown, ...rest: unknown[]): unknown\n}\n\ninterface ConfiguredLangGraphRunnable<TInput, TConfig, TReturn> {\n invoke(input: TInput, config?: TConfig): TReturn\n}\n\ninterface LangGraphRunnable<TInput, TConfig, TReturn> {\n withConfig(config: {\n callbacks: unknown[]\n }): ConfiguredLangGraphRunnable<TInput, TConfig, TReturn>\n}\n\ninterface EncodedToolMessage extends Record<string, unknown> {\n [TOOL_RESULT_TAG]: \"tool-message\"\n content: ToolMessageContent\n}\n\ninterface EncodedCommand extends Record<string, unknown> {\n [TOOL_RESULT_TAG]: \"command\"\n graph?: string\n update?: unknown\n resume?: unknown\n goto?: unknown\n}\n\ntype EncodedToolResult = EncodedToolMessage | EncodedCommand\n\n/**\n * Options for first-class LangGraph ToolNode replay interception.\n *\n * @experimental This API may change before it is stable.\n */\nexport interface LangGraphIntegrationOptions {\n /**\n * Tools marked for recorded-output mocking under replay's default\n * `mock: \"marked\"` strategy. Defaults to every wrapped tool. Pass a list to\n * mark only those tool names, or `false` to require `mock: \"all\"` or an\n * override.\n */\n mockToolsOnReplay?: boolean | readonly string[]\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null\n}\n\nfunction isToolMessage(value: unknown): value is Record<string, unknown> & {\n content: ToolMessageContent\n} {\n return (\n isRecord(value) &&\n value.lc_direct_tool_output === true &&\n value.type === \"tool\" &&\n (typeof value.content === \"string\" || Array.isArray(value.content))\n )\n}\n\nfunction isCommand(value: unknown): value is Record<string, unknown> {\n return isRecord(value) && value.lg_name === \"Command\"\n}\n\nfunction encodeNested(value: unknown): unknown {\n if (isToolMessage(value) || isCommand(value)) {\n return encodeNativeToolResult(value)\n }\n if (Array.isArray(value)) {\n return value.map(encodeNested)\n }\n if (isRecord(value)) {\n return Object.fromEntries(\n Object.entries(value).map(([key, entry]) => [key, encodeNested(entry)]),\n )\n }\n return value\n}\n\nfunction encodeNativeToolResult(value: unknown): EncodedToolResult {\n if (isToolMessage(value)) {\n return {\n [TOOL_RESULT_TAG]: \"tool-message\",\n content: value.content,\n name: typeof value.name === \"string\" ? value.name : undefined,\n id: typeof value.id === \"string\" ? value.id : undefined,\n status:\n value.status === \"success\" || value.status === \"error\"\n ? value.status\n : undefined,\n artifact: encodeNested(value.artifact),\n metadata: encodeNested(value.metadata),\n additionalKwargs: encodeNested(value.additional_kwargs),\n responseMetadata: encodeNested(value.response_metadata),\n }\n }\n\n return {\n [TOOL_RESULT_TAG]: \"command\",\n graph:\n isRecord(value) && typeof value.graph === \"string\"\n ? value.graph\n : undefined,\n update: isRecord(value) ? encodeNested(value.update) : undefined,\n resume: isRecord(value) ? encodeNested(value.resume) : undefined,\n goto: isRecord(value) ? encodeNested(value.goto) : undefined,\n }\n}\n\nfunction finalizeToolResult(value: unknown): unknown {\n return isToolMessage(value) || isCommand(value)\n ? encodeNativeToolResult(value)\n : value\n}\n\nfunction isEncodedToolResult(value: unknown): value is EncodedToolResult {\n return isRecord(value) && typeof value[TOOL_RESULT_TAG] === \"string\"\n}\n\nasync function loadLangChainCore(): Promise<LangChainCoreRuntime> {\n try {\n return await importOptionalPeer<LangChainCoreRuntime>([\n \"@langchain\",\n \"core\",\n \"messages\",\n ])\n } catch {\n throw new BitfabError(\n \"LangGraph tool replay requires @langchain/core. Install @langchain/langgraph before using getLangGraphIntegration().\",\n \"https://docs.bitfab.ai/frameworks/langgraph\",\n )\n }\n}\n\nasync function loadLangGraph(): Promise<LangGraphRuntime> {\n try {\n return await importOptionalPeer<LangGraphRuntime>([\n \"@langchain\",\n \"langgraph\",\n ])\n } catch {\n throw new BitfabError(\n \"Replaying a LangGraph Command requires @langchain/langgraph.\",\n \"https://docs.bitfab.ai/frameworks/langgraph\",\n )\n }\n}\n\nasync function reviveNested(\n value: unknown,\n toolCallId: string,\n): Promise<unknown> {\n if (isEncodedToolResult(value)) {\n return reviveToolResult(value, toolCallId)\n }\n if (Array.isArray(value)) {\n return Promise.all(value.map((entry) => reviveNested(entry, toolCallId)))\n }\n if (isRecord(value)) {\n const entries = await Promise.all(\n Object.entries(value).map(async ([key, entry]) => [\n key,\n await reviveNested(entry, toolCallId),\n ]),\n )\n return Object.fromEntries(entries)\n }\n return value\n}\n\nasync function reviveToolResult(\n value: EncodedToolResult,\n toolCallId: string,\n): Promise<unknown> {\n if (value[TOOL_RESULT_TAG] === \"tool-message\") {\n const { ToolMessage } = await loadLangChainCore()\n return new ToolMessage({\n content: value.content,\n tool_call_id: toolCallId,\n ...(typeof value.name === \"string\" && { name: value.name }),\n ...(typeof value.id === \"string\" && { id: value.id }),\n ...((value.status === \"success\" || value.status === \"error\") && {\n status: value.status,\n }),\n ...(value.artifact !== undefined && {\n artifact: await reviveNested(value.artifact, toolCallId),\n }),\n ...(isRecord(value.metadata) && {\n metadata: await reviveNested(value.metadata, toolCallId),\n }),\n ...(isRecord(value.additionalKwargs) && {\n additional_kwargs: await reviveNested(\n value.additionalKwargs,\n toolCallId,\n ),\n }),\n ...(isRecord(value.responseMetadata) && {\n response_metadata: await reviveNested(\n value.responseMetadata,\n toolCallId,\n ),\n }),\n } as ToolMessageFields)\n }\n\n const { Command } = await loadLangGraph()\n return new Command({\n ...(typeof value.graph === \"string\" && { graph: value.graph }),\n ...(value.update !== undefined && {\n update: await reviveNested(value.update, toolCallId),\n }),\n ...(value.resume !== undefined && {\n resume: await reviveNested(value.resume, toolCallId),\n }),\n ...(value.goto !== undefined && {\n goto: await reviveNested(value.goto, toolCallId),\n }),\n })\n}\n\n/**\n * First-class LangGraph integration for callback tracing and replayable\n * `ToolNode` tools.\n *\n * @experimental This API may change before it is stable.\n */\nexport class BitfabLangGraphIntegration {\n /** Callback handler for the compiled graph's invocation config. */\n // biome-ignore lint/suspicious/noExplicitAny: avoids leaking an optional peer's declarations into every SDK consumer\n readonly callbackHandler: any\n\n private readonly client: SpanClient\n private readonly traceFunctionKey: string\n private readonly mockToolsOnReplay: boolean | readonly string[]\n\n constructor(config: {\n client: SpanClient\n traceFunctionKey: string\n callbackHandler: BitfabLangGraphCallbackHandler\n options?: LangGraphIntegrationOptions\n }) {\n this.client = config.client\n this.traceFunctionKey = config.traceFunctionKey\n this.callbackHandler = config.callbackHandler\n this.mockToolsOnReplay = config.options?.mockToolsOnReplay ?? true\n }\n\n /**\n * Wrap tools before passing the same returned array to both\n * `model.bindTools()` and `new ToolNode()`. Each invocation becomes an\n * independently mockable child span.\n */\n wrapTools<T extends readonly LangGraphTool[]>(tools: T): T {\n return tools.map((tool) => this.wrapTool(tool)) as unknown as T\n }\n\n /**\n * Create the normal graph entry point. The returned function adds Bitfab's\n * callback handler, preserves invocation config, and records only the graph\n * input as the replayable root input.\n *\n * @experimental This API may change before it is stable.\n */\n createInvoker<TInput, TConfig, TReturn>(\n graph: LangGraphRunnable<TInput, TConfig, TReturn>,\n ): (input: TInput, config?: TConfig) => TReturn {\n const configuredGraph = graph.withConfig({\n callbacks: [this.callbackHandler],\n })\n\n return (input, config) => {\n const invoke = this.wrapInvoke((rootInput: TInput) =>\n configuredGraph.invoke(rootInput, config),\n )\n return invoke(input)\n }\n }\n\n private wrapTool<T extends LangGraphTool>(tool: T): T {\n const toolName = tool.name\n if (typeof toolName !== \"string\" || toolName.length === 0) {\n throw new BitfabError(\n \"LangGraph replayable tools must have a name.\",\n \"https://docs.bitfab.ai/frameworks/langgraph\",\n )\n }\n\n const mockToolsOnReplay = this.mockToolsOnReplay\n const shouldMock =\n typeof mockToolsOnReplay === \"boolean\"\n ? mockToolsOnReplay\n : mockToolsOnReplay.includes(toolName)\n const originalInvoke = tool.invoke.bind(tool)\n\n return new Proxy(tool, {\n get: (target, property) => {\n if (property === \"invoke\") {\n return async (input: unknown, ...rest: unknown[]) => {\n const toolCallId =\n isRecord(input) && typeof input.id === \"string\" ? input.id : \"\"\n const args = isRecord(input) && \"args\" in input ? input.args : input\n this.assertReplayToolResultExists(toolName, shouldMock)\n const execute = this.client.withSpan(\n this.traceFunctionKey,\n {\n name: toolName,\n type: \"function\",\n captureWhen: \"nested\",\n mockOnReplay: shouldMock,\n finalize: finalizeToolResult,\n surface: \"inherit\",\n },\n async (_args: unknown) => await originalInvoke(input, ...rest),\n )\n const result = await execute(args)\n return isEncodedToolResult(result)\n ? await reviveToolResult(result, toolCallId)\n : result\n }\n }\n\n const value = Reflect.get(target, property, target)\n return typeof value === \"function\" ? value.bind(target) : value\n },\n })\n }\n\n private assertReplayToolResultExists(\n toolName: string,\n shouldMock: boolean,\n ): void {\n const replayContext = getReplayContext()\n if (!replayContext?.mockTree) {\n return\n }\n\n const counterKey = `${this.traceFunctionKey}:${toolName}`\n const callIndex = replayContext.callCounters?.get(counterKey) ?? 0\n const mockSpan = replayContext.mockTree.spans.get(\n `${counterKey}:${callIndex}`,\n )\n const hasMatchingOverride = replayContext.mockOverrides?.some((override) =>\n override.match({\n traceFunctionKey: this.traceFunctionKey,\n spanName: toolName,\n type: \"function\",\n originalSpanId: mockSpan?.sourceSpanId,\n }),\n )\n const expectsRecordedOutput =\n replayContext.mockStrategy === \"all\" ||\n (replayContext.mockStrategy === \"marked\" && shouldMock)\n\n if (hasMatchingOverride !== true && expectsRecordedOutput && !mockSpan) {\n throw new BitfabError(\n `No recorded LangGraph tool result for \"${toolName}\" at call ${callIndex + 1}; refusing to execute the live tool during replay.`,\n \"https://docs.bitfab.ai/frameworks/langgraph\",\n )\n }\n }\n\n /** Wrap the function that invokes the compiled graph as the replay root. */\n wrapInvoke<TArgs extends unknown[], TReturn>(\n fn: (...args: TArgs) => TReturn,\n ): (...args: TArgs) => TReturn {\n return this.client.withSpan(\n this.traceFunctionKey,\n { name: this.traceFunctionKey, type: \"agent\", surface: \"inherit\" },\n fn,\n )\n }\n}\n","/**\n * OpenAI Agents SDK handler for Bitfab tracing.\n *\n * The OpenAI Agents SDK is instrumented in two layers:\n *\n * 1. A process-wide `TracingProcessor` (see `getOpenAiTracingProcessor` /\n * `BitfabOpenAITracingProcessor`) registered once with `addTraceProcessor`.\n * It captures everything *inside* a run - LLM calls, tool calls, handoffs -\n * as Bitfab spans.\n * 2. This handler's `wrapRun`, which owns the *root*. The processor never sees\n * the caller's input (the SDK's trace events don't carry it), so a\n * processor-only run records a root span with an empty input and is not\n * replayable. `wrapRun` is a thin drop-in for `run()` that opens a\n * `withSpan` root carrying the input and final output, so the run is\n * replayable with no hand-written `withSpan`. The processor's spans nest\n * underneath it automatically (it remaps onto the active span context).\n *\n * When `wrapRun` runs inside an enclosing Bitfab span (the replay auto-wrap, or\n * a caller's own `withSpan`), that span is already the replayable root: the\n * handler skips opening a second one and lets the processor nest the run's spans\n * under the existing root. This mirrors the Claude Agent SDK and LangGraph\n * handlers, which no-op their root span under an enclosing span, and keeps a\n * replayed run's span tree identical to the original (no doubled root agent\n * span).\n *\n * Use both together: register the processor once at startup, then call\n * `handler.wrapRun(agent, input)` instead of `run(agent, input)`.\n */\n\nimport { importOptionalPeer } from \"./optionalPeer.js\"\n\n// Local structural stand-ins for the OpenAI Agents SDK types this handler\n// touches. Declared here so neither this module nor the SDK's published `.d.ts`\n// references `@openai/agents` (an optional peer most consumers never install):\n// a top-level `import ... from \"@openai/agents\"` in the shipped types breaks a\n// consumer's `tsc` under `skipLibCheck: false` even when they never use this\n// handler. The stand-ins are deliberately loose supersets, so a consumer's real\n// `Agent` / run input is still assignable when they DO call `wrapRun`. The\n// concrete `@openai/agents` types enter only inside the function body (via\n// `importOptionalPeer<typeof import(\"@openai/agents\")>`), which the declaration\n// output erases.\n\n// biome-ignore lint/suspicious/noExplicitAny: structural stand-in for the agent SDK's `Agent<any, any>`\ntype AgentLike = any\n\n// The run input union `run()` accepts: a prompt string, a list of input items,\n// or a serialized run state. Items/state are opaque here (we only forward them).\ntype RunInput = string | unknown[] | Record<string, unknown>\n\n// The run options `run()` accepts; only `stream` is read by this handler.\ntype RunOptions = {\n stream?: boolean\n} & Record<string, unknown>\n\n// What this handler reads off a run result: streamed runs expose `completed`,\n// both variants expose `finalOutput`.\ntype RunResultLike = {\n finalOutput?: unknown\n completed?: Promise<void>\n}\n\n// The exact span options this handler passes to `withSpan`. Declared locally\n// (a structural subset of the client's `SpanOptions`, so the bound `withSpan`\n// is assignable) rather than imported from client.ts - that would create an\n// import cycle, since client.ts imports this handler. Mirrors how the other\n// framework handlers stay free of any client import.\ntype RootSpanOptions = {\n type: \"agent\"\n finalize: (result: unknown) => unknown | Promise<unknown>\n surface: \"inherit\"\n}\n\n// The subset of the Bitfab client this handler needs: a bound `withSpan`.\ntype WithSpanFn = <TArgs extends unknown[], TReturn>(\n traceFunctionKey: string,\n options: RootSpanOptions,\n fn: (...args: TArgs) => TReturn,\n) => (...args: TArgs) => TReturn\n\n// Returns the active Bitfab span context (or null) so wrapRun can detect an\n// enclosing span and skip opening its own root. Only nullness is read, so the\n// context shape is left opaque (avoids importing SpanContext from client.ts,\n// which would create an import cycle).\ntype GetActiveSpanContextFn = () => unknown | null\n\n/**\n * OpenAI Agents SDK handler that records a replayable root span around a run.\n *\n * ```typescript\n * import { Bitfab } from \"@bitfab/sdk\";\n * import { addTraceProcessor, Agent, run } from \"@openai/agents\";\n *\n * const bitfab = new Bitfab({ apiKey: \"...\" });\n * addTraceProcessor(bitfab.getOpenAiTracingProcessor()); // captures internals\n *\n * const agent = new Agent({ name: \"Researcher\", instructions: \"...\" });\n * const handler = bitfab.getOpenAiAgentHandler(\"research-topic\");\n *\n * // Swap run(agent, input) -> handler.wrapRun(agent, input)\n * const result = await handler.wrapRun(agent, \"Find X\");\n * return result.finalOutput;\n * ```\n */\nexport class BitfabOpenAIAgentHandler {\n private readonly traceFunctionKey: string\n private readonly withSpanFn: WithSpanFn\n private readonly getActiveSpanContext?: GetActiveSpanContextFn\n\n constructor(config: {\n traceFunctionKey: string\n withSpan: WithSpanFn\n getActiveSpanContext?: GetActiveSpanContextFn\n }) {\n this.traceFunctionKey = config.traceFunctionKey\n this.withSpanFn = config.withSpan\n this.getActiveSpanContext = config.getActiveSpanContext\n }\n\n /**\n * Drop-in replacement for the OpenAI Agents SDK's `run()` that records a\n * replayable root `agent` span.\n *\n * The `input` is captured as the root span's input (as a single positional\n * argument, so `replay(key, fn)` re-feeds it), and the run's `finalOutput`\n * is recorded as the root output. For streaming runs (`{ stream: true }`),\n * the result is handed back immediately and the final output is recorded\n * once the stream completes - first-byte latency is untouched.\n *\n * The process-wide tracing processor (`getOpenAiTracingProcessor`) must still\n * be registered: it captures the LLM/tool/handoff spans that nest beneath\n * this root.\n */\n async wrapRun(\n agent: AgentLike,\n input: RunInput,\n options?: RunOptions,\n ): Promise<RunResultLike> {\n // Dynamic import keeps `@openai/agents` an optional peer dependency and\n // matches the SDK's browser-safe import rules (no static Node/agent SDK\n // imports). Callers of this handler necessarily have the package installed.\n // Routed through `importOptionalPeer` so the specifier never appears as a\n // literal - otherwise a consumer's bundler tries to resolve `@openai/agents`\n // at build time and fails even when they never use this handler.\n const { run } = await importOptionalPeer<typeof import(\"@openai/agents\")>([\n \"@openai\",\n \"agents\",\n ])\n\n // The local stand-in types are looser than `run()`'s real parameters, so\n // cast at the call boundary. These casts live in the function body, which\n // the declaration output erases, so no `@openai/agents` reference leaks\n // into the published `.d.ts`.\n type RunInputArg = Parameters<typeof run>[1]\n type RunOptionsArg = Parameters<typeof run>[2]\n\n // An enclosing span is already the replayable root: run directly and let the\n // processor nest the run's spans under it, instead of opening (and doubling)\n // a second root agent span. Covers the replay auto-wrap and a caller's own\n // withSpan; mirrors the Claude Agent SDK and LangGraph handlers.\n if (this.getActiveSpanContext?.() != null) {\n return run(\n agent,\n input as RunInputArg,\n options as RunOptionsArg,\n ) as Promise<RunResultLike>\n }\n\n const isStreaming = options?.stream === true\n\n // The recorded output is the run's final answer, not the (non-serializable)\n // result object. `finalize` records it without disturbing the caller's\n // return value; for streaming it also waits for the stream to drain so the\n // final output is present before the span is recorded.\n const finalize = async (result: unknown): Promise<unknown> => {\n const res = result as RunResultLike | null\n if (isStreaming && res?.completed) {\n try {\n await res.completed\n } catch {\n // Stream errors surface to the caller; the span still records what\n // final output is available rather than crashing finalize.\n }\n }\n return res?.finalOutput\n }\n\n const options_: RootSpanOptions = {\n type: \"agent\",\n finalize,\n surface: \"inherit\",\n }\n\n // Wrap a function that TAKES the input as its argument and call it with the\n // input, so withSpan records `[input]` as the root span input. run() runs\n // inside the withSpan context, so the tracing processor's onTraceStart sees\n // this root and nests the run's internal spans beneath it.\n const traced = this.withSpanFn(\n this.traceFunctionKey,\n options_,\n (agentInput: RunInput) =>\n run(\n agent,\n agentInput as RunInputArg,\n options as RunOptionsArg,\n ) as Promise<RunResultLike>,\n )\n\n return traced(input)\n }\n}\n","/**\n * The database branch a single replay item runs against.\n *\n * `getCurrentReplayBranch()` hands you one inside a replayed function when the\n * source trace carried a DB snapshot reference and the Bitfab service resolved\n * a branch from it. Outside a replay item, or when no branch was resolved, that\n * accessor returns null and your code keeps reading `process.env.DATABASE_URL`\n * the normal way.\n *\n * Immutable and scoped to one item: the accessor builds it from the replay\n * AsyncLocalStorage context, so parallel replay items each see their own branch\n * and no lease state lives on a long-lived object.\n *\n * Internally the resolved per-item state is a `DbBranchLease` (see\n * replayContext.ts), the SDK/server protocol term. Its useful fields are\n * exposed directly here so customer code never sees the word.\n */\n\nimport type { DbBranchLease, ReplayContext } from \"./replayContext.js\"\n\nexport class ReplayBranch implements Omit<DbBranchLease, \"databaseUrl\"> {\n /** The provider's own id for this branch, e.g. for correlating with its console. */\n declare readonly neonBranchId: string\n /** Env var name the customer's app reads, e.g. `DATABASE_URL`. */\n declare readonly envKey: string\n /** When this branch's URL stops being valid. ISO-8601. */\n declare readonly expiresAt: string\n /**\n * The instant this branch is pinned to: the source trace's wall clock, read\n * just before the traced function ran. Compare it against the trace you meant\n * to replay to confirm the branch is the right point in history.\n */\n declare readonly snapshotTimestamp?: string\n /** Deep link to the branch in the provider console, if available. */\n declare readonly providerConsoleUrl?: string\n /**\n * True if the branch is read-only. Use it to skip write operations during\n * replay when the provider returned a read-only lease.\n */\n declare readonly readOnly?: boolean\n /**\n * The branch's region, e.g. `aws-us-east-1`. A compute runs in its project's\n * region, so a replay runner elsewhere pays that round trip on every query.\n */\n declare readonly region?: string\n /** The historical trace ID that produced the input for this replay item. */\n declare readonly traceId: string\n\n // Genuine JS private fields, not TypeScript `private`: these must be\n // non-enumerable so neither the connection string nor the whole replay\n // context can ride along into a log line or a serialized payload.\n readonly #url: string\n readonly #context: ReplayContext\n\n /** @internal Built by `getCurrentReplayBranch()`; never constructed by callers. */\n constructor(lease: DbBranchLease, traceId: string, context: ReplayContext) {\n // Copy the lease wholesale minus the connection string, so a field the\n // server starts sending reaches customer code without an SDK release.\n // Everything here must stay a plain data property: `databaseUrl` is the\n // only member allowed to mark the branch as accessed.\n //\n // defineProperty, not Object.assign: assignment runs setters, so a lease\n // carrying a `__proto__` key would swap this object's prototype and leave\n // `databaseUrl` returning undefined, which reads as \"no branch\" and sends\n // the replay to the live database.\n const { databaseUrl, ...exposed } = lease\n for (const [key, value] of Object.entries(exposed)) {\n Object.defineProperty(this, key, {\n value,\n enumerable: true,\n configurable: true,\n })\n }\n Object.defineProperty(this, \"traceId\", {\n value: traceId,\n enumerable: true,\n configurable: true,\n })\n this.#url = databaseUrl\n this.#context = context\n }\n\n /**\n * Connection string for this item's branch. Point your database client at it\n * instead of the live database for the duration of the replayed call.\n *\n * Reading it records on the trace that the replayed code obtained the branch\n * URL, which is what separates \"a branch was provisioned\" from \"the branch\n * was actually used\". The other fields inspect the lease without exposing the\n * connection string, so they deliberately do not record anything. That is\n * also why this is a getter and not a plain field: the URL is absent from\n * `JSON.stringify(branch)` and from logging the object.\n */\n get databaseUrl(): string {\n this.#context.dbSnapshotAccessed = true\n return this.#url\n }\n}\n","import {\n type AsyncLocalStorageLike,\n asyncStorageReady,\n createAsyncLocalStorage,\n} from \"./asyncStorage.js\"\n\nexport interface SeedContext {\n traceId: string\n}\n\nlet seedContextStorage: AsyncLocalStorageLike<SeedContext | null> | null = null\nconst SEED_CONTEXT_STORAGE_SYMBOL = Symbol.for(\"bitfab.seedContextStorage\")\n\nexport const seedContextReady: Promise<void> = asyncStorageReady.then(() => {\n const shared = globalThis as typeof globalThis & Record<symbol, unknown>\n const existing = shared[SEED_CONTEXT_STORAGE_SYMBOL] as\n | AsyncLocalStorageLike<SeedContext | null>\n | undefined\n if (existing) {\n seedContextStorage = existing\n return\n }\n const created = createAsyncLocalStorage<SeedContext | null>()\n if (created) {\n shared[SEED_CONTEXT_STORAGE_SYMBOL] = created\n seedContextStorage = created\n }\n})\n\nexport function getSeedContext(): SeedContext | null {\n return seedContextStorage?.getStore() ?? null\n}\n\nexport function inSeedScope(): boolean {\n return getSeedContext() !== null\n}\n\nexport function runWithSeedContext<T>(ctx: SeedContext, fn: () => T): T {\n if (seedContextStorage) {\n return seedContextStorage.run(ctx, fn)\n }\n return fn()\n}\n","/**\n * Tracing utilities for external trace submission to Bitfab.\n *\n * This module provides utilities for sending external traces (e.g., from OpenAI API calls)\n * to Bitfab for monitoring and analysis.\n */\n\nimport { DEFAULT_SERVICE_URL } from \"./constants.js\"\nimport { type ApiKeyInput, HttpClient } from \"./http.js\"\nimport { finalizeSpanPayload } from \"./processorPayload.js\"\nimport { randomUuid } from \"./randomUuid.js\"\n\n// Minimal structural shapes of the OpenAI Agents SDK's `Trace` and `Span`,\n// declared locally so neither this module nor the SDK's published `.d.ts`\n// references `@openai/agents` - an optional peer many consumers never install.\n// We only touch the fields below; the real SDK objects are structural\n// supersets, so a consumer's `addTraceProcessor(processor)` still type-checks.\ninterface Trace {\n traceId: string\n toJSON(): unknown\n}\n\n// biome-ignore lint/suspicious/noExplicitAny: mirrors the agent SDK's `Span<any>`\ninterface Span<_T = any> {\n traceId?: string\n toJSON(): unknown\n spanData?: {\n type?: string\n _input?: unknown\n _response?: unknown\n } | null\n}\n\nexport interface TraceResponse {\n traceId: string\n status: \"success\"\n}\n\nexport interface ActiveSpanContext {\n traceId: string\n spanId: string\n}\n\n/**\n * TracingProcessor interface from OpenAI Agents SDK v0.3.7\n */\nexport interface TracingProcessor {\n onTraceStart(trace: Trace): Promise<void>\n onTraceEnd(trace: Trace): Promise<void>\n // biome-ignore lint/suspicious/noExplicitAny: OpenAI Agents SDK uses any for span data\n onSpanStart(span: Span<any>): Promise<void>\n // biome-ignore lint/suspicious/noExplicitAny: OpenAI Agents SDK uses any for span data\n onSpanEnd(span: Span<any>): Promise<void>\n forceFlush(): Promise<void>\n shutdown(timeout?: number): Promise<void>\n}\n\n/**\n * Tracing processor for OpenAI Agents SDK integration.\n *\n * Implements the TracingProcessor interface from the OpenAI Agents SDK to\n * automatically capture traces and spans and send them to Bitfab for\n * monitoring and analysis.\n *\n * Example usage:\n * ```typescript\n * import { Bitfab } from 'bitfab';\n * import { addTraceProcessor } from '@openai/agents';\n *\n * const client = new Bitfab({ apiKey: 'your-api-key' });\n * const processor = client.getOpenAiTracingProcessor();\n * addTraceProcessor(processor);\n * ```\n */\nexport class BitfabOpenAITracingProcessor implements TracingProcessor {\n private readonly httpClient: HttpClient\n private readonly ownsHttpClient: boolean\n private activeTraces: Record<string, Trace> = {}\n private readonly getActiveSpanContext: (() => ActiveSpanContext | null) | null\n private activeSpanMappings: Record<string, ActiveSpanContext> = {}\n private canonicalTraceIds: Record<string, string> = {}\n\n private getCanonicalTraceId(sourceTraceId: string): string {\n const existing = this.canonicalTraceIds[sourceTraceId]\n if (existing) {\n return existing\n }\n\n const created = randomUuid()\n this.canonicalTraceIds[sourceTraceId] = created\n return created\n }\n\n /**\n * Initialize the tracing processor.\n *\n * @param config - Configuration options\n */\n constructor(config: {\n apiKey?: ApiKeyInput\n serviceUrl?: string\n timeout?: number\n getActiveSpanContext?: () => ActiveSpanContext | null\n /**\n * The owning `Bitfab` client's HTTP client. Supplied by\n * `getOpenAiTracingProcessor()` so this processor shares that client's\n * single span-transport worker instead of starting a second one.\n * @internal\n */\n _httpClient?: HttpClient\n }) {\n this.ownsHttpClient = config._httpClient === undefined\n this.httpClient =\n config._httpClient ??\n new HttpClient({\n apiKey: config.apiKey,\n serviceUrl: config.serviceUrl ?? DEFAULT_SERVICE_URL,\n timeout: config.timeout ?? 10000,\n })\n this.getActiveSpanContext = config.getActiveSpanContext ?? null\n }\n\n /**\n * Flush and release the span transport this processor started. A no-op when\n * the processor borrowed a `Bitfab` client's HTTP client: that client's\n * `close()` owns the worker's lifetime.\n */\n async close(timeoutMs?: number): Promise<boolean> {\n return this.ownsHttpClient ? this.httpClient.close(timeoutMs) : true\n }\n\n /**\n * Called when a trace is started.\n * If there's an active withSpan context, the trace ID is remapped to the\n * outer trace and sent to pre-create the external_traces row on the server.\n */\n async onTraceStart(trace: Trace): Promise<void> {\n this.activeTraces[trace.traceId] = trace\n\n const activeContext = this.getActiveSpanContext?.()\n if (activeContext) {\n this.activeSpanMappings[trace.traceId] = activeContext\n }\n\n const canonicalTraceId =\n activeContext?.traceId ?? this.getCanonicalTraceId(trace.traceId)\n this.canonicalTraceIds[trace.traceId] = canonicalTraceId\n\n this.sendTrace(trace, {\n id: canonicalTraceId,\n sourceTraceId: activeContext?.traceId,\n })\n }\n\n /**\n * Called when a trace is ended.\n * If mapped to a withSpan trace, sends with remapped ID and completed=false\n * since the parent withSpan handles completion.\n */\n async onTraceEnd(trace: Trace): Promise<void> {\n const mapping = this.activeSpanMappings[trace.traceId]\n\n this.sendTrace(trace, {\n completed: mapping === undefined,\n id: mapping?.traceId ?? this.getCanonicalTraceId(trace.traceId),\n sourceTraceId: mapping?.traceId,\n })\n\n delete this.activeSpanMappings[trace.traceId]\n delete this.canonicalTraceIds[trace.traceId]\n delete this.activeTraces[trace.traceId]\n }\n\n /**\n * Called when a span is started. Span payloads are authoritative completed\n * snapshots, so start notifications do not cross the transport boundary.\n */\n // biome-ignore lint/suspicious/noExplicitAny: OpenAI Agents SDK uses any for span data\n async onSpanStart(_span: Span<any>): Promise<void> {}\n\n /**\n * Called when a span is ended.\n *\n * Send the finalized span snapshot to Bitfab for complete trace capture.\n */\n // biome-ignore lint/suspicious/noExplicitAny: OpenAI Agents SDK uses any for span data\n async onSpanEnd(span: Span<any>): Promise<void> {\n // Send the completed span to Bitfab (fire-and-forget).\n this.sendSpan(span)\n }\n\n /**\n * Called when a trace is being flushed.\n */\n async forceFlush(): Promise<void> {\n // Spans now enter a buffered transport, so this is no longer a no-op: the\n // agent SDK's own flush would otherwise return while Bitfab spans sit\n // queued, and a run that flushes then exits would lose them.\n await this.httpClient.waitForPendingRequests()\n }\n\n /**\n * Called when the trace processor is shutting down.\n */\n async shutdown(timeout?: number): Promise<void> {\n this.activeTraces = {}\n this.activeSpanMappings = {}\n this.canonicalTraceIds = {}\n // A directly constructed processor owns its transport worker and no\n // Bitfab client will ever close it, so this is its only release point.\n // A borrowed client's worker is left alone (see close()).\n await this.close(timeout)\n }\n\n /**\n * Send trace to Bitfab API (fire-and-forget).\n * When traceIdOverride is provided, the trace ID is remapped to link\n * the OpenAI trace into an outer withSpan trace.\n */\n private sendTrace(\n trace: Trace,\n options: {\n completed?: boolean\n id?: string\n sourceTraceId?: string\n } = {},\n ): void {\n try {\n const traceData = trace.toJSON() as Record<string, unknown>\n if (options.sourceTraceId) {\n traceData.id = options.sourceTraceId\n }\n\n this.httpClient.sendExternalTrace({\n ...(options.id && { id: options.id }),\n type: \"openai\",\n source: \"typescript-sdk-openai-tracing\",\n externalTrace: traceData,\n completed: options.completed ?? false,\n })\n } catch {\n // Silently ignore - never crash the host app\n }\n }\n\n /**\n * Export span to JSON object, collecting any errors.\n */\n private exportSpan(\n // biome-ignore lint/suspicious/noExplicitAny: OpenAI Agents SDK uses any for span data\n span: Span<any>,\n ): [\n Record<string, unknown>,\n Array<{ source: string; step: string; error: string }>,\n ] {\n const errors: Array<{ source: string; step: string; error: string }> = []\n let serializedSpan: Record<string, unknown>\n\n try {\n const jsonResult = span.toJSON()\n if (typeof jsonResult !== \"object\" || jsonResult === null) {\n errors.push({\n source: \"sdk\",\n step: \"span.toJSON()\",\n error: `Returned unexpected type: ${typeof jsonResult}`,\n })\n serializedSpan = {}\n } else {\n serializedSpan = jsonResult as Record<string, unknown>\n }\n } catch (error) {\n errors.push({\n source: \"sdk\",\n step: \"span.toJSON()\",\n error: error instanceof Error ? error.message : String(error),\n })\n serializedSpan = {}\n }\n\n if (!serializedSpan.span_data) {\n serializedSpan.span_data = {} as Record<string, unknown>\n }\n\n return [serializedSpan, errors]\n }\n\n /**\n * Extract and add input/response to serialized span, updating errors list.\n */\n private extractSpanInputResponse(\n // biome-ignore lint/suspicious/noExplicitAny: OpenAI Agents SDK uses any for span data\n span: Span<any>,\n serializedSpan: Record<string, unknown>,\n errors: Array<{ source: string; step: string; error: string }>,\n ): void {\n // Only ResponseSpanData hides its content from toJSON(): the SDK's\n // removePrivateFields strips its _input/_response, so we recover them here.\n // Every other span type (function, generation, agent, custom, ...) already\n // carries its data in span_data, so writing here would clobber a real input\n // with an empty placeholder. Gate strictly to response spans, and only set a\n // field when the value is actually present (never stamp []/null).\n if (span.spanData?.type !== \"response\") {\n return\n }\n\n const spanData = serializedSpan.span_data as Record<string, unknown>\n\n try {\n const input = span.spanData?._input\n if (input !== undefined) {\n spanData.input = input\n }\n } catch (error) {\n errors.push({\n source: \"sdk\",\n step: \"access_input\",\n error: error instanceof Error ? error.message : String(error),\n })\n }\n\n try {\n const response = span.spanData?._response\n if (response !== undefined) {\n spanData.response = response\n }\n } catch (error) {\n errors.push({\n source: \"sdk\",\n step: \"access_response\",\n error: error instanceof Error ? error.message : String(error),\n })\n }\n }\n\n /**\n * If the span's trace is mapped to a withSpan trace, rewrite trace_id and parent_id.\n */\n private applySpanOverrides(\n serializedSpan: Record<string, unknown>,\n traceId: string,\n ): void {\n const mapping = this.activeSpanMappings[traceId]\n if (mapping) {\n serializedSpan.trace_id = mapping.traceId\n if (!serializedSpan.parent_id) {\n serializedSpan.parent_id = mapping.spanId\n }\n }\n }\n\n /**\n * Build span payload for the external spans API.\n */\n private buildSpanPayload(\n serializedSpan: Record<string, unknown>,\n errors: Array<{ source: string; step: string; error: string }>,\n ): Record<string, unknown> {\n const payload: Record<string, unknown> = {\n id: randomUuid(),\n type: \"openai\",\n source: \"typescript-sdk-openai-tracing\",\n sourceTraceId: serializedSpan.trace_id ?? \"unknown\",\n rawSpan: serializedSpan,\n }\n\n if (errors.length > 0) {\n payload.errors = errors\n }\n\n // Sanitize the whole span (the raw OpenAI span_data is otherwise shipped\n // unsanitized, relying only on the http-layer net) and mark a lossy capture\n // non-replayable, merging with the SDK-level errors collected above.\n return finalizeSpanPayload(payload)\n }\n\n /**\n * Send span to Bitfab API (fire-and-forget).\n * If the span belongs to a trace mapped to a withSpan trace, the trace_id\n * and parent_id are rewritten to link the span into the withSpan tree.\n */\n private sendSpan(\n // biome-ignore lint/suspicious/noExplicitAny: OpenAI Agents SDK uses any for span data\n span: Span<any>,\n ): void {\n const errors: Array<{ source: string; step: string; error: string }> = []\n const [serializedSpan, exportErrors] = this.exportSpan(span)\n errors.push(...exportErrors)\n\n this.extractSpanInputResponse(span, serializedSpan, errors)\n\n this.applySpanOverrides(serializedSpan, span.traceId ?? \"\")\n\n const payload = this.buildSpanPayload(serializedSpan, errors)\n const canonicalTraceId = span.traceId\n ? this.getCanonicalTraceId(span.traceId)\n : undefined\n if (canonicalTraceId) {\n payload.traceId = canonicalTraceId\n }\n\n this.httpClient.sendExternalSpan(payload)\n }\n}\n","/**\n * Vercel AI SDK integration for Bitfab tracing.\n *\n * The Vercel AI SDK (`ai`) routes every `generateText` / `streamText` /\n * `generateObject` / `streamObject` call through a language model. Bitfab hooks\n * that model with a *language-model middleware* (`wrapLanguageModel`), so each\n * model call is captured as a keyed `llm` span with no hand-written `withSpan`:\n *\n * ```typescript\n * import { Bitfab } from \"@bitfab/sdk\";\n * import { wrapLanguageModel, streamText } from \"ai\";\n * import { openai } from \"@ai-sdk/openai\";\n *\n * const bitfab = new Bitfab({ apiKey: \"...\" });\n *\n * const model = wrapLanguageModel({\n * model: openai(\"gpt-4o\"),\n * middleware: bitfab.getVercelAiMiddleware(\"chat-turn\"),\n * });\n *\n * const result = streamText({ model, messages });\n * return result.toUIMessageStreamResponse(); // live stream untouched\n * ```\n *\n * The span records the call parameters (the prompt/messages) as its input and a\n * serializable summary (`{ text, toolCalls, usage, finishReason }`) as its\n * output. Streaming is handled by passing the model's stream through a\n * transform that accumulates the assembled text/usage as the caller consumes\n * it: the live stream is handed back unchanged (first-byte latency untouched)\n * and the span is finalized once the stream completes.\n *\n * The middleware is fully duck-typed (no static or dynamic `ai` import), so it\n * adds no dependency and is browser-safe. It works with `ai` v5 and v6.\n */\n\n// The exact span options this middleware passes to `withSpan`. Declared locally\n// (a structural subset of the client's `SpanOptions`, so the bound `withSpan`\n// is assignable) rather than imported from client.ts - that would create an\n// import cycle, since client.ts imports this handler. Mirrors how the other\n// framework handlers stay free of any client import.\ntype LlmSpanOptions = {\n type: \"llm\"\n finalize: (result: unknown) => unknown | Promise<unknown>\n surface: \"inherit\"\n}\n\n// The subset of the Bitfab client this middleware needs: a bound `withSpan`.\ntype WithSpanFn = <TArgs extends unknown[], TReturn>(\n traceFunctionKey: string,\n options: LlmSpanOptions,\n fn: (...args: TArgs) => TReturn,\n) => (...args: TArgs) => TReturn\n\n/**\n * Duck-typed subset of the Vercel AI SDK language-model call parameters. The\n * only field we read for the span input is `prompt` (the messages), but the\n * whole object is recorded so the call is reconstructable on replay.\n */\nexport interface VercelCallParams {\n prompt?: unknown\n [key: string]: unknown\n}\n\n/** A content part of a non-streaming `doGenerate` result. */\ninterface VercelContentPart {\n type: string\n text?: string\n toolCallId?: string\n toolName?: string\n // v3 names tool arguments `input`; v5/v2 used `args`.\n input?: unknown\n args?: unknown\n}\n\n/** Duck-typed subset of a non-streaming `doGenerate` result. */\nexport interface VercelGenerateResult {\n content?: VercelContentPart[]\n // Some providers expose a flattened `text`; prefer it when present.\n text?: string\n usage?: unknown\n finishReason?: unknown\n [key: string]: unknown\n}\n\n/** Duck-typed subset of a single streaming part from `doStream`. */\ninterface VercelStreamPart {\n type: string\n // v3 text-delta carries `delta`; v2 carried `textDelta`.\n delta?: string\n textDelta?: string\n toolCallId?: string\n toolName?: string\n input?: unknown\n args?: unknown\n usage?: unknown\n finishReason?: unknown\n}\n\n/** Duck-typed subset of a streaming `doStream` result. */\nexport interface VercelStreamResult {\n stream: ReadableStream<VercelStreamPart>\n [key: string]: unknown\n}\n\ninterface MiddlewareCall<TResult> {\n doGenerate: () => PromiseLike<VercelGenerateResult>\n doStream: () => PromiseLike<VercelStreamResult>\n params: VercelCallParams\n model: unknown\n __result?: TResult\n}\n\n/**\n * The structural shape of a Vercel AI SDK language-model middleware. Matches\n * `LanguageModelV3Middleware` from `@ai-sdk/provider` without importing it, so\n * the SDK stays dependency-free. `wrapLanguageModel` only reads the method\n * fields (it ignores `specificationVersion`), so this object drops straight in.\n */\nexport interface BitfabLanguageModelMiddleware {\n specificationVersion: \"v3\"\n // The wrap methods hand the provider's own result straight back (only the\n // span output is derived from it), so the return is typed `any` to stay\n // assignable to `LanguageModelV{2,3}Middleware` across AI SDK majors - the\n // SDK's strict result types (which require `warnings`, `content`, etc.) are a\n // superset of the duck-typed subset declared here. Implementation returns the\n // precise `VercelGenerateResult` / `VercelStreamResult` shapes.\n wrapGenerate: (\n options: MiddlewareCall<VercelGenerateResult>,\n // biome-ignore lint/suspicious/noExplicitAny: passthrough of the provider result; see note above\n ) => Promise<any>\n wrapStream: (\n options: MiddlewareCall<VercelStreamResult>,\n // biome-ignore lint/suspicious/noExplicitAny: passthrough of the provider result; see note above\n ) => Promise<any>\n}\n\n/** The provider/model that served a call (e.g. `{ provider, modelId }`). */\ntype ModelLabel = { provider?: string; modelId?: string }\n\n/** The serializable summary recorded as a model call's span output. */\ntype CallSummary = {\n text: string\n toolCalls?: unknown[]\n usage?: unknown\n finishReason?: unknown\n // Which provider/model actually served this call. Invaluable when a single\n // wrapped key spans multiple providers (e.g. a Claude-primary, GPT-4o-fallback\n // setup) so each span shows who answered.\n model?: ModelLabel\n}\n\n/** Read `{ provider, modelId }` off an AI SDK language model, defensively. */\nfunction modelLabel(model: unknown): ModelLabel | undefined {\n if (!model || typeof model !== \"object\") {\n return undefined\n }\n const m = model as { provider?: unknown; modelId?: unknown }\n const provider = typeof m.provider === \"string\" ? m.provider : undefined\n const modelId = typeof m.modelId === \"string\" ? m.modelId : undefined\n if (provider == null && modelId == null) {\n return undefined\n }\n return { provider, modelId }\n}\n\n/** Collapse a non-streaming generate result into a serializable span output. */\nfunction summarizeGenerate(\n result: VercelGenerateResult,\n model: ModelLabel | undefined,\n): CallSummary {\n const content = Array.isArray(result.content) ? result.content : []\n const text =\n typeof result.text === \"string\"\n ? result.text\n : content\n .filter((p) => p.type === \"text\" && typeof p.text === \"string\")\n .map((p) => p.text)\n .join(\"\")\n const toolCalls = content\n .filter((p) => p.type === \"tool-call\")\n .map((p) => ({\n toolCallId: p.toolCallId,\n toolName: p.toolName,\n input: p.input ?? p.args,\n }))\n const summary: CallSummary = {\n text,\n toolCalls: toolCalls.length > 0 ? toolCalls : undefined,\n usage: result.usage,\n finishReason: result.finishReason,\n }\n if (model) {\n summary.model = model\n }\n return summary\n}\n\n/**\n * A pass-through transform that accumulates the assembled text, tool calls, and\n * final usage from a model's stream, resolving `onComplete` with that summary\n * once the stream finishes. Parts are enqueued unchanged so the caller's stream\n * is untouched; capture errors are swallowed so tracing never breaks the stream.\n */\nfunction accumulateStream(\n onComplete: (summary: CallSummary) => void,\n model: ModelLabel | undefined,\n): TransformStream<VercelStreamPart, VercelStreamPart> {\n let text = \"\"\n const toolCalls: unknown[] = []\n let usage: unknown\n let finishReason: unknown\n let completed = false\n const complete = (): void => {\n if (completed) {\n return\n }\n completed = true\n const summary: CallSummary = {\n text,\n toolCalls: toolCalls.length > 0 ? toolCalls : undefined,\n usage,\n finishReason,\n }\n if (model) {\n summary.model = model\n }\n onComplete(summary)\n }\n return new TransformStream<VercelStreamPart, VercelStreamPart>({\n transform(part, controller) {\n try {\n if (part?.type === \"text-delta\") {\n text += part.delta ?? part.textDelta ?? \"\"\n } else if (part?.type === \"tool-call\") {\n toolCalls.push({\n toolCallId: part.toolCallId,\n toolName: part.toolName,\n input: part.input ?? part.args,\n })\n } else if (part?.type === \"finish\") {\n usage = part.usage\n finishReason = part.finishReason\n // The `finish` part is the stream's last meaningful event; resolve\n // the span output as soon as it passes rather than waiting for the\n // reader to close the stream.\n complete()\n }\n } catch {\n // Never let span capture break the caller's stream.\n }\n controller.enqueue(part)\n },\n flush() {\n // Fallback when a provider omits an explicit `finish` part.\n complete()\n },\n })\n}\n\n/**\n * Vercel AI SDK middleware that records each language-model call as a keyed\n * `llm` span. Obtain it from {@link BitfabClient.getVercelAiMiddleware} rather\n * than constructing it directly.\n */\nexport class BitfabVercelAiHandler {\n private readonly traceFunctionKey: string\n private readonly withSpanFn: WithSpanFn\n\n constructor(config: { traceFunctionKey: string; withSpan: WithSpanFn }) {\n this.traceFunctionKey = config.traceFunctionKey\n this.withSpanFn = config.withSpan\n }\n\n /** The `wrapLanguageModel` middleware object for this trace function key. */\n get middleware(): BitfabLanguageModelMiddleware {\n const key = this.traceFunctionKey\n const withSpan = this.withSpanFn\n return {\n specificationVersion: \"v3\",\n wrapGenerate: async ({ doGenerate, params, model }) => {\n const label = modelLabel(model)\n // Wrap a function that TAKES the call params as its argument and call it\n // with them, so withSpan records `[params]` (the prompt/settings) as the\n // span input. `finalize` records the serializable summary as the output\n // while the raw result is returned to the AI SDK unchanged.\n const traced = withSpan<\n [VercelCallParams],\n Promise<VercelGenerateResult>\n >(\n key,\n {\n type: \"llm\",\n finalize: (result) =>\n summarizeGenerate((result ?? {}) as VercelGenerateResult, label),\n surface: \"inherit\",\n },\n () => doGenerate() as Promise<VercelGenerateResult>,\n )\n return traced(params)\n },\n wrapStream: async ({ doStream, params, model }) => {\n const label = modelLabel(model)\n let resolveSummary: (summary: CallSummary) => void = () => {}\n const summary = new Promise<CallSummary>((resolve) => {\n resolveSummary = resolve\n })\n const traced = withSpan<\n [VercelCallParams],\n Promise<VercelStreamResult>\n >(\n key,\n // The wrapped fn returns immediately with the live stream, so the span\n // output cannot be read from the return value. `finalize` instead\n // awaits the summary the accumulator resolves once the stream drains.\n { type: \"llm\", finalize: () => summary, surface: \"inherit\" },\n async () => {\n const result = await doStream()\n const stream = result.stream.pipeThrough(\n accumulateStream(resolveSummary, label),\n )\n return { ...result, stream }\n },\n )\n return traced(params)\n },\n }\n }\n}\n","/**\n * Bitfab client for provider-based API calls.\n */\n\nexport type {\n AllowedEnvVars,\n BamlExecutionResult,\n ProviderDefinition,\n} from \"./baml.js\"\nexport { BitfabClaudeAgentHandler } from \"./claudeAgentSdk.js\"\nexport type {\n BitfabConfig,\n CaptureSurface,\n CaptureWhen,\n CurrentSpan,\n CurrentTrace,\n DetachedTrace,\n NodeMethodDecorator,\n NodeOptions,\n SeedCaseOptions,\n SeedRunOptions,\n SpanMethodDecorator,\n SpanMethodDecoratorContext,\n SpanOptions,\n SpanType,\n WrapBAMLOptions,\n WrappedBamlFn,\n} from \"./client.js\"\nexport {\n Bitfab,\n BitfabError,\n BitfabFunction,\n getCurrentReplayBranch,\n getCurrentSpan,\n getCurrentTrace,\n MixedTracingError,\n} from \"./client.js\"\nexport { __version__, DEFAULT_SERVICE_URL } from \"./constants.js\"\nexport type {\n AddDatasetGradersResult,\n AddDatasetTracesResult,\n Dataset,\n DatasetGraderRef,\n DatasetTraceIds,\n GraderRerun,\n GraderRerunProgress,\n GraderRerunResult,\n GraderRerunStatus,\n ListDatasetsParams,\n RemoveDatasetGradersResult,\n RemoveDatasetTracesResult,\n RerunGradersOptions,\n RerunGradersResult,\n SaveDatasetParams,\n SaveDatasetResult,\n} from \"./datasets.js\"\nexport { DatasetsClient } from \"./datasets.js\"\nexport type {\n DbSnapshotConfig,\n DbSnapshotProvider,\n DbSnapshotRef,\n} from \"./dbSnapshot.js\"\nexport { SUPPORTED_PROVIDERS } from \"./dbSnapshot.js\"\nexport { finalizers } from \"./finalizers.js\"\nexport type {\n CapturedSpan,\n SpanLookup,\n SpanOccurrence,\n} from \"./http.js\"\nexport { flushTraces, HttpClient } from \"./http.js\"\nexport {\n BitfabLangGraphCallbackHandler,\n BitfabLangGraphCallbackHandler as BitfabLangChainCallbackHandler,\n} from \"./langgraph.js\"\nexport {\n BitfabLangGraphIntegration,\n type LangGraphIntegrationOptions,\n} from \"./langgraphIntegration.js\"\nexport type {\n MockOverride,\n MockOverrideCtx,\n MockOverrideInput,\n MockOverrideResolver,\n MockValue,\n NodeMatcher,\n SpanNodeMeta,\n} from \"./mockOverride.js\"\nexport { NO_MOCK_OVERRIDE } from \"./mockOverride.js\"\nexport { BitfabOpenAIAgentHandler } from \"./openaiAgentSdk.js\"\nexport type {\n AdaptContext,\n AdaptInputsFn,\n CodeChangeFile,\n DbBranchOptions,\n MockStrategy,\n ReplayItem,\n ReplayItemFinishProgress,\n ReplayItemStartProgress,\n ReplayOptions,\n ReplayProgress,\n ReplayProgressItem,\n ReplayResult,\n TokenUsage,\n TraceIngestionType,\n} from \"./replay.js\"\nexport {\n BITFAB_PROGRESS_PREFIX,\n DbBranchReplayError,\n ReplayError,\n reportReplayProgress,\n serializeReplayResult,\n} from \"./replay.js\"\nexport type { ReplayBranch } from \"./replayBranch.js\"\nexport type { DbBranchTimings } from \"./replayContext.js\"\nexport type {\n ReplayOptionsFactory,\n ReplayRegistration,\n ReplayRegistry,\n ReplayRegistryContext,\n ReplayRegistryOptions,\n SeedCase,\n SeedResult,\n} from \"./replayRegistry.js\"\nexport {\n defineReplayRegistry,\n seedFromRegistry,\n} from \"./replayRegistry.js\"\nexport type {\n ActiveSpanContext,\n TraceResponse,\n TracingProcessor,\n} from \"./tracing.js\"\nexport { BitfabOpenAITracingProcessor } from \"./tracing.js\"\nexport type {\n BitfabLanguageModelMiddleware,\n VercelCallParams,\n VercelGenerateResult,\n VercelStreamResult,\n} from \"./vercelAiSdk.js\"\nexport { BitfabVercelAiHandler } from \"./vercelAiSdk.js\"\n","/**\n * Prebuilt `finalize` helpers for `withSpan({ finalize }, fn)`.\n *\n * A streaming function returns a live stream object that the caller consumes\n * directly (SSE, a UI message stream). `withSpan` hands that object back\n * unchanged; a `finalize` function tells it what serializable view to record\n * as the span output instead of the raw, non-serializable stream.\n */\n\n/**\n * Duck-typed subset of the Vercel AI SDK `streamText` / `streamObject`\n * result. Each field is exposed as a promise that resolves once the stream\n * finishes; reading them does not consume the live stream (the AI SDK tees\n * internally), so the caller's own consumption is unaffected. We avoid a\n * hard dependency on `ai` by matching structurally.\n */\ninterface AiSdkStreamResultLike {\n text?: Promise<string> | string\n usage?: Promise<unknown> | unknown\n totalUsage?: Promise<unknown> | unknown\n finishReason?: Promise<unknown> | unknown\n toolCalls?: Promise<unknown> | unknown\n toolResults?: Promise<unknown> | unknown\n reasoningText?: Promise<string> | string\n}\n\n/** Await a value that may be a promise, swallowing rejection to `undefined`. */\nasync function settle<T>(\n value: Promise<T> | T | undefined,\n): Promise<T | undefined> {\n try {\n return await value\n } catch {\n return undefined\n }\n}\n\n/**\n * Drain a Vercel AI SDK streaming result into a serializable, replayable\n * span output: `{ text, usage, finishReason, toolCalls, toolResults }`.\n *\n * Pass it straight to `withSpan`:\n *\n * ```ts\n * import { finalizers } from \"@bitfab/sdk\"\n *\n * const traced = bitfab.withSpan(\n * \"chat-turn\",\n * { type: \"agent\", finalize: finalizers.aiSdk },\n * () => streamText({ model, messages }),\n * )\n * const result = traced() // caller still gets the live StreamTextResult\n * return result.toUIMessageStreamResponse()\n * ```\n *\n * Never throws: any field that is absent or rejects is recorded as\n * `undefined` so finalize never drops the span.\n */\nasync function aiSdk(result: unknown): Promise<Record<string, unknown>> {\n const r = (result ?? {}) as AiSdkStreamResultLike\n const [text, usage, totalUsage, finishReason, toolCalls, toolResults] =\n await Promise.all([\n settle(r.text),\n settle(r.usage),\n settle(r.totalUsage),\n settle(r.finishReason),\n settle(r.toolCalls),\n settle(r.toolResults),\n ])\n return {\n text,\n usage: totalUsage ?? usage,\n finishReason,\n toolCalls,\n toolResults,\n }\n}\n\n/**\n * Collect a `ReadableStream`'s chunks into an array for the span output,\n * via a `tee()` so the caller's branch is untouched. The caller MUST use\n * the returned stream, not the original, since a stream can only be read\n * once:\n *\n * ```ts\n * let live: ReadableStream\n * const traced = bitfab.withSpan(\n * \"render\",\n * { finalize: (r) => finalizers.readableStream(r, (s) => { live = s }) },\n * () => makeReadableStream(),\n * )\n * traced()\n * return new Response(live!)\n * ```\n *\n * Prefer `aiSdk` for the Vercel AI SDK, whose result tees internally and\n * needs no caller rewiring.\n */\nasync function readableStream(\n stream: ReadableStream,\n onLive: (live: ReadableStream) => void,\n): Promise<{ chunks: unknown[] }> {\n const [live, copy] = stream.tee()\n onLive(live)\n const chunks: unknown[] = []\n const reader = copy.getReader()\n try {\n for (;;) {\n const { done, value } = await reader.read()\n if (done) {\n break\n }\n chunks.push(value)\n }\n } catch {\n // Never let span capture crash the host app.\n }\n return { chunks }\n}\n\nexport const finalizers = {\n aiSdk,\n readableStream,\n}\n","import type { Bitfab } from \"./client.js\"\nimport { BitfabError } from \"./errors.js\"\nimport {\n type CodeChangeFile,\n ReplayError,\n type ReplayItem,\n type ReplayOptions,\n type ReplayResult,\n reportReplayProgress,\n serializeReplayResult,\n} from \"./replay.js\"\n\ntype ReplayFunction = (\n // biome-ignore lint/suspicious/noExplicitAny: replay functions receive historical arguments\n ...args: any[]\n) => unknown | Promise<unknown>\n\nexport type ReplayRegistryOptions = Omit<\n ReplayOptions,\n \"onItemStart\" | \"onItemFinish\" | \"onProgress\"\n>\n\nexport interface ReplayRegistryContext {\n /** Values supplied through `--params` and repeated `--param name=value`. */\n params: Readonly<Record<string, unknown>>\n}\n\nexport type ReplayOptionsFactory = (\n context: ReplayRegistryContext,\n) => ReplayRegistryOptions | Promise<ReplayRegistryOptions>\n\nexport interface ReplayRegistration {\n /** Client instance used by the production traced function. */\n client: Bitfab\n /** The exact traced function production calls. */\n fn: ReplayFunction\n /**\n * Required for handler-instrumented or otherwise plain callables. Omit for a\n * `withSpan`-wrapped function and the registry reads the wrapper's key.\n */\n traceFunctionKey?: string\n /**\n * Per-function replay behavior and defaults. Put executable configuration\n * such as `mockOverride` and `adaptInputs` here; command-line values override\n * overlapping scalar defaults such as `mock` and `maxConcurrency`.\n */\n options?: ReplayRegistryOptions\n /** Build executable replay behavior from caller-supplied CLI parameters. */\n optionsFactory?: ReplayOptionsFactory\n}\n\nexport type ReplayRegistry = Record<string, ReplayRegistration>\n\n/**\n * Define the project-owned list of replayable functions.\n *\n * The registry is deliberately data-only: the SDK owns the replay CLI, so an\n * SDK upgrade can add replay features without regenerating the project file.\n */\nexport function defineReplayRegistry<TRegistry extends ReplayRegistry>(\n registry: TRegistry,\n): TRegistry {\n return registry\n}\n\nexport interface ReplayCliIo {\n stdout?: (line: string) => void\n stderr?: (line: string) => void\n readFile?: (path: string) => Promise<string>\n}\n\ninterface ReplayCliArgs {\n pipeline: string\n limit?: number\n attempts?: number\n traceIds?: string[]\n name?: string\n maxConcurrency?: number\n codeChangePath?: string\n experimentGroupId?: string\n datasetId?: string\n graderIds?: string[]\n mock?: \"none\" | \"all\" | \"marked\"\n dbBranch?: boolean\n noCodeChange?: boolean\n dryRun?: boolean\n paramsPath?: string\n params: string[]\n}\n\ninterface CodeChange {\n description: string\n files: CodeChangeFile[]\n}\n\nconst VALUE_FLAGS = new Set([\n \"--limit\",\n \"--attempts\",\n \"--trace-ids\",\n \"--name\",\n \"--concurrency\",\n \"--max-concurrency\",\n \"--code-change\",\n \"--experiment-group-id\",\n \"--dataset-id\",\n \"--grader-ids\",\n \"--mock\",\n \"--param\",\n \"--params\",\n])\n\nconst BOOLEAN_FLAGS = new Set([\n \"--db-branch\",\n \"--no-db-branch\",\n \"--no-code-change\",\n \"--dry-run\",\n])\n\nconst HELP_FLAGS = new Set([\"--help\", \"-h\"])\n\nconst MAX_ATTEMPTS = 100\n\nfunction usage(registry: ReplayRegistry): string {\n return `Usage: bitfab-replay --registry <path> <${Object.keys(registry).join(\"|\")}> [options]\\n\\nOptions:\\n --limit N\\n --attempts N (replay each trace N times in this run, max ${MAX_ATTEMPTS})\\n --trace-ids id1,id2\\n --name NAME\\n --concurrency N, --max-concurrency N\\n --code-change PATH, --no-code-change\\n --experiment-group-id UUID\\n --dataset-id UUID\\n --grader-ids id1,id2\\n --mock none|all|marked\\n --db-branch, --no-db-branch\\n --dry-run (resolve inputs, run nothing)\\n --params PATH\\n --param name=value (repeatable)\\n -h, --help`\n}\n\nexport class ReplayCliHelp extends Error {}\n\n/** One case to seed, in the shape `--seed` reads from JSON or JSONL. */\nexport interface SeedCase {\n /** Arguments spread into the registered function at replay. */\n input: unknown[]\n /** The output this case should produce. */\n expected?: unknown\n /** Recorded on the trace, for tracing a seeded case back to its source row. */\n metadata?: Record<string, unknown>\n sessionId?: string\n}\n\nexport interface SeedResult {\n pipeline: string\n traceFunctionKey: string\n traceIds: string[]\n}\n\nfunction parseSeedCases(raw: string, path: string, run: boolean): SeedCase[] {\n const trimmed = raw.trim()\n if (trimmed.length === 0) {\n throw new BitfabError(`Seed file '${path}' is empty.`)\n }\n const values: unknown[] = trimmed.startsWith(\"[\")\n ? (JSON.parse(trimmed) as unknown[])\n : trimmed\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter((line) => line.length > 0)\n .map((line) => JSON.parse(line) as unknown)\n\n return values.map((value, index) => {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n throw new BitfabError(\n `Seed case ${index} in '${path}' must be an object with an \"input\" array.`,\n )\n }\n const { input } = value as { input?: unknown }\n if (!Array.isArray(input)) {\n throw new BitfabError(\n `Seed case ${index} in '${path}' is missing an \"input\" array. Wrap a single argument as [arg].`,\n )\n }\n if (run && \"expected\" in value) {\n throw new BitfabError(\n `Seed case ${index} in '${path}' carries \"expected\", which --run does not record: the case is run once and its output is what the run produced. Remove the field, or drop --run to record the case without running it.`,\n )\n }\n return value as SeedCase\n })\n}\n\n/**\n * Seed cases through an already-registered pipeline.\n *\n * The registration is the whole point: it already holds the client, the exact\n * function production calls, and the trace function key replay selects by, so\n * a seeded case is guaranteed to line up with the replay that will read it.\n * Passing the registered function to `seedTrace` also means a case that cannot\n * supply its required arguments is rejected here rather than at replay.\n */\nexport async function seedFromRegistry(\n registry: ReplayRegistry,\n pipeline: string,\n cases: readonly SeedCase[],\n options: { run?: boolean } = {},\n): Promise<SeedResult> {\n const registration = registry[pipeline]\n if (registration === undefined) {\n throw new BitfabError(\n `Unknown pipeline '${pipeline}'. Registered: ${Object.keys(registry).join(\", \")}`,\n )\n }\n const traceFunctionKey = resolveTraceFunctionKey(registration)\n if (options.run === true) {\n const traceIds: string[] = []\n for (const seedCase of cases) {\n traceIds.push(\n await registration.client.seedTrace(traceFunctionKey, registration.fn, {\n args: seedCase.input,\n metadata: seedCase.metadata,\n sessionId: seedCase.sessionId,\n }),\n )\n }\n return { pipeline, traceFunctionKey, traceIds }\n }\n const traceIds = cases.map((seedCase) =>\n registration.client.seedTrace(traceFunctionKey, {\n input: seedCase.input,\n expected: seedCase.expected,\n fn: registration.fn,\n metadata: seedCase.metadata,\n sessionId: seedCase.sessionId,\n }),\n )\n const { flushTraces } = await import(\"./http.js\")\n await flushTraces(30_000)\n return { pipeline, traceFunctionKey, traceIds }\n}\n\nconst SEED_USAGE =\n 'Usage: bitfab-replay --registry <path> <pipeline> --seed <cases.jsonl> [--run]\\n\\nEach case is a JSON object with an \"input\" array, plus optional \"expected\", \"metadata\", and \"sessionId\". A JSON array of those objects works too.\\n\\nWithout --run, each case is written as a trace directly: \"input\" becomes the root span input and \"expected\" its output, and nothing executes.\\n\\nWith --run, each case is run once through the registered function with capture off and the execution is recorded, so the output is what the run produced. Cases carrying \"expected\" are rejected.'\n\nexport async function runSeedCli(\n registry: ReplayRegistry,\n argv: readonly string[],\n io: ReplayCliIo = {},\n): Promise<SeedResult> {\n const stdout = io.stdout ?? console.log\n const stderr = io.stderr ?? console.error\n if (argv.some((value) => HELP_FLAGS.has(value))) {\n throw new ReplayCliHelp(SEED_USAGE)\n }\n const pipeline = argv[0]\n if (pipeline === undefined || registry[pipeline] === undefined) {\n throw new BitfabError(SEED_USAGE)\n }\n const seedIndex = argv.indexOf(\"--seed\")\n const casesPath = argv[seedIndex + 1]\n if (casesPath === undefined || casesPath.startsWith(\"--\")) {\n throw new BitfabError(\"--seed requires a path to a cases file.\")\n }\n const run = argv.includes(\"--run\")\n const readFile = io.readFile ?? defaultReadFile\n const cases = parseSeedCases(await readFile(casesPath), casesPath, run)\n\n stderr(\n run\n ? `[seed] Running ${cases.length} case(s) through \"${pipeline}\"...`\n : `[seed] Seeding ${cases.length} case(s) into \"${pipeline}\"...`,\n )\n const result = await seedFromRegistry(registry, pipeline, cases, { run })\n stderr(\n `[seed] ${run ? \"Recorded\" : \"Wrote\"} ${result.traceIds.length} trace(s) for \"${result.traceFunctionKey}\". Replay them with --trace-ids ${result.traceIds.slice(0, 3).join(\",\")}${result.traceIds.length > 3 ? \",...\" : \"\"}`,\n )\n stdout(JSON.stringify(result, null, 2))\n return result\n}\n\nfunction requirePositiveInteger(\n flag: string,\n raw: string,\n max?: number,\n): number {\n const value = Number(raw)\n if (!Number.isInteger(value) || value < 1) {\n throw new BitfabError(\n `${flag} must be a positive integer (received '${raw}').`,\n )\n }\n if (max !== undefined && value > max) {\n throw new BitfabError(`${flag} must be at most ${max} (received '${raw}').`)\n }\n return value\n}\n\nfunction commaSeparated(flag: string, raw: string): string[] {\n const values = raw\n .split(\",\")\n .map((value) => value.trim())\n .filter((value) => value.length > 0)\n if (values.length === 0) {\n throw new BitfabError(`${flag} must contain at least one value.`)\n }\n return values\n}\n\nfunction parseReplayCliArgs(\n registry: ReplayRegistry,\n argv: readonly string[],\n): ReplayCliArgs {\n if (argv.some((value) => HELP_FLAGS.has(value))) {\n throw new ReplayCliHelp(usage(registry))\n }\n const pipeline = argv[0]\n if (pipeline === undefined || registry[pipeline] === undefined) {\n throw new BitfabError(usage(registry))\n }\n\n const parsed: ReplayCliArgs = { pipeline, params: [] }\n for (let index = 1; index < argv.length; index += 1) {\n const flag = argv[index]\n if (BOOLEAN_FLAGS.has(flag)) {\n switch (flag) {\n case \"--db-branch\":\n if (parsed.dbBranch === false) {\n throw new BitfabError(\n \"--db-branch and --no-db-branch cannot be used together.\",\n )\n }\n parsed.dbBranch = true\n break\n case \"--no-db-branch\":\n if (parsed.dbBranch === true) {\n throw new BitfabError(\n \"--db-branch and --no-db-branch cannot be used together.\",\n )\n }\n parsed.dbBranch = false\n break\n case \"--no-code-change\":\n parsed.noCodeChange = true\n break\n case \"--dry-run\":\n parsed.dryRun = true\n break\n }\n continue\n }\n if (!VALUE_FLAGS.has(flag)) {\n throw new BitfabError(\n `Unknown replay option '${flag}'.\\n${usage(registry)}`,\n )\n }\n const raw = argv[index + 1]\n if (raw === undefined || raw.startsWith(\"--\")) {\n throw new BitfabError(`${flag} requires a value.`)\n }\n index += 1\n\n switch (flag) {\n case \"--limit\":\n parsed.limit = requirePositiveInteger(flag, raw)\n break\n case \"--attempts\":\n parsed.attempts = requirePositiveInteger(flag, raw, MAX_ATTEMPTS)\n break\n case \"--trace-ids\":\n parsed.traceIds = commaSeparated(flag, raw)\n break\n case \"--name\":\n parsed.name = raw\n break\n case \"--concurrency\":\n case \"--max-concurrency\":\n parsed.maxConcurrency = requirePositiveInteger(flag, raw)\n break\n case \"--code-change\":\n parsed.codeChangePath = raw\n break\n case \"--experiment-group-id\":\n parsed.experimentGroupId = raw\n break\n case \"--dataset-id\":\n parsed.datasetId = raw\n break\n case \"--grader-ids\":\n parsed.graderIds = commaSeparated(flag, raw)\n break\n case \"--mock\":\n if (raw !== \"none\" && raw !== \"all\" && raw !== \"marked\") {\n throw new BitfabError(\n `--mock must be one of: none, all, marked (received '${raw}').`,\n )\n }\n parsed.mock = raw\n break\n case \"--params\":\n parsed.paramsPath = raw\n break\n case \"--param\":\n parsed.params.push(raw)\n break\n }\n }\n if (parsed.traceIds !== undefined && parsed.datasetId !== undefined) {\n throw new BitfabError(\n \"--trace-ids and --dataset-id select different replay sources and cannot be used together.\",\n )\n }\n if (parsed.codeChangePath !== undefined && parsed.noCodeChange === true) {\n throw new BitfabError(\n \"--code-change and --no-code-change cannot be used together.\",\n )\n }\n return parsed\n}\n\nfunction resolveTraceFunctionKey(registration: ReplayRegistration): string {\n const wrappedKey = (\n registration.fn as ReplayFunction & {\n _bitfabTraceFunctionKey?: string\n }\n )._bitfabTraceFunctionKey\n const key = registration.traceFunctionKey ?? wrappedKey\n if (key === undefined) {\n throw new BitfabError(\n \"Replay registry entry uses a plain function. Set traceFunctionKey to the key its production handler records.\",\n )\n }\n return key\n}\n\nasync function defaultReadFile(path: string): Promise<string> {\n const fs = await import(\"node:fs/promises\").catch(() => null)\n if (fs === null) {\n throw new BitfabError(\n \"--code-change requires a runtime that can read local files.\",\n )\n }\n return fs.readFile(path, \"utf8\")\n}\n\nasync function loadCodeChange(\n path: string | undefined,\n readFile: (path: string) => Promise<string>,\n): Promise<CodeChange | undefined> {\n if (path === undefined) {\n return undefined\n }\n const value = JSON.parse(await readFile(path)) as Partial<CodeChange>\n if (typeof value.description !== \"string\" || !Array.isArray(value.files)) {\n throw new BitfabError(\n `Invalid --code-change file '${path}': expected { description, files }.`,\n )\n }\n return { description: value.description, files: value.files }\n}\n\nfunction parseParameter(raw: string): [string, unknown] {\n const separator = raw.indexOf(\"=\")\n const key = raw.slice(0, separator).trim()\n if (separator < 1 || key.length === 0) {\n throw new BitfabError(\n `Invalid --param '${raw}': expected a non-empty name=value pair.`,\n )\n }\n const value = raw.slice(separator + 1)\n try {\n return [key, JSON.parse(value) as unknown]\n } catch {\n return [key, value]\n }\n}\n\nasync function loadParameters(\n path: string | undefined,\n rawParameters: readonly string[],\n readFile: (path: string) => Promise<string>,\n): Promise<Record<string, unknown>> {\n let params: Record<string, unknown> = {}\n if (path !== undefined) {\n const value = JSON.parse(await readFile(path)) as unknown\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n throw new BitfabError(\n `Invalid --params file '${path}': expected a JSON object.`,\n )\n }\n params = { ...(value as Record<string, unknown>) }\n }\n for (const raw of rawParameters) {\n const [key, value] = parseParameter(raw)\n params[key] = value\n }\n return params\n}\n\nfunction valuesEqual(left: unknown, right: unknown): boolean {\n try {\n return JSON.stringify(left) === JSON.stringify(right)\n } catch {\n return Object.is(left, right)\n }\n}\n\nfunction renderSummary(\n pipeline: string,\n result: ReplayResult<unknown>,\n stderr: (line: string) => void,\n): void {\n let same = 0\n let changed = 0\n let matched = 0\n let missed = 0\n let errors = 0\n\n for (const item of result.items) {\n if (item.error !== null) {\n errors += 1\n continue\n }\n const equal = valuesEqual(item.result, item.originalOutput)\n if (item.ingestionType === \"seeded\") {\n if (equal) {\n matched += 1\n } else {\n missed += 1\n }\n } else if (equal) {\n same += 1\n } else {\n changed += 1\n }\n }\n\n stderr(\"\\n─── Summary ───\")\n stderr(` Pipeline: ${pipeline}`)\n stderr(` Replayed: ${result.items.length}`)\n if (result.attempts > 1) {\n stderr(` Attempts: ${result.attempts}`)\n }\n if (same > 0 || changed > 0 || matched + missed === 0) {\n stderr(` Same: ${same}`)\n stderr(` Changed: ${changed}`)\n }\n if (matched > 0 || missed > 0) {\n stderr(` Matched expected: ${matched}`)\n stderr(` Missed expected: ${missed}`)\n }\n if (errors > 0) {\n stderr(` Errors: ${errors}`)\n }\n stderr(`\\n ${result.testRunUrl}`)\n}\n\nfunction renderDryRun(\n pipeline: string,\n result: ReplayResult<unknown>,\n stderr: (line: string) => void,\n): void {\n stderr(\"\\n─── Dry run ───\")\n stderr(` Pipeline: ${pipeline}`)\n stderr(` Resolved: ${result.items.length} (nothing was executed)`)\n for (const item of result.items) {\n stderr(`\\n ${item.originalTraceId}`)\n stderr(` args: ${safeJson(item.input)}`)\n }\n stderr(`\\n ${result.testRunUrl}`)\n}\n\nfunction safeJson(value: unknown): string {\n try {\n return JSON.stringify(value) ?? String(value)\n } catch {\n return String(value)\n }\n}\n\nfunction reportReplayError(\n error: ReplayError,\n stderr: (line: string) => void,\n): void {\n for (const item of error.items as ReplayItem<unknown>[]) {\n stderr(\n `${item.originalTraceId}: ${String(item.traceError ?? item.replayError ?? item.error)}`,\n )\n }\n}\n\n/**\n * Run the SDK-owned replay command against a project-owned registry.\n *\n * The installed `bitfab-replay` executable calls this after loading the\n * registry passed through `--registry`. The SDK owns every common flag,\n * lifecycle callback, and output contract.\n */\nexport async function runReplayCli(\n registry: ReplayRegistry,\n argv: readonly string[] = typeof process === \"undefined\"\n ? []\n : process.argv.slice(2),\n io: ReplayCliIo = {},\n): Promise<ReplayResult<unknown>> {\n const stdout = io.stdout ?? console.log\n const stderr = io.stderr ?? console.error\n const args = parseReplayCliArgs(registry, argv)\n const registration = registry[args.pipeline]\n const traceFunctionKey = resolveTraceFunctionKey(registration)\n const readFile = io.readFile ?? defaultReadFile\n const params = await loadParameters(args.paramsPath, args.params, readFile)\n const dynamicOptions = await registration.optionsFactory?.({ params })\n const registrationOptions: ReplayRegistryOptions = {\n ...registration.options,\n ...dynamicOptions,\n }\n if (\n registrationOptions.traceIds !== undefined &&\n registrationOptions.datasetId !== undefined\n ) {\n throw new BitfabError(\n \"Replay registry options traceIds and datasetId select different sources and cannot be used together.\",\n )\n }\n const codeChange = await loadCodeChange(args.codeChangePath, readFile)\n\n const options: ReplayOptions = {\n ...registrationOptions,\n ...(args.name === undefined ? {} : { name: args.name }),\n ...(args.attempts === undefined ? {} : { attempts: args.attempts }),\n ...(args.maxConcurrency === undefined\n ? {}\n : { maxConcurrency: args.maxConcurrency }),\n ...(args.experimentGroupId === undefined\n ? {}\n : { experimentGroupId: args.experimentGroupId }),\n ...(args.datasetId === undefined ? {} : { datasetId: args.datasetId }),\n ...(args.graderIds === undefined ? {} : { graderIds: args.graderIds }),\n ...(args.mock === undefined ? {} : { mock: args.mock }),\n ...(args.dbBranch === undefined\n ? {}\n : {\n dbBranch:\n args.dbBranch &&\n registrationOptions.dbBranch !== undefined &&\n registrationOptions.dbBranch !== false\n ? registrationOptions.dbBranch\n : args.dbBranch,\n }),\n ...(args.noCodeChange === true\n ? { codeChangeDescription: null, codeChangeFiles: null }\n : {}),\n ...(args.dryRun === true ? { dryRun: true } : {}),\n ...(codeChange === undefined\n ? {}\n : {\n codeChangeDescription: codeChange.description,\n codeChangeFiles: codeChange.files,\n }),\n onItemStart: reportReplayProgress,\n onItemFinish: reportReplayProgress,\n }\n\n if (args.traceIds !== undefined) {\n options.traceIds = args.traceIds\n options.datasetId = undefined\n options.limit = undefined\n } else if (args.datasetId !== undefined) {\n options.traceIds = undefined\n options.limit = undefined\n } else if (args.limit !== undefined) {\n options.traceIds = undefined\n options.datasetId = undefined\n options.limit = args.limit\n } else if (\n registrationOptions.traceIds !== undefined ||\n registrationOptions.datasetId !== undefined\n ) {\n options.limit = undefined\n } else {\n options.limit = registrationOptions.limit ?? 10\n }\n\n const attemptsSuffix =\n options.attempts !== undefined && options.attempts > 1\n ? ` (${options.attempts} attempts each)`\n : \"\"\n stderr(\n `[replay] ${args.dryRun === true ? \"Resolving inputs for\" : \"Replaying\"} ${options.traceIds?.length ?? options.limit ?? \"dataset\"} traces from \"${traceFunctionKey}\"${attemptsSuffix}...`,\n )\n\n try {\n const result = await registration.client.replay(\n traceFunctionKey,\n registration.fn,\n options,\n )\n if (args.dryRun === true) {\n renderDryRun(args.pipeline, result, stderr)\n } else {\n renderSummary(args.pipeline, result, stderr)\n }\n stdout(serializeReplayResult(result))\n // A command that selected nothing did nothing, so it must not exit 0. This\n // is the shape an unseeded corpus takes: `--limit 10` against a trace\n // function with no traces reads as a clean run rather than as no run.\n if (result.items.length === 0) {\n throw new BitfabError(\n `No traces matched \"${traceFunctionKey}\", so nothing was replayed. Seed cases with --seed, or capture a trace first.`,\n )\n }\n return result\n } catch (error) {\n if (error instanceof ReplayError) {\n reportReplayError(error, stderr)\n }\n throw error\n }\n}\n"],"mappings":"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","names":["isRecord","DEFAULT_LIFECYCLE_TIMEOUT_MS","superjson","error","mapWithConcurrency","_context","nowIso","asTokenCount","extractUsage","readEnv","readEnv","method","flushTraces","traceIds","flushTraces"]}
1
+ {"version":3,"sources":["../src/asyncStorage.ts","../src/version.generated.ts","../src/constants.ts","../src/readEnv.ts","../src/compress.ts","../src/errors.ts","../src/replayContext.ts","../src/payloadBudget.ts","../src/warnOnce.ts","../src/serializePayload.ts","../src/transportTypes.ts","../src/unrefTimer.ts","../src/otel.ts","../src/transport.ts","../src/http.ts","../src/serialize.ts","../src/randomUuid.ts","../src/mockOverride.ts","../src/codeChange.ts","../src/replay.ts","../src/node.ts","../src/asyncStorageNode.ts","../src/claudeAgentSdk.ts","../src/processorPayload.ts","../src/timestamp.ts","../src/client.ts","../src/autoTrace.ts","../src/optionalPeer.ts","../src/baml.ts","../src/captureSurface.ts","../src/datasets.ts","../src/dbSnapshot.ts","../src/langgraph.ts","../src/langgraphIntegration.ts","../src/openaiAgentSdk.ts","../src/replayBranch.ts","../src/seedContext.ts","../src/tracing.ts","../src/vercelAiSdk.ts","../src/index.ts","../src/finalizers.ts","../src/replayRegistry.ts"],"sourcesContent":["/**\n * Shared AsyncLocalStorage loader.\n *\n * Provides two ways to initialize AsyncLocalStorage:\n *\n * 1. **Synchronous registration** (preferred for Node.js):\n * `asyncStorageNode.ts` calls `registerAsyncLocalStorageClass()` at module\n * evaluation time, so the class is available immediately - no async gap.\n * The `node.ts` entry point imports it before anything else.\n *\n * 2. **Async dynamic import** (fallback for the default entry point):\n * Loads `node:async_hooks` via a bundler-safe dynamic import. This is used\n * by the default `index.ts` entry point so the SDK works in browsers\n * (where the import silently fails) and in Node.js when imported via the\n * default entry point.\n *\n * ## Why the dynamic import looks like this\n *\n * We need to handle three environments:\n *\n * 1. **Pure Node.js** - `import(\"node:async_hooks\")` works natively.\n * 2. **Webpack/Turbopack (Next.js server)** - The bundler processes\n * `import()` calls at build time. The `webpackIgnore` magic comment tells\n * webpack (and turbopack) to emit a native `import()` call instead of\n * trying to resolve it, so Node.js handles it at runtime.\n * 3. **Browsers / Edge** - The `process.versions?.node` guard prevents\n * execution entirely. If it somehow runs, `.catch(() => {})` swallows\n * the failure.\n */\n\nexport interface AsyncLocalStorageLike<T> {\n getStore(): T | undefined\n run<R>(store: T, fn: () => R): R\n}\n\nlet AsyncLocalStorageClass: (new () => AsyncLocalStorageLike<unknown>) | null =\n null\nlet initDone = false\n\n/**\n * Register the AsyncLocalStorage class synchronously.\n *\n * Called by `asyncStorageNode.ts` at module evaluation time so the class\n * is available before any span is created - no async gap, no race condition.\n *\n * Safe to call multiple times; subsequent calls are no-ops.\n */\nexport function registerAsyncLocalStorageClass(\n cls: new () => AsyncLocalStorageLike<unknown>,\n): void {\n if (!AsyncLocalStorageClass) {\n AsyncLocalStorageClass = cls\n }\n initDone = true\n}\n\n/**\n * Assert that AsyncLocalStorage was registered successfully.\n *\n * Called by `node.ts` after importing `asyncStorageNode.ts` to catch\n * import-order bugs at startup rather than silently degrading to the\n * browser fallback (flat spans with no nesting).\n *\n * This should ONLY be called from the Node.js entry point where we\n * know `node:async_hooks` must be available.\n */\nexport function assertAsyncStorageRegistered(): void {\n if (!AsyncLocalStorageClass) {\n console.warn(\n \"Bitfab: AsyncLocalStorage not available - nested span context will not propagate.\",\n )\n }\n}\n\nexport const asyncStorageReady: Promise<void> = (\n typeof process !== \"undefined\" && process.versions?.node\n ? // The join trick hides \"node:async_hooks\" from static analysis so\n // bundlers that ban Node.js built-ins don't fail at build time.\n // webpackIgnore tells webpack/turbopack to emit a native import()\n // so Node.js can resolve the module at runtime.\n import(\n /* webpackIgnore: true */\n [\"node\", \"async_hooks\"].join(\":\")\n )\n .then(\n (mod: {\n AsyncLocalStorage: new () => AsyncLocalStorageLike<unknown>\n }) => {\n registerAsyncLocalStorageClass(mod.AsyncLocalStorage)\n },\n )\n .catch(() => {})\n : Promise.resolve()\n).then(() => {\n initDone = true\n})\n\nexport function isAsyncStorageInitDone(): boolean {\n return initDone\n}\n\nexport function createAsyncLocalStorage<T>(): AsyncLocalStorageLike<T> | null {\n return AsyncLocalStorageClass\n ? (new AsyncLocalStorageClass() as AsyncLocalStorageLike<T>)\n : null\n}\n","/**\n * Auto-generated package metadata.\n * This file is generated by scripts/generate-version.ts during build.\n * DO NOT EDIT MANUALLY.\n */\n\n/**\n * SDK version from package.json (injected at build time)\n */\nexport const __version__ = \"0.44.1\"\n\n/**\n * Published npm package name from package.json (injected at build time)\n */\nexport const __packageName__ = \"@bitfab/sdk\"\n","/**\n * Constants for the Bitfab SDK.\n */\n\n/**\n * Default service URL for Bitfab API.\n */\nexport const DEFAULT_SERVICE_URL = \"https://bitfab.ai\"\n\n/**\n * SDK version from package.json (injected at build time)\n *\n * The version is generated at build time by scripts/generate-version.ts\n * to ensure compatibility with both Node.js and browser environments.\n */\nexport { __packageName__, __version__ } from \"./version.generated.js\"\n","/**\n * Read an environment variable without throwing in non-Node runtimes\n * (browsers, edge workers) where `process` is absent. The SDK ships to\n * browsers, so this must never assume `process` exists.\n */\nexport function readEnv(name: string): string | undefined {\n if (typeof process !== \"undefined\" && process.env) {\n return process.env[name]\n }\n return undefined\n}\n","import { readEnv } from \"./readEnv.js\"\n\nconst DISABLE_COMPRESSION_ENV = \"BITFAB_DISABLE_COMPRESSION\"\n\n/**\n * Below this, compressing costs more than the saved bytes are worth, so small\n * requests (function lookups, replay status polls, single-span batches) ride\n * uncompressed.\n */\nconst MIN_COMPRESSED_BYTES = 8_192\n\nexport interface EncodedRequestBody {\n body: string | ArrayBuffer\n contentEncoding?: \"gzip\"\n rawBytes: number\n wireBytes: number\n}\n\n/**\n * Node's gzip, loaded dynamically so browser bundlers never have to resolve\n * `node:zlib`. Deliberately the async form: it runs on libuv's threadpool\n * rather than the event loop. Measured on 8 concurrent 1 MB bodies, the\n * synchronous form stalled the loop for 326ms and the async form for 1ms,\n * while also finishing 3.8x sooner because the threadpool compresses in\n * parallel. A tracing SDK must not block its host's event loop.\n */\nlet gzipNode: ((data: Uint8Array) => Promise<Uint8Array>) | undefined\n\ntype NodeZlib = {\n gzip: (\n data: Uint8Array,\n callback: (error: Error | null, result: Uint8Array) => void,\n ) => void\n}\n\nexport const _nodeGzipReady: Promise<void> = (\n typeof process !== \"undefined\" && process.versions?.node\n ? // The join trick hides \"node:zlib\" from static analysis so bundlers that\n // ban Node.js built-ins don't fail at build time. webpackIgnore tells\n // webpack/turbopack to emit a native import() so Node.js can resolve the\n // module at runtime. Same pattern as `asyncStorage.ts`.\n import(\n /* webpackIgnore: true */\n [\"node\", \"zlib\"].join(\":\")\n )\n .then(({ gzip }: NodeZlib) => {\n gzipNode = (data) =>\n new Promise((resolve, reject) => {\n gzip(data, (error, result) => {\n if (error) {\n reject(error)\n } else {\n resolve(result)\n }\n })\n })\n })\n .catch(() => {})\n : Promise.resolve()\n).then(() => {})\n\n/** Test seam for exercising the browser path on Node. */\nexport function _setNodeGzip(\n impl: ((data: Uint8Array) => Promise<Uint8Array>) | undefined,\n): void {\n gzipNode = impl\n}\n\nfunction toArrayBuffer(view: Uint8Array): ArrayBuffer {\n return view.buffer.slice(\n view.byteOffset,\n view.byteOffset + view.byteLength,\n ) as ArrayBuffer\n}\n\nfunction compressedRequest(\n body: string,\n rawBytes: number,\n compressed: Uint8Array | ArrayBuffer,\n): EncodedRequestBody {\n if (compressed.byteLength >= rawBytes) {\n return { body, rawBytes, wireBytes: rawBytes }\n }\n return {\n body:\n compressed instanceof Uint8Array ? toArrayBuffer(compressed) : compressed,\n contentEncoding: \"gzip\",\n rawBytes,\n wireBytes: compressed.byteLength,\n }\n}\n\nasync function gzipViaStream(bytes: Uint8Array): Promise<ArrayBuffer> {\n const stream = new Blob([bytes as BlobPart])\n .stream()\n .pipeThrough(new CompressionStream(\"gzip\"))\n return await new Response(stream).arrayBuffer()\n}\n\n/**\n * Compression is best-effort: any failure sends the original body rather than\n * dropping the span. `CompressionStream` is absent on older browsers, so its\n * presence is checked rather than assumed.\n *\n * Returns a plain value (not a promise) whenever it can, so a request still\n * reaches `fetch` in the caller's tick rather than one microtask later. Callers\n * await the union.\n */\nexport function encodeRequestBody(\n body: string,\n): EncodedRequestBody | Promise<EncodedRequestBody> {\n if (readEnv(DISABLE_COMPRESSION_ENV)) {\n const rawBytes = new TextEncoder().encode(body).byteLength\n return { body, rawBytes, wireBytes: rawBytes }\n }\n const bytes = new TextEncoder().encode(body)\n if (bytes.byteLength < MIN_COMPRESSED_BYTES) {\n return {\n body,\n rawBytes: bytes.byteLength,\n wireBytes: bytes.byteLength,\n }\n }\n if (gzipNode) {\n return gzipNode(bytes).then(\n (compressed) => compressedRequest(body, bytes.byteLength, compressed),\n () => ({\n body,\n rawBytes: bytes.byteLength,\n wireBytes: bytes.byteLength,\n }),\n )\n }\n if (typeof CompressionStream === \"undefined\") {\n return {\n body,\n rawBytes: bytes.byteLength,\n wireBytes: bytes.byteLength,\n }\n }\n return gzipViaStream(bytes).then(\n (compressed) => compressedRequest(body, bytes.byteLength, compressed),\n () => ({\n body,\n rawBytes: bytes.byteLength,\n wireBytes: bytes.byteLength,\n }),\n )\n}\n","/**\n * Shared error type for Bitfab SDK runtime errors. Lives in its own\n * module to avoid import cycles between `http.ts` and modules that need\n * to throw structured errors (e.g. `dbSnapshot.ts` validation).\n */\n\nexport class BitfabError extends Error {\n constructor(\n message: string,\n public readonly url?: string,\n /**\n * HTTP status the request failed with, when it failed with one. The\n * transport's retry policy needs the code itself (retry 408/425/429/5xx,\n * never a 4xx the server will reject again), which a formatted message\n * cannot supply. Absent for network failures and non-HTTP errors.\n */\n public readonly status?: number,\n /**\n * `Retry-After` in milliseconds, when the server sent one. A 429 or 503\n * carries the server's own instruction about when to come back; retrying\n * on our own schedule ignores it and keeps the pressure on.\n */\n public readonly retryAfterMs?: number,\n ) {\n super(message)\n this.name = \"BitfabError\"\n }\n}\n\nexport class MixedTracingError extends Error {\n constructor(message: string) {\n super(message)\n this.name = \"MixedTracingError\"\n }\n}\n","/**\n * Replay context propagation via AsyncLocalStorage.\n *\n * When set, the withSpan wrapper injects testRunId into the span payload\n * so that new spans created during replay are linked to the test run.\n * Optionally carries a mock tree so child spans can return historical\n * outputs instead of executing.\n */\n\nimport {\n type AsyncLocalStorageLike,\n asyncStorageReady,\n createAsyncLocalStorage,\n} from \"./asyncStorage.js\"\nimport type { MockOverride } from \"./mockOverride.js\"\n\n/**\n * A single span entry in the mock tree.\n *\n * Under the eager path (`mock: \"all\"`) `output`/`outputMeta` are populated\n * inline, even when overrides are present. Under a non-`all` path that needs a\n * tree (`marked`, or `none` with overrides), they are absent and the recorded\n * output is fetched on demand via `externalSpanId` - see\n * {@link ReplayContext.fetchSpanOutput}.\n */\nexport interface MockSpan {\n sourceSpanId: string\n /** Row id accepted by `getExternalSpan`, for the lazy per-span output fetch. */\n externalSpanId?: string\n output?: unknown\n outputMeta?: unknown\n}\n\n/**\n * Per-item DB branch resolved by the Bitfab service from the source\n * trace's `dbSnapshotRef`. Carried on the replay context so that\n * customer code reads `databaseUrl` through `getCurrentReplayBranch()`, and so\n * the process-isolated replay runner can materialize it into a `.env`\n * overlay file before customer code initializes its DB client.\n *\n * `neonBranchId` is the literal Neon branch id; passing it to\n * `releaseDbBranchLease` deletes that branch.\n */\nexport interface DbBranchLease {\n neonBranchId: string\n /** Env var name the customer's app reads, e.g. \"DATABASE_URL\". */\n envKey: string\n databaseUrl: string\n expiresAt: string\n /**\n * The instant the branch was pinned to (the source trace's wall clock).\n * Echoed back in `db_snapshot_usage` on the replayed trace's completion.\n */\n snapshotTimestamp?: string\n providerConsoleUrl?: string\n readOnly?: boolean\n /**\n * The branch's region, e.g. `aws-us-east-1`. A compute runs in its project's\n * region, so a runner elsewhere pays that round trip on every query.\n */\n region?: string\n}\n\n/**\n * How long each phase of provisioning one replay branch took, measured\n * server-side. A runner in another region sees these plus its own round trip.\n *\n * Durations, not instants: an instant is approximately `startedAt` plus the\n * running sum, and per-phase wall-clock stamps would make clock skew between\n * the server and your runner look like latency. Approximately, because\n * `totalMs` is the resolve's true wall time and covers a little work no phase\n * owns, so the phases account for it without summing to it exactly.\n *\n * `startedAt` and `totalMs` are always present. The phases are optional\n * because a failed resolve reports only the ones it reached, and `totalMs` is\n * then time-to-failure. On success every phase is present except `warmupMs`,\n * which is absent when no warm-up SQL was supplied.\n */\nexport interface DbBranchTimings {\n /** When the resolve began, ISO. */\n startedAt: string\n /** Resolving the project, plus its retention and region reads. */\n projectResolveMs?: number\n /** Creating the branch, through its provider operations reaching terminal. */\n branchCreateMs?: number\n /** Resolving the connection URI. 0 when the provider returns one inline. */\n connectionUriMs?: number\n /** The compute accepting a connection. */\n computeConnectMs?: number\n /** The branch answering a readiness query. */\n baseProbeMs?: number\n /** Your warm-up SQL. Absent when you supplied none. */\n warmupMs?: number\n /** The whole resolve, or time-to-failure when it threw. */\n totalMs: number\n}\n\n/**\n * Wire shape of the caller's `ReplayOptions.dbBranch`, sent to\n * `/api/sdk/replay/start` and applied per lease.\n */\nexport interface DbBranchSettings {\n minCu?: number\n maxCu?: number\n warmupSql?: string\n}\n\n/**\n * Pre-built lookup table of historical span outputs.\n * Keys are `${traceFunctionKey}:${spanName}:${callIndex}` so that repeated\n * calls with the same (key, name) are matched by call order, but spans\n * sharing only the traceFunctionKey (different name) do not collide.\n */\nexport interface MockTree {\n spans: Map<string, MockSpan>\n}\n\nexport interface ReplayContext {\n testRunId: string\n traceId?: string\n inputSourceSpanId?: string\n /**\n * External trace ID from `external_traces.id`. Used for span-chain\n * lookup against the source platform's trace tree (Braintrust, etc.).\n * NOT the same as the Bitfab `traceId` - see `sourceBitfabTraceId`.\n */\n inputSourceTraceId?: string\n /**\n * The Bitfab `traces.id` of the historical trace that produced this\n * replay item's input. This is what customer-facing surfaces (e.g.\n * `ReplayBranch.traceId`) should expose, since it's the ID the\n * customer sees in the Bitfab dashboard.\n */\n sourceBitfabTraceId?: string\n replayAttempt?: number\n mockTree?: MockTree\n callCounters?: Map<string, number>\n mockStrategy?: \"none\" | \"all\" | \"marked\"\n /**\n * Resolved override chain for this replay, per-call overrides first then\n * registered ones (first matcher wins). Empty/absent when no overrides apply.\n */\n mockOverrides?: MockOverride[]\n /**\n * Memoized lazy fetch of a span's recorded output (deserialized), keyed by\n * `externalSpanId`. Present ONLY on a non-`all` path that needs a tree\n * (`marked`, or `none` with overrides); absent under `mock: \"all\"`, where\n * outputs are inline even when overrides are present. Its presence is the\n * signal that outputs must be fetched rather than read inline.\n */\n fetchSpanOutput?: (externalSpanId: string) => Promise<unknown>\n dbBranchLease?: DbBranchLease\n /**\n * Server-measured provisioning timings for this item's branch, echoed back\n * on the trace completion so the trace records what it cost to set up. Kept\n * off `ReplayBranch`: customer code reads that mid-replay to reach the\n * branch, and provisioning latency is a property of the run, not of the\n * connection.\n */\n dbBranchTimings?: DbBranchTimings\n /**\n * Set to true by `ReplayBranch` the first time customer code actually\n * obtains `databaseUrl` for this item. Reported on the trace completion inside\n * `db_snapshot_usage` so the server can distinguish \"branch was\n * provisioned and exposed\" from \"branch URL was actually consumed\".\n * Only an explicit `databaseUrl` read may set it. A path that hands the URL\n * over by other means (e.g. a process-isolated runner writing an env\n * overlay) must leave it alone: setting it there would make every such\n * replay report `accessed` for free, and the flag would stop separating\n * \"branch was used\" from \"branch was offered\".\n */\n dbSnapshotAccessed?: boolean\n}\n\nlet replayContextStorage: AsyncLocalStorageLike<ReplayContext | null> | null =\n null\nconst REPLAY_CONTEXT_STORAGE_SYMBOL = Symbol.for(\"bitfab.replayContextStorage\")\n\nexport const replayContextReady: Promise<void> = asyncStorageReady.then(() => {\n const shared = globalThis as typeof globalThis & Record<symbol, unknown>\n const existing = shared[REPLAY_CONTEXT_STORAGE_SYMBOL] as\n | AsyncLocalStorageLike<ReplayContext | null>\n | undefined\n if (existing) {\n replayContextStorage = existing\n return\n }\n const created = createAsyncLocalStorage<ReplayContext | null>()\n if (created) {\n shared[REPLAY_CONTEXT_STORAGE_SYMBOL] = created\n replayContextStorage = created\n }\n})\n\n/** Get the current replay context, if any. */\nexport function getReplayContext(): ReplayContext | null {\n return replayContextStorage?.getStore() ?? null\n}\n\n/** Run a function within a replay context. */\nexport function runWithReplayContext<T>(ctx: ReplayContext, fn: () => T): T {\n if (replayContextStorage) {\n return replayContextStorage.run(ctx, fn)\n }\n return fn()\n}\n","/**\n * The ceiling on a span's encoded carrier, and the trimming that enforces it.\n *\n * A span's whole payload (input, output, contexts, prompt, metadata) ships as\n * a single `bitfab.payload` string attribute, and the exporter drops any\n * carrier that exceeds the per-request byte ceiling outright rather than\n * trimming it. Capping each value on its own cannot prevent that: two values\n * that each fit can still add up to an undeliverable span. So the budget is\n * enforced on the whole span, and an oversized one ships with its largest\n * fields stubbed instead of vanishing.\n *\n * The budget is measured on the *carrier* (the payload re-escaped into the\n * OTLP attribute), not on the payload body, because the carrier is what the\n * exporter weighs. Bounding the body instead leaves escape-heavy content to\n * blow the request ceiling anyway: a body of escaped JSON, Windows paths, or\n * regexes is nearly all backslashes, and every one of them doubles. Measured\n * on a body sized exactly to a 2.4 MB cap, prose produced a 2.4 MB carrier but\n * backslash-dense content produced 4.8 MB, which the exporter dropped.\n *\n * The normal 2.8 MB fallback leaves room beneath the 3 MB wire target. Trace\n * transport may first preserve a carrier up to 7.8 MB when its single-span\n * request compresses below that wire target and remains below ingress's 8 MB\n * decompressed ceiling.\n */\nexport const MAX_SPAN_CARRIER_BYTES = 2_800_000\n\n/**\n * A larger carrier may still fit when its single-span request is compressed.\n * This leaves 200 kB beneath ingress's 8 MB decompressed-body ceiling for the\n * OTLP span and request envelopes.\n */\nexport const MAX_COMPRESSIBLE_SPAN_CARRIER_BYTES = 7_800_000\n\nconst textEncoder =\n typeof TextEncoder !== \"undefined\" ? new TextEncoder() : null\n\nexport function byteLength(value: string): number {\n return textEncoder ? textEncoder.encode(value).length : value.length\n}\n\n/**\n * The byte length `body` occupies once re-escaped as a JSON string value.\n *\n * `body` is itself JSON text, so the first encode already replaced every\n * control character with a `\\uXXXX` sequence, leaving only `\"` and `\\` to\n * escape at one extra byte each.\n *\n * Counts UTF-8 width and escapes in the same pass and allocates nothing.\n * `TextEncoder.encode().length` would be the obvious way to get the byte count,\n * but it copies the entire body into a fresh array just to read its length,\n * which on a multi-megabyte span costs more than producing the body did.\n */\nexport function carrierByteLength(body: string): number {\n return carrierBytesOf(textEncoder ? textEncoder.encode(body) : null, body)\n}\n\n/**\n * Counts escapes over the UTF-8 bytes rather than the UTF-16 string. Bytes\n * `0x22` and `0x5c` are unambiguous there (a multi-byte sequence never uses a\n * byte below `0x80`), so a flat byte scan is exact, and it reuses the array the\n * byte count already had to produce instead of walking the string a second\n * time. Measured ~2x faster than the equivalent `charCodeAt` loop.\n */\nfunction carrierBytesOf(encoded: Uint8Array | null, body: string): number {\n if (!encoded) {\n // No TextEncoder (a browser old enough to lack it). Fall back to the string,\n // where `length` is the best available byte estimate.\n return body.length + 2\n }\n let extra = 2 // the quotes wrapping the attribute value\n for (let i = 0; i < encoded.length; i++) {\n const byte = encoded[i]\n if (byte === 34 || byte === 92) {\n extra += 1 // `\"` and `\\` take a leading backslash\n } else if (byte < 0x20) {\n extra +=\n byte === 8 || byte === 9 || byte === 10 || byte === 12 || byte === 13\n ? 1 // \\b \\f \\n \\r \\t\n : 5 // \\uXXXX\n }\n }\n return encoded.length + extra\n}\n\n/**\n * The most carrier bytes one UTF-16 code unit of a *JSON body* can become.\n *\n * A unit is at most 3 UTF-8 bytes, and the only characters that grow under\n * escaping are `\"` and `\\`, which are one byte and become two. A unit cannot be\n * both, so 3 is the ceiling. This holds because every caller passes the output\n * of a JSON encoder, which by specification never emits a raw control character\n * (the case that would otherwise expand to a 6-byte `\\uXXXX`); the invariant is\n * pinned by a test so a future caller that broke it would fail loudly rather\n * than silently ship an oversized carrier.\n */\nconst MAX_BYTES_PER_UNIT = 3\n\n/**\n * Whether `body` fits the carrier budget, escalating only as far as it must.\n *\n * `body.length` is O(1) and brackets the answer for both ordinary spans (far\n * under the budget) and hopeless ones (already past it on raw length alone),\n * which is every span in normal traffic: neither case touches the string. Only\n * a body near the budget is measured exactly, and that costs one encode plus\n * one byte scan.\n */\nexport function fitsCarrierBudget(\n body: string,\n maxBytes: number = MAX_SPAN_CARRIER_BYTES,\n): boolean {\n const units = body.length\n if (units * MAX_BYTES_PER_UNIT + 2 <= maxBytes) {\n return true\n }\n if (units + 2 > maxBytes) {\n return false\n }\n return carrierByteLength(body) <= maxBytes\n}\n\n/**\n * Span fields that identify the span rather than carry user data. Trimming one\n * would leave a span that no longer says what it is, so they stay whatever the\n * payload costs.\n */\nconst STRUCTURAL_SPAN_KEYS = new Set([\n \"name\",\n \"type\",\n \"function_name\",\n \"error_source\",\n])\n\nfunction asRecord(value: unknown): Record<string, unknown> | undefined {\n return typeof value === \"object\" && value !== null && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : undefined\n}\n\ninterface Candidate {\n container: Record<string, unknown>\n key: string\n size: number\n}\n\n/**\n * The records holding user data, cloned so trimming never mutates the caller's\n * objects. Returns the payload copy to encode plus the containers to trim.\n */\nfunction cloneTrimmable(payload: Record<string, unknown>): {\n copy: Record<string, unknown>\n containers: Record<string, unknown>[]\n} {\n const copy = { ...payload }\n const containers: Record<string, unknown>[] = []\n\n const spanData = asRecord(copy.span_data)\n if (spanData) {\n const clone = { ...spanData }\n copy.span_data = clone\n containers.push(clone)\n }\n\n const rawSpan = asRecord(copy.rawSpan)\n const rawSpanData = rawSpan && asRecord(rawSpan.span_data)\n if (rawSpan && rawSpanData) {\n const clone = { ...rawSpanData }\n copy.rawSpan = { ...rawSpan, span_data: clone }\n containers.push(clone)\n }\n\n // No span_data anywhere: a trace-level or otherwise unfamiliar payload. Trim\n // its own fields rather than give up, so an oversized body still ships.\n if (containers.length === 0) {\n containers.push(copy)\n }\n\n return { copy, containers }\n}\n\nfunction collectCandidates(containers: Record<string, unknown>[]): Candidate[] {\n const candidates: Candidate[] = []\n for (const container of containers) {\n for (const [key, value] of Object.entries(container)) {\n if (STRUCTURAL_SPAN_KEYS.has(key) || value == null) {\n continue\n }\n let size: number\n try {\n size = byteLength(JSON.stringify(value) ?? \"\")\n } catch {\n continue\n }\n candidates.push({ container, key, size })\n }\n }\n return candidates.sort((a, b) => b.size - a.size)\n}\n\n/**\n * Stub the largest payload fields until the encoded body fits the budget.\n *\n * Returns the trimmed payload and the names of the fields that were stubbed, or\n * `undefined` when nothing could be trimmed (the caller then ships the\n * oversized body and lets the exporter report the drop, which is still better\n * than silently emptying a span).\n */\nexport function trimPayloadToBudget(\n payload: Record<string, unknown>,\n encode: (value: Record<string, unknown>) => string,\n maxBytes: number = MAX_SPAN_CARRIER_BYTES,\n): { value: Record<string, unknown>; trimmed: string[] } | undefined {\n const { copy, containers } = cloneTrimmable(payload)\n const candidates = collectCandidates(containers)\n if (candidates.length === 0) {\n return undefined\n }\n\n const trimmed: string[] = []\n for (const candidate of candidates) {\n candidate.container[candidate.key] =\n `<unserializable: too_large_${candidate.size}_bytes>`\n trimmed.push(candidate.key)\n let body: string\n try {\n body = encode(copy)\n } catch {\n return undefined\n }\n if (fitsCarrierBudget(body, maxBytes)) {\n return { value: copy, trimmed }\n }\n }\n return undefined\n}\n\n/**\n * Record a trim in the payload's own `errors`, which is what the server reads\n * to flag a trace as incomplete.\n */\nexport function markPayloadTrimmed(\n value: Record<string, unknown>,\n trimmed: string[],\n maxBytes: number = MAX_SPAN_CARRIER_BYTES,\n): void {\n const existing = Array.isArray(value.errors) ? value.errors : []\n value.errors = [\n ...existing,\n {\n source: \"sdk\",\n step: \"payload_budget\",\n error: `trimmed oversized field(s) to fit the ${maxBytes}-byte span carrier budget: ${[\n ...new Set(trimmed),\n ].join(\", \")}`,\n },\n ]\n}\n","/**\n * Emit a `console.warn` at most once per distinct `key` for the life of the\n * process.\n *\n * The SDK must NEVER crash a host app, so every failure on the user's path\n * degrades silently (a span is dropped, a call runs untraced, a payload is\n * stubbed). Silent is safe but undebuggable: a user who suddenly has no traces,\n * or sees `<unserializable>` in a span, has no signal as to why. A one-time\n * warning per distinct issue restores that signal without spamming the console\n * from a hot path.\n *\n * Keys should identify the specific degradation (e.g. include the traced\n * function key) so each distinct issue warns once, not just the first one seen.\n */\nconst warned = new Set<string>()\n\nexport function warnOnce(key: string, message: string): void {\n if (warned.has(key)) {\n return\n }\n warned.add(key)\n try {\n console.warn(`[bitfab] ${message}`)\n } catch {\n // Logging must never crash the host app (e.g. a closed/replaced console).\n }\n}\n\n/** Test-only: clear the dedup set so a warning can fire again. */\nexport function _resetWarnOnce(): void {\n warned.clear()\n}\n","/**\n * Defensive payload encoding, shared by the HTTP path and the OTel carrier\n * path. Lives in its own module because `otel.ts` needs it and importing it\n * from `http.ts` would close an http -> transport -> otel -> http cycle.\n */\n\nimport {\n fitsCarrierBudget,\n MAX_SPAN_CARRIER_BYTES,\n markPayloadTrimmed,\n trimPayloadToBudget,\n} from \"./payloadBudget.js\"\nimport { warnOnce } from \"./warnOnce.js\"\n\n/**\n * JSON-encode a request body without ever throwing on a stray value, and\n * within the per-span byte budget.\n *\n * Upstream serialization (`serializeValue` / the LangGraph handler's\n * `safeSerialize`) should already have flattened user data. This is the\n * boundary backstop: if anything non-serializable still slips through\n * (BigInt, function, symbol, circular ref), it is stubbed in place instead of\n * letting `JSON.stringify` throw and drop the whole span/trace silently.\n *\n * The fast path is a plain `JSON.stringify`; the sanitizing replacer only runs\n * when that throws, so happy-path payloads (and shared non-circular refs) are\n * untouched. Returns `dropped` (the stubbed type names) so the caller can warn\n * loudly rather than ship a degraded payload in silence.\n */\nexport function serializePayloadBody(payload: Record<string, unknown>): {\n body: string\n dropped: string[]\n}\nexport function serializePayloadBody(\n payload: Record<string, unknown>,\n maxCarrierBytes: number,\n): { body: string; dropped: string[] }\nexport function serializePayloadBody(\n payload: Record<string, unknown>,\n maxCarrierBytes: number = MAX_SPAN_CARRIER_BYTES,\n): { body: string; dropped: string[] } {\n const encoded = encodePayloadBody(payload)\n if (fitsCarrierBudget(encoded.body, maxCarrierBytes)) {\n return { body: encoded.body, dropped: encoded.dropped }\n }\n return applyPayloadBudget(encoded, maxCarrierBytes)\n}\n\n/**\n * Trim an over-budget payload, preferring its largest fields, so the span\n * ships degraded rather than being dropped whole by the exporter.\n *\n * Trims the value that was actually encoded, not the caller's original: a\n * cyclic or otherwise non-encodable field cannot be sized (`JSON.stringify`\n * throws on it), so on the original graph the biggest field is skipped as a\n * trim candidate and the oversized body ships anyway. The sanitized copy has\n * those values already replaced with stubs, so every field is sizeable.\n */\nfunction applyPayloadBudget(\n encoded: EncodedPayload,\n maxCarrierBytes: number,\n): {\n body: string\n dropped: string[]\n} {\n const result = encoded.value\n ? trimPayloadToBudget(\n encoded.value,\n (value) => encodePayloadBody(value).body,\n maxCarrierBytes,\n )\n : undefined\n if (!result) {\n return { body: encoded.body, dropped: encoded.dropped }\n }\n warnOnce(\n \"payload:over-budget\",\n `a span payload exceeded the ${maxCarrierBytes}-byte carrier budget; its largest field(s) (${[\n ...new Set(result.trimmed),\n ].join(\n \", \",\n )}) were replaced with placeholders so the span still ships. The span is incomplete and may not be replayable.`,\n )\n markPayloadTrimmed(result.value, result.trimmed, maxCarrierBytes)\n // `dropped` names values that could not be encoded, which drives the\n // \"non-serializable value(s)\" warning. A budget trim is a size decision, not\n // an encoding failure, and already has its own warning and `payload_budget`\n // error entry, so it must not be reported as one.\n return {\n body: encodePayloadBody(result.value).body,\n dropped: encoded.dropped,\n }\n}\n\ninterface EncodedPayload {\n body: string\n dropped: string[]\n /**\n * The value the body was encoded from: the payload itself, or its sanitized\n * copy. Undefined when the encoded value isn't an object, which leaves\n * nothing with named fields to trim.\n */\n value: Record<string, unknown> | undefined\n}\n\nfunction encodePayloadBody(payload: Record<string, unknown>): EncodedPayload {\n try {\n return { body: JSON.stringify(payload), dropped: [], value: payload }\n } catch {\n const dropped: string[] = []\n // An explicit backtracking walk, not a JSON.stringify replacer: a replacer\n // gets no subtree-exit signal, so a single WeakSet would mis-tag a shared\n // (DAG) reference under sibling keys as a cycle. Tracking only the\n // current-path ancestors stubs real cycles while serializing DAGs in full.\n const sanitize = (value: unknown, seen: WeakSet<object>): unknown => {\n const t = typeof value\n if (\n value === null ||\n t === \"string\" ||\n t === \"number\" ||\n t === \"boolean\"\n ) {\n return value\n }\n if (t === \"bigint\") {\n dropped.push(\"BigInt\")\n return \"<unserializable: BigInt>\"\n }\n if (t === \"function\") {\n const name = (value as { name?: string }).name || \"Function\"\n dropped.push(name)\n return `<unserializable: ${name}>`\n }\n if (t === \"symbol\") {\n dropped.push(\"Symbol\")\n return \"<unserializable: Symbol>\"\n }\n if (t !== \"object\") {\n return undefined // e.g. undefined; JSON omits/normalizes it\n }\n const obj = value as object\n const className =\n (obj as { constructor?: { name?: string } }).constructor?.name ||\n \"object\"\n if (seen.has(obj)) {\n dropped.push(className)\n return `<cycle: ${className}>`\n }\n seen.add(obj)\n let result: unknown\n if (Array.isArray(obj)) {\n result = obj.map((item) => sanitize(item, seen))\n } else if (typeof (obj as { toJSON?: unknown }).toJSON === \"function\") {\n try {\n result = sanitize((obj as { toJSON(): unknown }).toJSON(), seen)\n } catch {\n dropped.push(className)\n result = `<unserializable: ${className}>`\n }\n } else {\n try {\n const out: Record<string, unknown> = {}\n for (const [k, v] of Object.entries(obj)) {\n out[k] = sanitize(v, seen)\n }\n result = out\n } catch {\n // A throwing getter or Proxy on `obj` can make `Object.entries`\n // throw. Stub just this object instead of failing the whole payload\n // (which would drop every span field). Mirrors the toJSON branch.\n warnOnce(\n \"payload:field-getter-threw\",\n \"a value with a throwing getter/proxy could not be serialized into a span payload; it was replaced with a placeholder. The span still ships with its other fields intact.\",\n )\n dropped.push(className)\n result = `<unserializable: ${className}>`\n }\n }\n seen.delete(obj) // backtrack: only ancestors stay tracked\n return result\n }\n let sanitized: unknown\n try {\n sanitized = sanitize(payload, new WeakSet())\n } catch (error) {\n // Truly pathological. Still never drop silently: send a marker body.\n const message = error instanceof Error ? error.message : String(error)\n const marker = { error: `payload_serialize_failed: ${message}` }\n return { body: JSON.stringify(marker), dropped, value: marker }\n }\n // Keep the server-side signal that the SDK had to stub values, so the\n // trace can be flagged as possibly incomplete / not replayable, while the\n // span content (everything that did serialize) is preserved.\n const isRecord =\n typeof sanitized === \"object\" &&\n sanitized !== null &&\n !Array.isArray(sanitized)\n if (dropped.length > 0 && isRecord) {\n const obj = sanitized as Record<string, unknown>\n const existing = Array.isArray(obj.errors) ? obj.errors : []\n obj.errors = [\n ...existing,\n {\n source: \"sdk\",\n step: \"json_serialize\",\n error: `stubbed non-serializable value(s): ${[\n ...new Set(dropped),\n ].join(\", \")}`,\n },\n ]\n }\n return {\n body: JSON.stringify(sanitized),\n dropped,\n value: isRecord ? (sanitized as Record<string, unknown>) : undefined,\n }\n }\n}\n","/**\n * The boundary every instrumentation path crosses to hand a Bitfab payload to\n * the network. Kept in its own module, free of both `http.ts` and `otel.ts`,\n * so the HTTP client can depend on the transport contract without importing\n * the OpenTelemetry implementation (and vice versa).\n */\n\nimport type { EncodedRequestBody } from \"./compress.js\"\n\n/** Which Bitfab payload a carrier span holds. */\nexport type TraceOperation =\n | \"external_span\"\n | \"external_trace\"\n | \"internal_trace\"\n\n/**\n * Posts one fully-encoded request body and resolves once the server has\n * accepted it whole. Supplied by `HttpClient`, which owns the endpoint, the\n * auth, and what the server's answer means: a rejection arrives here as a\n * {@link DeliveryError}, so the transport decides whether to retry without ever\n * reading a response.\n *\n * The request arrives already encoded, carrying its own content encoding and\n * byte counts: the exporter assembles it from per-span encodes it has to\n * produce anyway to size a request, so handing over an object here would make\n * the client encode the same batch a second time.\n */\nexport type DirectBatchSender = (\n request: EncodedRequestBody,\n timeoutMs: number,\n) => Promise<void>\n\n/**\n * Why a delivery failed, in the only two terms the transport acts on. A sender\n * classifies everything it can see, including a network fault carrying no\n * verdict; anything else reaching the transport is a fault in the sender and is\n * not retried.\n */\nexport class DeliveryError extends Error {\n readonly retryable: boolean\n readonly oversized: boolean\n /** How long the server asked us to wait, when it said so. */\n readonly retryAfterMs?: number\n\n constructor(\n message: string,\n options: {\n retryable?: boolean\n oversized?: boolean\n retryAfterMs?: number\n } = {},\n ) {\n super(message)\n this.name = \"DeliveryError\"\n this.retryable = options.retryable ?? false\n this.oversized = options.oversized ?? false\n this.retryAfterMs = options.retryAfterMs\n }\n}\n\n/**\n * Which carrier a payload is, for delivery accounting only. Supplied by the\n * caller that built the payload: the transport never reads inside one.\n *\n * `spanId` is omitted for the carrier that closes a trace, which is what tells\n * the transport the trace's expected set has stopped growing.\n */\nexport interface CarrierRef {\n traceId: string\n spanId?: string\n}\n\n/**\n * Everything the transport needs to know ABOUT a payload without reading one.\n * Supplied by the caller that built it; each field falls back to something the\n * transport can decide without looking inside.\n */\nexport interface CarrierMeta {\n /** Delivery identity. Omitted for carriers nobody accounts for. */\n ref?: CarrierRef\n /** Carrier span name. Defaults to `bitfab.<operation>`. */\n name?: string\n /** Epoch ms. Omitted lets OTel stamp the carrier as it is created. */\n startTime?: number\n endTime?: number\n /** Marks the carrier span errored. */\n errored?: boolean\n}\n\nexport interface TraceTransport {\n /** Queue a payload. Never throws; delivery failures degrade silently. */\n submit(\n operation: TraceOperation,\n payload: Record<string, unknown>,\n meta?: CarrierMeta,\n ): void\n /** Drain the queue within `timeoutMs`. False on export failure or timeout. */\n flush(timeoutMs?: number): Promise<boolean>\n /** Flush, then permanently stop this transport. */\n shutdown(timeoutMs?: number): Promise<boolean>\n}\n","/**\n * Best-effort `unref()` on a timer handle so a pending timeout never keeps the\n * Node.js event loop alive on its own. An un-unref'd timeout would delay\n * process exit, prolong a serverless function's billed lifetime, and hang test\n * runners until it fires.\n *\n * In the browser `setTimeout` returns a number with no `unref`, so this is a\n * no-op there. Callers should still `clearTimeout` the handle once the work it\n * guards has settled.\n */\nexport function unrefTimer(timer: ReturnType<typeof setTimeout>): void {\n const handle = timer as { unref?: () => void }\n if (typeof handle.unref === \"function\") {\n handle.unref()\n }\n}\n","/**\n * OpenTelemetry transport for Bitfab spans and trace completions.\n *\n * OTel is used here as a queueing, batching, and delivery engine only. Bitfab\n * keeps ownership of logical trace identity: every payload travels inside an\n * internal *carrier* span whose `bitfab.payload` attribute holds the encoded\n * Bitfab body, and the server reconstructs the stored tree from that payload\n * rather than from the carrier's OTel topology. The provider and processor are\n * private to each client, so an application's own OTel traces are never mixed\n * into Bitfab traces and the global provider is never replaced.\n */\n\nimport { type Span, SpanStatusCode, type Tracer } from \"@opentelemetry/api\"\nimport {\n type ExportResult,\n ExportResultCode,\n type InstrumentationScope,\n} from \"@opentelemetry/core\"\nimport { resourceFromAttributes } from \"@opentelemetry/resources\"\nimport {\n AlwaysOnSampler,\n BasicTracerProvider,\n BatchSpanProcessor,\n type ReadableSpan,\n type SpanExporter,\n} from \"@opentelemetry/sdk-trace-base\"\nimport { type EncodedRequestBody, encodeRequestBody } from \"./compress.js\"\nimport { __version__ } from \"./constants.js\"\nimport { BitfabError } from \"./errors.js\"\nimport {\n byteLength,\n MAX_COMPRESSIBLE_SPAN_CARRIER_BYTES,\n MAX_SPAN_CARRIER_BYTES,\n} from \"./payloadBudget.js\"\nimport { readEnv } from \"./readEnv.js\"\nimport { serializePayloadBody } from \"./serializePayload.js\"\nimport type {\n CarrierMeta,\n CarrierRef,\n DirectBatchSender,\n TraceOperation,\n TraceTransport,\n} from \"./transportTypes.js\"\nimport { DeliveryError } from \"./transportTypes.js\"\nimport { unrefTimer } from \"./unrefTimer.js\"\nimport { warnOnce } from \"./warnOnce.js\"\n\nconst OPERATION_ATTRIBUTE = \"bitfab.operation\"\nconst PAYLOAD_ATTRIBUTE = \"bitfab.payload\"\nconst MAX_EXPORT_REQUEST_BYTES = 3_000_000\nconst MAX_DECOMPRESSED_REQUEST_BYTES = 8_000_000\nconst MAX_REQUEST_BYTES_ENV = \"BITFAB_OTEL_MAX_REQUEST_BYTES\"\nconst EXPORT_CONCURRENCY_ENV = \"BITFAB_OTEL_EXPORT_CONCURRENCY\"\nconst MAX_QUEUE_SIZE = 8_192\nconst DIRECT_MAX_EXPORT_BATCH_SIZE = 512\nconst DIRECT_MAX_REQUEST_BATCH_SIZE = 128\nconst DEFAULT_EXPORT_CONCURRENCY = 32\nconst MAX_EXPORT_CONCURRENCY = 64\nconst SCHEDULE_DELAY_MILLIS = 5_000\nconst EXPORT_TIMEOUT_MILLIS = 30_000\nconst RETRY_BASE_DELAY_MILLIS = 100\n// Ceiling on the exponential growth of our OWN backoff. It does not bound a\n// wait the server asked for: OTLP says to honor Retry-After, and warns that a\n// delay big enough to make the client drop data is the server's mistake to\n// avoid, not the client's cue to discard. What bounds an honored wait is the\n// export budget below, since a wait outliving the export cannot be served.\nconst RETRY_BACKOFF_CEILING_MILLIS = 5_000\nconst MAX_SEND_ATTEMPTS = 3\nconst DEFAULT_LIFECYCLE_TIMEOUT_MS = 30_000\n\nconst liveTransports = new Set<OtelBatchTransport>()\n\n// Keyed by the carrier span object so a dropped span needs no cleanup. The ref\n// cannot ride on the span as an attribute: `spanLimits` caps carriers at two,\n// and `bitfab.operation` and `bitfab.payload` hold both.\nconst carrierRefs = new WeakMap<object, CarrierRef>()\n\nfunction readBoundedIntEnv(\n name: string,\n max: number,\n fallback: number,\n warnKey: string,\n): number {\n const raw = readEnv(name)\n if (raw === undefined) {\n return fallback\n }\n const value = Number(raw)\n if (Number.isInteger(value) && value > 0 && value <= max) {\n return value\n }\n warnOnce(\n warnKey,\n `${name} must be a positive integer no greater than ${max}; using ${fallback}`,\n )\n return fallback\n}\n\nfunction logError(message: string, error?: unknown): void {\n try {\n if (error === undefined) {\n console.error(`[bitfab] ${message}`)\n } else {\n console.error(`[bitfab] ${message}`, error)\n }\n } catch {\n // Logging must never crash the host app.\n }\n}\n\nfunction otlpValue(value: unknown): Record<string, unknown> {\n if (typeof value === \"boolean\") {\n return { boolValue: value }\n }\n if (typeof value === \"number\") {\n return Number.isInteger(value)\n ? { intValue: String(value) }\n : { doubleValue: value }\n }\n if (typeof value === \"string\") {\n return { stringValue: value }\n }\n if (Array.isArray(value)) {\n return { arrayValue: { values: value.map(otlpValue) } }\n }\n return { stringValue: String(value) }\n}\n\nfunction otlpAttributes(\n attributes: Record<string, unknown> | undefined,\n): Record<string, unknown>[] {\n if (!attributes) {\n return []\n }\n return Object.entries(attributes)\n .filter(([, value]) => value !== undefined)\n .map(([key, value]) => ({ key, value: otlpValue(value) }))\n}\n\n/**\n * Nanoseconds since the epoch as a decimal string. Built by concatenation\n * rather than arithmetic because the value exceeds `Number.MAX_SAFE_INTEGER`,\n * so multiplying seconds out would silently lose the low digits.\n */\nfunction hrTimeToNanoString(time: [number, number] | undefined): string {\n if (!time) {\n return \"0\"\n }\n return `${time[0]}${String(time[1]).padStart(9, \"0\")}`\n}\n\nfunction spanToOtlp(span: ReadableSpan): Record<string, unknown> {\n const spanContext = span.spanContext()\n const result: Record<string, unknown> = {\n traceId: spanContext.traceId,\n spanId: spanContext.spanId,\n name: span.name,\n kind: span.kind + 1,\n startTimeUnixNano: hrTimeToNanoString(span.startTime),\n endTimeUnixNano: hrTimeToNanoString(span.endTime),\n attributes: otlpAttributes(span.attributes as Record<string, unknown>),\n droppedAttributesCount: span.droppedAttributesCount,\n droppedEventsCount: span.droppedEventsCount,\n droppedLinksCount: span.droppedLinksCount,\n status: {\n code: span.status.code,\n ...(span.status.message ? { message: span.status.message } : {}),\n },\n flags: spanContext.traceFlags,\n }\n const parentSpanId = span.parentSpanContext?.spanId\n if (parentSpanId) {\n result.parentSpanId = parentSpanId\n }\n if (spanContext.traceState) {\n result.traceState = spanContext.traceState.serialize()\n }\n return result\n}\n\n/**\n * A span encoded exactly as it will appear on the wire, carrying its own byte\n * count. Encoding once and remembering the size is what keeps request packing\n * linear: sizing a candidate batch by re-encoding the whole request re-escapes\n * every carrier's `bitfab.payload` string on every span considered.\n */\ninterface EncodedSpan {\n json: string\n size: number\n ref?: CarrierRef\n}\n\ninterface RequestBatch {\n spans: EncodedSpan[]\n size: number\n}\n\n/**\n * The invariant head and tail of an OTLP request for one export window. Key\n * order matches what `JSON.stringify` emits for the equivalent object, so a\n * body assembled by concatenation is byte-identical to encoding that object.\n */\ninterface RequestEnvelope {\n head: string\n tail: string\n size: number\n}\n\n/** The comma `join` puts between adjacent spans in the request's span list. */\nconst SPAN_SEPARATOR_BYTES = 1\n\nfunction encodeSpan(span: ReadableSpan): EncodedSpan {\n const json = JSON.stringify(spanToOtlp(span))\n return {\n json,\n size: byteLength(json),\n ref: carrierRefs.get(span),\n }\n}\n\nfunction trimEncodedSpan(span: EncodedSpan): EncodedSpan | undefined {\n try {\n const carrier = JSON.parse(span.json) as {\n attributes?: Array<{\n key?: string\n value?: { stringValue?: string }\n }>\n }\n const attribute = carrier.attributes?.find(\n (entry) => entry.key === PAYLOAD_ATTRIBUTE,\n )\n const payloadBody = attribute?.value?.stringValue\n if (!attribute?.value || payloadBody === undefined) {\n return undefined\n }\n const payload = JSON.parse(payloadBody) as Record<string, unknown>\n attribute.value.stringValue = serializePayloadBody(\n payload,\n MAX_SPAN_CARRIER_BYTES,\n ).body\n const json = JSON.stringify(carrier)\n return { json, size: byteLength(json) }\n } catch {\n return undefined\n }\n}\n\nasync function prepareRequest(body: string): Promise<EncodedRequestBody> {\n const prepared = encodeRequestBody(body)\n return prepared instanceof Promise ? await prepared : prepared\n}\n\nfunction requestEnvelope(first: ReadableSpan): RequestEnvelope {\n const scope = first.instrumentationScope as InstrumentationScope\n const resource = JSON.stringify({\n attributes: otlpAttributes(\n first.resource.attributes as Record<string, unknown>,\n ),\n })\n const scopeJson = JSON.stringify({\n name: scope.name,\n version: scope.version ?? \"\",\n })\n const head = `{\"resourceSpans\":[{\"resource\":${resource},\"scopeSpans\":[{\"scope\":${scopeJson},\"spans\":[`\n const tail = \"]}]}]}\"\n return { head, tail, size: byteLength(head) + byteLength(tail) }\n}\n\nfunction encodeRequest(\n envelope: RequestEnvelope,\n spans: EncodedSpan[],\n): string {\n return (\n envelope.head + spans.map((span) => span.json).join(\",\") + envelope.tail\n )\n}\n\nfunction delay(ms: number): Promise<void> {\n return new Promise((resolve) => {\n const timer = setTimeout(resolve, ms)\n unrefTimer(timer)\n })\n}\n\n/**\n * Race `work` against `timeoutMs`. Resolves `false` when the deadline wins, so\n * a wedged export can never hold a flush or shutdown open past its budget.\n */\nasync function withDeadline(\n work: Promise<boolean>,\n timeoutMs: number,\n): Promise<boolean> {\n let timer: ReturnType<typeof setTimeout> | undefined\n try {\n return await Promise.race([\n work,\n new Promise<boolean>((resolve) => {\n timer = setTimeout(() => resolve(false), Math.max(0, timeoutMs))\n unrefTimer(timer)\n }),\n ])\n } finally {\n if (timer) {\n clearTimeout(timer)\n }\n }\n}\n\n/** Run `task` over `items` with at most `limit` in flight at any moment. */\nasync function mapWithConcurrency<T, R>(\n items: T[],\n limit: number,\n task: (item: T) => Promise<R>,\n): Promise<R[]> {\n const results = new Array<R>(items.length)\n let next = 0\n const workers = Array.from(\n { length: Math.min(Math.max(limit, 1), items.length) },\n async () => {\n while (next < items.length) {\n const index = next\n next += 1\n results[index] = await task(items[index])\n }\n },\n )\n await Promise.all(workers)\n return results\n}\n\n/**\n * Only what the sender classified. Anything else reaching here is a fault in\n * the sender itself, and retrying a deterministic bug just delays it.\n */\nfunction isRetryable(error: unknown): boolean {\n return error instanceof DeliveryError && error.retryable\n}\n\nfunction isOversized(error: unknown): boolean {\n return error instanceof DeliveryError && error.oversized\n}\n\n/**\n * How long to wait before the next send attempt, or `null` to stop trying.\n *\n * A server that sent `Retry-After` has told us when it wants us back, so that\n * wait is honored exactly. Clamping it would return early, which is the single\n * thing the server asked us not to do; when the wait is longer than we are\n * willing to hold a batch, the honest answer is to give up rather than come\n * back sooner and add load to something already struggling.\n *\n * Absent an instruction, back off exponentially so a struggling server is not\n * hit on a fixed cadence, and jitter it so every client in a fleet does not\n * return in lockstep.\n */\n/**\n * How long to wait before the next attempt, or null when the wait cannot be\n * served inside `remainingMillis` and the batch has to be given up.\n *\n * A server that sent Retry-After told us when it wants us back, so that wait is\n * honored whole rather than shortened: coming back early is the one thing it\n * asked us not to do. It is refused only when it outlasts the export budget,\n * where waiting would mean being killed mid-wait and losing the batch anyway.\n *\n * Absent an instruction, back off exponentially so a struggling server is not\n * hit on a fixed cadence, and jitter it so a fleet does not return in lockstep.\n */\nfunction retryWaitMillis(\n error: unknown,\n attempt: number,\n remainingMillis: number,\n): number | null {\n const requested =\n error instanceof DeliveryError ? error.retryAfterMs : undefined\n // Half the remaining budget, not all of it: a wait is only worth taking if\n // what is left afterwards can still carry the request. Spending the whole\n // budget waiting means being killed mid-wait, which loses the batch AND holds\n // an export slot for the duration.\n const affordable = remainingMillis / 2\n if (requested !== undefined) {\n return requested < affordable ? requested : null\n }\n const backoff = Math.min(\n RETRY_BASE_DELAY_MILLIS * 2 ** attempt,\n RETRY_BACKOFF_CEILING_MILLIS,\n )\n const jittered = backoff / 2 + Math.random() * (backoff / 2)\n return jittered < affordable ? jittered : null\n}\n\n/**\n * Direct delivery to Bitfab's OTLP/JSON ingress.\n *\n * OTel hands this exporter one batch as a candidate window. The window is\n * repacked into requests bounded by both a carrier count and the exact encoded\n * request size, and those complete requests are sent concurrently. That keeps\n * OTel's queue, scheduling, force-flush and shutdown while restoring the small\n * independent requests Bitfab's serverless ingress is built to scale.\n */\nexport class BitfabSpanExporter implements SpanExporter {\n constructor(\n private readonly directSender: DirectBatchSender,\n private readonly maxRequestBytes: number,\n private readonly maxRequestBatchSize: number,\n private readonly exportConcurrency: number,\n private readonly onDelivered?: (refs: CarrierRef[]) => void,\n // The same budget the processor enforces around this export. Waits are\n // measured against it, so a configured timeout and the deadline a wait is\n // judged by can never drift apart.\n private readonly exportTimeoutMillis: number = EXPORT_TIMEOUT_MILLIS,\n ) {}\n\n /** Epoch ms until which the server has asked this exporter to stay away. */\n private throttledUntil = 0\n\n export(\n spans: ReadableSpan[],\n resultCallback: (result: ExportResult) => void,\n ): void {\n void this.exportAsync(spans).then(\n (succeeded) => {\n resultCallback({\n code: succeeded ? ExportResultCode.SUCCESS : ExportResultCode.FAILED,\n })\n },\n (error) => {\n resultCallback({ code: ExportResultCode.FAILED, error })\n },\n )\n }\n\n private async exportAsync(spans: ReadableSpan[]): Promise<boolean> {\n if (spans.length === 0) {\n return true\n }\n let encoded: EncodedSpan[]\n let envelope: RequestEnvelope\n try {\n encoded = spans.map(encodeSpan)\n envelope = requestEnvelope(spans[0])\n } catch (error) {\n logError(\"failed to encode an OpenTelemetry span batch\", error)\n return false\n }\n\n const batches = this.buildRequestBatches(envelope, encoded)\n const results = await mapWithConcurrency(\n batches,\n this.exportConcurrency,\n (batch) => this.send(envelope, batch),\n )\n return results.every(Boolean)\n }\n\n private buildRequestBatches(\n envelope: RequestEnvelope,\n spans: EncodedSpan[],\n ): RequestBatch[] {\n const batches: RequestBatch[] = []\n let current: EncodedSpan[] = []\n let size = envelope.size\n\n for (const span of spans) {\n const addition =\n span.size + (current.length > 0 ? SPAN_SEPARATOR_BYTES : 0)\n if (\n current.length > 0 &&\n (current.length >= this.maxRequestBatchSize ||\n size + addition > this.maxRequestBytes)\n ) {\n batches.push({ spans: current, size })\n current = []\n size = envelope.size\n }\n current.push(span)\n size += span.size + (current.length > 1 ? SPAN_SEPARATOR_BYTES : 0)\n }\n\n if (current.length > 0) {\n batches.push({ spans: current, size })\n }\n return batches\n }\n\n private async send(\n envelope: RequestEnvelope,\n batch: RequestBatch,\n ): Promise<boolean> {\n try {\n let requestSpans = batch.spans\n let requestRawBytes = batch.size\n let alreadyTrimmed = false\n while (true) {\n if (requestRawBytes <= MAX_DECOMPRESSED_REQUEST_BYTES) {\n const prepared = await prepareRequest(\n encodeRequest(envelope, requestSpans),\n )\n if (prepared.wireBytes <= this.maxRequestBytes) {\n await this.sendWithRetries(prepared)\n // Refs come from the batch, not the possibly-trimmed request:\n // trimming rebuilds a span without its ref, and a trimmed carrier\n // still reached the server under its original identity.\n this.reportDelivered(batch.spans)\n return true\n }\n }\n\n if (batch.spans.length !== 1) {\n logError(\n \"an OpenTelemetry span batch exceeded the configured request-size target and could not be exported\",\n )\n return false\n }\n if (alreadyTrimmed) {\n logError(\n \"a single OpenTelemetry span exceeded the configured request-size target after trimming\",\n )\n return false\n }\n const trimmed = trimEncodedSpan(batch.spans[0])\n if (!trimmed) {\n logError(\n \"a single OpenTelemetry span exceeded the configured request-size target and could not be trimmed\",\n )\n return false\n }\n requestSpans = [trimmed]\n requestRawBytes = envelope.size + trimmed.size\n alreadyTrimmed = true\n }\n } catch (error) {\n if (isOversized(error)) {\n logError(\n batch.spans.length === 1\n ? \"a single OpenTelemetry span exceeded the ingestion request limit and could not be exported\"\n : \"an OpenTelemetry span batch exceeded the ingestion request limit and could not be exported\",\n )\n return false\n }\n logError(\"failed to export an OpenTelemetry span batch\", error)\n return false\n }\n }\n\n /**\n * Retries transient failures. Span and trace-completion carriers are safe to\n * retry: the server keys them idempotently on `sourceSpanId`/`sourceTraceId`,\n * so a duplicate delivery cannot create a duplicate row.\n *\n * KNOWN LIMITATION: an `internal_trace` (a `call()` BAML trace) carries no\n * such key, so retrying a batch that holds one can create a duplicate trace -\n * including when a request times out client-side but the server goes on to\n * persist it. Accepted deliberately for now, matching the other SDKs, rather\n * than skipping retries for a whole batch or inventing an idempotency scheme\n * the server does not yet understand. The fix is a client-supplied\n * idempotency key that ingestion dedupes on.\n */\n /**\n * Remember a throttle the server asked for, so the requests fanned out\n * alongside this one respect it too. Delaying only the request that was\n * refused leaves the other seven in the window hitting a server that just\n * asked for room.\n */\n private recordThrottle(error: unknown): void {\n const requested =\n error instanceof DeliveryError ? error.retryAfterMs : undefined\n if (requested !== undefined) {\n this.throttledUntil = Math.max(\n this.throttledUntil,\n Date.now() + requested,\n )\n }\n }\n\n /**\n * Waits out an active throttle, or reports the batch undeliverable when the\n * throttle outlasts what we are willing to hold it for. Either way nothing is\n * sent while the server has asked us to stay away.\n */\n private async awaitThrottle(deadline: number): Promise<void> {\n const remaining = this.throttledUntil - Date.now()\n if (remaining <= 0) {\n return\n }\n // Waited out, not refused: OTLP asks the client to hold off until the\n // window passes, and treats data dropped while throttled as the outcome to\n // avoid. Only a throttle outliving the export budget is refused, because\n // the processor would kill the wait before it could send anyway.\n if (remaining >= (deadline - Date.now()) / 2) {\n throw new DeliveryError(\n `OTLP ingestion is throttled for another ${remaining}ms, longer than the export budget`,\n )\n }\n await delay(remaining)\n }\n\n private async sendWithRetries(request: EncodedRequestBody): Promise<void> {\n // One budget for the whole exchange, waits included: the processor kills\n // the export at this deadline, so a wait past it cannot be served.\n const deadline = Date.now() + this.exportTimeoutMillis\n for (let attempt = 0; attempt < MAX_SEND_ATTEMPTS; attempt += 1) {\n try {\n await this.awaitThrottle(deadline)\n await this.directSender(request, Math.max(0, deadline - Date.now()))\n return\n } catch (error) {\n if (isOversized(error)) {\n throw error\n }\n this.recordThrottle(error)\n if (attempt === MAX_SEND_ATTEMPTS - 1 || !isRetryable(error)) {\n throw error\n }\n const wait = retryWaitMillis(error, attempt, deadline - Date.now())\n if (wait === null) {\n throw error\n }\n await delay(wait)\n }\n }\n }\n\n /**\n * Announce the carriers a request delivered. Wrapped because a listener that\n * throws must never turn a delivered batch into a failed export.\n */\n private reportDelivered(spans: EncodedSpan[]): void {\n if (this.onDelivered === undefined) {\n return\n }\n const refs = spans\n .map((span) => span.ref)\n .filter((ref): ref is CarrierRef => ref !== undefined)\n if (refs.length === 0) {\n return\n }\n try {\n this.onDelivered(refs)\n } catch (error) {\n logError(\"a delivery listener threw\", error)\n }\n }\n\n async shutdown(): Promise<void> {}\n\n async forceFlush(): Promise<void> {}\n}\n\n/**\n * Counts export failures so `flush` can answer \"was this delivered?\" instead of\n * only \"did the processor queue drain?\". Without it a flush would report\n * success for a batch the exporter dropped, and replay would finalize a run\n * whose traces never landed.\n */\nclass DeliveryTrackingExporter implements SpanExporter {\n // Deliberately unscoped, matching the Python SDK. An export can outlive\n // OTel's export timeout and report failure after the flush that was waiting\n // on it already returned, so that failure surfaces on the NEXT flush instead.\n // That over-reports: a good flush can inherit an older failure. The\n // alternative - discarding failures from completed flush windows - under-\n // reports, and `BatchSpanProcessor` also runs scheduled exports that belong\n // to no flush at all, so their failures would vanish entirely. For a\n // telemetry SDK a false \"flush failed\" is investigable; a false \"flush\n // succeeded\" silently loses traces. We take the noisy direction on purpose.\n private failedExports = 0\n\n constructor(private readonly exporter: SpanExporter) {}\n\n export(\n spans: ReadableSpan[],\n resultCallback: (result: ExportResult) => void,\n ): void {\n try {\n this.exporter.export(spans, (result) => {\n if (result.code !== ExportResultCode.SUCCESS) {\n this.failedExports += 1\n }\n resultCallback(result)\n })\n } catch (error) {\n this.failedExports += 1\n resultCallback({ code: ExportResultCode.FAILED, error: error as Error })\n }\n }\n\n takeFailedExports(): number {\n const failed = this.failedExports\n this.failedExports = 0\n return failed\n }\n\n shutdown(): Promise<void> {\n return this.exporter.shutdown()\n }\n\n forceFlush(): Promise<void> {\n return this.exporter.forceFlush?.() ?? Promise.resolve()\n }\n}\n\nexport interface OtelBatchTransportOptions {\n directSender: DirectBatchSender\n /** Called with the refs of every carrier a request delivered. */\n onDelivered?: (refs: CarrierRef[]) => void\n maxExportBatchSize?: number\n maxRequestBatchSize?: number\n maxQueueSize?: number\n exportConcurrency?: number\n maxRequestBytes?: number\n /** Overridable so tests can drive OTel's export-timeout path in ms, not 30s. */\n exportTimeoutMillis?: number\n}\n\nexport class OtelBatchTransport implements TraceTransport {\n private readonly provider: BasicTracerProvider\n private readonly processor: BatchSpanProcessor\n private readonly deliveryTracker: DeliveryTrackingExporter\n private readonly tracer: Tracer\n private closed = false\n private pendingFlush: Promise<boolean> | undefined\n\n constructor(options: OtelBatchTransportOptions) {\n const maxRequestBytes = options.maxRequestBytes ?? MAX_EXPORT_REQUEST_BYTES\n const maxRequestBatchSize =\n options.maxRequestBatchSize ?? DIRECT_MAX_REQUEST_BATCH_SIZE\n if (maxRequestBatchSize <= 0) {\n throw new BitfabError(\"maxRequestBatchSize must be a positive integer\")\n }\n\n this.deliveryTracker = new DeliveryTrackingExporter(\n new BitfabSpanExporter(\n options.directSender,\n maxRequestBytes,\n maxRequestBatchSize,\n options.exportConcurrency ?? DEFAULT_EXPORT_CONCURRENCY,\n options.onDelivered,\n options.exportTimeoutMillis ?? EXPORT_TIMEOUT_MILLIS,\n ),\n )\n\n this.processor = new BatchSpanProcessor(this.deliveryTracker, {\n maxQueueSize: options.maxQueueSize ?? MAX_QUEUE_SIZE,\n maxExportBatchSize:\n options.maxExportBatchSize ?? DIRECT_MAX_EXPORT_BATCH_SIZE,\n scheduledDelayMillis: SCHEDULE_DELAY_MILLIS,\n exportTimeoutMillis: options.exportTimeoutMillis ?? EXPORT_TIMEOUT_MILLIS,\n })\n\n // Every option is passed explicitly: `BasicTracerProvider` otherwise reads\n // OTEL_* defaults, so a host application's sampler or attribute-length\n // limit would silently drop or truncate Bitfab payloads.\n this.provider = new BasicTracerProvider({\n sampler: new AlwaysOnSampler(),\n resource: resourceFromAttributes({\n \"service.name\": \"bitfab-typescript-sdk\",\n \"service.version\": __version__,\n }),\n spanLimits: {\n attributeCountLimit: 2,\n attributeValueLengthLimit: Number.POSITIVE_INFINITY,\n },\n spanProcessors: [this.processor],\n })\n this.tracer = this.provider.getTracer(\"bitfab\", __version__)\n liveTransports.add(this)\n }\n\n submit(\n operation: TraceOperation,\n payload: Record<string, unknown>,\n meta: CarrierMeta = {},\n ): void {\n if (this.closed) {\n warnOnce(\n \"otel-submit-after-shutdown\",\n \"OpenTelemetry transport is shut down; dropping spans\",\n )\n return\n }\n try {\n // Not a bare JSON.stringify: contexts, metadata and `call()` inputs\n // never pass through `serializeValue`, so one stray value here would\n // throw and drop the whole span rather than being stubbed. This is the\n // same backstop the pre-transport HTTP path applied.\n const { body, dropped } = serializePayloadBody(\n payload,\n MAX_COMPRESSIBLE_SPAN_CARRIER_BYTES,\n )\n if (dropped.length > 0) {\n warnOnce(\n \"otel-carrier-payload-stubbed\",\n `a span payload held non-serializable value(s) (${[\n ...new Set(dropped),\n ].join(\", \")}); they were stubbed so the span still ships, but the ` +\n \"trace may be incomplete or not replayable.\",\n )\n }\n const span = this.tracer.startSpan(meta.name ?? `bitfab.${operation}`, {\n attributes: {\n [OPERATION_ATTRIBUTE]: operation,\n [PAYLOAD_ATTRIBUTE]: body,\n },\n startTime: meta.startTime,\n })\n if (meta.ref !== undefined) {\n carrierRefs.set(span, meta.ref)\n }\n if (meta.errored === true) {\n span.setStatus({ code: SpanStatusCode.ERROR })\n }\n endSpan(span, meta.endTime)\n } catch (error) {\n logError(\"failed to queue an OpenTelemetry span\", error)\n }\n }\n\n async flush(\n timeoutMs: number = DEFAULT_LIFECYCLE_TIMEOUT_MS,\n ): Promise<boolean> {\n // Serialized: two concurrent force-flushes would race for the same\n // delivery counter and one would report the other's failures as success.\n const pending = (this.pendingFlush ?? Promise.resolve(true)).then(() =>\n this.forceFlushOnce(),\n )\n this.pendingFlush = pending.catch(() => false)\n return withDeadline(pending, timeoutMs)\n }\n\n private async forceFlushOnce(): Promise<boolean> {\n try {\n await this.processor.forceFlush()\n } catch (error) {\n logError(\"failed to flush OpenTelemetry spans\", error)\n this.deliveryTracker.takeFailedExports()\n return false\n }\n return this.deliveryTracker.takeFailedExports() === 0\n }\n\n async shutdown(\n timeoutMs: number = DEFAULT_LIFECYCLE_TIMEOUT_MS,\n ): Promise<boolean> {\n const deadline = Date.now() + Math.max(timeoutMs, 0)\n this.closed = true\n const flushed = await this.flush(Math.max(0, deadline - Date.now()))\n liveTransports.delete(this)\n const shutdownCompleted = await withDeadline(\n this.provider\n .shutdown()\n .then(() => true)\n .catch((error) => {\n logError(\"failed to shut down the OpenTelemetry transport\", error)\n return false\n }),\n Math.max(0, deadline - Date.now()),\n )\n return flushed && shutdownCompleted\n }\n}\n\nfunction endSpan(span: Span, endTime: number | undefined): void {\n span.end(endTime)\n}\n\nexport function createOtelTransport(options: {\n directSender: DirectBatchSender\n onDelivered?: (refs: CarrierRef[]) => void\n}): OtelBatchTransport {\n return new OtelBatchTransport({\n ...options,\n exportConcurrency: readBoundedIntEnv(\n EXPORT_CONCURRENCY_ENV,\n MAX_EXPORT_CONCURRENCY,\n DEFAULT_EXPORT_CONCURRENCY,\n \"otel-export-concurrency-invalid\",\n ),\n maxRequestBytes: readBoundedIntEnv(\n MAX_REQUEST_BYTES_ENV,\n MAX_EXPORT_REQUEST_BYTES,\n MAX_EXPORT_REQUEST_BYTES,\n \"otel-max-request-bytes-invalid\",\n ),\n })\n}\n\nasync function forEachLiveTransport(\n timeoutMs: number,\n run: (transport: OtelBatchTransport, remainingMs: number) => Promise<boolean>,\n): Promise<boolean> {\n const deadline = Date.now() + Math.max(timeoutMs, 0)\n let succeeded = true\n for (const transport of [...liveTransports]) {\n succeeded =\n (await run(transport, Math.max(0, deadline - Date.now()))) && succeeded\n }\n return succeeded\n}\n\nexport function flushOtelTransports(\n timeoutMs: number = DEFAULT_LIFECYCLE_TIMEOUT_MS,\n): Promise<boolean> {\n return forEachLiveTransport(timeoutMs, (transport, remaining) =>\n transport.flush(remaining),\n )\n}\n\nexport function shutdownOtelTransports(\n timeoutMs: number = DEFAULT_LIFECYCLE_TIMEOUT_MS,\n): Promise<boolean> {\n return forEachLiveTransport(timeoutMs, (transport, remaining) =>\n transport.shutdown(remaining),\n )\n}\n","/**\n * The single seam between the HTTP client and whichever transport implements\n * span delivery. Keeping the factory here (rather than importing `otel.ts`\n * from `http.ts` directly) is what lets the OpenTelemetry implementation\n * depend on `HttpClient`'s request path without an import cycle.\n */\n\nimport {\n createOtelTransport,\n flushOtelTransports,\n shutdownOtelTransports,\n} from \"./otel.js\"\nimport type {\n CarrierRef,\n DirectBatchSender,\n TraceTransport,\n} from \"./transportTypes.js\"\n\nexport function createTraceTransport(options: {\n directSender: DirectBatchSender\n onDelivered?: (refs: CarrierRef[]) => void\n}): TraceTransport {\n return createOtelTransport(options)\n}\n\nexport function flushTraceTransports(timeoutMs?: number): Promise<boolean> {\n return flushOtelTransports(timeoutMs)\n}\n\nexport function shutdownTraceTransports(timeoutMs?: number): Promise<boolean> {\n return shutdownOtelTransports(timeoutMs)\n}\n","/**\n * HTTP client utilities for Bitfab API requests.\n *\n * This module provides:\n * - HttpClient class for making API requests\n * - awaitOnExit helper so deferred span work still gates process exit\n */\n\nimport { type EncodedRequestBody, encodeRequestBody } from \"./compress.js\"\nimport { __packageName__, __version__ } from \"./constants.js\"\nimport type { DbSnapshotRef } from \"./dbSnapshot.js\"\nimport { BitfabError } from \"./errors.js\"\nimport {\n type DbBranchLease,\n type DbBranchSettings,\n type DbBranchTimings,\n replayContextReady,\n} from \"./replayContext.js\"\nimport { serializePayloadBody } from \"./serializePayload.js\"\nimport {\n createTraceTransport,\n flushTraceTransports,\n shutdownTraceTransports,\n} from \"./transport.js\"\nimport {\n type CarrierMeta,\n type CarrierRef,\n DeliveryError,\n type TraceOperation,\n type TraceTransport,\n} from \"./transportTypes.js\"\nimport { unrefTimer } from \"./unrefTimer.js\"\nimport { warnOnce } from \"./warnOnce.js\"\n\n// BitfabError lives in `errors.ts` to break the http ↔ dbSnapshot import\n// cycle. Re-exported here for backwards compatibility with existing\n// callers that import it from \"./http.js\".\nexport { BitfabError }\nexport { serializePayloadBody }\n\nconst REPLAY_DB_BRANCH_REQUEST_TIMEOUT_MS = 300_000\nconst REPLAY_COMPLETE_REQUEST_TIMEOUT_MS = 120_000\nconst OTLP_TRACES_ENDPOINT = \"/api/sdk/otel/v1/traces\"\n// OTLP's retryable set, plus 500. Every other 4xx is the server's verdict on\n// the payload and will be the same next time.\n//\n// 500 is a deliberate deviation: OTLP treats it as the app being broken, which\n// assumes a collector that fails deterministically. Bitfab ingestion answers\n// every unhandled error with 500, so a connection blip or a cold start arrives\n// here indistinguishable from a real fault, and giving up on the first one\n// drops spans that a second attempt would have delivered.\nconst RETRYABLE_STATUSES = new Set([429, 500, 502, 503, 504])\nconst EXIT_FLUSH_TIMEOUT_MS = 5_000\nconst DEFAULT_LIFECYCLE_TIMEOUT_MS = 30_000\n\n// Global set to track pending trace creation promises\n// This prevents promises from being garbage collected before they complete\nconst pendingTracePromises = new Set<Promise<unknown>>()\n\n/**\n * Track a promise so `flushTraces()` and the exit hook wait for it.\n *\n * Exactly one caller remains: the deferred `finalize` chain, which hands its\n * span to the transport only after finalize settles. Everything else submits\n * synchronously, so the transport's own queue is the complete picture. Python\n * has no equivalent because its finalize runs inline.\n *\n * @param promise - The promise to track\n * @returns The same promise (for chaining)\n */\nexport function awaitOnExit<T>(promise: Promise<T>): Promise<T> {\n pendingTracePromises.add(promise)\n // Use void to prevent unhandled rejection warnings from the .finally() chain\n // The actual error handling is done by the caller's .catch() on the returned promise\n void promise\n .finally(() => {\n pendingTracePromises.delete(promise)\n })\n .catch(() => {\n // Swallow rejection in this chain - the caller handles errors via their own .catch()\n })\n return promise\n}\n\n/**\n * Wait for pending fire-and-forget requests AND every live span transport to\n * deliver, within one total deadline. Useful in tests and scripts to ensure all\n * data has been sent before asserting or exiting.\n *\n * Returns `false` when delivery failed or the deadline expired, so a caller\n * that depends on persistence (replay does) can react instead of assuming a\n * drained queue means the server has the data.\n *\n * @param timeoutMs - Maximum total time to wait in milliseconds (default: 5000)\n */\nexport async function flushTraces(timeoutMs: number = 5000): Promise<boolean> {\n const deadline = Date.now() + Math.max(timeoutMs, 0)\n const requestsFlushed = await awaitPendingRequests(timeoutMs)\n const transportsFlushed = await flushTraceTransports(\n Math.max(0, deadline - Date.now()),\n )\n return requestsFlushed && transportsFlushed\n}\n\n/**\n * Wait for in-flight fire-and-forget requests and deferred span work, WITHOUT\n * flushing the transports.\n *\n * Replay needs this half on its own: a `finalize` span reaches the transport\n * only after its deferred chain settles, so the expected-span tally has to be\n * read after that work lands but before a flush is issued (which would be\n * wasted, and would emit a request, when the run submitted nothing).\n */\nexport async function awaitPendingRequests(\n timeoutMs: number = DEFAULT_LIFECYCLE_TIMEOUT_MS,\n): Promise<boolean> {\n // Async-context storage loads asynchronously, and spans traced before it\n // resolves have their recording deferred behind it. Without this, a script\n // that traces and immediately flushes or closes races its own first spans.\n await replayContextReady.catch(() => {})\n return waitForPromises(Array.from(pendingTracePromises), timeoutMs)\n}\n\n/**\n * Await `promises` within `timeoutMs`, reporting whether they all settled in\n * time rather than throwing. Rejections count as settled: a failed span upload\n * is already reported by its own catch handler, and the caller is asking about\n * completion, not success.\n */\nasync function waitForPromises(\n promises: Promise<unknown>[],\n timeoutMs: number,\n): Promise<boolean> {\n if (promises.length === 0) {\n return true\n }\n // Clear and unref the timeout so the loser of the race never leaves a\n // dangling timer holding the event loop open after flush resolves.\n let timer: ReturnType<typeof setTimeout> | undefined\n try {\n return await Promise.race([\n Promise.allSettled(promises).then(() => true),\n new Promise<boolean>((resolve) => {\n timer = setTimeout(() => resolve(false), timeoutMs)\n unrefTimer(timer)\n }),\n ])\n } finally {\n if (timer) {\n clearTimeout(timer)\n }\n }\n}\n\n// Register beforeExit handler to wait for pending traces (Node.js only)\n// This ensures traces are sent before the process exits (for scripts).\n// The transport is included: its batch worker sits on an unref'd timer, so a\n// script that ends without an explicit flush would otherwise exit with a queue\n// of spans still waiting on the scheduled delay.\nif (\n typeof process !== \"undefined\" &&\n process.versions != null &&\n process.versions.node != null\n) {\n let isFlushing = false\n process.on(\"beforeExit\", () => {\n if (isFlushing) {\n return\n }\n isFlushing = true\n // Awaiting here keeps the event loop alive until delivery settles.\n void Promise.allSettled([\n ...Array.from(pendingTracePromises).map((p) => p.catch(() => {})),\n shutdownTraceTransports(EXIT_FLUSH_TIMEOUT_MS).catch(() => false),\n ]).then(() => {\n isFlushing = false\n })\n })\n}\n\n/**\n * How the API key is supplied internally: either a literal string or a\n * function resolved each time the key is needed (at request/send time). The\n * function form is what defers key resolution past module-load construction\n * so an env var loaded after the client is built (the ESM dotenv-hoisting\n * case) is still picked up.\n */\nexport type ApiKeyInput = string | (() => string | undefined)\n\nexport interface HttpClientConfig {\n apiKey?: ApiKeyInput\n serviceUrl: string\n timeout?: number\n}\n\nexport type SpanOccurrence = \"first\" | \"last\" | number\n\nexport type SpanLookup =\n | { id: string; name?: never; occurrence?: never }\n | { name: string; id?: never; occurrence?: SpanOccurrence }\n\nexport interface CapturedSpan {\n id: string\n traceId: string\n parentSpanId: string | null\n name: string | null\n type: string\n input: unknown\n output: unknown\n contexts: Record<string, unknown>[]\n prompt: string | null\n metadata: Record<string, unknown>\n metrics: Record<string, unknown> | null\n errors: unknown\n startedAt: string | null\n endedAt: string | null\n}\n\n/**\n * HTTP client for Bitfab API requests.\n *\n * Provides methods for different API endpoints with proper error handling,\n * timeouts, and authentication.\n */\n/**\n * `Retry-After` as milliseconds. The header is either a delay in seconds or an\n * HTTP date; both forms appear in the wild, so both are read. Anything else, or\n * a date already in the past, yields `undefined` so the caller falls back to\n * its own backoff.\n */\n/**\n * Read one response header without letting it break delivery. `Response.headers`\n * is always present from a real `fetch`, but polyfills and doubles are looser,\n * and an optional header must never be the reason a batch fails to send.\n */\nfunction readHeader(response: Response, name: string): string | null {\n try {\n return response.headers?.get(name) ?? null\n } catch {\n return null\n }\n}\n\nexport function parseRetryAfterMs(header: string | null): number | undefined {\n // Trimmed and emptiness-checked before Number(), which reads \"\" and \" \" as\n // 0 and would turn a blank header into \"retry immediately\", skipping the\n // backoff entirely. The other SDKs treat a blank header as no instruction.\n const value = header?.trim()\n if (!value) {\n return undefined\n }\n const seconds = Number(value)\n if (Number.isFinite(seconds)) {\n return seconds >= 0 ? seconds * 1_000 : undefined\n }\n const at = Date.parse(value)\n if (Number.isNaN(at)) {\n return undefined\n }\n return Math.max(0, at - Date.now())\n}\n\n/**\n * The delivery identity of a carrier, read from the payload here because this\n * is where the payload shape is owned. The transport is handed the result and\n * never looks inside a payload itself.\n */\n/**\n * Everything the transport needs to know about a carrier, derived here because\n * this is where the payload shape is owned. The transport applies these and\n * never looks inside a payload itself.\n */\nfunction carrierMeta(\n operation: TraceOperation,\n payload: Record<string, unknown>,\n ref: CarrierRef | undefined,\n): CarrierMeta {\n return {\n ref,\n name: carrierName(operation, payload),\n startTime: payloadTimestamp(payload, \"started_at\"),\n endTime: payloadTimestamp(payload, \"ended_at\"),\n errored: payloadHasError(payload),\n }\n}\n\nfunction carrierName(\n operation: TraceOperation,\n payload: Record<string, unknown>,\n): string {\n if (operation === \"external_span\") {\n const spanData = asPayloadRecord(\n asPayloadRecord(payload.rawSpan)?.span_data,\n )\n if (typeof spanData?.name === \"string\") {\n return spanData.name\n }\n }\n if (typeof payload.traceFunctionKey === \"string\") {\n return payload.traceFunctionKey\n }\n return `bitfab.${operation}`\n}\n\n/**\n * Milliseconds since the epoch for a payload timestamp, or `undefined` to let\n * OTel stamp the carrier with the current time.\n */\nfunction payloadTimestamp(\n payload: Record<string, unknown>,\n field: string,\n): number | undefined {\n const rawSpan = asPayloadRecord(payload.rawSpan)\n const rawTrace =\n asPayloadRecord(payload.externalTrace) ?? asPayloadRecord(payload.rawTrace)\n const raw = rawSpan?.[field] ?? rawTrace?.[field]\n if (typeof raw !== \"string\") {\n return undefined\n }\n const parsed = Date.parse(raw)\n return Number.isNaN(parsed) ? undefined : parsed\n}\n\nfunction payloadHasError(payload: Record<string, unknown>): boolean {\n const spanData = asPayloadRecord(asPayloadRecord(payload.rawSpan)?.span_data)\n if (spanData?.error != null) {\n return true\n }\n const errors = payload.errors\n return Array.isArray(errors) ? errors.length > 0 : Boolean(errors)\n}\n\nfunction asPayloadRecord(value: unknown): Record<string, unknown> | undefined {\n return typeof value === \"object\" && value !== null && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : undefined\n}\n\n/** What a caller learns about one tracked trace once it takes it back. */\nexport interface DeliveryReport {\n spanCount: number\n /** A closing carrier was submitted, so the expected set is final. */\n closed: boolean\n /** Every carrier submitted under this trace came back accepted. */\n delivered: boolean\n /**\n * The server's assigned `traces.id`, read back from the OTLP ingest response.\n * Absent when talking to a server that predates this field, or before any\n * carrier for the trace has been acked.\n */\n serverTraceId?: string\n}\n\ninterface TraceDelivery {\n submittedSpanIds: Set<string>\n ackedSpanIds: Set<string>\n closed: boolean\n closingAcked: boolean\n serverTraceId?: string\n}\n\nfunction carrierRef(payload: Record<string, unknown>): CarrierRef | undefined {\n const traceId = sourceTraceIdOf(payload)\n if (traceId === undefined) {\n return undefined\n }\n const rawSpan = payload.rawSpan\n if (rawSpan === undefined) {\n return { traceId }\n }\n const spanId = (rawSpan as Record<string, unknown>)?.id\n return {\n traceId,\n spanId: typeof spanId === \"string\" ? spanId : `submission-${++carrierSeq}`,\n }\n}\n\nfunction sourceTraceIdOf(payload: Record<string, unknown>): string | undefined {\n if (typeof payload.sourceTraceId === \"string\") {\n return payload.sourceTraceId\n }\n const rawTrace = (payload.externalTrace ?? payload.rawTrace) as\n | Record<string, unknown>\n | undefined\n const id = rawTrace?.id\n return typeof id === \"string\" ? id : undefined\n}\n\nlet carrierSeq = 0\n\nexport class HttpClient {\n private readonly apiKey: ApiKeyInput | undefined\n private readonly serviceUrl: string\n private readonly timeout: number\n private traceTransport: TraceTransport | undefined\n // Only traces a caller asked about are tracked, so ordinary tracing stores\n // nothing here.\n private readonly traceDeliveries = new Map<string, TraceDelivery>()\n // Deferred span work owned by THIS client. The module-global set backs the\n // process-wide `flushTraces()` and the exit hook, but per-client lifecycle\n // must not wait on another client's slow finalize: a false `close()` failure\n // caused by unrelated work is worse than no signal at all.\n private readonly deferredWork = new Set<Promise<unknown>>()\n private closed = false\n private closing: Promise<boolean> | undefined\n\n constructor(config: HttpClientConfig) {\n this.apiKey = config.apiKey\n this.serviceUrl = config.serviceUrl\n this.timeout = config.timeout ?? 120000\n }\n\n /**\n * Resolve the API key at the moment it is needed (request time), invoking\n * the function form if one was supplied. Never read at construction.\n */\n private resolveApiKey(): string | undefined {\n return typeof this.apiKey === \"function\" ? this.apiKey() : this.apiKey\n }\n\n /**\n * This client's span transport, built on first use.\n *\n * Lazy on purpose: a client that never sends a span must never start a batch\n * worker. Every framework integration created from a `Bitfab` client shares\n * the owning client's `HttpClient`, so handlers reuse this one worker instead\n * of each spinning up their own.\n */\n private getTraceTransport(): TraceTransport | undefined {\n if (this.closed) {\n warnOnce(\n \"http-client-closed\",\n \"the Bitfab client is closed; dropping spans\",\n )\n return undefined\n }\n if (!this.traceTransport) {\n this.traceTransport = createTraceTransport({\n directSender: (request, timeoutMs) =>\n this.deliverCarriers(request, timeoutMs),\n onDelivered: (refs) => this.recordDeliveredCarriers(refs),\n })\n }\n return this.traceTransport\n }\n\n /**\n * Post one encoded batch and decide what the server's answer means, so the\n * transport never reads a response. Rejections and permanent statuses come\n * back as a non-retryable {@link DeliveryError}; anything the server might\n * still accept on a second try comes back retryable.\n */\n private async deliverCarriers(\n request: EncodedRequestBody,\n timeoutMs: number,\n ): Promise<void> {\n let response: Record<string, unknown>\n try {\n // sendPrepared, not sendEncoded: the exporter already encoded this batch\n // to size the request, and re-encoding here would do that work twice.\n response = await this.sendPrepared<Record<string, unknown>>(\n OTLP_TRACES_ENDPOINT,\n request,\n { timeout: timeoutMs },\n )\n } catch (error) {\n const status = error instanceof BitfabError ? error.status : undefined\n if (status === undefined) {\n // No verdict from the server (a network fault): worth another attempt.\n throw new DeliveryError(`OTLP ingestion failed: ${String(error)}`, {\n retryable: true,\n })\n }\n throw new DeliveryError(`OTLP ingestion failed with HTTP ${status}`, {\n retryable: RETRYABLE_STATUSES.has(status),\n oversized: status === 413,\n ...(error instanceof BitfabError && error.retryAfterMs !== undefined\n ? { retryAfterMs: error.retryAfterMs }\n : {}),\n })\n }\n\n const serverTraceIds = asPayloadRecord(response?.traceIds)\n if (serverTraceIds !== undefined) {\n this.recordServerTraceIds(serverTraceIds)\n }\n\n const partialSuccess = asPayloadRecord(response?.partialSuccess)\n const rejected = partialSuccess?.rejectedSpans\n if (rejected !== undefined && rejected !== \"0\" && rejected !== 0) {\n // The server's verdict on the payload, not a transient fault.\n throw new DeliveryError(\n `OTLP ingestion rejected ${rejected} span(s): ${\n partialSuccess?.errorMessage ?? \"no reason provided\"\n }`,\n )\n }\n }\n\n /**\n * Start tracking delivery for `traceIds`. Nothing is recorded for a trace\n * that was never tracked, so ordinary tracing costs no bookkeeping at all.\n */\n trackTraceDeliveries(traceIds: string[]): void {\n for (const traceId of traceIds) {\n if (!this.traceDeliveries.has(traceId)) {\n this.traceDeliveries.set(traceId, {\n submittedSpanIds: new Set(),\n ackedSpanIds: new Set(),\n closed: false,\n closingAcked: false,\n })\n }\n }\n }\n\n /**\n * The server's assigned `traces.id` for a tracked trace if it has already\n * been read back off an ingest response, without stopping tracking. Lets a\n * replay surface the id mid-run for items whose spans already landed.\n */\n peekServerTraceId(traceId: string): string | undefined {\n return this.traceDeliveries.get(traceId)?.serverTraceId\n }\n\n /** Whether any tracked trace has had its closing carrier submitted. */\n hasClosedDeliveries(traceIds: string[]): boolean {\n return traceIds.some((traceId) => this.traceDeliveries.get(traceId)?.closed)\n }\n\n /**\n * Report what each tracked trace submitted and whether the server confirmed\n * it, and stop tracking them. Every id passed is freed, so a caller cannot\n * leak a record for a trace that never closed.\n *\n * `delivered` is only meaningful once a flush has settled: acks land before\n * an export resolves, so a flush that reported success has already collected\n * every ack it is going to collect.\n */\n takeTraceDeliveries(traceIds: string[]): Record<string, DeliveryReport> {\n const reports: Record<string, DeliveryReport> = {}\n for (const traceId of traceIds) {\n const delivery = this.traceDeliveries.get(traceId)\n if (delivery === undefined) {\n continue\n }\n this.traceDeliveries.delete(traceId)\n reports[traceId] = {\n spanCount: delivery.submittedSpanIds.size,\n closed: delivery.closed,\n delivered:\n delivery.closingAcked &&\n [...delivery.submittedSpanIds].every((spanId) =>\n delivery.ackedSpanIds.has(spanId),\n ),\n serverTraceId: delivery.serverTraceId,\n }\n }\n return reports\n }\n\n /** Build a carrier's meta and record what it adds to its trace's expected set. */\n private recordedMeta(\n operation: TraceOperation,\n payload: Record<string, unknown>,\n ref: CarrierRef | undefined,\n ): CarrierMeta {\n this.recordSubmittedCarrier(ref)\n return carrierMeta(operation, payload, ref)\n }\n\n private recordSubmittedCarrier(ref: CarrierRef | undefined): void {\n if (ref === undefined) {\n return\n }\n const delivery = this.traceDeliveries.get(ref.traceId)\n if (delivery === undefined) {\n return\n }\n if (ref.spanId === undefined) {\n delivery.closed = true\n } else {\n delivery.submittedSpanIds.add(ref.spanId)\n }\n }\n\n /**\n * Ingestion commits every carrier in a request before it answers, so a\n * delivered ref is proof its row exists: the same fact the replay status\n * endpoint would report, already in hand.\n */\n /**\n * Record the server's assigned `traces.id` for each tracked source trace,\n * read back from the OTLP ingest response. Keyed by source trace id, the same\n * key the delivery ledger uses. Untracked ids are ignored.\n */\n private recordServerTraceIds(map: Record<string, unknown>): void {\n for (const [sourceTraceId, serverTraceId] of Object.entries(map)) {\n if (typeof serverTraceId !== \"string\") {\n continue\n }\n const delivery = this.traceDeliveries.get(sourceTraceId)\n if (delivery === undefined) {\n continue\n }\n delivery.serverTraceId = serverTraceId\n }\n }\n\n private recordDeliveredCarriers(refs: CarrierRef[]): void {\n for (const ref of refs) {\n const delivery = this.traceDeliveries.get(ref.traceId)\n if (delivery === undefined) {\n continue\n }\n if (ref.spanId === undefined) {\n delivery.closingAcked = true\n } else {\n delivery.ackedSpanIds.add(ref.spanId)\n }\n }\n }\n\n /**\n * Track deferred span work so this client's own lifecycle waits for it, and\n * so the process-wide flush and exit hook do too.\n */\n trackDeferred<T>(promise: Promise<T>): Promise<T> {\n this.deferredWork.add(promise)\n void promise\n .finally(() => this.deferredWork.delete(promise))\n .catch(() => {})\n return awaitOnExit(promise)\n }\n\n /**\n * Settle only THIS client's deferred span work. Scoped deliberately: the\n * global set can contain another client's long-running finalize, and\n * attributing its timeout here would fail a client whose own work succeeded.\n */\n async settleDeferredWork(\n timeoutMs: number = DEFAULT_LIFECYCLE_TIMEOUT_MS,\n ): Promise<boolean> {\n await replayContextReady.catch(() => {})\n return waitForPromises(Array.from(this.deferredWork), timeoutMs)\n }\n\n /**\n * Wait for spans queued by this client to be delivered, within one deadline.\n * Returns false on delivery failure or timeout.\n */\n async waitForPendingRequests(\n timeoutMs: number = DEFAULT_LIFECYCLE_TIMEOUT_MS,\n ): Promise<boolean> {\n const deadline = Date.now() + Math.max(timeoutMs, 0)\n const settled = await this.settleDeferredWork(timeoutMs)\n const flushed =\n (await this.traceTransport?.flush(Math.max(0, deadline - Date.now()))) ??\n true\n return settled && flushed\n }\n\n /**\n * Flush and permanently close this client's tracing transport. Idempotent:\n * a second call joins the first rather than tearing down a pipeline the\n * first call already owns.\n */\n close(timeoutMs: number = DEFAULT_LIFECYCLE_TIMEOUT_MS): Promise<boolean> {\n if (this.closing) {\n return this.closing\n }\n const deadline = Date.now() + Math.max(timeoutMs, 0)\n this.closing = (async () => {\n // Settle deferred span work BEFORE refusing submissions. A span whose\n // recording is still queued (the `finalize` chain, or any call made\n // before async-context storage finished loading) has not reached the\n // transport yet; flipping `closed` first would reject it on arrival and\n // silently drop a span the caller had every reason to think was captured.\n const settled = await this.settleDeferredWork(\n Math.max(0, deadline - Date.now()),\n )\n this.closed = true\n const transport = this.traceTransport\n this.traceTransport = undefined\n const shutdownOk =\n (await transport?.shutdown(Math.max(0, deadline - Date.now()))) ?? true\n // Deferred work that outran the deadline will submit into a closed\n // client and be dropped, so close cannot report success for it.\n return settled && shutdownOk\n })()\n return this.closing\n }\n\n /**\n * Make an HTTP request to the Bitfab API. Defaults to POST; pass\n * `options.method` to use a different verb (e.g. \"PATCH\").\n *\n * @param endpoint - The API endpoint (without base URL)\n * @param payload - The request body\n * @param options - Optional request options\n * @returns The parsed JSON response\n * @throws {BitfabError} If the request fails\n */\n async request<T>(\n endpoint: string,\n payload: Record<string, unknown>,\n options?: { timeout?: number; method?: \"POST\" | \"PATCH\" | \"PUT\" },\n ): Promise<T> {\n // Serialize the payload so a stray non-serializable value (BigInt,\n // function, circular ref, a class instance that slipped past upstream\n // serialization) can never abort the send and silently drop the span.\n // Strays are stubbed in place, preserving span content, and a degraded\n // payload warns loudly.\n const { body, dropped } = serializePayloadBody(payload)\n if (dropped.length > 0) {\n try {\n console.warn(\n `Bitfab: request body to ${endpoint} held ${dropped.length} ` +\n `non-serializable value(s) (${[...new Set(dropped)].join(\", \")}); ` +\n \"they were stubbed so the span still sends, but the trace may be \" +\n \"incomplete or not replayable. Capture a JSON-safe projection of \" +\n \"this input to make it replayable.\",\n )\n } catch {}\n }\n return this.sendEncoded<T>(endpoint, body, options)\n }\n\n /**\n * POST an already-encoded body. The span transport encodes its own batches,\n * so routing them back through {@link HttpClient.request} would encode the\n * same data twice.\n */\n async sendEncoded<T>(\n endpoint: string,\n body: string,\n options?: { timeout?: number; method?: \"POST\" | \"PATCH\" | \"PUT\" },\n ): Promise<T> {\n // Awaited only when compression actually runs, so an uncompressed request\n // still calls `fetch` synchronously the way it did before compression.\n const prepared = encodeRequestBody(body)\n const encoded = prepared instanceof Promise ? await prepared : prepared\n return this.sendPrepared<T>(endpoint, encoded, options)\n }\n\n private async sendPrepared<T>(\n endpoint: string,\n encoded: EncodedRequestBody,\n options?: { timeout?: number; method?: \"POST\" | \"PATCH\" | \"PUT\" },\n ): Promise<T> {\n const url = `${this.serviceUrl}${endpoint}`\n const timeout = options?.timeout ?? this.timeout\n const method = options?.method ?? \"POST\"\n\n const controller = new AbortController()\n const timeoutId = setTimeout(() => controller.abort(), timeout)\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${this.resolveApiKey() ?? \"\"}`,\n }\n if (encoded.contentEncoding) {\n headers[\"Content-Encoding\"] = encoded.contentEncoding\n }\n\n try {\n const response = await fetch(url, {\n method,\n headers,\n body: encoded.body,\n signal: controller.signal,\n })\n\n if (!response.ok) {\n const errorText = await response.text()\n throw new BitfabError(\n `HTTP ${response.status}: ${errorText.slice(0, 500)}`,\n undefined,\n response.status,\n parseRetryAfterMs(readHeader(response, \"retry-after\")),\n )\n }\n\n const result = await response.json()\n\n // Check for errors in the response\n if (result.error) {\n if (result.url) {\n throw new BitfabError(\n `${result.error} Configure it at: ${this.serviceUrl}${result.url}`,\n result.url,\n )\n }\n throw new BitfabError(result.error)\n }\n\n return result as T\n } catch (error) {\n if (error instanceof BitfabError) {\n throw error\n }\n if (error instanceof Error) {\n if (error.name === \"AbortError\") {\n throw new BitfabError(`Request timed out after ${timeout}ms`)\n }\n throw new BitfabError(error.message)\n }\n throw new BitfabError(\"Unknown error occurred\")\n } finally {\n clearTimeout(timeoutId)\n }\n }\n\n /**\n * Look up a function by name.\n * Blocks until complete - needed for function execution.\n */\n async lookupFunction<T>(name: string): Promise<T> {\n return this.request<T>(\"/api/sdk/functions/lookup\", { name })\n }\n\n async getAutoTracePolicy<T>(\n traceFunctionKey: string,\n protocol: string,\n ): Promise<T> {\n return this.request<T>(\"/api/sdk/auto-trace/policy\", {\n traceFunctionKey,\n protocol,\n })\n }\n\n async getTraceSpan(\n traceId: string,\n lookup: SpanLookup,\n ): Promise<CapturedSpan | null> {\n const searchParams = new URLSearchParams()\n if (lookup.id !== undefined) {\n searchParams.set(\"id\", lookup.id)\n } else {\n searchParams.set(\"name\", lookup.name)\n searchParams.set(\"occurrence\", String(lookup.occurrence ?? \"last\"))\n }\n\n const endpoint = `/api/sdk/traces/${encodeURIComponent(traceId)}/span?${searchParams.toString()}`\n const response = await this.get<{ span: CapturedSpan | null }>(endpoint)\n return response.span\n }\n\n /**\n * GET a JSON endpoint on the service with the client's API key. Throws a\n * `BitfabError` carrying the status text for any non-2xx response.\n */\n async get<T>(endpoint: string): Promise<T> {\n const url = `${this.serviceUrl}${endpoint}`\n const controller = new AbortController()\n const timeoutId = setTimeout(() => controller.abort(), this.timeout)\n\n try {\n const response = await fetch(url, {\n method: \"GET\",\n headers: { Authorization: `Bearer ${this.resolveApiKey() ?? \"\"}` },\n signal: controller.signal,\n })\n if (!response.ok) {\n const errorText = await response.text()\n throw new BitfabError(\n `HTTP ${response.status}: ${errorText.slice(0, 500)}`,\n undefined,\n response.status,\n parseRetryAfterMs(readHeader(response, \"retry-after\")),\n )\n }\n return (await response.json()) as T\n } catch (error) {\n if (error instanceof BitfabError) {\n throw error\n }\n if (error instanceof Error) {\n if (error.name === \"AbortError\") {\n throw new BitfabError(`Request timed out after ${this.timeout}ms`)\n }\n throw new BitfabError(error.message)\n }\n throw new BitfabError(\"Unknown error occurred\")\n } finally {\n clearTimeout(timeoutId)\n }\n }\n\n /**\n * Queue an internal trace (from local BAML execution via `call()`) onto this\n * client's batching transport. `functionId` moves into the payload because\n * the OTLP carrier has no path to carry it.\n */\n sendInternalTrace(\n functionId: string,\n payload: Record<string, unknown>,\n ): void {\n const body = {\n ...payload,\n functionId,\n sdkPackage: __packageName__,\n sdkVersion: __version__,\n }\n this.getTraceTransport()?.submit(\n \"internal_trace\",\n body,\n carrierMeta(\"internal_trace\", body, undefined),\n )\n }\n\n /**\n * Queue an external span (from withSpan wrapper or OpenAI tracing) onto this\n * client's batching transport. Fire-and-forget: the transport owns delivery,\n * so callers await `flushTraces()` or `close()` rather than a per-span\n * promise.\n */\n sendExternalSpan(payload: Record<string, unknown>): void {\n this.getTraceTransport()?.submit(\n \"external_span\",\n { ...payload, sdkVersion: __version__ },\n this.recordedMeta(\"external_span\", payload, carrierRef(payload)),\n )\n }\n\n /**\n * Queue an external trace completion (from OpenAI tracing) onto this\n * client's batching transport. Fire-and-forget for the same reason as\n * {@link HttpClient.sendExternalSpan}; replay confirms persistence with the\n * server-authoritative barrier in `replay.ts`, not by awaiting this call.\n */\n sendExternalTrace(payload: Record<string, unknown>): void {\n this.getTraceTransport()?.submit(\n \"external_trace\",\n {\n ...payload,\n sdkPackage: __packageName__,\n sdkVersion: __version__,\n },\n this.recordedMeta(\n \"external_trace\",\n payload,\n payload.completed === true ? carrierRef(payload) : undefined,\n ),\n )\n }\n\n /**\n * Partial update of an existing trace identified by its Bitfab trace ID.\n * Used by the detached `client.getTrace(id)` handle.\n *\n * Blocking, like the other trace-API calls: it resolves once the server has\n * applied the change and rejects if the server refused it. A patch targets a\n * trace that is already closed, so there is no batch for it to ride along\n * with and no later signal that would reveal a silent failure.\n */\n async patchTrace(\n traceId: string,\n payload: {\n appendContexts?: Record<string, unknown>[]\n mergeMetadata?: Record<string, unknown>\n setSessionId?: string\n setName?: string\n },\n ): Promise<void> {\n const endpoint = `/api/sdk/traces/${encodeURIComponent(traceId)}`\n await this.request(endpoint, payload, { method: \"PATCH\" })\n }\n\n /**\n * Start a replay session by fetching historical traces.\n * Blocking call - creates a test run and returns lightweight item references.\n */\n async startReplay(\n traceFunctionKey: string,\n limit: number | undefined,\n traceIds?: string[],\n name?: string,\n codeChangeDescription?: string | null,\n codeChangeFiles?: CodeChangeFile[] | null,\n includeDbBranchLease?: boolean,\n experimentGroupId?: string,\n datasetId?: string,\n graderIds?: string[],\n dbBranchSettings?: DbBranchSettings,\n attempts?: number,\n includeOriginalMetadata?: boolean,\n ): Promise<StartReplayResponse> {\n // limit is only meaningful without traceIds (an explicit ID list\n // already determines the count), so it's omitted when undefined.\n const payload: Record<string, unknown> = { traceFunctionKey }\n if (limit !== undefined) {\n payload.limit = limit\n }\n if (traceIds) {\n payload.traceIds = traceIds\n }\n if (name !== undefined) {\n payload.name = name\n }\n if (codeChangeDescription !== undefined) {\n payload.codeChangeDescription = codeChangeDescription\n }\n if (codeChangeFiles !== undefined) {\n payload.codeChangeFiles = codeChangeFiles\n }\n if (includeDbBranchLease) {\n payload.includeDbBranchLease = true\n payload.lazyDbBranchLease = true\n }\n if (experimentGroupId !== undefined) {\n payload.experimentGroupId = experimentGroupId\n }\n if (datasetId !== undefined) {\n payload.datasetId = datasetId\n }\n if (graderIds !== undefined) {\n payload.graderIds = graderIds\n }\n if (dbBranchSettings !== undefined) {\n payload.dbBranchSettings = dbBranchSettings\n }\n if (attempts !== undefined && attempts > 1) {\n payload.attempts = attempts\n }\n if (includeOriginalMetadata) {\n payload.includeOriginalMetadata = true\n }\n // When DB branching is on, the server resolves a Neon preview branch\n // per item (snapshot + restore + poll), which can run ~5-10s each, and\n // runs any `warmupSql` against each branch on a 240s budget of its own.\n // The server gives up at 280s and answers, so this is a backstop for a\n // reply that never comes rather than the thing that normally fires; it\n // sits above the server's own ceiling so the server's error is the one\n // callers see. Not raisable in practice either: undici's default\n // `headersTimeout` is also 300s and `fetch` cannot override it per\n // request.\n const timeout = includeDbBranchLease\n ? REPLAY_DB_BRANCH_REQUEST_TIMEOUT_MS\n : 30_000\n return this.request<StartReplayResponse>(\"/api/sdk/replay/start\", payload, {\n timeout,\n })\n }\n\n /**\n * Fetch an external span by ID.\n * Blocking GET request.\n * The replay view limits rawData to input/output serialization fields.\n */\n async getExternalSpan(\n spanId: string,\n options?: { view?: \"full\" | \"replay\" },\n ): Promise<ExternalSpanResponse> {\n const query = options?.view === \"replay\" ? \"?view=replay\" : \"\"\n const url = `${this.serviceUrl}/api/sdk/externalSpans/${spanId}${query}`\n const controller = new AbortController()\n const timeoutId = setTimeout(() => controller.abort(), 30_000)\n\n try {\n const response = await fetch(url, {\n method: \"GET\",\n headers: { Authorization: `Bearer ${this.resolveApiKey() ?? \"\"}` },\n signal: controller.signal,\n })\n\n if (!response.ok) {\n const errorText = await response.text()\n throw new BitfabError(\n `HTTP ${response.status}: ${errorText.slice(0, 500)}`,\n )\n }\n\n return (await response.json()) as ExternalSpanResponse\n } catch (error) {\n if (error instanceof BitfabError) {\n throw error\n }\n if (error instanceof Error) {\n if (error.name === \"AbortError\") {\n throw new BitfabError(\"Request timed out after 30000ms\")\n }\n throw new BitfabError(error.message)\n }\n throw new BitfabError(\"Unknown error occurred\")\n } finally {\n clearTimeout(timeoutId)\n }\n }\n\n /**\n * Fetch the span tree for a root span.\n * Blocking GET request.\n *\n * Pass `includeOutputs: false` for a payload-free tree (structure +\n * `externalSpanId` only), so recorded outputs are fetched lazily per mocked\n * span instead of all up front. Omit it (default eager) for `mock: \"all\"`.\n * Pass `includeRootOutput: false` when the root was already fetched.\n */\n async getSpanTree(\n externalSpanId: string,\n options?: { includeOutputs?: boolean; includeRootOutput?: boolean },\n ): Promise<SpanTreeResponse> {\n const searchParams = new URLSearchParams()\n if (options?.includeOutputs === false) {\n searchParams.set(\"includeOutputs\", \"false\")\n }\n if (options?.includeRootOutput === false) {\n searchParams.set(\"includeRootOutput\", \"false\")\n }\n const encodedQuery = searchParams.toString()\n const query = encodedQuery ? `?${encodedQuery}` : \"\"\n const url = `${this.serviceUrl}/api/sdk/replay/spanTree/${externalSpanId}${query}`\n const controller = new AbortController()\n const timeoutId = setTimeout(() => controller.abort(), 30_000)\n\n try {\n const response = await fetch(url, {\n method: \"GET\",\n headers: { Authorization: `Bearer ${this.resolveApiKey() ?? \"\"}` },\n signal: controller.signal,\n })\n\n if (!response.ok) {\n const errorText = await response.text()\n throw new BitfabError(\n `HTTP ${response.status}: ${errorText.slice(0, 500)}`,\n )\n }\n\n return (await response.json()) as SpanTreeResponse\n } catch (error) {\n if (error instanceof BitfabError) {\n throw error\n }\n if (error instanceof Error) {\n if (error.name === \"AbortError\") {\n throw new BitfabError(\"Request timed out after 30000ms\")\n }\n throw new BitfabError(error.message)\n }\n throw new BitfabError(\"Unknown error occurred\")\n } finally {\n clearTimeout(timeoutId)\n }\n }\n\n /**\n * Read which of a replay run's traces the server has fully persisted.\n *\n * With `expectedSpanCounts`, a trace appears in the response only once it\n * has a final status AND at least that many persisted spans, which is what\n * makes this a real barrier rather than a \"the row exists\" check.\n */\n async getReplayStatus(\n testRunId: string,\n expectedSpanCounts: Record<string, number>,\n ): Promise<ReplayStatusResponse> {\n return this.request<ReplayStatusResponse>(\n \"/api/sdk/replay/status\",\n { testRunId, expectedSpanCounts },\n { timeout: 30_000 },\n )\n }\n\n /**\n * Mark a replay test run as completed.\n * Blocking call.\n */\n async completeReplay(testRunId: string): Promise<CompleteReplayResponse> {\n return this.request<CompleteReplayResponse>(\n \"/api/sdk/replay/complete\",\n { testRunId },\n { timeout: REPLAY_COMPLETE_REQUEST_TIMEOUT_MS },\n )\n }\n\n /**\n * Ask the server to materialize a per-trace DB branch lease from a\n * captured `dbSnapshotRef`. Blocking - the resolver creates a Neon\n * snapshot + preview branch and polls operations to readiness, which\n * can take seconds.\n */\n async resolveDbBranchLease(\n testRunId: string,\n traceId: string,\n dbBranchSettings?: DbBranchSettings,\n attempt?: number,\n ): Promise<{\n dbSnapshotRef: DbSnapshotRef | null\n lease: DbBranchLease | null\n leaseError: { code: string; message: string } | null\n timings: DbBranchTimings | null\n }> {\n return this.request<{\n dbSnapshotRef: DbSnapshotRef | null\n lease: DbBranchLease | null\n leaseError: { code: string; message: string } | null\n timings: DbBranchTimings | null\n }>(\n \"/api/sdk/replay/resolveDbBranchLease\",\n {\n testRunId,\n traceId,\n dbBranchSettings,\n ...(attempt !== undefined && attempt > 0 ? { attempt } : {}),\n },\n { timeout: REPLAY_DB_BRANCH_REQUEST_TIMEOUT_MS },\n )\n }\n\n /** Release a previously-resolved DB branch by deleting its Neon branch. Idempotent server-side. */\n async releaseDbBranchLease(neonBranchId: string): Promise<void> {\n await this.request<{ released: true }>(\n \"/api/sdk/replay/releaseDbBranchLease\",\n { neonBranchId },\n { timeout: 30_000 },\n )\n }\n}\n\nexport interface TokenUsage {\n input: number | null\n output: number | null\n cached: number | null\n total: number | null\n}\n\nexport interface TraceOutlineSpanError {\n source: string\n error: string\n step?: string\n}\n\nexport interface TraceOutlineSpan {\n spanId: string\n name: string | null\n type: string\n traceFunctionKey: string | null\n durationMs: number | null\n tokens: TokenUsage | null\n model: string | null\n errors: TraceOutlineSpanError[] | null\n mocked: boolean\n children: TraceOutlineSpan[]\n}\n\nexport interface TraceOutline {\n traceId: string\n name: string | null\n status: string\n traceFunctionKey: string | null\n durationMs: number | null\n spanCount: number\n spans: TraceOutlineSpan[]\n}\n\n/**\n * Describes a single file edited as part of a code change.\n *\n * - `path`: file path (relative to the repo root, or any consistent root)\n * - `before`: file contents before the change (\"\" for newly created files)\n * - `after`: file contents after the change (\"\" for deleted files)\n */\nexport interface CodeChangeFile {\n path: string\n before: string\n after: string\n}\n\nexport interface StartReplayResponse {\n testRunId: string\n testRunUrl: string\n attempts?: number\n items: Array<{\n /** Bitfab trace ID of the original (historical) trace being replayed. */\n originalTraceId?: string\n /** External span ID the recorded inputs were read from (the original root span). */\n originalSpanId?: string\n /** @deprecated alias for `originalTraceId`; the only key emitted by servers that predate the rename. */\n sourceTraceId: string\n /** @deprecated alias for `originalSpanId`; the only key emitted by servers that predate the rename. */\n sourceSpanId: string\n durationMs: number | null\n tokens: TokenUsage | null\n model: string | null\n /**\n * The DB snapshot ref captured by the SDK at trace open. Surfaced so\n * the SDK can pass it to the lease-resolver step (or report when no\n * snapshot was captured for this trace).\n */\n dbSnapshotRef?: DbSnapshotRef\n /**\n * Populated once the server-side resolver has materialized a per-item\n * branch from `dbSnapshotRef`. The SDK exposes this to customer code\n * via `getCurrentReplayBranch()`. Absent until the resolver lands.\n */\n dbBranchLease?: DbBranchLease\n /**\n * Why the branch could not be resolved, when one was requested and the\n * attempt failed. Distinct from both fields being absent, which means the\n * trace carried no snapshot ref so nothing was attempted.\n */\n dbBranchLeaseError?: { code: string; message: string }\n /**\n * How long provisioning took, per phase. Sits beside the two fields above\n * rather than inside either: it is reported on both outcomes, complete on\n * success and partial up to the failing phase on error. Absent from\n * servers that predate it.\n */\n dbBranchTimings?: DbBranchTimings\n originalMetadata?: Record<string, unknown>\n }>\n}\n\nexport interface ExternalSpanResponse {\n id: string\n externalTraceId: string\n rawData: {\n span_data: {\n input: unknown\n output: unknown\n input_meta?: unknown\n output_meta?: unknown\n input_serialized?: { json: unknown; meta: unknown }\n output_serialized?: { json: unknown; meta: unknown }\n }\n }\n}\n\nexport interface ReplayStatusResponse {\n /**\n * Local replay trace id -> server trace row id, for the traces the server\n * considers fully persisted. Traces still short of their expected span count\n * are simply absent.\n */\n traceIds?: Record<string, string>\n}\n\nexport interface CompleteReplayResponse {\n id: string\n status: string\n traceIds?: Record<string, string>\n /**\n * Per-replay-trace token usage, keyed by the server trace id (the values of\n * `traceIds`). Aggregated server-side from the freshly-uploaded replay spans,\n * so it's the REPLAYED run's tokens (the same source Studio reads), not the\n * original trace's. The SDK maps each item onto this to set\n * `ReplayItem.tokens`. Absent on servers that predate this field.\n */\n tokens?: Record<string, TokenUsage | null>\n traceOutlines?: Record<string, TraceOutline>\n originalTraceOutlines?: Record<string, TraceOutline>\n /**\n * Number of traces the server has persisted for this test run at\n * completion time. Lets the SDK distinguish \"uploads failed\" from\n * \"server never saw them\" when the trace-ID mapping is incomplete.\n */\n traceCount?: number\n}\n\nexport interface SpanTreeNode {\n /** Upstream platform span id. Stable structural identity; NOT the row id. */\n sourceSpanId: string\n /**\n * The `externalSpans` row id, accepted by {@link HttpClient.getExternalSpan}.\n * Distinct from `sourceSpanId`; used to lazily fetch this node's output when\n * the tree was fetched with `includeOutputs: false`. Optional so trees from\n * older servers (which omit it) still deserialize.\n */\n externalSpanId?: string\n traceFunctionKey: string\n spanName: string\n type: string\n /** Omitted when the tree was fetched payload-free (`includeOutputs: false`). */\n output?: unknown\n outputMeta?: unknown\n children: SpanTreeNode[]\n}\n\nexport interface SpanTreeResponse {\n root: SpanTreeNode\n}\n","/**\n * Serialization utilities for Bitfab SDK.\n *\n * This module provides serialization with type metadata preservation,\n * using superjson for handling special JavaScript types like Date, Map,\n * Set, BigInt, undefined, etc.\n */\n\nimport superjson from \"superjson\"\nimport { MAX_COMPRESSIBLE_SPAN_CARRIER_BYTES } from \"./payloadBudget.js\"\nimport { warnOnce } from \"./warnOnce.js\"\n\n/**\n * Serialized value with JSON data and optional superjson meta for type preservation.\n *\n * The json field contains the JSON-serializable data.\n * The meta field (if present) contains superjson type information for deserializing\n * special types like Date, Map, Set, BigInt, etc.\n */\nexport interface SerializedValue {\n json: unknown\n meta?: unknown\n}\n\n// Cap on a single serialized value. superjson can succeed on values like SDK\n// client instances (OpenAI, etc.) and produce hundreds of KB to MB of useless\n// internal state, so this is the cheap early-out that stops the walk before a\n// pathological object is carried any further. It is deliberately the same\n// number as the whole-span budget: one legitimately large value may use the\n// entire budget, and `serializePayloadBody` is what enforces the total once\n// every field is in. Anything past it is replaced with a stub so the span\n// still ships and the trace isn't dropped server-side.\nconst MAX_SERIALIZED_BYTES = MAX_COMPRESSIBLE_SPAN_CARRIER_BYTES\n\n// The framework-capture path (toJsonSafe) shares that ceiling. Agent/graph\n// states (LangGraph, Claude Agent SDK) are legitimately larger than a single\n// function's args/return, and capping them lower than ordinary values only\n// discarded detail the span had room for.\nconst MAX_FRAMEWORK_SERIALIZED_BYTES = MAX_COMPRESSIBLE_SPAN_CARRIER_BYTES\n\nfunction describeValue(value: unknown): string {\n try {\n const ctorName = (value as { constructor?: { name?: string } })?.constructor\n ?.name\n if (ctorName && ctorName !== \"Object\") {\n return ctorName\n }\n } catch {\n // Property access on `value` can throw (Proxy, poisoned getter).\n }\n return typeof value\n}\n\nfunction unserializableStub(value: unknown, reason: string): SerializedValue {\n // Normalize the byte count out of the key so a too_large warning dedups\n // across differently-sized payloads instead of warning once per size.\n warnOnce(\n `serialize:${reason.replace(/\\d+/g, \"N\")}`,\n `a value could not be fully serialized for a span (${reason}); it was replaced with a placeholder. The span still ships, but its captured input/output is incomplete.`,\n )\n let summary: string\n try {\n summary = `<unserializable: ${describeValue(value)} (${reason})>`\n } catch {\n summary = `<unserializable (${reason})>`\n }\n return { json: summary }\n}\n\n/**\n * Serialize a value using superjson for trace storage.\n *\n * Handles arbitrary JavaScript values including:\n * - Date, RegExp, Error\n * - Map, Set\n * - BigInt\n * - undefined (in objects/arrays)\n * - Circular references\n *\n * Guarantees:\n * - Never throws. Pathological inputs (SDK clients, proxies, poisoned\n * getters, circular graphs that defeat superjson) return a stub string.\n * - Never returns a payload larger than MAX_SERIALIZED_BYTES; oversized\n * inputs are replaced with a stub. Without this the wire-side\n * `JSON.stringify` in http.ts can produce a request that times out or\n * gets rejected, leaving a trace with zero spans.\n *\n * @param value - Any JavaScript value to serialize\n * @returns SerializedValue with 'json' field containing the data.\n * If type metadata is needed for reconstruction, includes 'meta' field.\n *\n * @example\n * ```typescript\n * const result = serializeValue(new Date('2024-01-15T10:30:00Z'))\n * // result.json contains the ISO string\n * // result.meta contains type info for Date reconstruction\n * ```\n */\nexport function serializeValue(value: unknown): SerializedValue {\n try {\n const { json, meta } = superjson.serialize(value)\n\n let size: number\n try {\n size = JSON.stringify(json).length\n } catch {\n return unserializableStub(value, \"stringify_failed_after_superjson\")\n }\n if (size > MAX_SERIALIZED_BYTES) {\n return unserializableStub(value, `too_large_${size}_bytes`)\n }\n\n return meta ? { json, meta } : { json }\n } catch {\n try {\n return { json: JSON.parse(JSON.stringify(value)) }\n } catch {\n return unserializableStub(value, \"json_stringify_failed\")\n }\n }\n}\n\n/**\n * Deserialize a value that was serialized with serializeValue.\n *\n * @param serialized - A SerializedValue object with 'json' and optional 'meta'\n * @returns The reconstructed JavaScript value\n *\n * @example\n * ```typescript\n * const serialized = serializeValue(new Date('2024-01-15'))\n * const date = deserializeValue(serialized)\n * // date is a Date object\n * ```\n */\nexport function deserializeValue(serialized: SerializedValue): unknown {\n if (serialized.meta === undefined) {\n // No metadata, return as-is\n return serialized.json\n }\n\n // Use superjson to deserialize with type reconstruction\n // Cast json to the expected superjson type\n type SuperJSONResult = Parameters<typeof superjson.deserialize>[0]\n return superjson.deserialize({\n json: serialized.json as SuperJSONResult[\"json\"],\n meta: serialized.meta as SuperJSONResult[\"meta\"],\n })\n}\n\nconst MAX_SAFE_DEPTH = 6\n\n/**\n * Convert any value to JSON-safe primitives, never throwing.\n *\n * Produces plain objects/arrays/scalars, recursing through `toJSON()` and\n * own-enumerable properties so no raw non-serializable value (a class, a\n * BigInt-bearing object) survives into a span payload. Cycles collapse to a\n * `<cycle ...>` marker; depth is capped.\n *\n * This is the single shared \"safe serialize\" used by the framework\n * integrations that capture raw objects (LangGraph, Claude Agent SDK). Keeping\n * the recurse-the-dump logic here, in one place, is what stops a new\n * integration from reintroducing the \"dump without recursing\" bug - see\n * `serializationInvariant.test.ts`.\n */\nexport function toJsonSafe(value: unknown): unknown {\n return toJsonSafeReport(value).safe\n}\n\n/**\n * Like {@link toJsonSafe}, but also reports what could not be faithfully\n * captured.\n *\n * Returns `{ safe, dropped }` where `dropped` lists the type name behind every\n * placeholder the walker had to emit: a cycle, a max-depth cut, an oversized\n * payload, or a value that could only be stringified (a function/symbol) or\n * stubbed after a throw. A non-empty `dropped` means the captured input/output\n * is lossy. Framework handlers carry it to the send boundary so a degraded\n * capture is marked non-replayable (`serialization_degraded`) instead of being\n * shipped as if it round-trips - mirrors the Python SDK's `to_json_safe_report`\n * + `finalize_span_payload`.\n */\nexport function toJsonSafeReport(value: unknown): {\n safe: unknown\n dropped: string[]\n} {\n const dropped: string[] = []\n const safe = toJsonSafeInner(value, 0, new WeakSet(), dropped)\n // Cap output size for parity with serializeValue. A multi-MB framework\n // payload (a large LangGraph state, a long message history) would otherwise\n // be JSON.stringify'd synchronously on the user's thread in http.ts and may\n // be rejected server-side, leaving a trace with zero spans. Stub it instead\n // so the span still ships. toJsonSafeInner produces only plain\n // objects/arrays/scalars/strings, so JSON.stringify here cannot throw; the\n // try is belt-and-suspenders.\n try {\n const size = JSON.stringify(safe)?.length ?? 0\n if (size > MAX_FRAMEWORK_SERIALIZED_BYTES) {\n warnOnce(\n \"toJsonSafe:too_large\",\n `a framework payload exceeded ${MAX_FRAMEWORK_SERIALIZED_BYTES} bytes and was replaced with a placeholder so the span still ships. The captured state for this span is incomplete.`,\n )\n // Keep any drops already accumulated by the walk (cycles, functions,\n // depth cuts); a payload can be both lossy AND oversized, and the\n // non-replayable marking needs the real types, not just the size stub.\n return {\n safe: `<unserializable: too_large_${size}_bytes>`,\n dropped: [...dropped, `too_large_${size}_bytes`],\n }\n }\n } catch {\n // Keep the recursed value; the http-layer sanitizer is the final backstop.\n }\n return { safe, dropped }\n}\n\nfunction toJsonSafeInner(\n value: unknown,\n depth: number,\n seen: WeakSet<object>,\n dropped: string[],\n): unknown {\n if (value === null || value === undefined) {\n return value\n }\n if (\n typeof value === \"string\" ||\n typeof value === \"number\" ||\n typeof value === \"boolean\"\n ) {\n return value\n }\n\n const className =\n (value as { constructor?: { name?: string } })?.constructor?.name ??\n typeof value\n if (depth > MAX_SAFE_DEPTH) {\n dropped.push(className)\n return `<${className}>`\n }\n\n // Non-object composites (bigint, function, symbol) stringify directly. A\n // bigint stringifies faithfully; a function/symbol becomes a lossy summary,\n // so those are reported as dropped.\n if (typeof value !== \"object\") {\n if (typeof value === \"function\" || typeof value === \"symbol\") {\n dropped.push(className)\n }\n try {\n return String(value)\n } catch {\n dropped.push(className)\n return `<${className}>`\n }\n }\n\n if (seen.has(value as object)) {\n dropped.push(className)\n return `<cycle ${className}>`\n }\n seen.add(value as object)\n\n let result: unknown\n if (Array.isArray(value)) {\n result = value.map((item) =>\n toJsonSafeInner(item, depth + 1, seen, dropped),\n )\n } else if (typeof (value as Record<string, unknown>).toJSON === \"function\") {\n // Recurse toJSON() output: it can still hold non-serializable values (e.g.\n // a LangChain tool whose schema is a class) that would otherwise survive\n // into the span payload and crash the wire-side JSON.stringify.\n try {\n result = toJsonSafeInner(\n (value as { toJSON(): unknown }).toJSON(),\n depth + 1,\n seen,\n dropped,\n )\n } catch {\n dropped.push(className)\n result = `<${className}>`\n }\n } else {\n try {\n const obj: Record<string, unknown> = {}\n for (const [k, v] of Object.entries(value)) {\n if (!k.startsWith(\"_\")) {\n obj[k] = toJsonSafeInner(v, depth + 1, seen, dropped)\n }\n }\n result = obj\n } catch {\n dropped.push(className)\n result = `<${className}>`\n }\n }\n\n // Backtrack: keep only ancestors on the current path in `seen`, so a shared\n // (DAG) reference under sibling keys is serialized again rather than stubbed\n // as a false cycle. Real cycles (an ancestor referencing itself) are still\n // caught above.\n seen.delete(value as object)\n return result\n}\n","/**\n * Generate a UUID v4 without assuming a global `crypto`.\n *\n * `crypto.randomUUID()` is the fast path and exists in every mainstream modern\n * runtime (Node >= 19, all browsers, Deno, Vercel edge, Cloudflare Workers).\n * But the SDK must NEVER crash a host app, and a few runtimes it can legitimately\n * run in lack a global `crypto` or `crypto.randomUUID` (Node < 19 without a\n * polyfill, older React Native, some sandboxes). There, an unguarded\n * `crypto.randomUUID()` throws on the user's call path. This helper falls back\n * to a `Math.random()`-based v4 string instead.\n *\n * The fallback is NOT cryptographically secure. That is fine: trace and span\n * IDs only need to be unique enough to correlate the spans of one trace; they\n * are never security-sensitive.\n */\nimport { warnOnce } from \"./warnOnce.js\"\n\nexport function randomUuid(): string {\n const globalCrypto = (\n globalThis as { crypto?: { randomUUID?: () => string } }\n ).crypto\n if (typeof globalCrypto?.randomUUID === \"function\") {\n try {\n return globalCrypto.randomUUID()\n } catch {\n // Fall through to the manual generator below.\n }\n }\n warnOnce(\n \"crypto-unavailable\",\n \"global crypto.randomUUID is unavailable; using a non-cryptographic fallback for trace/span ids. Tracing works normally (ids are correlation-only, not security-sensitive).\",\n )\n return fallbackUuidV4()\n}\n\n/**\n * RFC 4122 version 4 layout filled from `Math.random()`. Used only when a usable\n * global `crypto.randomUUID` is unavailable.\n */\nfunction fallbackUuidV4(): string {\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, (char) => {\n const rand = (Math.random() * 16) | 0\n const value = char === \"x\" ? rand : (rand & 0x3) | 0x8\n return value.toString(16)\n })\n}\n","/**\n * Selective mock overrides for replay.\n *\n * A mock override injects a custom value into a specific span (node) during\n * replay: the matched span short-circuits its real execution and returns the\n * value you supply, so downstream real code runs against the substituted\n * output. This is a third mock mode alongside \"run real code\" and \"replay\n * recorded output\" (see {@link MockStrategy}).\n *\n * The matcher and value are deliberately separate so matching stays cheap\n * (structural metadata only, no output fetch) and the recorded output is\n * fetched lazily - and only if the value function actually asks for it via\n * {@link MockOverrideCtx.getOriginalOutput}.\n */\n\n/**\n * Structural identity of a span during replay, passed to a {@link NodeMatcher}.\n * Carries no output payload - matching must not depend on the recorded output,\n * so the output fetch stays lazy and gated.\n */\nexport interface SpanNodeMeta {\n /** The `withSpan` key of the executing span (its code-side identity). */\n traceFunctionKey: string\n /** Resolved span name: `options.name ?? fn.name ?? traceFunctionKey`. */\n spanName: string\n /** Span type, e.g. \"llm\", \"agent\", \"tool\", \"custom\". */\n type: string\n /**\n * The id of this span in the original (replayed) trace, when it exists in\n * that trace's tree. Undefined when the live span has no recorded\n * counterpart (e.g. a span the changed code newly introduced).\n */\n originalSpanId?: string\n}\n\n/** Context passed to a {@link MockValue} function for a matched span. */\nexport interface MockOverrideCtx {\n /** The matched span's structural metadata. */\n node: SpanNodeMeta\n /** The live replay args passed to the wrapped function this run. */\n inputs: unknown[]\n /**\n * Lazily fetch this span's ORIGINAL recorded output (deserialized). The fetch\n * happens only when called and is memoized per replay item, so a purely flat\n * override that never calls it triggers zero output round trips. Rejects if\n * the span has no recorded counterpart. Being async, it is only usable for\n * spans wrapping async functions.\n */\n getOriginalOutput: () => Promise<unknown>\n}\n\n/**\n * Return this from a mock override resolver to decline the override for the\n * current span. Resolution continues with the next override, then the replay's\n * base mock strategy.\n */\nexport const NO_MOCK_OVERRIDE = Symbol(\"bitfab.noMockOverride\")\n\n/** Selects which spans an override applies to. Runs on structural metadata. */\nexport type NodeMatcher = (node: SpanNodeMeta) => boolean\n\n/** The function form of {@link MockValue}, receiving the override context. */\nexport type MockValueFn = (ctx: MockOverrideCtx) => unknown | Promise<unknown>\n\n/**\n * A client-wide, keyed, or per-replay resolver. A global resolver can route on\n * `ctx.node.traceFunctionKey`; a keyed resolver is only invoked for spans with\n * its registered key. Return {@link NO_MOCK_OVERRIDE} for spans the resolver\n * does not want to override.\n */\nexport type MockOverrideResolver = (\n ctx: MockOverrideCtx,\n) => unknown | Promise<unknown>\n\n/**\n * The value injected for a matched span: either a flat value used as-is, or a\n * function of the {@link MockOverrideCtx} that returns one (or a Promise of\n * one). Full replacement - the value IS the span's output, no merge with the\n * recorded output.\n *\n * The flat side is spelled out (rather than `unknown`) so an inline function\n * still gets a typed `ctx`: `unknown | Fn` would collapse to `unknown` and drop\n * the contextual type. To inject a value that is itself a function, wrap it:\n * `value: () => theFunction`.\n */\nexport type MockValue =\n | MockValueFn\n | string\n | number\n | boolean\n | bigint\n | symbol\n | object\n | null\n | undefined\n\n/** One (match, value) pair. */\nexport interface MockOverride {\n match: NodeMatcher\n value: MockValue\n}\n\n/** Accepted shape for one mock override declaration. */\nexport type MockOverrideInput = MockOverride | MockOverrideResolver\n\n/**\n * Resolve an override's `value`: call it with `ctx` when it's a function, else\n * use it as-is (a flat value).\n */\nexport function resolveMockValue(\n value: MockValue,\n ctx: MockOverrideCtx,\n): unknown | Promise<unknown> {\n return typeof value === \"function\"\n ? (value as (c: MockOverrideCtx) => unknown | Promise<unknown>)(ctx)\n : value\n}\n\n/**\n * Normalize the per-call `mockOverride` option (an override pair, a global\n * resolver, an array, or nothing) into an ordered internal override array.\n */\nexport function normalizeMockOverrides(\n mockOverride?: MockOverrideInput | MockOverrideInput[],\n): MockOverride[] {\n if (mockOverride === undefined) {\n return []\n }\n const overrides = Array.isArray(mockOverride) ? mockOverride : [mockOverride]\n return overrides.map((override) =>\n typeof override === \"function\"\n ? { match: () => true, value: override }\n : override,\n )\n}\n\n/**\n * What a replay mock replaced on a span, and where the replacement came from.\n * Reported alongside `mocked` so a trace can say how a span was produced rather\n * than only that it was not re-run.\n *\n * `target` is `\"output\"` for every mock today: both the recorded-output path\n * and an override short-circuit the call. `\"input\"` is reserved for\n * substituting a span's arguments and letting the real code run.\n */\nexport type MockTarget = \"output\" | \"input\"\n\n/**\n * `recorded` is the original trace's own value; `override` is one the caller\n * supplied via `mockOverride` / `registerMockOverride`. Deliberately not\n * \"dynamic\": an override value may be a flat constant.\n */\nexport type MockSource = \"recorded\" | \"override\"\n","import type { CodeChangeFile } from \"./http\"\n\n/**\n * Auto-capture the code change to attach to a replay, when the caller passed\n * none explicitly.\n *\n * This lives in the SDK (not a wrapper) on purpose: `replay()` is the only point\n * guaranteed to run on every replay, so capturing here works no matter how the\n * replay was launched (plugin wrapper, a hand-run script, CI). Precedence:\n *\n * 1. `BITFAB_CODE_CHANGE_PATH` file — an override a caller/tool can inject.\n * 2. `git diff` vs trunk — the default fallback.\n *\n * Both are best-effort and browser-safe: any failure (no git, no fs, not a repo,\n * bad JSON) yields `null` and the replay proceeds with no code change. The diff\n * is cumulative (whole branch vs trunk), not per-experiment; an explicit\n * `codeChangeFiles` on `replay()` always wins over this and is what carries a\n * precise per-experiment before/after.\n */\n\nexport interface ResolvedCodeChange {\n description?: string\n files?: CodeChangeFile[]\n}\n\n// Bounds so a large delta never bloats the experiment payload.\nconst MAX_FILES = 60\nconst MAX_FILE_BYTES = 500_000\nconst MAX_TOTAL_BYTES = 2_000_000\n\n// Candidate trunk refs, tried in order, when no explicit base is supplied.\nconst TRUNK_CANDIDATES = [\n \"origin/HEAD\",\n \"origin/main\",\n \"origin/master\",\n \"main\",\n \"master\",\n]\n\nconst NUL = String.fromCharCode(0)\n\n/**\n * Resolve an auto code change: the `BITFAB_CODE_CHANGE_PATH` override first,\n * then the git-vs-trunk diff. Returns null when neither yields anything.\n */\nexport async function resolveAutoCodeChange(\n label?: string,\n): Promise<ResolvedCodeChange | null> {\n if (typeof process === \"undefined\") {\n return null\n }\n if (process.env?.BITFAB_DISABLE_CODE_CHANGE_CAPTURE) {\n return null\n }\n const fromEnv = await readCodeChangeFile()\n if (fromEnv) {\n return fromEnv\n }\n return captureCodeChangeFromGit(process.cwd?.() ?? \".\", label)\n}\n\nasync function readCodeChangeFile(): Promise<ResolvedCodeChange | null> {\n const path = process.env?.BITFAB_CODE_CHANGE_PATH\n if (!path) {\n return null\n }\n try {\n const { readFile } = await import(\"node:fs/promises\")\n const parsed = JSON.parse(await readFile(path, \"utf8\"))\n // A malformed payload (non-array, or entries that aren't objects) must yield\n // no code change, never forward a bad shape to the start-replay request.\n const files =\n Array.isArray(parsed?.files) &&\n parsed.files.every(\n (f: unknown) =>\n typeof f === \"object\" && f !== null && !Array.isArray(f),\n )\n ? parsed.files\n : undefined\n const description =\n typeof parsed?.description === \"string\" ? parsed.description : undefined\n if (!files && description === undefined) {\n return null\n }\n return { description, files }\n } catch {\n return null\n }\n}\n\nasync function captureCodeChangeFromGit(\n cwd: string,\n label?: string,\n): Promise<ResolvedCodeChange | null> {\n let execFile: typeof import(\"node:child_process\").execFile\n let readFile: typeof import(\"node:fs/promises\").readFile\n try {\n ;({ execFile } = await import(\"node:child_process\"))\n ;({ readFile } = await import(\"node:fs/promises\"))\n } catch {\n // No child_process / fs (e.g. a browser bundle): capture is a no-op.\n return null\n }\n\n const git = (dir: string, args: string[]): Promise<string | null> =>\n new Promise((resolve) => {\n execFile(\n \"git\",\n args,\n // 30s timeout so a hung git (e.g. a network-touching ref op) can't\n // block the whole replay indefinitely.\n { cwd: dir, maxBuffer: 64 * 1024 * 1024, timeout: 30_000 },\n (err, stdout) => resolve(err ? null : stdout),\n )\n })\n\n try {\n const root = (await git(cwd, [\"rev-parse\", \"--show-toplevel\"]))?.trim()\n if (!root) {\n return null\n }\n\n const resolved = await resolveBase(git, root)\n if (!resolved) {\n return null\n }\n const { base, fromTrunk } = resolved\n\n // Size of a path on either side WITHOUT reading its contents: the git blob\n // size for `before`, a stat for the working `after`. Lets us skip an\n // oversized file before loading it into memory.\n const blobBytes = async (ref: string, path: string): Promise<number> => {\n const out = await git(root, [\"cat-file\", \"-s\", `${ref}:${path}`])\n const n = out ? Number.parseInt(out.trim(), 10) : Number.NaN\n return Number.isFinite(n) ? n : 0\n }\n const workingBytes = async (path: string): Promise<number> => {\n try {\n const { stat } = await import(\"node:fs/promises\")\n const { join } = await import(\"node:path\")\n return (await stat(join(root, path))).size\n } catch {\n return 0\n }\n }\n\n // Tracked changes vs base. `:!.bitfab` keeps replay artifacts out.\n const tracked = await git(root, [\n \"diff\",\n \"--name-status\",\n \"--find-renames\",\n \"-z\",\n base,\n \"--\",\n \":!.bitfab\",\n ])\n // Untracked-but-not-ignored files (the diff above omits these).\n const untracked = await git(root, [\n \"ls-files\",\n \"--others\",\n \"--exclude-standard\",\n \"-z\",\n \"--\",\n \":!.bitfab\",\n ])\n\n const entries: GitChange[] = [\n ...parseNameStatusZ(tracked ?? \"\"),\n ...(untracked ?? \"\")\n .split(NUL)\n .filter((p) => p.length > 0)\n .map((path) => ({ status: \"A\", beforePath: path, path })),\n ]\n if (entries.length === 0) {\n return null\n }\n\n const files: CodeChangeFile[] = []\n let totalBytes = 0\n for (const { status, beforePath, path } of entries) {\n if (files.length >= MAX_FILES) {\n break\n }\n // Skip oversized files by size BEFORE reading their full contents, so a\n // huge changed file can't OOM/stall the replay just to be discarded.\n const beforeBytes = status === \"A\" ? 0 : await blobBytes(base, beforePath)\n const afterBytes = status === \"D\" ? 0 : await workingBytes(path)\n if (beforeBytes > MAX_FILE_BYTES || afterBytes > MAX_FILE_BYTES) {\n continue\n }\n // Normalize CRLF -> LF on both sides: git's blob is already LF-normalized\n // (autocrlf clean), so a raw CRLF working file would otherwise skew every\n // line as changed. Comparing/storing LF keeps the diff meaningful.\n const before = (\n status === \"A\"\n ? \"\"\n : ((await git(root, [\"show\", `${base}:${beforePath}`])) ?? \"\")\n ).replace(/\\r\\n/g, \"\\n\")\n const after = (\n status === \"D\" ? \"\" : await readWorkingFile(readFile, root, path)\n ).replace(/\\r\\n/g, \"\\n\")\n if (before === after) {\n continue\n }\n // Bytes, not chars: a multi-byte source file must count against the byte\n // cap the same way Ruby's `bytesize` does.\n const size =\n Buffer.byteLength(before, \"utf8\") + Buffer.byteLength(after, \"utf8\")\n if (\n totalBytes + size > MAX_TOTAL_BYTES ||\n looksBinary(before) ||\n looksBinary(after)\n ) {\n continue\n }\n totalBytes += size\n files.push({ path, before, after })\n }\n\n if (files.length === 0) {\n return null\n }\n\n const subject = (\n await git(root, [\"log\", \"-1\", \"--format=%s\", \"HEAD\"])\n )?.trim()\n const fileWord = files.length === 1 ? \"file\" : \"files\"\n const head = label?.trim() || subject || \"Working-tree change\"\n // \"vs trunk\" only when we actually diffed against a trunk merge-base; the\n // HEAD fallback captures uncommitted work only, so label it honestly.\n const against = fromTrunk ? \"vs trunk\" : \"uncommitted (vs HEAD)\"\n return {\n description: `${head} (${files.length} ${fileWord} changed ${against})`,\n files,\n }\n } catch {\n return null\n }\n}\n\nasync function resolveBase(\n git: (dir: string, args: string[]) => Promise<string | null>,\n root: string,\n): Promise<{ base: string; fromTrunk: boolean } | null> {\n const forced = process.env?.BITFAB_CODE_CHANGE_BASE\n if (forced && (await refExists(git, root, forced))) {\n const base =\n (await git(root, [\"merge-base\", \"HEAD\", forced]))?.trim() ||\n (await git(root, [\"rev-parse\", \"--verify\", forced]))?.trim() ||\n null\n return base ? { base, fromTrunk: true } : null\n }\n for (const candidate of TRUNK_CANDIDATES) {\n if (!(await refExists(git, root, candidate))) {\n continue\n }\n const mb = (await git(root, [\"merge-base\", \"HEAD\", candidate]))?.trim()\n if (mb) {\n return { base: mb, fromTrunk: true }\n }\n }\n return (await refExists(git, root, \"HEAD\"))\n ? { base: \"HEAD\", fromTrunk: false }\n : null\n}\n\nasync function refExists(\n git: (dir: string, args: string[]) => Promise<string | null>,\n root: string,\n ref: string,\n): Promise<boolean> {\n return (\n (await git(root, [\"rev-parse\", \"--verify\", `${ref}^{object}`])) !== null\n )\n}\n\nasync function readWorkingFile(\n readFile: typeof import(\"node:fs/promises\").readFile,\n root: string,\n path: string,\n): Promise<string> {\n try {\n const { join } = await import(\"node:path\")\n return await readFile(join(root, path), \"utf8\")\n } catch {\n return \"\"\n }\n}\n\ninterface GitChange {\n status: string\n beforePath: string\n path: string\n}\n\nfunction parseNameStatusZ(raw: string): GitChange[] {\n const parts = raw.split(NUL).filter((p) => p.length > 0)\n const out: GitChange[] = []\n let i = 0\n while (i + 1 < parts.length) {\n const status = parts[i].charAt(0)\n i += 1\n const beforePath = parts[i]\n i += 1\n if ((status === \"R\" || status === \"C\") && i < parts.length) {\n out.push({ status, beforePath, path: parts[i] })\n i += 1\n } else {\n out.push({ status, beforePath, path: beforePath })\n }\n }\n return out\n}\n\nfunction looksBinary(s: string): boolean {\n return s.slice(0, 8000).includes(NUL)\n}\n","/**\n * Replay historical traces through a function and create a test run.\n *\n * The replay flow has three phases:\n * 1. Start: fetches historical traces from the server and creates a test run\n * 2. Execute: re-runs each trace's inputs through the provided function locally\n * 3. Complete: marks the test run as completed on the server\n */\n\nimport { resolveAutoCodeChange } from \"./codeChange.js\"\nimport type { DbSnapshotRef } from \"./dbSnapshot.js\"\nimport { BitfabError } from \"./errors.js\"\nimport {\n type CodeChangeFile,\n flushTraces,\n type HttpClient,\n type SpanTreeNode,\n type TokenUsage,\n type TraceOutline,\n type TraceOutlineSpan,\n type TraceOutlineSpanError,\n} from \"./http.js\"\nimport type { MockOverride, MockOverrideInput } from \"./mockOverride.js\"\nimport { normalizeMockOverrides } from \"./mockOverride.js\"\nimport { randomUuid } from \"./randomUuid.js\"\nimport type {\n DbBranchLease,\n DbBranchSettings,\n DbBranchTimings,\n MockSpan,\n MockTree,\n} from \"./replayContext.js\"\nimport { replayContextReady, runWithReplayContext } from \"./replayContext.js\"\nimport { deserializeValue } from \"./serialize.js\"\n\nexport type MockStrategy = \"none\" | \"all\" | \"marked\"\n\nexport type TraceIngestionType = \"captured\" | \"seeded\"\n\nconst REPLAY_PERSISTENCE_TIMEOUT_MS = 30_000\nconst MAX_REPLAY_ATTEMPTS = 100\n\nfunction expandReplayWork<T>(\n serverItems: T[],\n attempts: number,\n): Array<{ serverItem: T; attempt: number }> {\n return Array.from({ length: attempts }, (_, attempt) =>\n serverItems.map((serverItem) => ({ serverItem, attempt })),\n ).flat()\n}\n\nfunction resolveAttempts(attempts: number | undefined): number {\n if (attempts === undefined) {\n return 1\n }\n if (\n !Number.isInteger(attempts) ||\n attempts < 1 ||\n attempts > MAX_REPLAY_ATTEMPTS\n ) {\n throw new BitfabError(\n `attempts must be an integer from 1 to ${MAX_REPLAY_ATTEMPTS} (got ${attempts}).`,\n )\n }\n return attempts\n}\n\n/**\n * How the DB-snapshot branch each replay item runs against is sized and warmed.\n *\n * Every field is optional, so this object is only worth passing when you want\n * to override the mirror project's own sizing. To branch with those defaults,\n * pass `dbBranch: true` instead of an empty object.\n */\nexport interface DbBranchOptions {\n /**\n * Autoscaling floor for the branch's compute, in Neon Compute Units (0.25 to\n * 56). Omit to keep the mirror project's own default. Raise it when the\n * mirror is provisioned smaller than the database it stands in for, so\n * replay latency reflects your code rather than a cold, undersized branch.\n */\n minCu?: number\n /**\n * Autoscaling ceiling for the branch's compute, in Neon Compute Units.\n * Setting it equal to `minCu` pins the size, which keeps items comparable:\n * otherwise a later item can run against an endpoint that has already\n * scaled up and post a better number for the same code.\n */\n maxCu?: number\n /**\n * SQL that warms the branch's cache. The server appends it to the branch's\n * readiness check, so it runs BEFORE your function sees the branch and its\n * time is not charged to the replayed call. Invalid SQL fails the branch\n * rather than silently leaving it cold.\n */\n warmupSql?: string\n}\n\n/**\n * Whether the caller asked for database branching. `true` and a settings object\n * both turn it on; `false` and omission leave it off. Kept separate from\n * `resolveDbBranchSettings` because `dbBranch: true` enables branching while\n * contributing no settings, so presence of settings can't stand in for the\n * switch.\n */\nfunction dbBranchEnabled(\n dbBranch: DbBranchOptions | boolean | undefined,\n): boolean {\n return dbBranch !== undefined && dbBranch !== false\n}\n\n/**\n * Narrow the caller's branch options to the wire shape, dropping the object\n * entirely when nothing was set so the request stays byte-identical to what\n * older SDKs send. Booleans carry no settings: they only move the switch.\n */\nfunction resolveDbBranchSettings(\n dbBranch: DbBranchOptions | boolean | undefined,\n): DbBranchSettings | undefined {\n if (!dbBranch || dbBranch === true) {\n return undefined\n }\n const { minCu, maxCu, warmupSql } = dbBranch\n const settings: DbBranchSettings = {\n ...(minCu === undefined ? {} : { minCu }),\n ...(maxCu === undefined ? {} : { maxCu }),\n ...(warmupSql === undefined ? {} : { warmupSql }),\n }\n return Object.keys(settings).length === 0 ? undefined : settings\n}\n\nexport interface ReplayOptions {\n /**\n * Maximum number of traces to replay (1-5,000, default 5). Ignored when\n * `traceIds` is passed (with a warning), or when `datasetId` is passed,\n * because either source already determines how many traces replay.\n */\n limit?: number\n attempts?: number\n /** Optional list of specific trace IDs to replay (max 100). Mutually exclusive with `datasetId`. */\n traceIds?: string[]\n /** Optional display name for the resulting experiment/test run. */\n name?: string\n /** Maximum number of items to process in parallel. Set to 1 for sequential. Default 10. */\n maxConcurrency?: number\n /**\n * Description of the code change being tested in this replay. Stored on\n * the resulting experiment so the change can be reviewed alongside results.\n * Supplying a description without `codeChangeFiles` preserves this text\n * while the SDK automatically captures the files.\n * Pass `null` when the replay should have no description; use\n * `codeChangeFiles: null` to suppress automatic file capture.\n */\n codeChangeDescription?: string | null\n /**\n * Files edited as part of this code change. Each entry holds the file path\n * and the full `before`/`after` contents. The agent reads each file before\n * and after editing and passes the two strings. Use `\"\"` for newly created\n * files (`before`) or deleted files (`after`). Omit this field to capture\n * automatically, or pass `null` to suppress file capture for this replay.\n */\n codeChangeFiles?: CodeChangeFile[] | null\n /**\n * Mock strategy for child spans during replay.\n * - \"marked\": only spans tagged with { mockOnReplay: true } in SpanOptions are mocked (default)\n * - \"none\": everything runs real code\n * - \"all\": every matched recorded child withSpan returns historical output;\n * a missing occurrence fails the replay item closed\n */\n mock?: MockStrategy\n /**\n * Selective mock overrides: inject custom values into specific spans during\n * replay, so downstream real code runs against the substituted output. Each\n * Pass `{ match, value }` pairs, or one resolver invoked for every child span.\n * A resolver can route on `ctx.node.traceFunctionKey` and return\n * `NO_MOCK_OVERRIDE` to continue to the next override and base strategy.\n * Per-call overrides take precedence over registrations on the client.\n */\n mockOverride?: MockOverrideInput | MockOverrideInput[]\n /**\n * Run each item against a database branch restored to the state its source\n * trace saw. Pass `true` to branch with the mirror project's own sizing, or a\n * {@link DbBranchOptions} object to tune how each branch is sized and warmed.\n * `false` and omission leave branching off. Inside `fn`, read the resolved\n * branch with `getCurrentReplayBranch()`.\n *\n * Items whose source trace carried no DB snapshot reference get no branch and\n * use the app's normal database path. Unsafe calls on that path still require\n * replay mocking. An item whose branch was requested but could not be resolved\n * fails instead of running, so replay never silently reports a result that did\n * not use the historical data you asked for.\n */\n dbBranch?: DbBranchOptions | boolean\n /** Group ID to associate this replay with an experiment group for live streaming in Studio. */\n experimentGroupId?: string\n /**\n * Dataset this replay runs against. Mutually exclusive with `traceIds`. When\n * set, the resulting experiment is\n * durably attributed to the dataset (stored on the test run), so it appears\n * under the dataset's experiments even if the trace lineage can't be\n * reconstructed. Validated server-side against the org.\n */\n datasetId?: string\n /**\n * Graders to attach directly to this experiment (test run), independent of any\n * graders already on the dataset. The resulting experiment is graded by the\n * union of these and the dataset's runnable graders at completion, so use this\n * to grade a single run with a check you don't want to add to the dataset\n * permanently. Each id must be an active/live grader belonging to the same\n * organization and trace function, otherwise the server rejects the replay.\n */\n graderIds?: string[]\n /**\n * Reshape recorded inputs before they are spread into `fn`.\n *\n * Replay pulls each trace's inputs exactly as they were captured against the\n * function's signature AT TRACE TIME. When the function's shape has since\n * changed (params renamed, reordered, collapsed into an options object, etc.),\n * the recorded inputs no longer line up and `fn(...inputs)` throws. This hook\n * lets a caller map the recorded inputs onto the current signature so replay\n * can still run.\n *\n * Receives the deserialized recorded inputs and a per-trace {@link AdaptContext}\n * (so a table-driven adapter can look up the adapted inputs by `traceId`), and\n * returns the array actually spread into `fn`. The returned array is also what\n * `ReplayItem.input` reports, so the experiment shows what was really run.\n *\n * Runs per item, inside the same try/catch as `fn`: if the adapter throws, the\n * failure is surfaced on that item's `error` rather than crashing the run.\n * Omit it to spread the recorded inputs unchanged.\n */\n adaptInputs?: (inputs: unknown[], ctx: AdaptContext) => unknown[]\n /**\n * Resolve every item's inputs and stop, without calling the function.\n *\n * Selection, span fetch, deserialization, and `adaptInputs` all run, so each\n * item reports the exact arguments the function would have received. Nothing\n * executes and no replay traces are produced, which is the cheap way to check\n * that recorded inputs still fit the current signature.\n */\n dryRun?: boolean\n /**\n * Called once per item as it finishes, in completion order (not input\n * order), with running totals for the whole run. Use it to render replay\n * progress, for example a terminal progress bar. Replay does not know\n * pass/fail at this point (verdicts are assigned later), so the totals only\n * distinguish items whose function ran (`succeeded`) from items that threw\n * (`errored`).\n *\n * Invoked synchronously right after each item finishes, so keep it cheap. A\n * throwing callback never crashes the run: the error is swallowed so progress\n * UI can't break replay.\n */\n onItemFinish?: (progress: ReplayItemFinishProgress) => void\n /**\n * @deprecated Use {@link onItemFinish}. This compatibility callback receives\n * the same per-item finish events plus the legacy whole-run `\"complete\"`\n * event. It is ignored when `onItemFinish` is also provided.\n */\n onProgress?: (progress: ReplayProgress) => void\n /**\n * Called once when each replay item begins processing, before input loading,\n * mock preparation, database branching, or the customer function runs. Use\n * it with {@link onItemFinish} to distinguish queued items from items that\n * are still in flight. A throwing callback never crashes the run.\n */\n onItemStart?: (progress: ReplayItemStartProgress) => void\n}\n\n/** Emitted through {@link ReplayOptions.onItemStart} when a worker starts an item. */\nexport interface ReplayItemStartProgress {\n type: \"started\"\n /** Test run ID created for this replay. */\n testRunId: string\n /** Items whose processing has started so far. */\n started: number\n /** Items that have finished so far, whether they succeeded or errored. */\n completed: number\n /** Total number of items in this replay run. */\n total: number\n /** Of the completed items, how many finished without a code or replay error. */\n succeeded: number\n /** Of the completed items, how many finished with an error. */\n errored: number\n /** The historical trace and span whose replay processing just started. */\n item: {\n originalTraceId: string\n originalSpanId: string\n /** @deprecated alias for `originalTraceId`. */\n sourceTraceId: string\n /** @deprecated alias for `originalSpanId`. */\n sourceSpanId: string\n attempt: number\n }\n}\n\n/** Running totals reported to {@link ReplayOptions.onItemFinish} as replay proceeds. */\nexport interface ReplayItemFinishProgress {\n /** Event kind, omitted for backward-compatible per-item events. */\n type?: \"item\"\n /** Test run ID created for this replay. */\n testRunId: string\n /** Items that have finished so far, whether they succeeded or errored. */\n completed: number\n /** Total number of items in this replay run. */\n total: number\n /** Of the completed items, how many finished without a code or replay error. */\n succeeded: number\n /** Of the completed items, how many have `item.error` set. */\n errored: number\n /**\n * The single item that just finished to produce this event. Field-for-field\n * the same shape and meaning as {@link ReplayItem}, so a progress UI and a\n * final-result UI read one contract. `traceId` is null at this stage (the\n * server replay id arrives at completion), and `tokens` is null for the same\n * reason: the replayed run's usage is aggregated server-side by\n * completeReplay. `durationMs` is how long this item took to replay; the\n * `original*` fields describe the trace it replayed.\n */\n item: ReplayProgressItem\n}\n\n/** See {@link ReplayItemFinishProgress.item}. Mirrors {@link ReplayItem}. */\nexport interface ReplayProgressItem {\n /** Trace ID of the new replay trace (null during the run; the server id arrives at completion). */\n traceId?: string | null\n /** Bitfab trace ID of the original (historical) trace being replayed. */\n originalTraceId: string | null\n /** External span ID the recorded inputs were read from (the original root span). */\n originalSpanId?: string | null\n /** @deprecated alias for `originalTraceId`. */\n sourceTraceId: string | null\n /** @deprecated alias for `originalSpanId`. */\n sourceSpanId?: string | null\n attempt: number\n /** Deserialized inputs from the original trace. */\n input?: unknown[]\n /** The result returned by the replayed function, or undefined on error. */\n result?: unknown\n /** The original output from the historical trace. */\n originalOutput?: unknown\n /** Backward-compatible message for either error kind. */\n error: string | null\n /** The actual value thrown by the replayed customer function. */\n traceError?: unknown | null\n /** The actual value thrown while Bitfab prepared this replay item. */\n replayError?: unknown | null\n /** How long the replayed function took on this run. */\n durationMs?: number | null\n /** The original trace's duration, tokens, and model. */\n originalDurationMs?: number | null\n originalTokens?: TokenUsage | null\n originalModel?: string | null\n /** Always null here: the replayed run's usage is only known at completion. */\n tokens?: TokenUsage | null\n /** @deprecated renamed to `originalModel`. */\n model?: string | null\n dbSnapshotRef?: DbSnapshotRef | null\n dbBranchTimings?: DbBranchTimings | null\n traceOutline?: TraceOutline | null\n originalTraceOutline?: TraceOutline | null\n}\n\n/**\n * @deprecated Use {@link ReplayItemFinishProgress}. This legacy shape also\n * represents the item-less terminal `\"complete\"` event emitted by\n * {@link ReplayOptions.onProgress}.\n */\nexport interface ReplayProgress {\n type?: \"item\" | \"complete\"\n result?: ReplayResult<unknown>\n testRunId?: string\n completed: number\n total: number\n succeeded: number\n errored: number\n item?: ReplayItemFinishProgress[\"item\"]\n}\n\n/**\n * Wire prefix the Bitfab plugin scans for. Each line {@link reportReplayProgress}\n * writes is this prefix followed by the JSON of the running totals (plus the\n * finished `item`). The plugin polls these lines to report live progress while a\n * replay runs in the background; keep the SDK emitter and the plugin parser in\n * sync.\n */\nexport const BITFAB_PROGRESS_PREFIX = \"@@bitfab:progress \"\n\n/**\n * A ready-made replay lifecycle callback for replay scripts.\n * Pass it straight in:\n *\n * ```ts\n * await bitfab.replay(\"my-fn\", fn, {\n * limit,\n * onItemStart: reportReplayProgress,\n * onItemFinish: reportReplayProgress,\n * })\n * ```\n *\n * It writes `@@bitfab:progress` lines to stderr, which the Bitfab plugin polls\n * to report in-flight and finished items while replay runs in the background,\n * so scripts never hand-format the wire protocol.\n * stdout is left untouched for direct-run ReplayResult JSON. Outside Node (no\n * `process.stderr`, e.g. a browser) it is a no-op, and a write failure is\n * swallowed so progress can never crash a run.\n */\nexport function reportReplayProgress(\n progress: ReplayItemFinishProgress | ReplayItemStartProgress | ReplayProgress,\n): void {\n const stderr = typeof process !== \"undefined\" ? process.stderr : undefined\n if (!stderr) {\n return\n }\n try {\n stderr.write(\n `${BITFAB_PROGRESS_PREFIX}${JSON.stringify(progress, replayJsonReplacer)}\\n`,\n )\n } catch {\n // A progress reporter must never crash the replay run.\n }\n}\n\n/** Per-trace context passed to {@link ReplayOptions.adaptInputs}. */\nexport interface AdaptContext {\n /** Bitfab trace ID of the original (historical) trace being replayed. */\n originalTraceId: string\n /** External span ID the recorded inputs were read from. */\n originalSpanId: string\n /** @deprecated alias for {@link AdaptContext.originalTraceId}. */\n sourceTraceId: string\n /** @deprecated alias for {@link AdaptContext.originalSpanId}. */\n sourceSpanId: string\n metadata: Record<string, unknown>\n}\n\n/**\n * The shape an adapter module must export as `adaptInputs`.\n *\n * Author an adapter in its own file (e.g. `scripts/replay-adapters/<name>.ts`),\n * import it in your replay script, and pass it to `replay({ adaptInputs })`:\n *\n * ```ts\n * import type { AdaptInputsFn } from \"@bitfab/sdk\"\n * export const adaptInputs: AdaptInputsFn = (inputs, ctx) => [reshape(inputs)]\n * ```\n */\nexport type AdaptInputsFn = (inputs: unknown[], ctx: AdaptContext) => unknown[]\n\nexport interface ReplayItem<T> {\n /**\n * Server trace ID of the new replay trace this item produced. Written in by\n * `replay()` from the complete-replay response once the server has minted the\n * trace row; the client-side id used to correlate spans during the run is\n * never surfaced here. Null until completion, on older servers that omit the\n * mapping, or if the item produced no trace. Not the verdict-persistence key:\n * that is the original-trace lineage (`originalTraceId` + `testRunId`).\n */\n traceId: string | null\n /** Bitfab trace ID of the original (historical) trace being replayed. */\n originalTraceId: string\n /** External span ID the recorded inputs were read from (the original root span). */\n originalSpanId: string\n /** @deprecated alias for {@link ReplayItem.originalTraceId}. */\n sourceTraceId: string\n /** @deprecated alias for {@link ReplayItem.originalSpanId}. */\n sourceSpanId: string\n attempt: number\n /** Deserialized inputs from the original trace. */\n input: unknown[]\n /** The result returned by the function during replay, or undefined on error. */\n result: T | undefined\n originalOutput: unknown\n /**\n * How the source trace came to exist. Absent on servers that predate the\n * field, which only ever served captured traces.\n */\n ingestionType?: TraceIngestionType\n /**\n * Backward-compatible message for either error kind. Prefer `traceError` and\n * `replayError` when callers need the original exception and its source.\n */\n error: string | null\n /** The actual value thrown by the replayed customer function. */\n traceError: unknown | null\n /**\n * The actual value thrown by replay setup before the customer function ran,\n * such as database warmup, input hydration, or mock preparation.\n */\n replayError: unknown | null\n /**\n * How long the replayed function took on this run, in ms. Null if the item\n * failed before it ran. Compare against\n * {@link ReplayItem.originalDurationMs} for the before/after.\n */\n durationMs: number | null\n /** The original trace's duration in ms, or null if its timestamps are missing. */\n originalDurationMs: number | null\n /**\n * Token usage recorded on the original trace, or null if it captured none.\n * The \"old\" side of a token delta; {@link ReplayItem.tokens} is the new one.\n */\n originalTokens: TokenUsage | null\n /** Model name from the original trace, or null if not captured. */\n originalModel: string | null\n /**\n * Token usage from the REPLAYED run (this item's new execution), aggregated\n * server-side from the spans it produced, or null if the run captured no\n * token data. Compare against {@link ReplayItem.originalTokens} to see how\n * the code change moved cost. Matches what Studio's experiments view shows.\n *\n * Unprefixed because the replay is this item's subject: anything describing\n * the trace being replayed carries `original`.\n */\n tokens: TokenUsage | null\n /** @deprecated renamed to {@link ReplayItem.originalModel}. */\n model: string | null\n /**\n * The DB snapshot ref the SDK captured at trace open. Useful for debugging\n * (\"what state was this trace pinned to?\") and for customers building\n * their own resolvers. Undefined when the source trace was captured\n * without `dbSnapshot` configured.\n */\n dbSnapshotRef: DbSnapshotRef | null\n /**\n * How long this item's DB branch took to provision, per phase, measured\n * server-side. Present whenever a branch was attempted, on both outcomes:\n * complete on success, partial up to the failing phase when the resolve\n * failed. Null when no branch was asked for, when the source trace carried\n * no snapshot ref, or against a server that predates timings.\n */\n dbBranchTimings: DbBranchTimings | null\n traceOutline: TraceOutline | null\n originalTraceOutline: TraceOutline | null\n}\n\nexport type {\n CodeChangeFile,\n TokenUsage,\n TraceOutline,\n TraceOutlineSpan,\n TraceOutlineSpanError,\n}\n\nexport interface ReplayResult<T> {\n /** Individual replay items with inputs, results, and comparison data. */\n items: ReplayItem<T>[]\n /** The test run ID created on the server. */\n testRunId: string\n /** Full URL to view the test run in the dashboard. */\n testRunUrl: string\n attempts: number\n}\n\n/**\n * Whole-run replay failure that preserves every item collected before the run\n * failed. The original whole-run exception is available as `cause`.\n */\nexport class ReplayError<T = unknown> extends BitfabError {\n constructor(\n message: string,\n public readonly items: ReplayItem<T>[],\n public readonly testRunId: string,\n public readonly testRunUrl: string,\n public readonly cause: unknown,\n ) {\n super(message, testRunUrl)\n this.name = \"ReplayError\"\n }\n}\n\n/**\n * A database branch requested for one replay item could not be resolved.\n *\n * The server's resolver code and message are retained as structured fields so\n * callers can handle failures such as `branch_create_failed` and\n * `snapshot_from_replaced_origin` without parsing the compatible `item.error`\n * string.\n */\nexport class DbBranchReplayError extends BitfabError {\n constructor(\n public readonly code: string,\n message: string,\n public readonly originalTraceId: string,\n public readonly cause?: unknown,\n ) {\n super(message)\n this.name = \"DbBranchReplayError\"\n }\n}\n\nfunction isPlainRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value)\n}\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error)\n}\n\nfunction replayItemErrorMessage(error: unknown): string {\n if (error instanceof DbBranchReplayError) {\n return `Replay requested a database branch for trace ${error.originalTraceId} but it could not be resolved (${error.code}): ${error.message}. The function was not run, because replaying it against the live database would produce a result that looks valid but did not use the historical data you asked for.`\n }\n return errorMessage(error)\n}\n\nfunction replayJsonReplacer(_key: string, value: unknown): unknown {\n if (value instanceof Error) {\n const serialized: Record<string, unknown> = {\n name: value.name,\n message: value.message,\n stack: value.stack,\n }\n if (value instanceof DbBranchReplayError) {\n serialized.code = value.code\n serialized.originalTraceId = value.originalTraceId\n if (value.cause !== undefined) {\n serialized.cause = value.cause\n }\n }\n return serialized\n }\n return value\n}\n\n/**\n * Serialize a replay result as JSON while retaining structured trace and replay\n * errors. Use this for direct-run stdout instead of raw `JSON.stringify`, which\n * drops the useful fields on JavaScript `Error` objects.\n */\nexport function serializeReplayResult<T>(result: ReplayResult<T>): string {\n return JSON.stringify(result, replayJsonReplacer, 2)\n}\n\nasync function preserveReplayFailure<T, TItem>(\n operation: () => Promise<T>,\n items: ReplayItem<TItem>[],\n testRunId: string,\n testRunUrl: string,\n): Promise<T> {\n try {\n return await operation()\n } catch (cause) {\n if (cause instanceof ReplayError) {\n throw cause\n }\n throw new ReplayError(\n errorMessage(cause),\n items,\n testRunId,\n testRunUrl,\n cause,\n )\n }\n}\n\n/**\n * Deserialize inputs from a historical span's rawData.\n *\n * Prefers superjson-serialized `input_meta` for type preservation,\n * falls back to the raw `input` field.\n */\nfunction deserializeInputs(spanData: Record<string, unknown>): unknown[] {\n const inputMeta = spanData.input_meta as unknown\n const rawInput = spanData.input\n\n // If superjson meta is available, deserialize with type reconstruction\n if (inputMeta !== undefined && inputMeta !== null) {\n const deserialized = deserializeValue({ json: rawInput, meta: inputMeta })\n if (Array.isArray(deserialized)) {\n return deserialized\n }\n return deserialized !== undefined && deserialized !== null\n ? [deserialized]\n : []\n }\n\n // Fall back to raw input\n if (Array.isArray(rawInput)) {\n return rawInput\n }\n return rawInput !== undefined && rawInput !== null ? [rawInput] : []\n}\n\n/**\n * Deserialize the original output from a historical span's rawData.\n */\nfunction deserializeOutput(spanData: Record<string, unknown>): unknown {\n const outputMeta = spanData.output_meta as unknown\n const rawOutput = spanData.output\n\n if (outputMeta !== undefined && outputMeta !== null) {\n return deserializeValue({ json: rawOutput, meta: outputMeta })\n }\n\n return rawOutput\n}\n\n/**\n * Walk the children of a root span tree node in depth-first order and build\n * a MockTree keyed by `${traceFunctionKey}:${spanName}:${callIndex}`.\n *\n * The historical root itself is NOT walked. At replay time the runtime root\n * span has `isRootSpan === true` and never queries the mockTree (mock\n * interception is skipped for root spans by design), so the root has nothing\n * to look up. Walking it would just leave an unreachable entry in the table.\n *\n * The (key, name) compound match is what disambiguates same-key spans:\n * - A wrapped function's children commonly share its traceFunctionKey via\n * the fluent `getFunction(key).withSpan({ name }, ...)` pattern. They\n * disambiguate by `name`, never colliding with each other.\n * - Recursion: same (key, name) at every depth. callIndex per (key, name)\n * orders them correctly without leaking the historical root into the\n * nested call's slot.\n * - Outer-wrapper replay scripts: the outer wrapper's `name` is distinct\n * from anything in the historical tree (it only exists at replay), so\n * its presence never disturbs counters or lookups for spans that do\n * exist in the historical tree.\n */\nfunction buildMockTree(rootNode: SpanTreeNode): MockTree {\n const spans = new Map<string, MockSpan>()\n const counters = new Map<string, number>()\n\n function walk(node: SpanTreeNode): void {\n const key = node.traceFunctionKey\n if (key) {\n const name = node.spanName || key\n const counterKey = `${key}:${name}`\n const index = counters.get(counterKey) ?? 0\n counters.set(counterKey, index + 1)\n // `output`/`outputMeta` are undefined on a payload-free (lazy) tree;\n // `externalSpanId` is what the lazy path fetches them by. Both are copied\n // verbatim so eager and lazy trees build through the same walk.\n spans.set(`${counterKey}:${index}`, {\n sourceSpanId: node.sourceSpanId,\n externalSpanId: node.externalSpanId,\n output: node.output,\n outputMeta: node.outputMeta,\n })\n }\n for (const child of node.children) {\n walk(child)\n }\n }\n\n for (const child of rootNode.children) {\n walk(child)\n }\n\n return { spans }\n}\n\n/**\n * Execute a single replay item: fetch span data, deserialize inputs, call\n * the function within a replay context that injects testRunId into new spans.\n */\nasync function processItem<TReturn>(\n httpClient: HttpClient,\n serverItem: {\n originalTraceId?: string\n originalSpanId?: string\n /** @deprecated alias emitted by servers that predate the originalTraceId rename. */\n sourceTraceId: string\n /** @deprecated alias emitted by servers that predate the originalSpanId rename. */\n sourceSpanId: string\n originalDurationMs?: number | null\n originalTokens?: TokenUsage | null\n originalModel?: string | null\n originalMetadata?: Record<string, unknown>\n ingestionType?: TraceIngestionType\n /** @deprecated unprefixed aliases emitted by servers that predate the rename.\n * `tokens` here is the ORIGINAL trace's usage: the start item has never\n * carried the replay's, which only exists after completeReplay. */\n durationMs: number | null\n tokens?: TokenUsage | null\n model: string | null\n dbSnapshotRef?: DbSnapshotRef\n dbBranchLease?: DbBranchLease\n dbBranchLeaseError?: { code: string; message: string }\n dbBranchTimings?: DbBranchTimings\n },\n // biome-ignore lint/suspicious/noExplicitAny: replay deserializes inputs from historical data\n fn: (...args: any[]) => TReturn | Promise<TReturn>,\n testRunId: string,\n mockStrategy: MockStrategy,\n resolvedOverrides: MockOverride[],\n replayedTraceId: string,\n attempt: number,\n includeDbBranchLease: boolean,\n dbBranchSettings: DbBranchSettings | undefined,\n adaptInputs:\n | ((inputs: unknown[], ctx: AdaptContext) => unknown[])\n | undefined,\n dryRun: boolean,\n): Promise<ReplayItem<TReturn>> {\n // The server-side resolver materializes a Neon preview branch per item\n // during `/api/sdk/replay/start` (when the customer passed `dbBranch`,\n // which triggers `includeDbBranchLease: true`). The lease arrives on the\n // server item; we just attach it to the replay context and release the\n // branch in `finally` so any throw (in fetch, mock-tree build, or the\n // customer fn) frees the Neon resource. Items whose source trace had no\n // snapshot ref arrive without a lease; `getCurrentReplayBranch()` returns\n // null for those, and the app uses its normal DB path. Unsafe calls on that\n // path still require replay mocking.\n let lease = includeDbBranchLease ? serverItem.dbBranchLease : undefined\n // A resolve that was attempted and FAILED is different: the caller asked for\n // a branch, so running their function against live data would produce a\n // result that looks valid and isn't. Fail this item instead, loudly.\n let leaseError = includeDbBranchLease\n ? serverItem.dbBranchLeaseError\n : undefined\n let dbSnapshotRef = serverItem.dbSnapshotRef\n // Reported whichever way the resolve went, so it is tracked separately from\n // both the lease and the error rather than hanging off either.\n let dbBranchTimings = includeDbBranchLease\n ? serverItem.dbBranchTimings\n : undefined\n\n let inputs: unknown[] = []\n let originalOutput: unknown\n let result: TReturn | undefined\n let error: string | null = null\n let traceError: unknown | null = null\n let replayError: unknown | null = null\n // Timed around the replayed function only, so it is comparable to\n // originalDurationMs (that same function's wall time on the original run)\n // rather than to the span fetches and persistence around it.\n let replayDurationMs: number | null = null\n // Null until the replayed function actually starts, so an item that fails in\n // the span fetch or mock-tree build reports no replay duration rather than\n // timing work that was not the function.\n let replayStarted: number | null = null\n\n // The ORIGINAL (historical) trace/span this item replays. Canonical server\n // keys are originalTraceId/originalSpanId; older servers only send the\n // deprecated sourceTraceId/sourceSpanId aliases.\n const originalTraceId = serverItem.originalTraceId ?? serverItem.sourceTraceId\n const originalSpanId = serverItem.originalSpanId ?? serverItem.sourceSpanId\n\n try {\n if (includeDbBranchLease && !lease && !leaseError) {\n let resolved: Awaited<ReturnType<HttpClient[\"resolveDbBranchLease\"]>>\n try {\n resolved = await httpClient.resolveDbBranchLease(\n testRunId,\n originalTraceId,\n dbBranchSettings,\n attempt,\n )\n } catch (cause) {\n throw new DbBranchReplayError(\n \"lease_request_failed\",\n `Bitfab could not request the database branch: ${errorMessage(cause)}`,\n originalTraceId,\n cause,\n )\n }\n lease = resolved.lease ?? undefined\n leaseError = resolved.leaseError ?? undefined\n dbSnapshotRef = resolved.dbSnapshotRef ?? dbSnapshotRef\n dbBranchTimings = resolved.timings ?? dbBranchTimings\n }\n\n if (leaseError) {\n throw new DbBranchReplayError(\n leaseError.code,\n leaseError.message,\n originalTraceId,\n )\n }\n\n const span = await httpClient.getExternalSpan(originalSpanId, {\n view: \"replay\",\n })\n const spanData = (span.rawData?.span_data ?? {}) as Record<string, unknown>\n\n inputs = deserializeInputs(spanData)\n originalOutput = deserializeOutput(spanData)\n\n // Reshape the recorded inputs onto the current signature when an adapter\n // is supplied. Runs before the mock tree / fn call so the adapted array is\n // what fn receives and what `item.input` reports.\n if (adaptInputs) {\n const originalMetadata = serverItem.originalMetadata\n inputs = adaptInputs(inputs, {\n originalTraceId,\n originalSpanId,\n // Deprecated aliases for originalTraceId/originalSpanId.\n sourceTraceId: originalTraceId,\n sourceSpanId: originalSpanId,\n metadata: isPlainRecord(originalMetadata)\n ? { ...originalMetadata }\n : {},\n })\n }\n\n // Build the mock tree whenever mocking could apply: any non-\"none\" strategy,\n // OR overrides are present (overrides substitute even under \"none\" - the\n // \"run real code but replace node X\" case). Only \"all\" needs outputs inline;\n // Non-\"all\" runs that need a tree (\"marked\", or \"none\" with overrides)\n // keep it payload-free and pull outputs lazily, so we never drag down every\n // span's recorded output when only a few get mocked.\n const hasOverrides = resolvedOverrides.length > 0\n const needTree =\n mockStrategy === \"all\" || mockStrategy === \"marked\" || hasOverrides\n const includeOutputs = mockStrategy === \"all\"\n\n let mockTree: MockTree | undefined\n if (needTree) {\n try {\n const treeResponse = await httpClient.getSpanTree(originalSpanId, {\n includeOutputs,\n includeRootOutput: false,\n })\n if (!treeResponse.root) {\n throw new BitfabError(\n `Replay mock strategy \"${mockStrategy}\"${hasOverrides ? \" with overrides\" : \"\"} requires a span tree root for original span ${originalSpanId}.`,\n )\n }\n mockTree = buildMockTree(treeResponse.root)\n } catch (error) {\n if (mockStrategy !== \"marked\" || hasOverrides) {\n throw error\n }\n // The root still runs under \"marked\". An empty active tree lets an\n // unmarked-only root proceed, while any selected child fails closed at\n // its call site instead of executing the real span.\n mockTree = { spans: new Map() }\n }\n }\n\n // Lazy per-span output fetch, memoized per item so a span read twice (once\n // as a marked mock, once via an override's getOriginalOutput) fetches once.\n // Present only when outputs were NOT fetched inline (not the eager \"all\"\n // path); its presence signals the mock path to fetch on demand.\n const outputCache = new Map<string, Promise<unknown>>()\n const fetchSpanOutput =\n mockTree && !includeOutputs\n ? (externalSpanId: string): Promise<unknown> => {\n let pending = outputCache.get(externalSpanId)\n if (!pending) {\n pending = httpClient\n .getExternalSpan(externalSpanId, { view: \"replay\" })\n .then((s) =>\n deserializeOutput(\n (s.rawData?.span_data ?? {}) as Record<string, unknown>,\n ),\n )\n outputCache.set(externalSpanId, pending)\n }\n return pending\n }\n : undefined\n\n if (dryRun) {\n return {\n traceId: null,\n originalTraceId,\n originalSpanId,\n sourceTraceId: originalTraceId,\n sourceSpanId: originalSpanId,\n attempt,\n input: inputs,\n result: undefined,\n originalOutput,\n ...(serverItem.ingestionType && {\n ingestionType: serverItem.ingestionType,\n }),\n error: null,\n traceError: null,\n replayError: null,\n durationMs: null,\n originalDurationMs:\n serverItem.originalDurationMs ?? serverItem.durationMs ?? null,\n originalTokens: serverItem.originalTokens ?? serverItem.tokens ?? null,\n originalModel: serverItem.originalModel ?? serverItem.model ?? null,\n tokens: null,\n model: serverItem.originalModel ?? serverItem.model ?? null,\n dbSnapshotRef: dbSnapshotRef ?? null,\n dbBranchTimings: dbBranchTimings ?? null,\n traceOutline: null,\n originalTraceOutline: null,\n }\n }\n\n try {\n replayStarted = performance.now()\n const maybePromise = runWithReplayContext(\n {\n testRunId,\n traceId: replayedTraceId,\n inputSourceSpanId: span.id,\n inputSourceTraceId: span.externalTraceId,\n sourceBitfabTraceId: originalTraceId,\n replayAttempt: attempt,\n mockTree,\n callCounters: mockTree ? new Map() : undefined,\n mockStrategy,\n mockOverrides: hasOverrides ? resolvedOverrides : undefined,\n fetchSpanOutput,\n dbBranchLease: lease,\n dbBranchTimings,\n },\n () => fn(...inputs),\n )\n result =\n maybePromise instanceof Promise ? await maybePromise : maybePromise\n replayDurationMs = Math.round(performance.now() - replayStarted)\n } catch (e) {\n // The function ran and threw, so it still has a duration worth reporting.\n if (replayStarted !== null) {\n replayDurationMs = Math.round(performance.now() - replayStarted)\n }\n traceError = e\n error = errorMessage(e)\n }\n } catch (e) {\n // Replay setup failed. replayStarted is null unless the customer function\n // had already begun, so this leaves durationMs null for a genuine\n // setup failure rather than timing work that was not the function.\n if (replayStarted !== null) {\n replayDurationMs = Math.round(performance.now() - replayStarted)\n }\n replayError = e\n error = replayItemErrorMessage(e)\n } finally {\n if (lease) {\n try {\n await httpClient.releaseDbBranchLease(lease.neonBranchId)\n } catch (e) {\n try {\n console.warn(\n `Bitfab: failed to release DB branch ${lease.neonBranchId} (TTL janitor will catch it): ${\n e instanceof Error ? e.message : String(e)\n }`,\n )\n } catch {\n // Never crash the host\n }\n }\n }\n }\n\n // Canonical names first, falling back to the unprefixed ones a server that\n // predates the rename sends.\n const originalDurationMs =\n serverItem.originalDurationMs ?? serverItem.durationMs ?? null\n const originalModel = serverItem.originalModel ?? serverItem.model ?? null\n return {\n // Written in by replay() from the complete-replay response once the server\n // has minted this replay trace's row. Null until then: the client-side\n // correlation id (replayedTraceId) is never surfaced as the item's traceId.\n traceId: null,\n originalTraceId,\n originalSpanId,\n // Deprecated aliases for originalTraceId/originalSpanId.\n sourceTraceId: originalTraceId,\n sourceSpanId: originalSpanId,\n attempt,\n input: inputs,\n result,\n originalOutput,\n ...(serverItem.ingestionType && {\n ingestionType: serverItem.ingestionType,\n }),\n error,\n traceError,\n replayError,\n durationMs: replayDurationMs,\n originalDurationMs,\n originalTokens: serverItem.originalTokens ?? serverItem.tokens ?? null,\n originalModel,\n // Filled in by replay() from the complete-replay response once the\n // replay traces are persisted and their spans aggregated server-side.\n // Null here (and on older servers) means \"replay tokens not known\".\n tokens: null,\n model: originalModel,\n dbSnapshotRef: dbSnapshotRef ?? null,\n dbBranchTimings: dbBranchTimings ?? null,\n traceOutline: null,\n originalTraceOutline: null,\n }\n}\n\n/**\n * Block until the server has fully persisted every replay trace this run\n * submitted, or fail loudly.\n *\n * `completeReplay` reads at a single instant: it mints the trace-ID mapping and\n * aggregates each trace's tokens from its spans. Run it while spans are still\n * in flight and `item.traceId` comes back null with undercounted tokens.\n *\n * In the normal case the verdict is local: ingestion commits a request's\n * carriers before it answers, so a flush that delivered every carrier has\n * already proven the traces are whole and polling only asked the server to\n * repeat itself. Acks cannot settle a request that timed out client-side after\n * the server committed, so anything short of fully delivered falls through to\n * the server poll, which stays the authority there.\n *\n * Returns the server-assigned `traces.id` for each replay trace, read back off\n * the OTLP ingest response during the flush and keyed by the client-side replay\n * trace id. Empty when the server predates that field or nothing was delivered.\n */\nexport async function waitForReplayPersistence(\n httpClient: HttpClient,\n testRunId: string,\n replayedTraceIds: string[],\n): Promise<Record<string, string>> {\n // Settle deferred submissions before counting. A `finalize` root span only\n // reaches the transport once its finalize chain resolves, so tallying first\n // would under-count and let the barrier pass on a trace that is still short.\n // This waits for that work WITHOUT flushing: a run that submitted nothing\n // must not emit an export request just to discover it has nothing to wait on.\n const deferredSettled = await httpClient.settleDeferredWork(\n REPLAY_PERSISTENCE_TIMEOUT_MS,\n )\n\n // Checked BEFORE the tally: deferred work that never landed means no\n // completion may have registered at all, and an empty tally would then look\n // like \"nothing to wait for\" and finalize the run with root spans pending.\n if (!deferredSettled) {\n // Freed before throwing: every other exit releases these, and a retained\n // record would carry this run's submitted-but-unacked spans into the next\n // replay of the same trace ids.\n httpClient.takeTraceDeliveries(replayedTraceIds)\n throw new BitfabError(\n `Replay could not settle deferred span work before the deadline, so the ` +\n `expected span counts are incomplete (testRunId ${testRunId}).`,\n )\n }\n\n // Peeked before flushing: a run whose traces never closed submitted nothing\n // to wait on, and must not emit an export request just to discover that.\n if (!httpClient.hasClosedDeliveries(replayedTraceIds)) {\n httpClient.takeTraceDeliveries(replayedTraceIds)\n return {}\n }\n\n // A failed flush is a hint, not a verdict. It means delivery was not\n // CONFIRMED within the deadline, which is not the same as lost: the export\n // timeout can fire while requests are still in flight and the server goes on\n // to persist every one of them. Throwing here failed runs whose data had\n // fully landed.\n const flushed = await flushTraces(REPLAY_PERSISTENCE_TIMEOUT_MS)\n\n const deliveries = httpClient.takeTraceDeliveries(replayedTraceIds)\n const expectedSpanCounts: Record<string, number> = {}\n const readBackTraceIds: Record<string, string> = {}\n let allDelivered = true\n for (const [traceId, delivery] of Object.entries(deliveries)) {\n if (delivery.serverTraceId !== undefined) {\n readBackTraceIds[traceId] = delivery.serverTraceId\n }\n if (!delivery.closed) {\n continue\n }\n expectedSpanCounts[traceId] = delivery.spanCount\n allDelivered = allDelivered && delivery.delivered\n }\n if (allDelivered) {\n return readBackTraceIds\n }\n\n // Unacked is not unpersisted: a request that timed out client-side may have\n // committed anyway, and an export the flush deadline abandoned may still be\n // in flight. Neither is knowable here, so from this point the server is the\n // only authority and the run polls it until it answers or the budget ends.\n //\n // The poll gets its own budget. Sharing one deadline with the flush meant a\n // flush that used it all left zero polling window, so the barrier failed\n // after a single not-ready answer - exactly the case where the export is\n // still in flight and about to persist.\n const deadline = Date.now() + REPLAY_PERSISTENCE_TIMEOUT_MS\n\n let missing = Object.keys(expectedSpanCounts).length\n while (true) {\n const status = await httpClient.getReplayStatus(\n testRunId,\n expectedSpanCounts,\n )\n const ready = status.traceIds ?? {}\n missing = Object.keys(expectedSpanCounts).filter(\n (traceId) => ready[traceId] === undefined,\n ).length\n if (missing === 0) {\n return readBackTraceIds\n }\n if (Date.now() >= deadline) {\n break\n }\n await sleepForReplayPersistence(\n Math.min(100, Math.max(0, deadline - Date.now())),\n )\n }\n\n // Only now is it a real failure: the server itself never confirmed these.\n // Surface the flush result as the likely cause rather than as the verdict.\n const cause = flushed\n ? \"\"\n : \" Delivery was also not confirmed before the flush deadline, so the \" +\n \"spans likely never reached the server.\"\n throw new BitfabError(\n `Replay traces were not fully persisted before the delivery deadline ` +\n `(testRunId ${testRunId}, missing ${missing} of ` +\n `${Object.keys(expectedSpanCounts).length} trace(s)).${cause}`,\n )\n}\n\n/** @internal Wait between replay persistence polls without releasing Node. */\nexport function sleepForReplayPersistence(ms: number): Promise<void> {\n return new Promise((resolve) => {\n // This timer is part of an awaited persistence barrier. It must keep a CLI\n // process alive until the server confirms the replay or the deadline fires.\n setTimeout(resolve, ms)\n })\n}\n\n/**\n * Run async tasks with a concurrency limit.\n * Each task factory is called when a slot opens; results preserve input order.\n */\nasync function mapWithConcurrency<T>(\n tasks: Array<() => Promise<T>>,\n maxConcurrency: number,\n onSettled?: (result: T, index: number) => void | Promise<void>,\n onStarted?: (index: number) => void,\n): Promise<T[]> {\n const results: T[] = new Array(tasks.length)\n let nextIndex = 0\n\n async function worker(): Promise<void> {\n while (nextIndex < tasks.length) {\n const index = nextIndex++\n onStarted?.(index)\n const result = await tasks[index]()\n results[index] = result\n await onSettled?.(result, index)\n }\n }\n\n const workers = Array.from(\n { length: Math.min(maxConcurrency, tasks.length) },\n () => worker(),\n )\n await Promise.all(workers)\n return results\n}\n\n/**\n * Replay historical traces through a function and create a test run.\n *\n * @internal Called by Bitfab.replay, not part of the public API.\n */\nexport async function replay<TReturn>(\n httpClient: HttpClient,\n serviceUrl: string,\n traceFunctionKey: string,\n // biome-ignore lint/suspicious/noExplicitAny: replay deserializes inputs from historical data\n fn: (...args: any[]) => TReturn | Promise<TReturn>,\n options?: ReplayOptions,\n registeredOverrides: MockOverride[] = [],\n): Promise<ReplayResult<TReturn>> {\n if (options?.traceIds !== undefined) {\n if (options.traceIds.length === 0) {\n throw new BitfabError(\"traceIds must contain at least one trace ID.\")\n }\n if (options.traceIds.length > 100) {\n throw new BitfabError(\n `traceIds supports at most 100 trace IDs per replay (got ${options.traceIds.length}).`,\n )\n }\n }\n if (options?.traceIds !== undefined && options?.datasetId !== undefined) {\n throw new BitfabError(\n \"traceIds and datasetId select different replay sources and cannot be used together.\",\n )\n }\n if (options?.limit !== undefined && options?.traceIds !== undefined) {\n try {\n console.warn(\n \"Bitfab: limit is ignored when traceIds is passed: the explicit trace ID list already determines how many traces replay.\",\n )\n } catch {\n // Never crash the host app\n }\n }\n const attempts = resolveAttempts(options?.attempts)\n await replayContextReady\n\n // Resolve the code change to attach to this experiment. codeChangeFiles is\n // the capture control: omitted auto-captures, an array wins, and null opts\n // out. A caller-supplied description is preserved when files are captured.\n let codeChangeDescription = options?.codeChangeDescription\n let codeChangeFiles = options?.codeChangeFiles\n if (codeChangeFiles === undefined) {\n const captured = await resolveAutoCodeChange(options?.name)\n if (captured) {\n codeChangeFiles = captured.files\n if (codeChangeDescription === undefined) {\n codeChangeDescription = captured.description\n }\n }\n }\n\n const {\n testRunId,\n testRunUrl,\n items: serverItems,\n } = await httpClient.startReplay(\n traceFunctionKey,\n // limit is meaningless with explicit traceIds (the ID list determines\n // the count), so it's omitted from the request entirely.\n options?.traceIds ? undefined : (options?.limit ?? 5),\n options?.traceIds,\n options?.name,\n codeChangeDescription,\n codeChangeFiles,\n // A dry run executes nothing, so a branch would be provisioned (and billed)\n // for code that never runs, and a seeded source's refusal would fail the item\n // before it could report its resolved inputs.\n dbBranchEnabled(options?.dbBranch) && options?.dryRun !== true,\n options?.experimentGroupId,\n options?.datasetId,\n options?.graderIds,\n resolveDbBranchSettings(options?.dbBranch),\n attempts,\n options?.adaptInputs !== undefined,\n )\n\n // An empty selection is the common shape of \"the corpus was never seeded\".\n // The result still reports it faithfully (zero items), but a caller reading\n // only the exit path would otherwise see a clean run that did nothing.\n if (serverItems.length === 0) {\n try {\n console.warn(\n `Bitfab: no traces matched \"${traceFunctionKey}\", so this replay ran nothing. Capture a trace, or seed one with seedTrace, before replaying.`,\n )\n } catch {\n // Never crash the host app\n }\n }\n\n const mockStrategy: MockStrategy = options?.mock ?? \"marked\"\n const maxConcurrency = options?.maxConcurrency ?? 10\n const fullTestRunUrl = `${serviceUrl}${testRunUrl}`\n\n // Per-call overrides take precedence over registered ones: concatenating them\n // first means the first-match-wins scan hits per-call overrides before the\n // client-registered chain, and both before the base mock strategy.\n const resolvedOverrides = [\n ...normalizeMockOverrides(options?.mockOverride),\n ...registeredOverrides,\n ]\n\n // One client-side replay trace id per item. It tags that item's replay spans\n // during the run so the server can echo back the row id it minted for them\n // (resolved in the complete-replay mapping below). Kept out of the public\n // ReplayItem: it's a correlation handle, never an id callers use.\n const workItems = expandReplayWork(serverItems, attempts)\n const replayedTraceIds = workItems.map(() => randomUuid())\n // Declared before the first span is submitted: the transport records delivery\n // only for traces someone asked about, so anything submitted before this\n // would go untracked.\n httpClient.trackTraceDeliveries(replayedTraceIds)\n const tasks = workItems.map(\n ({ serverItem, attempt }, index) =>\n () =>\n processItem(\n httpClient,\n serverItem,\n fn,\n testRunId,\n mockStrategy,\n resolvedOverrides,\n replayedTraceIds[index],\n attempt,\n dbBranchEnabled(options?.dbBranch) && options?.dryRun !== true,\n resolveDbBranchSettings(options?.dbBranch),\n options?.adaptInputs,\n options?.dryRun === true,\n ),\n )\n const total = tasks.length\n const onItemFinish = options?.onItemFinish ?? options?.onProgress\n let completed = 0\n let started = 0\n let succeeded = 0\n let errored = 0\n\n // Flush an item's trace the moment it finishes, so its server traces.id is\n // read back off the ingest response and surfaced on the item as it settles,\n // instead of waiting for the end-of-run barrier. Waiting until the end is\n // worst at low concurrency: each trace is closed and ready when its item\n // finishes, but nothing fills a batch to force an export, so ready ids sit in\n // the queue for the whole run.\n //\n // Coalesced so a burst of concurrent finishes shares one flush: while a flush\n // runs, later finishers mark `pending` and await the same promise, which loops\n // once more to cover them. Every caller therefore waits for a flush that ran\n // after it asked, and low concurrency degrades to a clean flush per item.\n let flushInFlight: Promise<void> | null = null\n let flushPending = false\n const flushFinishedItemTrace = (): Promise<void> => {\n // Mark work waiting first, so a finisher that arrives mid-flush is always\n // picked up by another loop iteration. The runner clears `flushInFlight`\n // synchronously with the loop exit (no await between the `while` check and\n // the reset), so no caller can observe a stale in-flight promise.\n flushPending = true\n if (!flushInFlight) {\n flushInFlight = (async () => {\n try {\n while (flushPending) {\n flushPending = false\n await httpClient.settleDeferredWork(REPLAY_PERSISTENCE_TIMEOUT_MS)\n await flushTraces(REPLAY_PERSISTENCE_TIMEOUT_MS)\n }\n } finally {\n flushInFlight = null\n }\n })()\n }\n return flushInFlight\n }\n\n const resultItems = await mapWithConcurrency(\n tasks,\n maxConcurrency,\n async (item, index) => {\n // Deliver this item's trace now, then read its server id back off the\n // ingest response. A flush failure never crashes the run: the id degrades\n // to null and the end-of-run barrier stays the authority on persistence.\n // Done BEFORE touching the counters so the increment and emit below carry\n // no await between them: with items flushing concurrently, that keeps each\n // event's running totals a consistent snapshot.\n let serverTraceId: string | null = null\n try {\n await flushFinishedItemTrace()\n serverTraceId =\n httpClient.peekServerTraceId(replayedTraceIds[index]) ?? null\n } catch {\n // Best-effort: fall through with null; the barrier settles persistence.\n }\n item.traceId = serverTraceId\n completed += 1\n if (item.error === null) {\n succeeded += 1\n } else {\n errored += 1\n }\n try {\n onItemFinish?.({\n testRunId,\n completed,\n total,\n succeeded,\n errored,\n item: {\n // The server's assigned traces.id, read back off the ingest\n // response and surfaced as this item finishes. Null only if the\n // per-item flush could not confirm delivery in time; the end-of-run\n // barrier then fills the returned ReplayItem. The client-side\n // placeholder is never surfaced.\n traceId: serverTraceId,\n originalTraceId: item.originalTraceId ?? null,\n originalSpanId: item.originalSpanId ?? null,\n // Deprecated aliases for originalTraceId/originalSpanId.\n sourceTraceId: item.originalTraceId ?? null,\n sourceSpanId: item.originalSpanId ?? null,\n attempt: item.attempt,\n input: item.input,\n result: item.result,\n originalOutput: item.originalOutput,\n error: item.error,\n traceError: item.traceError,\n replayError: item.replayError,\n durationMs: item.durationMs,\n originalDurationMs: item.originalDurationMs,\n originalTokens: item.originalTokens,\n originalModel: item.originalModel,\n tokens: item.tokens,\n model: item.model,\n dbSnapshotRef: item.dbSnapshotRef,\n dbBranchTimings: item.dbBranchTimings,\n traceOutline: item.traceOutline,\n originalTraceOutline: item.originalTraceOutline,\n },\n })\n } catch {\n // Progress UI must never crash the replay run.\n }\n },\n options?.onItemStart\n ? (index) => {\n started += 1\n const { serverItem, attempt } = workItems[index]\n const originalTraceId =\n serverItem.originalTraceId ?? serverItem.sourceTraceId\n const originalSpanId =\n serverItem.originalSpanId ?? serverItem.sourceSpanId\n try {\n options.onItemStart?.({\n type: \"started\",\n testRunId,\n started,\n completed,\n total,\n succeeded,\n errored,\n item: {\n originalTraceId,\n originalSpanId,\n sourceTraceId: originalTraceId,\n sourceSpanId: originalSpanId,\n attempt,\n },\n })\n } catch {\n // Progress UI must never crash the replay run.\n }\n }\n : undefined,\n )\n\n // Items submit their spans through the same batching transport live traffic\n // uses, so nothing here has waited on the network yet. Flush the transports,\n // then let the SERVER confirm each trace reached a final status with all of\n // its spans before finalizing: a drained queue is not proof that Bitfab\n // committed the data.\n // A dry run executed nothing, so it produced no spans and no traces. The\n // persistence barrier asserts the opposite (every completed item has a\n // persisted trace) and would fail the whole run, so it is skipped along with\n // the trace-id mapping it feeds. The test run is still finalized so it does\n // not sit unfinished in the experiments list.\n if (options?.dryRun === true) {\n await httpClient.completeReplay(testRunId).catch(() => undefined)\n const dryResult: ReplayResult<TReturn> = {\n items: resultItems,\n testRunId,\n testRunUrl: fullTestRunUrl,\n attempts,\n }\n await writeReplayResultFile(dryResult)\n return dryResult\n }\n\n const deliveredTraceIds = await preserveReplayFailure(\n () => waitForReplayPersistence(httpClient, testRunId, replayedTraceIds),\n resultItems,\n testRunId,\n fullTestRunUrl,\n )\n\n // Primary source for item.traceId: the server's assigned traces.id, read back\n // per trace off the ingest response during the flush above (server-sourced, no\n // polling, already in hand before completeReplay). The completeReplay map below\n // remains the fallback for servers that don't return ids on ingest.\n for (let index = 0; index < resultItems.length; index += 1) {\n const localId = replayedTraceIds[index]\n const readBack = localId ? deliveredTraceIds[localId] : undefined\n if (readBack !== undefined) {\n resultItems[index].traceId = readBack\n }\n }\n\n // completeReplay finalizes the test run and returns the token/diagnostic\n // mapping; its failures propagate loudly because a run that never completed\n // can't be finalized and callers must hear about it.\n const completeResult = await preserveReplayFailure(\n () => httpClient.completeReplay(testRunId),\n resultItems,\n testRunId,\n fullTestRunUrl,\n )\n const serverTraceIds = completeResult.traceIds\n // Per-replay-trace token usage, keyed by server trace id. The REPLAYED run's\n // tokens (span-aggregated server-side), used below to fill each item.tokens.\n const replayTokens = completeResult.tokens\n\n // `serverTraceIds` maps each item's client-side replay trace id (its entry in\n // `replayedTraceIds`, which tagged that item's spans during the run) to the\n // server's trace row id. We use it to (a) write the real server replay trace\n // id into `item.traceId` now that the row exists, (b) attach each item's\n // server-aggregated token usage, and (c) detect a systemic upload failure\n // early. Verdict persistence does NOT use this map: it is keyed by the\n // original-trace lineage (`originalTraceId` + `testRunId`), which needs no\n // client-held server id. Older servers that omit the map yield no replay\n // tokens and leave `item.traceId` null.\n if (serverTraceIds !== undefined) {\n const missing: string[] = []\n let completedCount = 0\n for (let index = 0; index < resultItems.length; index += 1) {\n const item = resultItems[index]\n const localId = replayedTraceIds[index]\n const mapped = localId ? serverTraceIds[localId] : undefined\n // Fallback fill for servers that did not return ids on the ingest\n // response; the read-back loop above already set it when they did, so\n // never overwrite a resolved id with null here.\n item.traceId = item.traceId ?? mapped ?? null\n if (item.error === null) {\n completedCount += 1\n if (mapped === undefined) {\n missing.push(localId ?? item.originalTraceId)\n }\n }\n if (mapped !== undefined) {\n item.tokens = replayTokens?.[mapped] ?? null\n item.traceOutline = completeResult.traceOutlines?.[mapped] ?? null\n }\n item.originalTraceOutline =\n completeResult.originalTraceOutlines?.[item.originalTraceId] ?? null\n }\n // ALL completed items missing → systemic (the replayed function isn't\n // wrapped with withSpan, or uploads are wholesale broken). Throw; the run's\n // traces never persisted, so nothing can be labeled and silence here is the\n // exact bug this guarantee exists to prevent.\n if (completedCount > 0 && missing.length === completedCount) {\n const serverCount =\n completeResult.traceCount !== undefined\n ? ` The server persisted ${completeResult.traceCount} trace(s) for this run.`\n : \"\"\n const cause = new BitfabError(\n `Replay completed but the server has no persisted trace for any of the ${completedCount} completed item(s) (testRunId ${testRunId}).${serverCount} ` +\n `Trace uploads were awaited, so either the uploads failed (check for \"Bitfab: Failed to create\" errors above) or the replayed function is not wrapped with withSpan.`,\n )\n throw new ReplayError(\n cause.message,\n resultItems,\n testRunId,\n fullTestRunUrl,\n cause,\n )\n }\n // SOME completed items missing → per-item upload failure (transient blip,\n // one oversized payload). Log it, but return the run; the items that landed\n // can still be labeled via their lineage.\n if (missing.length > 0) {\n try {\n console.error(\n `Bitfab: server has no persisted trace for ${missing.length} of ${completedCount} completed replay item(s) (testRunId ${testRunId}). Their replay token usage is unavailable and they cannot be labeled.`,\n )\n } catch {\n // Never crash the host app\n }\n }\n }\n\n const result: ReplayResult<TReturn> = {\n items: resultItems,\n testRunId,\n testRunUrl: fullTestRunUrl,\n attempts,\n }\n // Persist the enriched result so the Bitfab plugin never has to parse the\n // replay's stdout, which a dependency's logging can corrupt.\n await writeReplayResultFile(result)\n // Preserve the legacy terminal event only for onProgress. onItemFinish is\n // strictly item-scoped, so every invocation always includes an item.\n if (!options?.onItemFinish) {\n try {\n options?.onProgress?.({\n type: \"complete\",\n testRunId,\n completed: total,\n total,\n succeeded,\n errored,\n result,\n })\n } catch {\n // A progress reporter must never crash the replay run.\n }\n }\n return result\n}\n\nasync function writeReplayResultFile(\n result: ReplayResult<unknown>,\n): Promise<void> {\n const resultPath =\n typeof process !== \"undefined\"\n ? process.env?.BITFAB_REPLAY_RESULT_PATH\n : undefined\n if (!resultPath) {\n return\n }\n\n try {\n const [{ dirname }, { mkdir, writeFile }] = await Promise.all([\n import(\"node:path\"),\n import(\"node:fs/promises\"),\n ])\n await mkdir(dirname(resultPath), { recursive: true })\n await writeFile(resultPath, `${serializeReplayResult(result)}\\n`)\n } catch (err) {\n try {\n console.warn(\n `Bitfab: failed to write replay result to BITFAB_REPLAY_RESULT_PATH (${resultPath}): ${\n err instanceof Error ? err.message : String(err)\n }`,\n )\n } catch {\n // Never crash the host app.\n }\n }\n}\n","/**\n * Node.js-specific entry point for the Bitfab SDK.\n *\n * Selected automatically via package.json `exports` conditions when the\n * consumer's runtime or bundler supports the \"node\" condition (Node.js,\n * most server-side bundlers).\n *\n * This entry point differs from the default (`index.ts`) in one way:\n * it synchronously registers Node.js's `AsyncLocalStorage` before any\n * other SDK code evaluates. This eliminates the async initialization\n * gap that the default entry point has (where the first span might\n * execute before the dynamic import of `node:async_hooks` resolves).\n *\n * The default entry point (`index.ts`) is used for browsers and other\n * environments where `node:async_hooks` is unavailable. There, span\n * nesting degrades gracefully to a shared stack (correct for sequential\n * async, but not for concurrent Promise.all patterns).\n */\n\n// ⚠️ IMPORT ORDER MATTERS\n// asyncStorageNode MUST be imported before index.js.\n// It registers the AsyncLocalStorage class synchronously during module\n// evaluation. index.js (via client.ts) reads from that registration at\n// span creation time. If this import is moved after index.js or removed,\n// span nesting silently degrades to the browser fallback (flat spans).\nimport \"./asyncStorageNode.js\"\n\nexport * from \"./index.js\"\n\n// Verify registration succeeded. This turns a silent degradation into a\n// loud error if someone reorders the imports above or if asyncStorageNode.ts\n// fails to register for any reason. Only runs in the Node.js entry point\n// where we know node:async_hooks must be available.\nimport { assertAsyncStorageRegistered } from \"./asyncStorage.js\"\n\nassertAsyncStorageRegistered()\n","/**\n * Synchronous AsyncLocalStorage registration for Node.js.\n *\n * This module is a side-effect-only import: it registers the Node.js\n * AsyncLocalStorage class into the shared registry so span nesting\n * works immediately - no async gap, no microtask delay.\n *\n * It is imported by `node.ts` (the Node.js-specific entry point) as\n * the FIRST import, before `index.ts` or `client.ts` are evaluated.\n *\n * This file must ONLY be imported in Node.js environments (not browsers).\n * It uses a static `import` of `node:async_hooks`, which will fail in\n * browser bundlers. The `node.ts` entry point is conditionally selected\n * via package.json `exports` conditions, so browsers never see this file.\n */\n\nimport { AsyncLocalStorage } from \"node:async_hooks\"\nimport type { AsyncLocalStorageLike } from \"./asyncStorage.js\"\nimport { registerAsyncLocalStorageClass } from \"./asyncStorage.js\"\n\nregisterAsyncLocalStorageClass(\n AsyncLocalStorage as unknown as new () => AsyncLocalStorageLike<unknown>,\n)\n","/**\n * Claude Agent SDK handler for Bitfab tracing.\n *\n * Hooks into the Claude Agent SDK's lifecycle to capture LLM turns,\n * tool invocations, and subagent execution as Bitfab spans.\n *\n * Uses two integration surfaces:\n * 1. SDK hooks (PreToolUse, PostToolUse, etc.) for tool/subagent lifecycle\n * 2. Stream wrapping for LLM turn capture from the message stream\n */\n\nimport { DEFAULT_SERVICE_URL } from \"./constants.js\"\nimport { type ApiKeyInput, HttpClient } from \"./http.js\"\nimport {\n finalizeSpanPayload,\n finalizeTracePayload,\n} from \"./processorPayload.js\"\nimport { randomUuid } from \"./randomUuid.js\"\nimport { toJsonSafe, toJsonSafeReport } from \"./serialize.js\"\nimport { nowIsoTimestamp } from \"./timestamp.js\"\n\nexport interface ActiveSpanContext {\n traceId: string\n spanId: string\n}\n\ninterface SpanInfo {\n id: string\n spanId: string\n traceId: string\n parentId: string | null\n startedAt: string\n endedAt?: string\n name: string\n type: string\n input?: unknown\n output?: unknown\n error?: string\n contexts: Array<Record<string, unknown>>\n // Type names of input/output values that could only be captured as\n // placeholders (serialized at capture time to snapshot a mutable value).\n // Carried to the send boundary so finalizeSpanPayload can mark the span.\n dropped?: string[]\n}\n\nfunction nowIso(): string {\n return nowIsoTimestamp()\n}\n\n// Delegates to the shared toJsonSafe so the recurse-the-dump logic lives in\n// exactly one place (see serialize.ts).\nconst safeSerialize = toJsonSafe\n\nfunction extractContentBlocks(\n content: unknown,\n): Array<Record<string, unknown>> {\n if (!Array.isArray(content)) {\n return []\n }\n return content.map((block) => safeSerialize(block) as Record<string, unknown>)\n}\n\nfunction asTokenCount(val: unknown): number | null {\n return typeof val === \"number\" && Number.isFinite(val) ? val : null\n}\n\nfunction extractUsage(\n message: Record<string, unknown>,\n): Record<string, unknown> {\n const usageInfo: Record<string, unknown> = {}\n const usage = message.usage as Record<string, unknown> | undefined\n if (!usage) {\n return usageInfo\n }\n\n // Anthropic reports `input_tokens` as the NON-cached prompt tokens, with\n // cache reads and cache writes counted separately. Bitfab's `inputTokens`\n // is the full prompt size (matching the LangGraph integration), so fold the\n // cache buckets in. `cacheReadTokens` stays the cached SUBSET, which the read\n // side uses to back out the uncached portion (`?tokenType=uncached`).\n const baseInput = asTokenCount(usage.input_tokens)\n const cacheRead = asTokenCount(usage.cache_read_input_tokens)\n const cacheCreation = asTokenCount(usage.cache_creation_input_tokens)\n if (baseInput !== null || cacheRead !== null || cacheCreation !== null) {\n usageInfo.inputTokens =\n (baseInput ?? 0) + (cacheRead ?? 0) + (cacheCreation ?? 0)\n }\n\n const output = asTokenCount(usage.output_tokens)\n if (output !== null) {\n usageInfo.outputTokens = output\n }\n if (cacheRead !== null) {\n usageInfo.cacheReadTokens = cacheRead\n }\n if (cacheCreation !== null) {\n usageInfo.cacheCreationTokens = cacheCreation\n }\n\n return usageInfo\n}\n\ntype HookCallback = (\n // biome-ignore lint/suspicious/noExplicitAny: Hook callback signatures from Claude Agent SDK use untyped dicts\n inputData: Record<string, any>,\n toolUseId: string | null,\n context: unknown,\n) => Promise<Record<string, unknown>>\n\n/**\n * Claude Agent SDK handler that sends traces to Bitfab.\n *\n * Captures LLM turns, tool invocations, and subagent execution as\n * Bitfab spans with proper parent-child hierarchy.\n *\n * The TypeScript Claude Agent SDK exposes a single `query()` entry point (there\n * is no `ClaudeSDKClient` class - that exists only in the Python SDK). Wrap the\n * `query()` async iterator with `wrapQuery`; tool and subagent spans come from\n * the hooks injected by `instrumentOptions`.\n *\n * ```typescript\n * import { Bitfab } from \"@bitfab/sdk\";\n * import { query } from \"@anthropic-ai/claude-agent-sdk\";\n *\n * const bitfab = new Bitfab({ apiKey: \"...\" });\n * const handler = bitfab.getClaudeAgentHandler(\"my-agent\");\n *\n * const options = handler.instrumentOptions({\n * model: \"claude-sonnet-4-5-...\",\n * });\n *\n * for await (const message of handler.wrapQuery(\n * query({ prompt: \"Do something\", options })\n * )) {\n * // process messages normally\n * }\n * ```\n */\nexport class BitfabClaudeAgentHandler {\n private readonly httpClient: HttpClient\n private readonly ownsHttpClient: boolean\n private readonly traceFunctionKey: string\n private readonly getActiveSpanContext: (() => ActiveSpanContext | null) | null\n\n // Span tracking\n private runToSpan: Map<string, SpanInfo> = new Map()\n private traceId: string | null = null\n private rootSpanId: string | null = null\n private activeContext: ActiveSpanContext | null = null\n private traceStartedAt: string | null = null\n\n // LLM turn tracking\n private conversationHistory: Array<Record<string, unknown>> = []\n private pendingMessages: Array<Record<string, unknown>> = []\n private currentLlmSpanId: string | null = null\n private currentLlmMessageId: string | null = null\n private currentLlmContent: Array<Record<string, unknown>> = []\n private currentLlmModel: string | null = null\n private currentLlmUsage: Record<string, unknown> = {}\n private currentLlmStartedAt: string | null = null\n private currentLlmHistorySnapshot: Array<Record<string, unknown>> = []\n\n // Subagent tracking\n private activeSubagentSpans: Map<string, string> = new Map()\n\n // Synthetic root span (handler-only replay). When an `input` is supplied to\n // wrapQuery/wrapResponse, the handler emits a root `agent` span carrying that\n // input, so a handler-instrumented run is replayable WITHOUT an enclosing\n // withSpan - matching the LangGraph handler, which records the graph input as\n // its root. The prompt is not present anywhere in the message stream, so it\n // must be handed in explicitly.\n private hasRootInput = false\n private rootInput: unknown\n private rootOutput: unknown\n\n constructor(config: {\n apiKey?: ApiKeyInput\n traceFunctionKey: string\n serviceUrl?: string\n timeout?: number\n getActiveSpanContext?: () => ActiveSpanContext | null\n /**\n * The owning `Bitfab` client's HTTP client. Supplied by\n * `getClaudeAgentHandler()` so this handler shares that client's single\n * span-transport worker instead of starting a second one.\n * @internal\n */\n _httpClient?: HttpClient\n }) {\n this.ownsHttpClient = config._httpClient === undefined\n this.httpClient =\n config._httpClient ??\n new HttpClient({\n apiKey: config.apiKey,\n serviceUrl: config.serviceUrl ?? DEFAULT_SERVICE_URL,\n timeout: config.timeout ?? 10000,\n })\n this.traceFunctionKey = config.traceFunctionKey\n this.getActiveSpanContext = config.getActiveSpanContext ?? null\n\n // Bind hook callbacks so they can be passed as standalone functions\n this.preToolUseHook = this.preToolUseHook.bind(this)\n this.postToolUseHook = this.postToolUseHook.bind(this)\n this.postToolUseFailureHook = this.postToolUseFailureHook.bind(this)\n this.subagentStartHook = this.subagentStartHook.bind(this)\n this.subagentStopHook = this.subagentStopHook.bind(this)\n }\n\n /**\n * Flush and release the span transport this handler started. A no-op when\n * the handler borrowed a `Bitfab` client's HTTP client: that client's\n * `close()` owns the worker's lifetime.\n */\n async close(timeoutMs?: number): Promise<boolean> {\n return this.ownsHttpClient ? this.httpClient.close(timeoutMs) : true\n }\n\n // ── trace lifecycle ──────────────────────────────────────────\n\n private ensureTrace(): string {\n if (this.traceId !== null) {\n return this.traceId\n }\n\n this.activeContext = this.getActiveSpanContext?.() ?? null\n\n if (this.activeContext) {\n this.traceId = this.activeContext.traceId\n } else {\n this.traceId = randomUuid()\n }\n\n this.traceStartedAt = nowIso()\n return this.traceId\n }\n\n private getParentId(agentId?: string): string | null {\n if (agentId) {\n const subagentSpanId = this.activeSubagentSpans.get(agentId)\n if (subagentSpanId) {\n return subagentSpanId\n }\n }\n // Prefer the synthetic root (handler-only mode) so every span nests under\n // it; fall back to the enclosing withSpan context. The two are never both\n // set - the synthetic root is only created when there is no active context.\n return this.rootSpanId ?? this.activeContext?.spanId ?? null\n }\n\n // Emit the synthetic root `agent` span once, before any child spans. No-op\n // unless an `input` was supplied AND there is no enclosing withSpan (in which\n // case that outer span is already the replayable root).\n private maybeStartRootSpan(): void {\n if (!this.hasRootInput || this.rootSpanId !== null) {\n return\n }\n this.ensureTrace()\n if (this.activeContext !== null) {\n return\n }\n const spanId = randomUuid()\n this.startSpan(spanId, this.traceFunctionKey, \"agent\", this.rootInput, null)\n this.rootSpanId = spanId\n }\n\n private completeRootSpan(): void {\n if (this.rootSpanId === null) {\n return\n }\n const spanId = this.rootSpanId\n this.rootSpanId = null\n this.completeSpan(spanId, this.rootOutput)\n }\n\n // ── span helpers ─────────────────────────────────────────────\n\n private startSpan(\n spanId: string,\n name: string,\n spanType: string,\n inputData?: unknown,\n parentId?: string | null,\n ): SpanInfo {\n const traceId = this.ensureTrace()\n\n // Serialize input now to snapshot it (tool input can mutate between\n // PreToolUse and PostToolUse), but keep the report so a lossy input is\n // still marked non-replayable at the send boundary.\n const { safe: safeInput, dropped: inputDropped } =\n toJsonSafeReport(inputData)\n\n const spanInfo: SpanInfo = {\n id: randomUuid(),\n spanId,\n traceId,\n parentId: parentId ?? null,\n startedAt: nowIso(),\n name,\n type: spanType,\n input: safeInput,\n contexts: [],\n }\n if (inputDropped.length > 0) {\n spanInfo.dropped = [...inputDropped]\n }\n this.runToSpan.set(spanId, spanInfo)\n return spanInfo\n }\n\n private completeSpan(\n spanId: string,\n output?: unknown,\n error?: string,\n extraContexts?: Record<string, unknown>,\n ): void {\n const spanInfo = this.runToSpan.get(spanId)\n if (!spanInfo) {\n return\n }\n this.runToSpan.delete(spanId)\n\n spanInfo.endedAt = nowIso()\n const { safe: safeOutput, dropped: outputDropped } =\n toJsonSafeReport(output)\n spanInfo.output = safeOutput\n if (outputDropped.length > 0) {\n spanInfo.dropped = [...(spanInfo.dropped ?? []), ...outputDropped]\n }\n if (error !== undefined) {\n spanInfo.error = error\n }\n\n if (extraContexts) {\n spanInfo.contexts.push(extraContexts)\n }\n\n this.sendSpan(spanInfo)\n }\n\n private sendSpan(spanInfo: SpanInfo): void {\n const spanData: Record<string, unknown> = {\n name: spanInfo.name,\n type: spanInfo.type,\n }\n if (spanInfo.input !== undefined) {\n spanData.input = spanInfo.input\n }\n if (spanInfo.output !== undefined) {\n spanData.output = spanInfo.output\n }\n if (spanInfo.error !== undefined) {\n spanData.error = spanInfo.error\n }\n if (spanInfo.contexts.length > 0) {\n spanData.contexts = spanInfo.contexts\n }\n\n const rawSpan: Record<string, unknown> = {\n id: spanInfo.spanId,\n trace_id: spanInfo.traceId,\n started_at: spanInfo.startedAt,\n ended_at: spanInfo.endedAt ?? nowIso(),\n span_data: spanData,\n }\n if (spanInfo.parentId !== null) {\n rawSpan.parent_id = spanInfo.parentId\n }\n\n const payload: Record<string, unknown> = {\n id: spanInfo.id,\n traceId: spanInfo.traceId,\n type: \"sdk-function\",\n source: \"typescript-sdk-claude-agent-sdk\",\n traceFunctionKey: this.traceFunctionKey,\n sourceTraceId: spanInfo.traceId,\n rawSpan,\n }\n\n // Sanitize the whole span (a non-serializable value in any field is\n // dumped/stubbed, a lossy capture is marked) instead of shipping it raw.\n // spanInfo.dropped carries losses from the capture-time input/output\n // snapshot above.\n const finalized = finalizeSpanPayload(payload, spanInfo.dropped)\n\n try {\n this.httpClient.sendExternalSpan(finalized)\n } catch {\n // Silently ignore - never crash the host app\n }\n }\n\n private sendTraceCompletion(\n endedAt?: string,\n metadata?: Record<string, unknown>,\n ): void {\n if (this.traceId === null) {\n return\n }\n\n const completed = this.activeContext === null\n const traceId = this.traceId\n\n // Mark as sent so the finally block doesn't re-send\n this.traceId = null\n\n const externalTrace: Record<string, unknown> = {\n id: traceId,\n started_at: this.traceStartedAt ?? nowIso(),\n ended_at: endedAt ?? nowIso(),\n }\n\n if (metadata) {\n externalTrace.metadata = metadata\n }\n\n const traceData: Record<string, unknown> = {\n id: traceId,\n type: \"sdk-function\",\n source: \"typescript-sdk-claude-agent-sdk\",\n traceFunctionKey: this.traceFunctionKey,\n externalTrace,\n completed,\n }\n\n // Sanitize the whole trace (warning when the capture was lossy) instead of\n // shipping it raw and risking a wire-side JSON.stringify failure.\n const finalized = finalizeTracePayload(traceData)\n\n try {\n this.httpClient.sendExternalTrace(finalized)\n } catch {\n // Silently ignore - never crash the host app\n }\n }\n\n // ── hook callbacks ───────────────────────────────────────────\n\n private async preToolUseHook(\n // biome-ignore lint/suspicious/noExplicitAny: Hook input from Claude Agent SDK is untyped\n inputData: Record<string, any>,\n toolUseId: string | null,\n _context: unknown,\n ): Promise<Record<string, unknown>> {\n try {\n const sid = (inputData.tool_use_id as string) ?? toolUseId ?? randomUuid()\n const toolName = (inputData.tool_name as string) ?? \"tool\"\n const toolInput = inputData.tool_input ?? {}\n const agentId = inputData.agent_id as string | undefined\n const parentId = this.getParentId(agentId)\n\n this.startSpan(sid, toolName, \"function\", toolInput, parentId)\n } catch {\n // Never crash the host app\n }\n return {}\n }\n\n private async postToolUseHook(\n // biome-ignore lint/suspicious/noExplicitAny: Hook input from Claude Agent SDK is untyped\n inputData: Record<string, any>,\n toolUseId: string | null,\n _context: unknown,\n ): Promise<Record<string, unknown>> {\n try {\n const sid = (inputData.tool_use_id as string) ?? toolUseId ?? \"\"\n const toolResponse = inputData.tool_response\n this.completeSpan(sid, toolResponse)\n } catch {\n // Never crash the host app\n }\n return {}\n }\n\n private async postToolUseFailureHook(\n // biome-ignore lint/suspicious/noExplicitAny: Hook input from Claude Agent SDK is untyped\n inputData: Record<string, any>,\n toolUseId: string | null,\n _context: unknown,\n ): Promise<Record<string, unknown>> {\n try {\n const sid = (inputData.tool_use_id as string) ?? toolUseId ?? \"\"\n const error = String(inputData.error ?? \"Unknown error\")\n this.completeSpan(sid, undefined, error)\n } catch {\n // Never crash the host app\n }\n return {}\n }\n\n private async subagentStartHook(\n // biome-ignore lint/suspicious/noExplicitAny: Hook input from Claude Agent SDK is untyped\n inputData: Record<string, any>,\n _toolUseId: string | null,\n _context: unknown,\n ): Promise<Record<string, unknown>> {\n try {\n const agentId = (inputData.agent_id as string) ?? randomUuid()\n const agentType = (inputData.agent_type as string) ?? \"subagent\"\n const parentId = this.getParentId()\n\n const spanId = randomUuid()\n this.activeSubagentSpans.set(agentId, spanId)\n\n this.startSpan(\n spanId,\n `Agent: ${agentType}`,\n \"agent\",\n undefined,\n parentId,\n )\n } catch {\n // Never crash the host app\n }\n return {}\n }\n\n private async subagentStopHook(\n // biome-ignore lint/suspicious/noExplicitAny: Hook input from Claude Agent SDK is untyped\n inputData: Record<string, any>,\n _toolUseId: string | null,\n _context: unknown,\n ): Promise<Record<string, unknown>> {\n try {\n const agentId = (inputData.agent_id as string) ?? \"\"\n const spanId = this.activeSubagentSpans.get(agentId)\n if (spanId) {\n this.activeSubagentSpans.delete(agentId)\n this.completeSpan(spanId)\n }\n } catch {\n // Never crash the host app\n }\n return {}\n }\n\n // ── public API ───────────────────────────────────────────────\n\n /**\n * Inject Bitfab tracing hooks into Claude Agent SDK options.\n *\n * Modifies the options object and returns it for convenience.\n * The SDK's `HookMatcher` is constructed as a plain object\n * (`{ matcher: null, hooks: [callback] }`) to avoid requiring\n * `@anthropic-ai/claude-agent-sdk` as a dependency.\n *\n * @param options - Options object with a `hooks` property\n * @returns The modified options object with Bitfab hooks injected\n */\n instrumentOptions<T extends Record<string, unknown>>(options: T): T {\n type HookEntry = { matcher: null; hooks: HookCallback[] }\n type HooksDict = Record<string, HookEntry[]>\n\n const hooks: HooksDict = (options.hooks as HooksDict) ?? {}\n if (!options.hooks) {\n ;(options as Record<string, unknown>).hooks = hooks\n }\n\n const hookConfig: Array<[string, HookCallback]> = [\n [\"PreToolUse\", this.preToolUseHook],\n [\"PostToolUse\", this.postToolUseHook],\n [\"PostToolUseFailure\", this.postToolUseFailureHook],\n [\"SubagentStart\", this.subagentStartHook],\n [\"SubagentStop\", this.subagentStopHook],\n ]\n\n for (const [event, callback] of hookConfig) {\n if (!hooks[event]) {\n hooks[event] = []\n }\n hooks[event].push({ matcher: null, hooks: [callback] })\n }\n\n return options\n }\n\n /**\n * Wrap any Claude Agent SDK message stream to capture LLM turns.\n *\n * Yields every message unchanged while capturing assistant message\n * content as LLM turn spans. Kept for naming symmetry with the Python\n * SDK's `wrapResponse` (which wraps `ClaudeSDKClient.receiveResponse()`);\n * in TypeScript, prefer `wrapQuery` around `query()`.\n *\n * Pass `{ input }` (the prompt) to record a replayable root span - see\n * `wrapQuery`.\n */\n async *wrapResponse(\n stream: AsyncIterable<unknown>,\n opts?: { input?: unknown },\n ): AsyncIterable<unknown> {\n this.setRootInput(opts)\n yield* this.processStream(stream)\n }\n\n /**\n * Wrap a `query()` async iterator to capture LLM turns.\n *\n * Tool and subagent spans are captured separately via the hooks injected\n * by `instrumentOptions` into the `options` passed to `query()`.\n *\n * Pass `{ input }` - the prompt (or the serializable args that produced it)\n * - to make a handler-only run replayable: the handler records a root `agent`\n * span with that input, so `replay(key, fn)` can re-feed it. Omit it only\n * when an enclosing `withSpan` already supplies the replayable root.\n *\n * ```typescript\n * handler.wrapQuery(query({ prompt, options }), { input: prompt })\n * ```\n */\n async *wrapQuery(\n stream: AsyncIterable<unknown>,\n opts?: { input?: unknown },\n ): AsyncIterable<unknown> {\n this.setRootInput(opts)\n yield* this.processStream(stream)\n }\n\n private setRootInput(opts?: { input?: unknown }): void {\n // Set deterministically on every wrap call so a prior call's input can\n // never leak into a later input-less run on a reused handler (e.g. if the\n // earlier stream's iterator was abandoned mid-iteration, so resetState\n // never ran).\n if (opts && opts.input !== undefined) {\n this.hasRootInput = true\n this.rootInput = opts.input\n } else {\n this.hasRootInput = false\n this.rootInput = undefined\n }\n this.rootOutput = undefined\n }\n\n // ── stream processing ────────────────────────────────────────\n\n private async *processStream(\n stream: AsyncIterable<unknown>,\n ): AsyncIterable<unknown> {\n try {\n this.maybeStartRootSpan()\n for await (const message of stream) {\n try {\n this.processMessage(message as Record<string, unknown>)\n } catch {\n // Never crash the host app\n }\n yield message\n }\n } finally {\n try {\n this.flushLlmTurn()\n this.completeRootSpan()\n this.sendTraceCompletion()\n } catch {\n // Never crash the host app\n }\n this.resetState()\n }\n }\n\n private processMessage(message: Record<string, unknown>): void {\n // The TypeScript Claude Agent SDK streams plain wire objects discriminated\n // by a `type` field (`{ type: \"assistant\", message: <BetaMessage>, ... }`),\n // NOT class instances. (The Python SDK, by contrast, yields AssistantMessage\n // / UserMessage / ResultMessage dataclasses - hence the different field\n // access here vs. claude_agent_sdk.py.) Routing on `constructor.name` would\n // always see \"Object\" and silently capture nothing.\n const typeName = message.type\n\n if (typeName === \"assistant\") {\n this.handleAssistantMessage(message)\n } else if (typeName === \"user\") {\n this.handleUserMessage(message)\n } else if (typeName === \"result\") {\n this.handleResultMessage(message)\n }\n }\n\n private handleAssistantMessage(message: Record<string, unknown>): void {\n this.ensureTrace()\n\n // Content, model, id, and usage live on the nested BetaMessage, not the\n // top-level SDK wire wrapper.\n const inner = (message.message as Record<string, unknown> | undefined) ?? {}\n\n const messageId =\n (inner.id as string | undefined) ?? (message.uuid as string | undefined)\n\n if (messageId !== this.currentLlmMessageId) {\n this.flushLlmTurn()\n\n // Drain pending user/tool messages into history before snapshot\n this.conversationHistory.push(...this.pendingMessages)\n this.pendingMessages = []\n\n this.currentLlmSpanId = randomUuid()\n this.currentLlmMessageId = messageId ?? null\n this.currentLlmContent = []\n this.currentLlmModel = (inner.model as string) ?? null\n this.currentLlmUsage = {}\n this.currentLlmStartedAt = nowIso()\n this.currentLlmHistorySnapshot = [...this.conversationHistory]\n }\n\n const content = inner.content\n if (Array.isArray(content)) {\n this.currentLlmContent.push(...extractContentBlocks(content))\n }\n\n const usage = extractUsage(inner)\n if (Object.keys(usage).length > 0) {\n Object.assign(this.currentLlmUsage, usage)\n }\n\n const model = inner.model as string | undefined\n if (model) {\n this.currentLlmModel = model\n }\n }\n\n private handleUserMessage(message: Record<string, unknown>): void {\n // User content lives on the nested MessageParam; tool_use_result is a\n // top-level field on the SDK wire wrapper.\n const inner = (message.message as Record<string, unknown> | undefined) ?? {}\n const content = inner.content\n const toolUseResult = message.tool_use_result\n\n if (toolUseResult !== undefined) {\n this.pendingMessages.push({\n role: \"tool\",\n content: safeSerialize(content),\n tool_result: safeSerialize(toolUseResult),\n })\n } else {\n this.pendingMessages.push({\n role: \"user\",\n content: safeSerialize(content),\n })\n }\n }\n\n private handleResultMessage(message: Record<string, unknown>): void {\n this.flushLlmTurn()\n\n // The final result text is the synthetic root span's output.\n if (message.result !== undefined) {\n this.rootOutput = message.result\n }\n this.completeRootSpan()\n\n const metadata: Record<string, unknown> = {}\n for (const attr of [\n \"num_turns\",\n \"total_cost_usd\",\n \"duration_ms\",\n \"duration_api_ms\",\n \"session_id\",\n ]) {\n const val = message[attr]\n if (val !== undefined && val !== null) {\n metadata[attr] = val\n }\n }\n\n const usage = message.usage\n if (usage && typeof usage === \"object\") {\n metadata.usage = safeSerialize(usage)\n }\n\n this.sendTraceCompletion(\n undefined,\n Object.keys(metadata).length > 0 ? metadata : undefined,\n )\n }\n\n private flushLlmTurn(): void {\n if (this.currentLlmSpanId === null) {\n return\n }\n\n const spanId = this.currentLlmSpanId\n const traceId = this.ensureTrace()\n const parentId = this.getParentId()\n\n const llmContext: Record<string, unknown> = {}\n if (this.currentLlmModel) {\n llmContext.model = this.currentLlmModel\n }\n Object.assign(llmContext, this.currentLlmUsage)\n\n const spanInfo: SpanInfo = {\n id: randomUuid(),\n spanId,\n traceId,\n parentId,\n startedAt: this.currentLlmStartedAt ?? nowIso(),\n endedAt: nowIso(),\n name: this.currentLlmModel ?? \"llm\",\n type: \"llm\",\n input: this.currentLlmHistorySnapshot,\n output: this.currentLlmContent,\n contexts: Object.keys(llmContext).length > 0 ? [llmContext] : [],\n }\n\n this.sendSpan(spanInfo)\n\n this.conversationHistory.push({\n role: \"assistant\",\n content: this.currentLlmContent,\n })\n\n this.currentLlmSpanId = null\n this.currentLlmMessageId = null\n this.currentLlmContent = []\n this.currentLlmModel = null\n this.currentLlmUsage = {}\n this.currentLlmStartedAt = null\n this.currentLlmHistorySnapshot = []\n }\n\n private resetState(): void {\n this.runToSpan.clear()\n this.traceId = null\n this.rootSpanId = null\n this.hasRootInput = false\n this.rootInput = undefined\n this.rootOutput = undefined\n this.activeContext = null\n this.traceStartedAt = null\n this.conversationHistory = []\n this.pendingMessages = []\n this.currentLlmSpanId = null\n this.currentLlmMessageId = null\n this.currentLlmContent = []\n this.currentLlmModel = null\n this.currentLlmUsage = {}\n this.currentLlmStartedAt = null\n this.currentLlmHistorySnapshot = []\n this.activeSubagentSpans.clear()\n }\n}\n","/**\n * Shared payload finalization for the framework tracing handlers.\n *\n * The OpenAI-Agents, LangGraph, and Claude Agent SDK handlers each build an\n * external span/trace payload that must be made JSON-safe before it is sent.\n *\n * Doing that silently with `toJsonSafe` hides a lossy capture. These helpers do\n * it in one place: sanitize via `toJsonSafeReport` and, when a value could only\n * be captured as a placeholder, mark the span (a `serialization_degraded`\n * error) or warn for the trace, so a degraded capture is surfaced as\n * non-replayable instead of being shipped silently. The HTTP boundary stays as\n * the final net. Mirrors the Python SDK's `processor_payload.py`.\n *\n * Note: this is only wired into the `toJsonSafe`-based framework surfaces. Core\n * `withSpan` / `@span` spans serialize via `serializeValue` (superjson, which\n * preserves the `meta` needed for typed replay); running this report serializer\n * there would strip that metadata, so the core path keeps its existing\n * http-layer sanitizer instead.\n */\n\nimport { toJsonSafeReport } from \"./serialize.js\"\nimport { warnOnce } from \"./warnOnce.js\"\n\nexport const SERIALIZATION_DEGRADED_STEP = \"serialization_degraded\"\n\ninterface DegradedError {\n source: \"sdk\"\n step: string\n error: string\n}\n\nfunction degradedError(dropped: string[]): DegradedError {\n const names = [...new Set(dropped)].sort().join(\", \")\n return {\n source: \"sdk\",\n step: SERIALIZATION_DEGRADED_STEP,\n error: `non-replayable: could not faithfully capture ${names}`,\n }\n}\n\n// Plain control fields carried through when the whole payload collapses to a\n// placeholder. Mirror of the Python SDK's `_rebuild_envelope` (plus\n// `traceFunctionKey`, which the TS payloads also carry): without them a\n// pathological top-level value would strip the routing fields the server needs,\n// not just the body. `completed` is span-irrelevant but harmless to copy.\nconst ENVELOPE_FIELDS = [\n \"type\",\n \"source\",\n \"traceFunctionKey\",\n \"sourceTraceId\",\n \"completed\",\n] as const\n\nfunction rebuildEnvelope(\n payload: Record<string, unknown>,\n bodyKey: string,\n placeholder: unknown,\n): Record<string, unknown> {\n const rebuilt: Record<string, unknown> = {}\n for (const k of ENVELOPE_FIELDS) {\n if (k in payload) {\n rebuilt[k] = payload[k]\n }\n }\n rebuilt[bodyKey] = { serialized: placeholder }\n return rebuilt\n}\n\n/**\n * Return a JSON-safe span payload, marking a lossy capture on its errors.\n *\n * The span body is preserved (never gutted). When a value could only be\n * captured as a placeholder, a `serialization_degraded` error is appended to\n * `payload.errors` so the lossy capture is recorded rather than shipped\n * silently.\n *\n * `extraDropped` carries losses detected by an earlier sanitization pass - e.g.\n * input/output that a handler serialized at capture time to snapshot a mutable\n * value. Without it, those fields reach this point as plain placeholder strings\n * and their loss would go unreported.\n */\nexport function finalizeSpanPayload(\n payload: Record<string, unknown>,\n extraDropped?: string[],\n): Record<string, unknown> {\n const { safe, dropped } = toJsonSafeReport(payload)\n const allDropped = [...(extraDropped ?? []), ...dropped]\n\n // toJsonSafeReport collapses to a non-object only for a pathological\n // top-level value; rebuild an envelope (carrying control fields) so the span\n // still ships and stays routable.\n const collapsed =\n safe === null || typeof safe !== \"object\" || Array.isArray(safe)\n const result: Record<string, unknown> = collapsed\n ? rebuildEnvelope(payload, \"rawSpan\", safe)\n : (safe as Record<string, unknown>)\n\n if (allDropped.length > 0) {\n const existing = result.errors\n const errors = Array.isArray(existing) ? existing : []\n errors.push(degradedError(allDropped))\n result.errors = errors\n }\n return result\n}\n\n/**\n * Return a JSON-safe trace payload, warning when the capture was lossy.\n *\n * The trace is preserved (never dropped). A trace payload has no errors field,\n * so a lossy capture is surfaced via `warnOnce` instead.\n */\nexport function finalizeTracePayload(\n payload: Record<string, unknown>,\n): Record<string, unknown> {\n const { safe, dropped } = toJsonSafeReport(payload)\n const collapsed =\n safe === null || typeof safe !== \"object\" || Array.isArray(safe)\n const result: Record<string, unknown> = collapsed\n ? rebuildEnvelope(payload, \"externalTrace\", safe)\n : (safe as Record<string, unknown>)\n\n if (dropped.length > 0 || collapsed) {\n const names =\n dropped.length > 0 ? [...new Set(dropped)].sort().join(\", \") : \"trace\"\n warnOnce(\n `finalizeTrace:${names.replace(/\\d+/g, \"N\")}`,\n `a trace held non-serializable value(s) (${names}); they were captured as placeholders, so the trace may not be replayable.`,\n )\n }\n return result\n}\n","let lastTimestampMicros = 0\n\nexport function nowIsoTimestamp(): string {\n const wallClockMicros = Date.now() * 1_000\n lastTimestampMicros = Math.max(wallClockMicros, lastTimestampMicros + 1)\n const milliseconds = Math.floor(lastTimestampMicros / 1_000)\n const remainingMicros = lastTimestampMicros % 1_000\n return new Date(milliseconds)\n .toISOString()\n .replace(\"Z\", `${remainingMicros.toString().padStart(3, \"0\")}Z`)\n}\n","/**\n * Bitfab client for provider-based API calls.\n */\n\nimport {\n type AsyncLocalStorageLike,\n asyncStorageReady,\n createAsyncLocalStorage,\n isAsyncStorageInitDone,\n} from \"./asyncStorage.js\"\nimport {\n __bitfabAutoTraceActive,\n __setBitfabAutoTraceCapturePolicy,\n type AutoTraceContext,\n type AutoTraceFunctionDefinition,\n type AutoTraceNodeConfiguration,\n getAutoTraceCapturePolicy,\n runWithAutoTraceContext,\n runWithAutoTraceNodeConfiguration,\n runWithAutoTraceRootContext,\n} from \"./autoTrace.js\"\nimport {\n type AllowedEnvVars,\n type ProviderDefinition,\n runFunctionWithBaml,\n} from \"./baml.js\"\nimport type { CaptureSurface, SurfaceRequest } from \"./captureSurface.js\"\nimport {\n assertSurfacesCompatible,\n DEFAULT_SURFACE,\n mixedTracingError,\n resolveSurface,\n} from \"./captureSurface.js\"\nimport { BitfabClaudeAgentHandler } from \"./claudeAgentSdk.js\"\nimport { DEFAULT_SERVICE_URL } from \"./constants.js\"\nimport { DatasetsClient } from \"./datasets.js\"\nimport type { DbSnapshotConfig, DbSnapshotRef } from \"./dbSnapshot.js\"\nimport { buildSnapshotRef, validateDbSnapshotConfig } from \"./dbSnapshot.js\"\nimport { MixedTracingError } from \"./errors.js\"\nimport {\n BitfabError,\n type CapturedSpan,\n HttpClient,\n type SpanLookup,\n} from \"./http.js\"\nimport { BitfabLangGraphCallbackHandler } from \"./langgraph.js\"\nimport {\n BitfabLangGraphIntegration,\n type LangGraphIntegrationOptions,\n} from \"./langgraphIntegration.js\"\nimport type {\n MockOverride,\n MockOverrideResolver,\n MockSource,\n MockTarget,\n MockValue,\n NodeMatcher,\n SpanNodeMeta,\n} from \"./mockOverride.js\"\nimport { NO_MOCK_OVERRIDE, resolveMockValue } from \"./mockOverride.js\"\nimport { BitfabOpenAIAgentHandler } from \"./openaiAgentSdk.js\"\nimport { importOptionalPeer } from \"./optionalPeer.js\"\nimport { randomUuid } from \"./randomUuid.js\"\nimport type {\n ReplayOptions,\n ReplayResult,\n TraceIngestionType,\n} from \"./replay.js\"\nimport { ReplayBranch } from \"./replayBranch.js\"\nimport type { DbBranchTimings } from \"./replayContext.js\"\nimport { getReplayContext } from \"./replayContext.js\"\nimport {\n getSeedContext,\n inSeedScope,\n runWithSeedContext,\n seedContextReady,\n} from \"./seedContext.js\"\nimport { deserializeValue, serializeValue } from \"./serialize.js\"\nimport { nowIsoTimestamp } from \"./timestamp.js\"\nimport { BitfabOpenAITracingProcessor } from \"./tracing.js\"\nimport { BitfabVercelAiHandler } from \"./vercelAiSdk.js\"\nimport { warnOnce } from \"./warnOnce.js\"\n\n// Context entry for addContext calls - each entry is an object with multiple key-value pairs\ntype ContextEntry = Record<string, unknown>\n\n// Trace state for tracking trace-level data\ninterface TraceState {\n traceId: string\n sessionId?: string\n name?: string\n metadata?: Record<string, unknown>\n contexts: ContextEntry[]\n startedAt: string\n testRunId?: string\n inputSourceTraceId?: string\n replayAttempt?: number\n dbSnapshotRef?: DbSnapshotRef\n // Set by getCurrentTrace().drop(); ridden out on trace completion so the\n // server scrubs and marks the trace `dropped` instead of `completed`.\n dropped?: boolean\n ingestionType?: TraceIngestionType\n}\n\nexport type { CaptureSurface } from \"./captureSurface.js\"\n\n// Span context for tracking nested spans\ninterface SpanContext {\n traceId: string\n spanId: string\n contexts: ContextEntry[]\n prompt?: string\n surface?: CaptureSurface\n}\n\n// Global map to track active trace states\nconst activeTraceStates = new Map<string, TraceState>()\n\nlet asyncLocalStorage: AsyncLocalStorageLike<SpanContext[]> | null = null\nconst SPAN_CONTEXT_STORAGE_SYMBOL = Symbol.for(\"bitfab.spanContextStorage\")\n\nconst initializeAsyncContext = () => {\n if (asyncLocalStorage) {\n return\n }\n const shared = globalThis as typeof globalThis & Record<symbol, unknown>\n const existing = shared[SPAN_CONTEXT_STORAGE_SYMBOL] as\n | AsyncLocalStorageLike<SpanContext[]>\n | undefined\n if (existing) {\n asyncLocalStorage = existing\n return\n }\n const created = createAsyncLocalStorage<SpanContext[]>()\n if (created) {\n shared[SPAN_CONTEXT_STORAGE_SYMBOL] = created\n asyncLocalStorage = created\n }\n}\n\nconst asyncLocalStorageReady: Promise<void> = asyncStorageReady.then(() => {\n initializeAsyncContext()\n})\n\n// Browser fallback: a single module-level stack shared across all async\n// execution chains. Works correctly for synchronous nesting and sequential\n// async nesting (the common browser cases), but breaks when multiple\n// independent spans are in-flight concurrently (e.g. Promise.all with\n// separate withSpan calls). In that scenario, whichever span resumes last\n// overwrites the shared stack, so inner spans may see the wrong parent.\n//\n// Node.js avoids this via AsyncLocalStorage, which gives each async chain\n// its own isolated copy of the stack.\n//\n// Potential future fixes:\n// - TC39 AsyncContext proposal (stage 2) would provide AsyncLocalStorage\n// semantics natively in all JS environments, including browsers.\n// https://github.com/tc39/proposal-async-context\n// - Zone.js could work today but is ~50KB, monkey-patches Promise/setTimeout/\n// fetch/etc., and can conflict with frameworks like React. Too invasive for\n// an SDK dependency.\nlet browserSpanStack: SpanContext[] = []\n\nfunction getSpanStack(): SpanContext[] {\n if (asyncLocalStorage) {\n return asyncLocalStorage.getStore() ?? []\n }\n return browserSpanStack\n}\n\nfunction enclosingSurface(): CaptureSurface | undefined {\n const stack = getSpanStack()\n return stack[stack.length - 1]?.surface\n}\n\nfunction runWithSpanStack<T>(stack: SpanContext[], fn: () => T): T {\n if (asyncLocalStorage) {\n return asyncLocalStorage.run(stack, fn)\n }\n // Browser fallback: save/restore the stack around the function call.\n // This is correct for sequential async but not for concurrent async -\n // see the browserSpanStack comment above for details.\n const previousStack = browserSpanStack\n browserSpanStack = stack\n try {\n const result = fn()\n if (result instanceof Promise) {\n return result.finally(() => {\n browserSpanStack = previousStack\n }) as T\n }\n browserSpanStack = previousStack\n return result\n } catch (error) {\n browserSpanStack = previousStack\n throw error\n }\n}\n\nfunction isAsyncGenerator(\n value: unknown,\n): value is AsyncGenerator<unknown, unknown, unknown> {\n if (value === null || typeof value !== \"object\") {\n return false\n }\n const candidate = value as Record<PropertyKey, unknown>\n return (\n typeof candidate.next === \"function\" &&\n typeof candidate.return === \"function\" &&\n typeof candidate.throw === \"function\" &&\n typeof candidate[Symbol.asyncIterator] === \"function\"\n )\n}\n\n// Wrap an async generator so that:\n// 1. Each .next()/.return()/.throw() resumes the generator body inside\n// the parent span's context, so nested withSpan calls nest correctly.\n// 2. The span is sent only after iteration completes (or errors), with\n// the yielded values plus any final return value as the result.\n//\n// Without this, async-generator functions returned from withSpan close their\n// span synchronously when the generator object is created - before any of\n// the body has run - and every child span becomes its own root trace.\nfunction wrapAsyncGenerator<TYield, TReturn>(\n source: AsyncGenerator<TYield, TReturn, unknown>,\n spanStack: SpanContext[],\n sendSpan: (params: { result: unknown; error?: string }) => Promise<void>,\n): AsyncGenerator<TYield, TReturn, unknown> {\n const yielded: TYield[] = []\n let returnValue: TReturn | undefined\n let finalized = false\n\n const finalize = (errorMsg?: string) => {\n if (finalized) {\n return\n }\n finalized = true\n void sendSpan({\n result: { yielded, return: returnValue },\n ...(errorMsg && { error: errorMsg }),\n })\n }\n\n const step = (\n method: \"next\" | \"return\" | \"throw\",\n arg: unknown,\n ): Promise<IteratorResult<TYield, TReturn>> =>\n runWithSpanStack(spanStack, () => {\n const op = source[method] as (\n a?: unknown,\n ) => Promise<IteratorResult<TYield, TReturn>>\n return op.call(source, arg)\n })\n\n const handle = async (\n method: \"next\" | \"return\" | \"throw\",\n arg: unknown,\n ): Promise<IteratorResult<TYield, TReturn>> => {\n try {\n const result = await step(method, arg)\n if (result.done) {\n returnValue = result.value\n finalize()\n } else {\n yielded.push(result.value)\n }\n return result\n } catch (error) {\n finalize(error instanceof Error ? error.message : String(error))\n throw error\n }\n }\n\n const wrapped = {\n next(arg?: unknown) {\n return handle(\"next\", arg)\n },\n return(value: TReturn | PromiseLike<TReturn>) {\n return handle(\"return\", value)\n },\n throw(err: unknown) {\n return handle(\"throw\", err)\n },\n [Symbol.asyncIterator]() {\n return wrapped\n },\n [Symbol.asyncDispose]() {\n return handle(\"return\", undefined).then(() => undefined)\n },\n } as AsyncGenerator<TYield, TReturn, unknown>\n\n return wrapped\n}\n\n// --- BAML Collector support for wrapBAML ---\n\ntype CollectorConstructor = new (name: string) => unknown\n\nlet cachedCollectorClass: CollectorConstructor | null | undefined\n\n/** @internal Reset the cached Collector class - for testing only. */\nexport function _resetCollectorCache(): void {\n cachedCollectorClass = undefined\n}\n\n/** @internal Inject a mock Collector class - for testing only. */\nexport function _setCollectorCache(cls: CollectorConstructor | null): void {\n cachedCollectorClass = cls\n}\n\n/** @internal Count of in-flight (registered, not yet completed) trace states - for testing only. */\nexport function _activeTraceStateCount(): number {\n return activeTraceStates.size\n}\n\nasync function loadCollectorClass(): Promise<CollectorConstructor | null> {\n if (cachedCollectorClass !== undefined) {\n return cachedCollectorClass\n }\n try {\n // Reconstructed specifier (see importOptionalPeer): a consumer's bundler\n // must not try to resolve `@boundaryml/baml` at build time when it is not\n // installed (optional peer, only needed for BAML execution / collectors).\n const baml = await importOptionalPeer<typeof import(\"@boundaryml/baml\")>([\n \"@boundaryml\",\n \"baml\",\n ])\n cachedCollectorClass = baml.Collector as CollectorConstructor\n return cachedCollectorClass\n } catch {\n cachedCollectorClass = null\n return null\n }\n}\n\n// Typed accessors for the BAML Collector's internal structure.\n// Uses defensive access since these are untyped objects from the BAML runtime.\n\ninterface CollectorCall {\n selected?: boolean\n clientName?: string\n provider?: string\n usage?: {\n inputTokens?: number\n outputTokens?: number\n cachedInputTokens?: number\n }\n httpRequest?: {\n url?: string\n body?: { json: () => Record<string, unknown> | null }\n }\n}\n\ninterface CollectorLog {\n calls?: CollectorCall[]\n timing?: { durationMs?: number }\n}\n\ninterface CollectorLike {\n last?: CollectorLog | null\n usage?: {\n inputTokens?: number\n outputTokens?: number\n cachedInputTokens?: number\n }\n}\n\nfunction extractPromptFromCollector(collector: unknown): string | null {\n try {\n const c = collector as CollectorLike\n const calls = c?.last?.calls ?? []\n const selectedCall = calls.find((call) => call.selected) ?? calls[0]\n if (!selectedCall?.httpRequest?.body) {\n return null\n }\n const body = selectedCall.httpRequest.body.json()\n if (!body || typeof body !== \"object\") {\n return null\n }\n const messages = body.messages\n if (!Array.isArray(messages) || messages.length === 0) {\n return null\n }\n const rendered = (messages as Record<string, unknown>[])\n .filter(\n (msg): msg is { role: string; content: unknown } =>\n typeof msg === \"object\" &&\n msg !== null &&\n \"role\" in msg &&\n typeof (msg as { role: unknown }).role === \"string\",\n )\n .map((msg) => ({\n role: msg.role,\n content:\n typeof msg.content === \"string\"\n ? msg.content\n : JSON.stringify(msg.content),\n }))\n if (rendered.length > 0) {\n return JSON.stringify(rendered)\n }\n return null\n } catch {\n return null\n }\n}\n\nfunction extractContextFromCollector(\n collector: unknown,\n): Record<string, unknown> | null {\n try {\n const c = collector as CollectorLike\n const calls = c?.last?.calls ?? []\n const selectedCall = calls.find((call) => call.selected) ?? calls[0]\n const usage = c?.usage\n\n const context: Record<string, unknown> = {}\n if (selectedCall?.provider) {\n context.provider = selectedCall.provider\n }\n\n // Extract model from HTTP request body (OpenAI/Anthropic) or URL (Vertex AI)\n const body = selectedCall?.httpRequest?.body?.json()\n if (body && typeof body === \"object\" && typeof body.model === \"string\") {\n context.model = body.model\n } else {\n const url = selectedCall?.httpRequest?.url\n if (url) {\n const match = url.match(/\\/models\\/([^/:]+)/)\n if (match?.[1]) {\n context.model = match[1]\n }\n }\n }\n\n const inputTokens =\n usage?.inputTokens ?? selectedCall?.usage?.inputTokens ?? null\n const outputTokens =\n usage?.outputTokens ?? selectedCall?.usage?.outputTokens ?? null\n if (inputTokens !== null) {\n context.inputTokens = inputTokens\n }\n if (outputTokens !== null) {\n context.outputTokens = outputTokens\n }\n\n const durationMs = c?.last?.timing?.durationMs ?? null\n if (durationMs !== null) {\n context.durationMs = durationMs\n }\n\n return Object.keys(context).length > 0 ? context : null\n } catch {\n return null\n }\n}\n\n/**\n * Options for wrapBAML.\n */\nexport interface WrapBAMLOptions {\n /** Called after each BAML invocation with the Collector instance. */\n onCollector?: (collector: unknown) => void\n}\n\n/**\n * A function returned by wrapBAML that exposes the BAML collector from the last call.\n */\nexport interface WrappedBamlFn<TArgs extends unknown[], TReturn> {\n (...args: TArgs): Promise<TReturn>\n /** The BAML Collector instance from the most recent call. `null` before the first call or if @boundaryml/baml is unavailable. */\n collector: unknown | null\n}\n\n/**\n * A handle to the current active span, allowing context to be added.\n */\nexport interface CurrentSpan {\n /** The Bitfab ID for the current span. */\n readonly id: string\n /** The trace ID for the current span. */\n readonly traceId: string\n /**\n * Add a context entry to this span. Each call appends to the contexts array.\n * Context entries are stored in span_data.contexts as [{key, value}, ...].\n */\n addContext(context: Record<string, unknown>): void\n /**\n * Set the prompt for this span. Stored in span_data.prompt.\n * Calling multiple times overwrites the previous value.\n */\n setPrompt(prompt: string): void\n}\n\n/**\n * A detached handle to a previously-created trace, looked up by its\n * canonical Bitfab trace ID.\n *\n * Unlike `getCurrentTrace()`, this handle is not tied to AsyncLocalStorage -\n * each method sends to the server immediately. Useful for adding context\n * to a trace from a different process, request, or thread (e.g. a forked\n * agent that wants to annotate the original conversation's trace).\n */\nexport interface DetachedTrace {\n /** The canonical Bitfab trace ID this handle resolves. */\n readonly traceId: string\n /**\n * Append a context entry to this trace. Each call adds one entry to the\n * server-side contexts array; existing entries are preserved.\n *\n * Resolves once the server has applied the change and REJECTS if the server\n * refused it. A detached patch targets an already-closed trace, so it rides\n * no batch and no later signal would reveal a silent failure - the caller is\n * the only one who can react.\n */\n addContext(context: Record<string, unknown>): Promise<void>\n /**\n * Merge metadata into this trace. Server-side shallow-merges the new keys\n * into the existing metadata object; existing keys are preserved unless\n * overwritten by the new values. Rejects if the server refused the update.\n */\n setMetadata(metadata: Record<string, unknown>): Promise<void>\n /**\n * Set the sessionId for this trace. Replaces any existing sessionId.\n * Rejects if the server refused the update.\n */\n setSessionId(sessionId: string): Promise<void>\n setName(name: string): Promise<void>\n}\n\nconst UUID_PATTERN =\n /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i\n\nfunction validateTraceId(traceId: string): void {\n if (typeof traceId !== \"string\" || !UUID_PATTERN.test(traceId)) {\n throw new BitfabError(\"traceId must be a valid Bitfab trace ID\")\n }\n}\n\nfunction validateSpanId(id: string): void {\n if (typeof id !== \"string\" || !UUID_PATTERN.test(id)) {\n throw new BitfabError(\"id must be a valid Bitfab span ID\")\n }\n}\n\n/**\n * A handle to the current active trace, allowing trace-level context to be set.\n */\nexport interface CurrentTrace {\n /**\n * Set the session ID for this trace. Stored in the database session_id column.\n */\n setSessionId(sessionId: string): void\n setName(name: string): void\n /**\n * Set metadata for this trace. Stored in rawData.metadata.\n * Subsequent calls merge with existing metadata, with later values taking precedence.\n */\n setMetadata(metadata: Record<string, unknown>): void\n /**\n * Add a context entry to this trace. Each call appends to the contexts array.\n * Context entries are stored in rawData.contexts as [{key, value}, ...].\n */\n addContext(context: Record<string, unknown>): void\n /**\n * Flag this trace to be dropped. Once flagged, spans that complete afterward\n * are not uploaded at all, and when the trace completes the server scrubs any\n * payloads that already raced out (trace, external trace, and sibling spans),\n * marking it `dropped` instead of `completed` and retaining only a skeleton\n * audit record. Use this to discard runs you never want stored (e.g. health\n * checks, or a run you know contains sensitive data). Takes effect\n * immediately for later spans; the server-side scrub takes effect at trace\n * completion, so a trace that is flagged but never completes is not scrubbed.\n */\n drop(): void\n}\n\n// No-op implementations for when called outside a span context\nconst noOpSpan: CurrentSpan = {\n id: \"\",\n traceId: \"\",\n addContext(): void {\n // No-op\n },\n setPrompt(): void {\n // No-op\n },\n}\n\nconst noOpTrace: CurrentTrace = {\n setSessionId(): void {\n // No-op\n },\n setName(): void {},\n setMetadata(): void {\n // No-op\n },\n addContext(): void {\n // No-op\n },\n drop(): void {\n // No-op\n },\n}\n\n/**\n * Get a handle to the current active span.\n *\n * Call this from inside a traced function (wrapped with `withSpan`) to get\n * a span handle that allows adding context at runtime.\n *\n * Returns a no-op object if called outside of a span context (methods do nothing).\n */\nexport function getCurrentSpan(): CurrentSpan {\n const stack = getSpanStack()\n const current = stack[stack.length - 1]\n if (!current) {\n return noOpSpan\n }\n return {\n id: current.spanId,\n traceId: current.traceId,\n addContext(context: Record<string, unknown>): void {\n try {\n if (typeof context !== \"object\" || context === null) {\n return\n }\n // Push the entire context object as one entry\n current.contexts.push(context)\n } catch {\n // Silently ignore - never crash the host app\n }\n },\n setPrompt(prompt: string): void {\n try {\n if (typeof prompt !== \"string\") {\n return\n }\n current.prompt = prompt\n } catch {\n // Silently ignore - never crash the host app\n }\n },\n }\n}\n\n/**\n * Get the database branch the current replay item is running against.\n *\n * Call this from inside a function being replayed with `replay({ dbBranch })`\n * and point your database client at `branch.databaseUrl` so the replay reads\n * the data as it was at trace time:\n *\n * ```ts\n * const branch = getCurrentReplayBranch()\n * const url = branch?.databaseUrl ?? process.env.DATABASE_URL\n * ```\n *\n * Returns null outside a replay item, and for an item whose source trace\n * carried no DB snapshot reference, so live request code takes the same path\n * it always did.\n */\nexport function getCurrentReplayBranch(): ReplayBranch | null {\n const ctx = getReplayContext()\n if (!ctx?.dbBranchLease) {\n return null\n }\n // Surface the Bitfab traceId (what the customer sees in the dashboard), not\n // the external_traces.id. Falling back to the external ID keeps replays from\n // external sources working until the source-system path is fully wired.\n const traceId = ctx.sourceBitfabTraceId ?? ctx.inputSourceTraceId\n if (!traceId) {\n return null\n }\n return new ReplayBranch(ctx.dbBranchLease, traceId, ctx)\n}\n\n/**\n * Get a handle to the current active trace.\n *\n * Call this from inside a traced function (wrapped with `withSpan`) to get\n * a trace handle that allows setting trace-level context at runtime.\n *\n * Returns a no-op object if called outside of a span context (methods do nothing).\n */\nexport function getCurrentTrace(): CurrentTrace {\n const stack = getSpanStack()\n const current = stack[stack.length - 1]\n if (!current) {\n return noOpTrace\n }\n\n const traceId = current.traceId\n\n const getOrCreateTraceState = (): TraceState => {\n let traceState = activeTraceStates.get(traceId)\n if (!traceState) {\n traceState = {\n traceId,\n startedAt: nowIsoTimestamp(),\n contexts: [],\n }\n activeTraceStates.set(traceId, traceState)\n }\n return traceState\n }\n\n return {\n setSessionId(sessionId: string): void {\n try {\n const traceState = getOrCreateTraceState()\n traceState.sessionId = sessionId\n } catch {\n // Silently ignore - never crash the host app\n }\n },\n setName(name: string): void {\n if (typeof name !== \"string\" || name.length === 0) {\n return\n }\n try {\n getOrCreateTraceState().name = name\n } catch {}\n },\n setMetadata(metadata: Record<string, unknown>): void {\n try {\n if (typeof metadata !== \"object\" || metadata === null) {\n return\n }\n const traceState = getOrCreateTraceState()\n traceState.metadata = { ...traceState.metadata, ...metadata }\n } catch {\n // Silently ignore - never crash the host app\n }\n },\n addContext(context: Record<string, unknown>): void {\n try {\n if (typeof context !== \"object\" || context === null) {\n return\n }\n const traceState = getOrCreateTraceState()\n // Push the entire context object as one entry\n traceState.contexts.push(context)\n } catch {\n // Silently ignore - never crash the host app\n }\n },\n drop(): void {\n try {\n getOrCreateTraceState().dropped = true\n } catch {\n // Silently ignore - never crash the host app\n }\n },\n }\n}\n\n/**\n * Read an environment variable without throwing in non-Node runtimes\n * (browsers, edge workers) where `process` is absent. The SDK ships to\n * browsers, so this must never assume `process` exists.\n */\nfunction readEnv(name: string): string | undefined {\n if (typeof process !== \"undefined\" && process.env) {\n return process.env[name]\n }\n return undefined\n}\n\nexport interface SeedCaseOptions {\n input: unknown[]\n expected?: unknown\n // biome-ignore lint/suspicious/noExplicitAny: matches the replay callable\n fn?: (...args: any[]) => unknown\n metadata?: Record<string, unknown>\n sessionId?: string\n name?: string\n spanName?: string\n spanType?: SpanType\n}\n\nexport interface SeedRunOptions<TArgs extends unknown[]> {\n args?: TArgs\n metadata?: Record<string, unknown>\n sessionId?: string\n name?: string\n}\n\nexport interface BitfabConfig {\n /**\n * The API key for Bitfab API authentication. Resolved lazily, the first\n * time a span actually needs it, not at construction. When it resolves\n * empty, tracing is disabled (a no-op, unless `strict` is set).\n *\n * Accepts either a string or a function returning the key. The function\n * form is resolved at first use, so it survives the ESM trap where a shim\n * built at module load runs before the script body's `dotenv.config()`:\n * `apiKey: () => process.env.BITFAB_API_KEY`. When omitted (or it resolves\n * empty), the SDK also falls back to reading `BITFAB_API_KEY` from the\n * environment itself, again at first use.\n */\n apiKey?: string | (() => string | null | undefined)\n /** The base URL for the Bitfab API (default: https://bitfab.ai) */\n serviceUrl?: string\n /** Request timeout in milliseconds (default: 120000) */\n timeout?: number\n /** Environment variables for LLM provider API keys (only OPENAI_API_KEY is supported) */\n envVars?: AllowedEnvVars\n captureEnabled?: boolean\n enabled?: boolean\n /**\n * Fail loud instead of degrading quietly. When true, the first traced call\n * with no resolvable API key throws a `BitfabError` rather than silently\n * disabling tracing. Off by default so a missing telemetry key never takes\n * down the host app; turn it on in standalone scripts where a run that\n * emits no traces is a failure you want surfaced immediately.\n */\n strict?: boolean\n /** The generated BAML client instance (e.g., `b` from your baml_client). Used by wrapBAML() when no explicit client is passed. */\n bamlClient?: unknown\n /**\n * Per-trace database snapshot config. When set, every root span captures\n * a wall-clock timestamp (and, if `captureRef` is provided, a provider-\n * specific point-in-time ref) so the trace can later be replayed against\n * a branch materialized from that point.\n */\n dbSnapshot?: DbSnapshotConfig\n}\n\n/**\n * Span types matching the backend enum.\n * - llm: LLM API calls\n * - agent: Autonomous orchestrators\n * - function: Tool implementations\n * - guardrail: Safety/validation checks\n * - handoff: Agent-to-agent transfers\n * - custom: Application-specific tracing (default)\n */\nexport type SpanType =\n | \"llm\"\n | \"agent\"\n | \"function\"\n | \"guardrail\"\n | \"handoff\"\n | \"custom\"\n\n/**\n * Controls when a span is captured.\n * - always: Capture the span even when it becomes the root of a new trace.\n * - nested: Capture the span only when another Bitfab span is already active.\n */\nexport type CaptureWhen = \"always\" | \"nested\"\n\n/**\n * Options for configuring span behavior.\n */\nexport interface SpanOptions {\n /**\n * The name of the span. Defaults to the function name if available,\n * otherwise falls back to the trace function key.\n */\n name?: string\n /**\n * The type of span. Defaults to \"custom\" if not specified.\n */\n type?: SpanType\n /**\n * Controls whether this span may start a new trace. Defaults to \"always\".\n *\n * Use \"nested\" for reusable helpers that should appear inside an existing\n * trace but should run untraced when called on their own.\n * Unknown values warn once and default to \"always\".\n */\n captureWhen?: CaptureWhen\n /**\n * When true, replay will reuse this span's historical output instead of\n * executing the wrapped function. Read by the \"marked\" replay strategy;\n * ignored outside replay and under the \"all\"/\"none\" strategies.\n *\n * Use this for child spans that are expensive (paid LLM/API calls),\n * slow, or non-deterministic - the root function still runs real code,\n * only the marked descendants return their recorded output. If a selected\n * occurrence is unavailable, replay fails the item without executing the\n * real child.\n */\n mockOnReplay?: boolean\n /** Optional test run ID included on the span and on the trace it starts. */\n testRunId?: string\n /**\n * Record a serializable view of a non-serializable result (e.g. a live\n * stream object) as the span output.\n *\n * When set, the wrapped function's raw return value is handed back to the\n * caller unchanged (so streaming and first-byte latency are untouched),\n * but instead of serializing that raw value, the span records\n * `await finalize(result)`. Use this to trace functions that return a live\n * stream consumed by the caller (Vercel AI SDK `streamText`, a\n * `ReadableStream`, an SSE response) while still capturing a serializable,\n * replayable output such as `{ text, usage, toolCalls }`.\n *\n * Reading from a multi-consumer stream result (like the AI SDK's, which\n * tees internally) does not disturb the caller's own consumption. For the\n * Vercel AI SDK shape, pass the prebuilt `finalizers.aiSdk` helper.\n *\n * Ignored for async-generator results, which are captured automatically.\n */\n // biome-ignore lint/suspicious/noExplicitAny: the result type is the wrapped fn's return; SpanOptions is not generic, so callers narrow it inside finalize\n finalize?: (result: any) => unknown | Promise<unknown>\n}\n\n/**\n * The standard method context passed to a decorator.\n *\n * Defined structurally instead of referencing TypeScript's built-in\n * `ClassMethodDecoratorContext`, which was added in TypeScript 5.0. This keeps\n * the SDK's non-decorator APIs consumable by projects on older compilers.\n */\nexport interface SpanMethodDecoratorContext<TThis, TValue> {\n readonly kind: \"method\"\n readonly name: string | symbol\n readonly static: boolean\n readonly private: boolean\n readonly access: {\n has(object: TThis): boolean\n get(object: TThis): TValue\n }\n addInitializer(initializer: (this: TThis) => void): void\n readonly metadata?: Record<PropertyKey, unknown>\n}\n\n/** A standard ECMAScript method decorator produced by {@link Bitfab.span}. */\nexport type SpanMethodDecorator = <TThis, TArgs extends unknown[], TReturn>(\n originalMethod: (this: TThis, ...args: TArgs) => TReturn,\n context: SpanMethodDecoratorContext<\n TThis,\n (this: TThis, ...args: TArgs) => TReturn\n >,\n) => (this: TThis, ...args: TArgs) => TReturn\n\n/** Trace-owned configuration for a function discovered beneath `trace()`. */\nexport interface NodeOptions extends Omit<SpanOptions, \"captureWhen\"> {\n /** Whether the enclosing trace captures this call. Defaults to true. */\n capture?: boolean\n}\n\ntype NodeConfigurationOptions = Omit<AutoTraceNodeConfiguration, \"functionName\">\n\ntype StandardNodeMethodDecorator = SpanMethodDecorator\n\ntype LegacyNodeMethodDecorator = <TThis, TArgs extends unknown[], TReturn>(\n target: object,\n propertyKey: string | symbol,\n descriptor: TypedPropertyDescriptor<(this: TThis, ...args: TArgs) => TReturn>,\n) => void\n\n/** A method decorator produced by {@link Bitfab.node}. */\nexport type NodeMethodDecorator = StandardNodeMethodDecorator &\n LegacyNodeMethodDecorator\n\n/** Options for experimental automatic subtree tracing. */\nexport interface TraceOptions {\n /** Root span name. Defaults to the decorated or wrapped function name. */\n name?: string\n /** Root span type. Descendants are always `function` spans. */\n type?: SpanType\n /**\n * Default replay-mocking policy for automatically captured descendants.\n * When true, those descendants are mocked by the default \"marked\" strategy\n * unless a node explicitly sets `mockOnReplay: false`. Defaults to false.\n */\n mockOnReplayDefault?: boolean\n /** Maximum number of recorded descendant levels. Defaults to 30. */\n maxDepth?: number\n /** Maximum descendant spans recorded per root invocation. Defaults to 500. */\n maxSpans?: number\n /** Qualified or simple function names to leave out of the subtree. */\n exclude?: readonly string[] | ReadonlySet<string>\n /** Record rest-argument wrapper functions. Defaults to false. */\n includeWrappers?: boolean\n}\n\ninterface InternalSpanOptions extends SpanOptions {\n functionId?: string\n captureContent?: boolean\n autoTraceDefinition?: AutoTraceFunctionDefinition\n surface?: SurfaceRequest\n}\n\ntype StandardTraceMethodDecorator = <This, TArgs extends unknown[], TReturn>(\n method: (this: This, ...args: TArgs) => TReturn,\n context: { kind: \"method\"; name: string | symbol },\n) => (this: This, ...args: TArgs) => TReturn\n\ntype LegacyTraceMethodDecorator = <This, TArgs extends unknown[], TReturn>(\n target: object,\n propertyKey: string | symbol,\n descriptor: TypedPropertyDescriptor<(this: This, ...args: TArgs) => TReturn>,\n) => void\n\ntype TraceMethodDecorator = StandardTraceMethodDecorator &\n LegacyTraceMethodDecorator\n\nconst DEFAULT_AUTO_TRACE_MAX_DEPTH = 30\nconst DEFAULT_AUTO_TRACE_MAX_SPANS = 500\nconst AUTO_TRACE_PROTOCOL = \"ts-auto-v1\"\nconst AUTO_TRACE_POLICY_REFRESH_MS = 60_000\nconst AUTO_TRACE_POLICY_RETRY_MS = 10_000\n\ninterface AutoTracePolicyResponse {\n protocol: typeof AUTO_TRACE_PROTOCOL\n functionIds: string[]\n revision: string | null\n}\n\ninterface AutoTracePolicyRefresh {\n refreshAfter: number\n inFlight?: Promise<void>\n}\n\nfunction autoTraceLimit(value: number | undefined, fallback: number): number {\n return value !== undefined && Number.isFinite(value) && value >= 0\n ? Math.floor(value)\n : fallback\n}\n\ninterface FunctionVersionResponse {\n id: string\n name: string\n versionId: string\n versionNumber: number | null\n prompt: string\n providers: ProviderDefinition[]\n}\n\nexport { MixedTracingError }\n\n// Re-export BitfabError for backwards compatibility\nexport { BitfabError }\n\n/**\n * Client for making provider-based API calls via BAML.\n */\nexport class Bitfab {\n private readonly apiKeyConfig:\n | string\n | (() => string | null | undefined)\n | undefined\n /** Cached only once a non-empty key is found, so an early resolve (before env loaded) can't poison a later one. */\n private resolvedApiKey: string | undefined\n /** Gate the empty-key warning to fire at most once. */\n private apiKeyWarned: boolean = false\n private readonly serviceUrl: string\n private readonly timeout: number\n private readonly envVars: AllowedEnvVars\n private readonly captureConfigured: boolean\n private readonly strict: boolean\n private readonly httpClient: HttpClient\n /** Dataset operations for the authenticated organization. */\n readonly datasets: DatasetsClient\n private readonly bamlClient: unknown\n private readonly dbSnapshot: DbSnapshotConfig | undefined\n private readonly autoTracePolicyRefreshes = new Map<\n string,\n AutoTracePolicyRefresh\n >()\n /**\n * Mock overrides registered via {@link Bitfab.registerMockOverride}, applied\n * to every `replay` on this client (after any per-call `mockOverride`). In\n * registration order; first matcher wins within this list.\n */\n private readonly mockOverrides: MockOverride[] = []\n\n /**\n * Initialize the Bitfab client.\n *\n * @param config - Configuration options for the client\n */\n constructor(config: BitfabConfig) {\n this.apiKeyConfig = config.apiKey\n this.serviceUrl = config.serviceUrl ?? DEFAULT_SERVICE_URL\n this.timeout = config.timeout ?? 120000\n this.envVars = config.envVars ?? {}\n if (config.enabled !== undefined) {\n warnOnce(\n \"deprecated-enabled-option\",\n \"Bitfab({ enabled }) is deprecated; pass captureEnabled instead.\",\n )\n }\n this.captureConfigured =\n (config.captureEnabled ?? true) && (config.enabled ?? true)\n this.strict = config.strict ?? false\n this.bamlClient = config.bamlClient ?? null\n if (config.dbSnapshot) {\n validateDbSnapshotConfig(config.dbSnapshot)\n }\n this.dbSnapshot = config.dbSnapshot\n // The key is NOT read here. HttpClient gets a thunk so the key is resolved\n // at send time, after any in-script dotenv.config() has run.\n this.httpClient = new HttpClient({\n apiKey: () => this.resolveApiKey(),\n serviceUrl: this.serviceUrl,\n timeout: this.timeout,\n })\n this.datasets = new DatasetsClient(this.httpClient)\n }\n\n /**\n * Decorate a class method as an automatically expanded trace root.\n *\n * Build instrumentation turns repository functions called beneath this\n * method into nested spans that capture inputs, outputs, and errors by\n * default. A confirmed capture policy can narrow rich capture to selected\n * function IDs.\n * Without a compatible build transform, this still records the decorated\n * method as a normal rich root span but cannot discover child calls.\n *\n * @param traceFunctionKey - Groups traces and their capture policy.\n * @param options - Root presentation, subtree bounds, and exclusions.\n * @experimental Automatic child-call instrumentation is experimental.\n */\n trace(\n traceFunctionKey: string,\n options: TraceOptions = {},\n ): TraceMethodDecorator {\n const decorator = (...args: unknown[]): unknown => {\n if (args.length === 3) {\n const propertyKey = args[1] as string | symbol\n const descriptor = args[2] as TypedPropertyDescriptor<\n (this: unknown, ...methodArgs: unknown[]) => unknown\n >\n if (!descriptor || typeof descriptor.value !== \"function\") {\n throw new BitfabError(\"@bitfab.trace can only decorate methods\")\n }\n descriptor.value = this.createAutoTraceRoot(\n traceFunctionKey,\n String(propertyKey),\n options,\n descriptor.value,\n )\n return\n }\n\n const method = args[0]\n const context = args[1] as\n | { kind?: string; name?: string | symbol }\n | undefined\n if (\n typeof method !== \"function\" ||\n context?.kind !== \"method\" ||\n context.name === undefined\n ) {\n throw new BitfabError(\"@bitfab.trace can only decorate methods\")\n }\n return this.createAutoTraceRoot(\n traceFunctionKey,\n String(context.name),\n options,\n method as (this: unknown, ...methodArgs: unknown[]) => unknown,\n )\n }\n\n return decorator as TraceMethodDecorator\n }\n\n /**\n * Wrap a function as an automatically expanded trace root.\n *\n * This is the function-oriented equivalent of {@link Bitfab.trace}. Build\n * instrumentation turns repository functions called beneath the wrapped\n * function into nested spans that capture inputs, outputs, and errors by\n * default. A confirmed capture policy can narrow rich capture to selected\n * function IDs. Without a compatible transform, this still records one\n * normal rich root span and runs the function unchanged.\n *\n * @param traceFunctionKey - Groups traces and their capture policy.\n * @param optionsOrFn - Options or the workflow entrypoint to wrap.\n * @param maybeFn - Workflow entrypoint when options are provided.\n * @experimental Automatic child-call instrumentation is experimental.\n */\n withTrace<This, TArgs extends unknown[], TReturn>(\n traceFunctionKey: string,\n fn: (this: This, ...args: TArgs) => TReturn,\n ): (this: This, ...args: TArgs) => TReturn\n withTrace<This, TArgs extends unknown[], TReturn>(\n traceFunctionKey: string,\n options: TraceOptions,\n fn: (this: This, ...args: TArgs) => TReturn,\n ): (this: This, ...args: TArgs) => TReturn\n withTrace<This, TArgs extends unknown[], TReturn>(\n traceFunctionKey: string,\n optionsOrFn: TraceOptions | ((this: This, ...args: TArgs) => TReturn),\n maybeFn?: (this: This, ...args: TArgs) => TReturn,\n ): (this: This, ...args: TArgs) => TReturn {\n const options = typeof optionsOrFn === \"function\" ? {} : optionsOrFn\n const fn = typeof optionsOrFn === \"function\" ? optionsOrFn : maybeFn\n if (!fn) {\n throw new BitfabError(\"bitfab.withTrace requires a function\")\n }\n const name = fn.name !== \"\" ? fn.name : traceFunctionKey\n return this.createAutoTraceRoot(traceFunctionKey, name, options, fn)\n }\n\n /**\n * Configure a transformed class method when it is discovered beneath a\n * {@link Bitfab.trace} root.\n *\n * The decorator creates no span or trace by itself. Beneath an active trace,\n * it can rename or retype the discovered call, capture its contents, mark it\n * for recorded-output replay, finalize its output, or omit it while leaving\n * captured descendants attached to the nearest captured parent.\n *\n * @param options - Trace-owned call configuration.\n * @experimental Automatic child-call instrumentation is experimental.\n */\n node(options: NodeOptions = {}): NodeMethodDecorator {\n const configuration = this.resolveNodeConfiguration(options)\n const decorator = (...args: unknown[]): unknown => {\n if (args.length === 3) {\n const descriptor = args[2] as TypedPropertyDescriptor<\n (this: unknown, ...methodArgs: unknown[]) => unknown\n >\n if (!descriptor || typeof descriptor.value !== \"function\") {\n throw new BitfabError(\"@bitfab.node can only decorate methods\")\n }\n descriptor.value = this.createAutoTraceNode(\n configuration,\n descriptor.value,\n String(args[1]),\n )\n return\n }\n\n const method = args[0]\n const context = args[1] as\n | { kind?: string; name?: string | symbol }\n | undefined\n if (typeof method !== \"function\" || context?.kind !== \"method\") {\n throw new BitfabError(\"@bitfab.node can only decorate methods\")\n }\n return this.createAutoTraceNode(\n configuration,\n method as (this: unknown, ...methodArgs: unknown[]) => unknown,\n String(context.name),\n )\n }\n\n return decorator as NodeMethodDecorator\n }\n\n /**\n * Configure a transformed standalone function when it is discovered beneath\n * a {@link Bitfab.trace} or {@link Bitfab.withTrace} root.\n *\n * This is the function-oriented equivalent of {@link Bitfab.node}. Without\n * an active automatic trace, the returned function runs normally and never\n * creates a span or trace. The function must be named so configuration can\n * be bound to its transformed definition without leaking to a descendant.\n *\n * @param optionsOrFn - Node options or the function to configure.\n * @param maybeFn - Function to configure when options are provided.\n * @experimental Automatic child-call instrumentation is experimental.\n */\n withNode<This, TArgs extends unknown[], TReturn>(\n fn: (this: This, ...args: TArgs) => TReturn,\n ): (this: This, ...args: TArgs) => TReturn\n withNode<This, TArgs extends unknown[], TReturn>(\n options: NodeOptions,\n fn: (this: This, ...args: TArgs) => TReturn,\n ): (this: This, ...args: TArgs) => TReturn\n withNode<This, TArgs extends unknown[], TReturn>(\n optionsOrFn: NodeOptions | ((this: This, ...args: TArgs) => TReturn),\n maybeFn?: (this: This, ...args: TArgs) => TReturn,\n internalFunctionName?: string,\n ): (this: This, ...args: TArgs) => TReturn {\n const options = typeof optionsOrFn === \"function\" ? {} : optionsOrFn\n const fn = typeof optionsOrFn === \"function\" ? optionsOrFn : maybeFn\n if (!fn) {\n throw new BitfabError(\"bitfab.withNode requires a function\")\n }\n const configuration = this.resolveNodeConfiguration(options)\n const functionName = internalFunctionName ?? fn.name\n if (functionName === \"\") {\n throw new BitfabError(\n \"bitfab.withNode requires a named function so the subtree transform can bind its configuration to the correct call.\",\n )\n }\n return this.createAutoTraceNode(configuration, fn, functionName)\n }\n\n private resolveNodeConfiguration(\n options: NodeOptions,\n ): NodeConfigurationOptions {\n const capture = options.capture ?? true\n if (!capture && options.mockOnReplay === true) {\n throw new BitfabError(\n \"bitfab.node({ capture: false }) cannot use mockOnReplay: true because an uncaptured node has no recorded output.\",\n )\n }\n return {\n capture,\n type: options.type ?? \"custom\",\n ...(options.name !== undefined && { name: options.name }),\n ...(options.testRunId !== undefined && {\n testRunId: options.testRunId,\n }),\n ...(options.mockOnReplay !== undefined && {\n mockOnReplay: options.mockOnReplay,\n }),\n ...(options.finalize !== undefined && { finalize: options.finalize }),\n }\n }\n\n private createAutoTraceNode<This, TArgs extends unknown[], TReturn>(\n configuration: NodeConfigurationOptions,\n fn: (this: This, ...args: TArgs) => TReturn,\n functionName: string,\n ): (this: This, ...args: TArgs) => TReturn {\n const nodeConfiguration = { ...configuration, functionName }\n return function (this: This, ...args: TArgs): TReturn {\n if (!__bitfabAutoTraceActive()) {\n if (enclosingSurface() === \"opt-in\") {\n throw mixedTracingError(\"node()\", \"opt-out\", \"opt-in\")\n }\n return fn.apply(this, args)\n }\n return runWithAutoTraceNodeConfiguration(nodeConfiguration, () =>\n fn.apply(this, args),\n )\n }\n }\n\n private createAutoTraceRoot<This, TArgs extends unknown[], TReturn>(\n traceFunctionKey: string,\n name: string,\n options: TraceOptions,\n fn: (this: This, ...args: TArgs) => TReturn,\n ): (this: This, ...args: TArgs) => TReturn {\n const self = this\n const maxDepth = autoTraceLimit(\n options.maxDepth,\n DEFAULT_AUTO_TRACE_MAX_DEPTH,\n )\n const maxSpans = autoTraceLimit(\n options.maxSpans,\n DEFAULT_AUTO_TRACE_MAX_SPANS,\n )\n const excluded = new Set(options.exclude ?? [])\n const includeWrappers = options.includeWrappers ?? false\n const rootOptions: InternalSpanOptions = {\n name: options.name ?? name,\n type: options.type ?? \"custom\",\n surface: \"opt-out\",\n }\n const tracedRoot = this.withSpan(\n traceFunctionKey,\n rootOptions,\n function (this: This, ...args: TArgs): TReturn {\n const capturePolicy = getAutoTraceCapturePolicy(self, traceFunctionKey)\n self.refreshAutoTraceCapturePolicy(traceFunctionKey)\n let spansUsed = 0\n let truncated = false\n const warnTruncated = (): void => {\n if (!truncated) {\n truncated = true\n getCurrentTrace().setMetadata({\n bitfabAutoTrace: {\n protocol: AUTO_TRACE_PROTOCOL,\n truncated: true,\n maxDepth,\n maxSpans,\n },\n })\n }\n warnOnce(\n `auto-trace-truncated:${traceFunctionKey}`,\n `\"${traceFunctionKey}\" hit an automatic subtree capture limit (maxDepth=${maxDepth}, maxSpans=${maxSpans}); its trace is incomplete. Raise the limits or narrow the subtree with exclude.`,\n )\n }\n const autoTraceContext: AutoTraceContext = {\n invoke<T>(\n definition: AutoTraceFunctionDefinition,\n inputs: unknown[],\n invokeFn: () => T,\n depth: number,\n nodeConfiguration?: AutoTraceNodeConfiguration,\n ): T {\n const nameParts = definition.name.split(\".\")\n const simpleName = nameParts[nameParts.length - 1]\n const invokeWithoutNode = (): T =>\n nodeConfiguration === undefined\n ? invokeFn()\n : runWithAutoTraceContext(autoTraceContext, invokeFn, depth)\n if (\n excluded.has(definition.name) ||\n (simpleName !== undefined && excluded.has(simpleName)) ||\n (nodeConfiguration === undefined &&\n definition.wrapper === true &&\n !includeWrappers)\n ) {\n return invokeWithoutNode()\n }\n if (nodeConfiguration?.capture === false) {\n return runWithAutoTraceContext(autoTraceContext, invokeFn, depth)\n }\n if (depth >= maxDepth || spansUsed >= maxSpans) {\n warnTruncated()\n return invokeWithoutNode()\n }\n spansUsed += 1\n const mockOnReplay =\n nodeConfiguration?.mockOnReplay ?? options.mockOnReplayDefault\n const childOptions: InternalSpanOptions = {\n name: nodeConfiguration?.name ?? definition.name,\n type: nodeConfiguration?.type ?? \"function\",\n captureWhen: \"nested\",\n surface: \"opt-out\",\n functionId: definition.id,\n captureContent:\n nodeConfiguration !== undefined ||\n capturePolicy === undefined ||\n capturePolicy.has(definition.id),\n autoTraceDefinition: definition,\n ...(nodeConfiguration?.testRunId !== undefined && {\n testRunId: nodeConfiguration.testRunId,\n }),\n ...(mockOnReplay !== undefined && {\n mockOnReplay,\n }),\n ...(nodeConfiguration?.finalize !== undefined && {\n finalize: nodeConfiguration.finalize,\n }),\n }\n const invokeWithAutoTraceContext = (): T =>\n runWithAutoTraceContext(autoTraceContext, invokeFn, depth + 1)\n if (definition.async === true) {\n const tracedAsyncChild = self.withSpan(\n traceFunctionKey,\n childOptions,\n async (..._inputs: unknown[]) =>\n await invokeWithAutoTraceContext(),\n )\n return tracedAsyncChild(...inputs) as T\n }\n const tracedChild = self.withSpan(\n traceFunctionKey,\n childOptions,\n (..._inputs: unknown[]): T => invokeWithAutoTraceContext(),\n )\n return tracedChild(...inputs)\n },\n }\n\n return runWithAutoTraceRootContext(autoTraceContext, () =>\n fn.apply(this, args),\n )\n },\n )\n const autoTraceRoot = function (this: This, ...args: TArgs): TReturn {\n if (!self.shouldRecord()) {\n return fn.apply(this, args)\n }\n return tracedRoot.apply(this, args)\n }\n Object.defineProperty(autoTraceRoot, \"_bitfabTraceFunctionKey\", {\n value: traceFunctionKey,\n })\n Object.defineProperty(autoTraceRoot, \"_bitfabWrappedFn\", { value: fn })\n return autoTraceRoot\n }\n\n private refreshAutoTraceCapturePolicy(traceFunctionKey: string): void {\n const now = Date.now()\n const state = this.autoTracePolicyRefreshes.get(traceFunctionKey) ?? {\n refreshAfter: 0,\n }\n if (state.inFlight || now < state.refreshAfter) {\n return\n }\n\n const request = this.httpClient\n .getAutoTracePolicy<AutoTracePolicyResponse>(\n traceFunctionKey,\n AUTO_TRACE_PROTOCOL,\n )\n .then((policy) => {\n if (policy.protocol !== AUTO_TRACE_PROTOCOL) {\n state.refreshAfter = Date.now() + AUTO_TRACE_POLICY_RETRY_MS\n return\n }\n const functionIds = Array.isArray(policy.functionIds)\n ? policy.functionIds\n .filter(\n (id): id is string =>\n typeof id === \"string\" &&\n id.startsWith(`${AUTO_TRACE_PROTOCOL}:`),\n )\n .slice(0, DEFAULT_AUTO_TRACE_MAX_SPANS)\n : []\n __setBitfabAutoTraceCapturePolicy(\n this,\n traceFunctionKey,\n policy.revision === null ? undefined : functionIds,\n )\n state.refreshAfter = Date.now() + AUTO_TRACE_POLICY_REFRESH_MS\n })\n .catch(() => {\n state.refreshAfter = Date.now() + AUTO_TRACE_POLICY_RETRY_MS\n })\n .finally(() => {\n state.inFlight = undefined\n })\n state.inFlight = request\n this.autoTracePolicyRefreshes.set(traceFunctionKey, state)\n }\n\n /**\n * Flush and permanently close this client's tracing resources: its pending\n * requests and the single span-transport worker shared by its decorators and\n * framework handlers.\n *\n * Resolves `false` when delivery failed or the deadline expired. Long-lived\n * processes never need this (the transport batches in the background and the\n * exit hook drains it); scripts and tests that want a hard guarantee should\n * await it.\n *\n * Deliberately not a `Symbol.asyncDispose` method: the SDK targets runtimes\n * where that symbol may be absent, and a computed key on a missing symbol\n * throws at class-definition time, taking the whole SDK down on load.\n */\n close(timeoutMs?: number): Promise<boolean> {\n return this.httpClient.close(timeoutMs)\n }\n\n /**\n * Resolve the API key lazily, the first time a span actually needs it.\n *\n * The key is intentionally NOT read at construction. In ESM, a shim that\n * does `new Bitfab({ apiKey: process.env.BITFAB_API_KEY })` is hoisted and\n * evaluated before the importing script's body runs `dotenv.config()`, so\n * the key would be empty at construction even though it is set moments\n * later. Resolving here (at first `withSpan` call / first request) reads\n * the key after env loading has run.\n *\n * Resolution order: the configured value (string, or function called each\n * time it is still unresolved), then a fallback read of `BITFAB_API_KEY`\n * from the environment. Once a non-empty key is found it is cached, so an\n * early resolve that found nothing never poisons a later one.\n */\n private resolveApiKey(): string | undefined {\n if (this.resolvedApiKey !== undefined) {\n return this.resolvedApiKey\n }\n const fromConfig =\n typeof this.apiKeyConfig === \"function\"\n ? this.apiKeyConfig()\n : this.apiKeyConfig\n const candidate =\n fromConfig && fromConfig.trim() !== \"\"\n ? fromConfig\n : readEnv(\"BITFAB_API_KEY\")\n const key = candidate && candidate.trim() !== \"\" ? candidate : undefined\n if (key) {\n this.resolvedApiKey = key\n return key\n }\n if (this.strict) {\n throw new BitfabError(\n \"Bitfab: no API key resolved. Set BITFAB_API_KEY or pass apiKey to \" +\n \"new Bitfab(). If a script loads env with dotenv, load it before the \" +\n \"module that constructs the client is imported (e.g. \" +\n \"`node --env-file=.env script.ts`), or pass \" +\n \"`apiKey: () => process.env.BITFAB_API_KEY`.\",\n )\n }\n if (this.captureConfigured && !this.apiKeyWarned) {\n this.apiKeyWarned = true\n console.warn(\n \"Bitfab: apiKey is empty - tracing is disabled. Provide a valid API key to enable tracing.\",\n )\n }\n return undefined\n }\n\n private isCaptureEnabled(): boolean {\n if (!this.captureConfigured) {\n return false\n }\n return this.resolveApiKey() !== undefined\n }\n\n private shouldRecord(): boolean {\n if (!this.captureConfigured && !getReplayContext() && !inSeedScope()) {\n return false\n }\n return this.resolveApiKey() !== undefined\n }\n\n get captureEnabled(): boolean {\n return this.isCaptureEnabled()\n }\n\n /**\n * Fetch the function with its current version and BAML prompt from the server.\n *\n * @param methodName - The name of the method to fetch\n * @returns The function with current version, BAML prompt, and provider definitions\n * @throws {BitfabError} If the function is not found or an error occurs\n */\n private async fetchFunctionVersion(\n methodName: string,\n ): Promise<FunctionVersionResponse> {\n const result =\n await this.httpClient.lookupFunction<FunctionVersionResponse>(methodName)\n\n // Check if function was not found\n if (result.id === null) {\n throw new BitfabError(\n `Function \"${methodName}\" not found. Create it at: ${this.serviceUrl}/functions`,\n \"/functions\",\n )\n }\n\n // Check if function has no prompt\n if (!result.prompt) {\n throw new BitfabError(\n `Function \"${methodName}\" has no prompt configured. Add one at: ${this.serviceUrl}/functions/${result.id}`,\n `/functions/${result.id}`,\n )\n }\n\n return result\n }\n\n /**\n * Call a method with the given named arguments via BAML execution.\n *\n * @param methodName - The name of the method to call\n * @param inputs - Named arguments to pass to the method\n * @returns The result of the BAML function execution\n * @throws {BitfabError} If service_url is not set, or if an error occurs\n */\n async call<T = unknown>(\n methodName: string,\n inputs: Record<string, unknown> = {},\n ): Promise<T> {\n try {\n const functionVersion = await this.fetchFunctionVersion(methodName)\n const executionResult = await runFunctionWithBaml(\n functionVersion.prompt,\n inputs,\n functionVersion.providers,\n this.envVars,\n )\n\n // Create trace for the local execution. A non-serializable result must\n // not throw into the user's `call()`: fall back to String() if\n // JSON.stringify throws or yields undefined (e.g. a function result).\n let resultStr: string\n if (typeof executionResult.result === \"string\") {\n resultStr = executionResult.result\n } else {\n try {\n resultStr =\n JSON.stringify(executionResult.result) ??\n String(executionResult.result)\n } catch {\n warnOnce(\n \"call-result-serialize\",\n \"a local execution result could not be JSON-serialized; storing its String() form instead. The call still returns its real value.\",\n )\n resultStr = String(executionResult.result)\n }\n }\n\n // Create trace in background so user doesn't have to wait\n this.httpClient.sendInternalTrace(functionVersion.id, {\n result: resultStr,\n source: \"typescript-sdk\",\n ...(Object.keys(inputs).length > 0 && { inputs }),\n ...(executionResult.rawCollector != null && {\n rawCollector: executionResult.rawCollector,\n }),\n })\n\n return executionResult.result as T\n } catch (error) {\n if (error instanceof BitfabError) {\n throw error\n }\n if (error instanceof Error) {\n throw new BitfabError(error.message)\n }\n throw new BitfabError(\"Unknown error occurred during local execution\")\n }\n }\n\n /**\n * Get a tracing processor for OpenAI Agents SDK integration.\n *\n * This processor automatically captures traces and spans from the OpenAI Agents SDK\n * and sends them to Bitfab for monitoring and analysis.\n *\n * Example usage:\n * ```typescript\n * import { addTraceProcessor } from '@openai/agents';\n *\n * const client = new Bitfab({ apiKey: 'your-api-key' });\n * const processor = client.getOpenAiTracingProcessor();\n * addTraceProcessor(processor);\n * ```\n *\n * @returns A BitfabOpenAITracingProcessor instance configured for this client\n */\n getOpenAiTracingProcessor() {\n return new BitfabOpenAITracingProcessor({\n // Resolved at getter-call time (framework handlers are set up after env\n // loads); the withSpan path stays lazy via the constructor HttpClient thunk.\n apiKey: this.resolveApiKey(),\n serviceUrl: this.serviceUrl,\n getActiveSpanContext: () => {\n const stack = getSpanStack()\n return stack[stack.length - 1] ?? null\n },\n _httpClient: this.httpClient,\n })\n }\n\n /**\n * Get an OpenAI Agents SDK handler that records a replayable root span.\n *\n * The processor from {@link getOpenAiTracingProcessor} captures everything\n * inside a run (LLM calls, tools, handoffs) but never sees the caller's\n * input, so a processor-only run records an empty-input root and is not\n * replayable. This handler's `wrapRun` is a drop-in for `run()` that opens a\n * `withSpan` root carrying the input and final output; the processor's spans\n * nest beneath it. Register the processor once at startup, then call\n * `handler.wrapRun(agent, input)` in place of `run(agent, input)`.\n *\n * ```typescript\n * import { addTraceProcessor, Agent, run } from \"@openai/agents\";\n *\n * addTraceProcessor(client.getOpenAiTracingProcessor());\n * const handler = client.getOpenAiAgentHandler(\"research-topic\");\n * const result = await handler.wrapRun(agent, \"Find X\");\n * ```\n *\n * @param traceFunctionKey - Groups traces under this key in Bitfab\n * @returns A BitfabOpenAIAgentHandler configured for this client\n */\n getOpenAiAgentHandler(traceFunctionKey: string) {\n return new BitfabOpenAIAgentHandler({\n traceFunctionKey,\n withSpan: this.withSpan.bind(this),\n getActiveSpanContext: () => {\n const stack = getSpanStack()\n return stack[stack.length - 1] ?? null\n },\n })\n }\n\n /**\n * Get a LangGraph/LangChain callback handler for tracing.\n *\n * The handler captures graph node execution, LLM calls, and tool\n * invocations as Bitfab spans with proper parent-child hierarchy.\n *\n * ```typescript\n * const handler = client.getLangGraphCallbackHandler(\"my-agent\");\n * const result = await agent.invoke(\n * { messages: [...] },\n * { callbacks: [handler] },\n * );\n * ```\n *\n * @param traceFunctionKey - Groups traces under this key in Bitfab\n * @returns A BitfabLangGraphCallbackHandler configured for this client\n */\n getLangGraphCallbackHandler(traceFunctionKey: string) {\n return new BitfabLangGraphCallbackHandler({\n apiKey: this.resolveApiKey(),\n traceFunctionKey,\n serviceUrl: this.serviceUrl,\n getActiveSpanContext: () => {\n const stack = getSpanStack()\n return stack[stack.length - 1] ?? null\n },\n _httpClient: this.httpClient,\n })\n }\n\n /**\n * Get a LangChain callback handler for tracing.\n *\n * Alias of {@link getLangGraphCallbackHandler}: LangChain chains and\n * LangGraph graphs share the same callback system, so one handler serves\n * both.\n *\n * ```typescript\n * const handler = client.getLangChainCallbackHandler(\"my-chain\");\n * const result = await chain.invoke(input, { callbacks: [handler] });\n * ```\n *\n * @param traceFunctionKey - Groups traces under this key in Bitfab\n * @returns A BitfabLangGraphCallbackHandler configured for this client\n */\n getLangChainCallbackHandler(traceFunctionKey: string) {\n return this.getLangGraphCallbackHandler(traceFunctionKey)\n }\n\n /**\n * Get the first-class LangGraph integration for tracing and replaying tools\n * executed by `ToolNode`.\n *\n * The integration combines `wrapTools()` for per-tool replay interception\n * with `createInvoker()` for a callback-configured replayable graph entry\n * point. Lower-level callback and root wrappers remain available.\n *\n * @param traceFunctionKey - Groups traces under this key in Bitfab\n * @param options - Controls which tools are marked for replay mocking\n * @experimental This API may change before it is stable.\n */\n getLangGraphIntegration(\n traceFunctionKey: string,\n options?: LangGraphIntegrationOptions,\n ): BitfabLangGraphIntegration {\n const callbackHandler = new BitfabLangGraphCallbackHandler({\n apiKey: this.resolveApiKey(),\n traceFunctionKey,\n serviceUrl: this.serviceUrl,\n getActiveSpanContext: () => {\n const stack = getSpanStack()\n return stack[stack.length - 1] ?? null\n },\n captureTools: false,\n _httpClient: this.httpClient,\n })\n return new BitfabLangGraphIntegration({\n client: this,\n traceFunctionKey,\n callbackHandler,\n options,\n })\n }\n\n /**\n * Get a Claude Agent SDK handler for tracing.\n *\n * The handler captures LLM turns, tool invocations, and subagent\n * execution as Bitfab spans with proper parent-child hierarchy.\n *\n * ```typescript\n * import { query } from \"@anthropic-ai/claude-agent-sdk\";\n *\n * const handler = client.getClaudeAgentHandler(\"my-agent\");\n * const options = handler.instrumentOptions({\n * model: \"claude-sonnet-4-5-...\",\n * });\n * for await (const msg of handler.wrapQuery(\n * query({ prompt: \"Do something\", options })\n * )) {\n * // process messages\n * }\n * ```\n *\n * @param traceFunctionKey - Groups traces under this key in Bitfab\n * @returns A BitfabClaudeAgentHandler configured for this client\n */\n getClaudeAgentHandler(traceFunctionKey: string) {\n return new BitfabClaudeAgentHandler({\n apiKey: this.resolveApiKey(),\n traceFunctionKey,\n serviceUrl: this.serviceUrl,\n getActiveSpanContext: () => {\n const stack = getSpanStack()\n return stack[stack.length - 1] ?? null\n },\n _httpClient: this.httpClient,\n })\n }\n\n /**\n * Get a Vercel AI SDK language-model middleware for tracing.\n *\n * Pass it to the AI SDK's `wrapLanguageModel` and use the wrapped model with\n * `generateText` / `streamText` / `generateObject` / `streamObject`. Every\n * call through that model is captured as a keyed `llm` span carrying the call\n * parameters (the prompt) as input and a serializable summary\n * (`{ text, toolCalls, usage, finishReason }`) as output. Streaming is\n * captured without disturbing the caller's live stream.\n *\n * ```typescript\n * import { wrapLanguageModel, streamText } from \"ai\";\n * import { openai } from \"@ai-sdk/openai\";\n *\n * const model = wrapLanguageModel({\n * model: openai(\"gpt-4o\"),\n * middleware: client.getVercelAiMiddleware(\"chat-turn\"),\n * });\n * const result = streamText({ model, messages });\n * ```\n *\n * @param traceFunctionKey - Groups traces under this key in Bitfab\n * @returns A Vercel AI SDK middleware configured for this client\n */\n getVercelAiMiddleware(traceFunctionKey: string) {\n return new BitfabVercelAiHandler({\n traceFunctionKey,\n withSpan: this.withSpan.bind(this),\n }).middleware\n }\n\n /**\n * Wrap a BAML client method to automatically capture prompt and LLM metadata.\n *\n * Creates a BAML Collector, calls the method through a tracked client,\n * then extracts rendered messages and token usage - calling setPrompt()\n * and addContext() on the current span automatically.\n *\n * The BAML client can be provided in the constructor or passed explicitly:\n *\n * ```typescript\n * // Option 1: bamlClient in constructor (use wrapBAML with just the method)\n * const client = new Bitfab({ apiKey: 'your-api-key', bamlClient: b });\n * const traced = client.withSpan('classify', { type: 'llm' },\n * client.wrapBAML(b.ClassifyText)\n * );\n *\n * // Option 2: pass bamlClient at call site\n * const client = new Bitfab({ apiKey: 'your-api-key' });\n * const traced = client.withSpan('classify', { type: 'llm' },\n * client.wrapBAML(b, b.ClassifyText)\n * );\n * ```\n *\n * @param methodOrClient - Either a BAML method (uses constructor bamlClient) or the BAML client instance\n * @param maybeMethodOrOptions - The BAML method when the first argument is a client, or WrapBAMLOptions when the first argument is the method\n * @param maybeOptions - WrapBAMLOptions when using the two-argument (client, method) form\n * @returns An async function with the same signature that instruments the BAML call\n */\n wrapBAML<TArgs extends unknown[], TReturn>(\n methodOrClient: unknown,\n maybeMethodOrOptions?:\n | ((...args: TArgs) => Promise<TReturn>)\n | WrapBAMLOptions,\n maybeOptions?: WrapBAMLOptions,\n ): WrappedBamlFn<TArgs, TReturn> {\n let bamlClient: unknown\n let method: (...args: TArgs) => Promise<TReturn>\n let options: WrapBAMLOptions | undefined\n\n if (typeof maybeMethodOrOptions === \"function\") {\n bamlClient = methodOrClient\n method = maybeMethodOrOptions\n options = maybeOptions\n } else {\n bamlClient = this.bamlClient\n method = methodOrClient as (...args: TArgs) => Promise<TReturn>\n options = maybeMethodOrOptions as WrapBAMLOptions | undefined\n if (!bamlClient) {\n throw new BitfabError(\n \"bamlClient is required for wrapBAML. Pass it in the constructor or as the first argument.\",\n )\n }\n }\n\n const methodName = method.name\n if (!methodName) {\n throw new BitfabError(\n \"wrapBAML requires a named function (e.g., b.ClassifyText).\",\n )\n }\n\n // Warm the Collector class cache so it's ready by the time the wrapper is called\n loadCollectorClass()\n\n const wrappedFn = async (...args: TArgs): Promise<TReturn> => {\n const CollectorClass = await loadCollectorClass()\n if (!CollectorClass) {\n // @boundaryml/baml not available - call method directly as fallback\n wrappedFn.collector = null\n return await (\n bamlClient as Record<string, (...a: TArgs) => Promise<TReturn>>\n )[methodName](...args)\n }\n\n const collector = new CollectorClass(\"bitfab-baml-tracing\")\n\n // Setting up the tracked client is a side-channel: a BAML version\n // mismatch, or a non-BAML object passed as `bamlClient`, must not stop\n // the user's call. If `withOptions` or the method lookup fails, fall back\n // to the untracked method so the call still runs (untraced).\n let trackedClient: Record<string, unknown>\n let trackedMethod: (...a: TArgs) => Promise<TReturn>\n try {\n trackedClient = (\n bamlClient as { withOptions: (opts: unknown) => unknown }\n ).withOptions({ collector }) as Record<string, unknown>\n const method = (\n trackedClient as Record<string, (...a: TArgs) => Promise<TReturn>>\n )[methodName]\n if (typeof method !== \"function\") {\n throw new BitfabError(\n \"bamlClient.withOptions did not return the wrapped method\",\n )\n }\n trackedMethod = method\n } catch {\n warnOnce(\n `wrapBAML-setup:${methodName}`,\n `BAML tracing setup failed for \"${methodName}\" (incompatible bamlClient or BAML version); calling it untraced. The call still runs; no span is recorded.`,\n )\n wrappedFn.collector = null\n return await (\n bamlClient as Record<string, (...a: TArgs) => Promise<TReturn>>\n )[methodName](...args)\n }\n\n const result = await trackedMethod.bind(trackedClient)(...args)\n\n wrappedFn.collector = collector\n\n try {\n const prompt = extractPromptFromCollector(collector)\n if (prompt) {\n getCurrentSpan().setPrompt(prompt)\n }\n const metadata = extractContextFromCollector(collector)\n if (metadata) {\n getCurrentSpan().addContext(metadata)\n }\n } catch {\n // Never crash the host app\n }\n\n try {\n options?.onCollector?.(collector)\n } catch {\n // Never crash the host app\n }\n\n return result\n }\n\n wrappedFn.collector = null as unknown | null\n\n return wrappedFn\n }\n\n /**\n * Wrap a function to automatically create a span for its inputs and outputs.\n *\n * The wrapped function behaves identically to the original, but sends\n * span data to Bitfab in the background after each call.\n *\n * Example usage:\n * ```typescript\n * const client = new Bitfab({ apiKey: 'your-api-key' });\n *\n * async function processOrder(orderId: string, items: string[]): Promise<{ total: number }> {\n * // ... process order\n * return { total: 100 };\n * }\n *\n * // Basic usage (defaults to \"custom\" span type)\n * const tracedProcessOrder = client.withSpan('order-processing', processOrder);\n *\n * // With explicit span type\n * const tracedProcessOrder = client.withSpan('order-processing', { type: 'function' }, processOrder);\n *\n * // Call the wrapped function normally\n * const result = await tracedProcessOrder('order-123', ['item-1', 'item-2']);\n * // Span is automatically sent to Bitfab\n * ```\n *\n * @param traceFunctionKey - A string identifier for grouping spans (e.g., 'order-processing', 'user-auth')\n * @param optionsOrFn - Either SpanOptions or the function to wrap\n * @param maybeFn - The function to wrap if options were provided\n * @returns A wrapped function with the same signature that creates spans for inputs and outputs\n */\n withSpan<TArgs extends unknown[], TReturn>(\n traceFunctionKey: string,\n optionsOrFn: SpanOptions | ((...args: TArgs) => TReturn),\n maybeFn?: (...args: TArgs) => TReturn,\n ): (...args: TArgs) => TReturn {\n // Handle overloaded signature\n const options: InternalSpanOptions =\n typeof optionsOrFn === \"function\" ? {} : optionsOrFn\n const fn: (...args: TArgs) => TReturn =\n typeof optionsOrFn === \"function\" ? optionsOrFn : maybeFn!\n const self = this\n\n // Detect Promise-returning fn at wrap time so the mock-fire path can\n // match the original return shape. `AsyncFunction` covers `async fn`\n // declarations; for plain functions that return a Promise we fall back\n // to a `fn.toString()` heuristic (looks for `Promise` or `await`).\n // Brittle for minified code, but mock-fire is the only consumer and a\n // sync fallback (returning a raw value) is the safe degradation.\n const fnIsAsyncFunction = fn.constructor.name === \"AsyncFunction\"\n const fnReturnsPromise =\n fnIsAsyncFunction ||\n (() => {\n try {\n const src = fn.toString()\n return /\\b(?:Promise|await)\\b/.test(src)\n } catch {\n return false\n }\n })()\n\n const wrappedFn = function (this: unknown, ...args: TArgs): TReturn {\n // Decide whether to trace at CALL time, not wrap time. The shim builds\n // this wrapper at module load, often before env (dotenv) has loaded, so\n // freezing the decision here would permanently disable tracing for a key\n // that is set moments later. Re-checking per call lets a late-resolved\n // key take effect; once a key is found the resolution is cached.\n if (!self.shouldRecord()) {\n return fn.apply(this, args)\n }\n\n // The Node-specific entry registers async_hooks synchronously, but ESM\n // chunk evaluation can load this module before that registration runs.\n // Re-check at call time so the first traced invocation gets native\n // context propagation instead of briefly using the browser fallback.\n initializeAsyncContext()\n\n // Defer until AsyncLocalStorage init completes. In Node.js, the\n // dynamic import resolves in one microtask; in browsers, the init\n // resolves immediately to a no-op. The `asyncLocalStorageInitDone`\n // flag prevents an infinite loop when AsyncLocalStorage is\n // unavailable (browsers).\n if (!asyncLocalStorage && !isAsyncStorageInitDone()) {\n return asyncLocalStorageReady.then(() =>\n wrappedFn.apply(this, args),\n ) as unknown as TReturn\n }\n\n const captureWhen: unknown =\n options.captureWhen === undefined ? \"always\" : options.captureWhen\n const resolvedCaptureWhen: CaptureWhen =\n captureWhen === \"always\" || captureWhen === \"nested\"\n ? captureWhen\n : \"always\"\n if (resolvedCaptureWhen !== captureWhen) {\n let invalidValue: string\n try {\n invalidValue = String(captureWhen)\n } catch {\n invalidValue = \"<unprintable>\"\n }\n warnOnce(\n `invalid-capture-when:${traceFunctionKey}`,\n `unknown captureWhen value \"${invalidValue}\"; defaulting to \"always\". Valid values: \"always\", \"nested\".`,\n )\n }\n\n if (resolvedCaptureWhen === \"nested\") {\n let hasParent = false\n try {\n hasParent = getSpanStack().length > 0\n } catch (setupError) {\n if (getReplayContext()) {\n throw setupError\n }\n warnOnce(\n `withSpan-setup:${traceFunctionKey}`,\n `tracing setup failed for \"${traceFunctionKey}\"; running it untraced. The function still runs and returns normally; no span is recorded.`,\n )\n return fn.apply(this, args) as TReturn\n }\n if (!hasParent) {\n return fn.apply(this, args) as TReturn\n }\n }\n\n // Tracing is a side-channel: building the span context must never stop\n // the user's function from running. If any of this setup throws (e.g. a\n // runtime without a usable `crypto`, or a context/snapshot edge), fall\n // back to running `fn` directly, untraced. The `!` definite-assignments\n // are sound because the catch always returns: reaching past the\n // try/catch means the try completed and both values were assigned.\n let newStack!: SpanContext[]\n let executeWithContext!: () => TReturn\n // Set only if THIS call registers root trace state below, so a setup\n // failure after registration can clean up the orphaned entry (see catch).\n let registeredTraceId: string | undefined\n try {\n // Get current span stack to determine trace context\n const currentStack = getSpanStack()\n const parentContext = currentStack[currentStack.length - 1]\n\n // Generate trace ID (replay override > parent > new)\n const replayCtxForTraceId = parentContext ? null : getReplayContext()\n const seedCtxForTraceId = parentContext ? null : getSeedContext()\n const traceId =\n parentContext?.traceId ??\n replayCtxForTraceId?.traceId ??\n seedCtxForTraceId?.traceId ??\n randomUuid()\n const spanId = randomUuid()\n const parentSpanId = parentContext?.spanId ?? null\n const isRootSpan = parentSpanId === null\n\n const requestedSurface: SurfaceRequest =\n options.surface ?? DEFAULT_SURFACE\n const surface = resolveSurface(requestedSurface, parentContext?.surface)\n assertSurfacesCompatible(\n requestedSurface,\n surface,\n parentContext?.surface,\n traceFunctionKey,\n )\n\n // Create new context for this span with empty contexts array\n const newContext: SpanContext = {\n traceId,\n spanId,\n contexts: [],\n ...(surface !== undefined && { surface }),\n }\n newStack = [...currentStack, newContext]\n\n // Capture inputs and start time\n const inputs = args\n const startedAt = nowIsoTimestamp()\n const replayCtxAtStart = getReplayContext()\n const testRunId = replayCtxAtStart?.testRunId ?? options.testRunId\n\n // Register trace state for root spans\n if (isRootSpan && !activeTraceStates.has(traceId)) {\n // Synchronously snapshot the wall clock the SDK sees right now,\n // before invoking the wrapped function. This timestamp is the Neon\n // snapshot pin used by the server-side resolver. It is captured on\n // every trace (no IO, harmless to store) so any trace can later be\n // replayed against a historical branch; the provider is attached\n // only when dbSnapshot is configured, otherwise resolved at replay.\n const dbSnapshotRef = buildSnapshotRef(self.dbSnapshot, startedAt)\n activeTraceStates.set(traceId, {\n traceId,\n startedAt,\n contexts: [],\n ...(testRunId !== undefined && { testRunId }),\n ...(replayCtxAtStart?.inputSourceTraceId && {\n inputSourceTraceId: replayCtxAtStart.inputSourceTraceId,\n }),\n ...(replayCtxAtStart?.replayAttempt !== undefined && {\n replayAttempt: replayCtxAtStart.replayAttempt,\n }),\n dbSnapshotRef,\n })\n registeredTraceId = traceId\n }\n\n // Shared span parameters\n const functionName = fn.name !== \"\" ? fn.name : undefined\n const baseSpanParams = {\n traceFunctionKey,\n functionName,\n spanName: options.name ?? functionName ?? traceFunctionKey,\n traceId,\n spanId,\n parentSpanId,\n inputs,\n startedAt,\n spanType: options.type ?? \"custom\",\n functionId: options.functionId,\n captureContent: options.captureContent ?? true,\n autoTraceDefinition: options.autoTraceDefinition,\n }\n\n // Helper to send the span and, for root spans, the trace completion\n // that follows it. Both are handed to the client's span transport,\n // which owns queueing, batching and delivery: nothing here waits on\n // the network, and replay confirms persistence with a server-side\n // barrier rather than by chaining upload promises.\n // Wrapped in try/catch so span errors never crash the host app.\n const sendSpan = async (params: {\n result: unknown\n error?: string\n mocked?: boolean\n mockTarget?: MockTarget\n mockSource?: MockSource\n }) => {\n const replayCtx = getReplayContext()\n try {\n const endedAt = nowIsoTimestamp()\n\n // If drop() was called on this trace, suppress the span PAYLOAD\n // upload for every span that completes after the flag was set.\n // The trace completion signal below still rides out with\n // `dropped: true`, so the server scrubs any sibling spans that\n // already raced out (fire-and-forget) before the flag was set.\n // Skipping the upload here is belt-and-suspenders on top of that\n // scrub: it avoids shipping payloads the server will only discard.\n const traceDropped =\n activeTraceStates.get(traceId)?.dropped === true\n\n // dbSnapshotRef is attached to the trace, not the span (see\n // sendTraceCompletion). A trace-level pin is what replay reads;\n // duplicating it on the root span would just leak the same\n // value into two places.\n if (!traceDropped) {\n self.sendWrapperSpan({\n ...baseSpanParams,\n ...params,\n contexts: newContext.contexts,\n prompt: newContext.prompt,\n endedAt,\n ...(testRunId !== undefined && { testRunId }),\n ...(replayCtx?.inputSourceSpanId && {\n inputSourceSpanId: replayCtx.inputSourceSpanId,\n }),\n })\n }\n\n // A root span closing its trace queues the completion right behind\n // its own span. No wait for the children first: the transport\n // preserves submission order and Bitfab's ingress keys spans and\n // traces idempotently, so completion never races ahead of content.\n if (isRootSpan) {\n const traceState = activeTraceStates.get(traceId)\n self.sendTraceCompletion({\n traceFunctionKey,\n traceId,\n startedAt: traceState?.startedAt ?? startedAt,\n endedAt,\n sessionId: traceState?.sessionId,\n name: traceState?.name,\n metadata: traceState?.metadata,\n contexts: traceState?.contexts ?? [],\n testRunId: traceState?.testRunId,\n inputSourceTraceId: traceState?.inputSourceTraceId,\n replayAttempt: traceState?.replayAttempt,\n dbSnapshotRef: traceState?.dbSnapshotRef,\n dropped: traceState?.dropped,\n ingestionType: traceState?.ingestionType,\n // Built AFTER the wrapped fn finished, so `accessed` reflects\n // whether customer code obtained the branch URL during this\n // item. Omitted entirely when no lease was attached, so the\n // server can distinguish \"no branch\" from \"branch ignored\".\n ...(replayCtx?.dbBranchLease && {\n dbSnapshotUsage: {\n neonBranchId: replayCtx.dbBranchLease.neonBranchId,\n snapshotTimestamp:\n replayCtx.dbBranchLease.snapshotTimestamp,\n region: replayCtx.dbBranchLease.region,\n originalTraceId: replayCtx.sourceBitfabTraceId,\n accessed: replayCtx.dbSnapshotAccessed === true,\n timings: replayCtx.dbBranchTimings,\n },\n }),\n })\n activeTraceStates.delete(traceId)\n }\n } catch {\n // Silently ignore - user's result/exception takes priority\n }\n }\n\n // Record the span output. With `finalize`, the raw result is handed\n // back to the caller untouched (streaming stays live) while a drained,\n // serializable view is recorded as the span output instead. finalize\n // runs in the background and never affects the caller's value; a\n // throwing finalize records an error rather than crashing the host.\n const recordSpan = (result: unknown): void => {\n if (options.finalize) {\n // Tracked on the OWNING client: the span reaches the transport\n // only once finalize settles, so a flush that merely drained the\n // transport would race a root span not yet queued - and in replay\n // that root's trace would miss the barrier. Scoped per client so\n // one client's slow finalize cannot fail another's close().\n void self.httpClient.trackDeferred(\n Promise.resolve()\n .then(() => options.finalize!(result))\n .then((output) => sendSpan({ result: output }))\n .catch((error: unknown) =>\n sendSpan({\n result: undefined,\n error:\n error instanceof Error\n ? `finalize failed: ${error.message}`\n : `finalize failed: ${String(error)}`,\n }),\n ),\n )\n } else {\n void sendSpan({ result })\n }\n }\n\n // Assign before mock interception because an asynchronous resolver can\n // decline after this setup block has already returned.\n executeWithContext = (): TReturn => {\n let result: TReturn\n try {\n result = fn.apply(this, args)\n } catch (error) {\n void sendSpan({\n result: undefined,\n error: error instanceof Error ? error.message : String(error),\n })\n throw error\n }\n\n if (result instanceof Promise) {\n return result\n .then((resolvedResult) => {\n recordSpan(resolvedResult)\n return resolvedResult\n })\n .catch((error: unknown) => {\n void sendSpan({\n result: undefined,\n error: error instanceof Error ? error.message : String(error),\n })\n throw error\n }) as TReturn\n }\n\n if (isAsyncGenerator(result)) {\n return wrapAsyncGenerator(result, newStack, sendSpan) as TReturn\n }\n\n recordSpan(result)\n return result\n }\n\n // Mock interception: for a non-root child span under an active mock\n // context, decide whether to substitute its output instead of running\n // real code. Precedence: a matching override wins (per-call before\n // registered, first matcher within each); otherwise the base strategy\n // (\"all\"/\"marked\") replays recorded output. The lookup key matches\n // buildMockTree: `${traceFunctionKey}:${spanName}:${idx}` with callIndex\n // scoped per (key, name) - see comment on buildMockTree.\n const replayCtxForMock = getReplayContext()\n if (replayCtxForMock?.mockTree && !isRootSpan) {\n const counters = replayCtxForMock.callCounters!\n const counterKey = `${traceFunctionKey}:${baseSpanParams.spanName}`\n const callIndex = counters.get(counterKey) ?? 0\n counters.set(counterKey, callIndex + 1)\n\n const mockKey = `${counterKey}:${callIndex}`\n const mockSpan = replayCtxForMock.mockTree.spans.get(mockKey)\n\n // Emit a mocked span (flagged so the trace view marks it), then return\n // the value in the wrapped fn's call shape. fnReturnsPromise keeps a\n // sync-but-Promise-returning fn's `.then()` consumers working.\n const emitMock = (\n output: unknown,\n mockSource: MockSource,\n ): TReturn => {\n void sendSpan({\n result: output,\n mocked: true,\n mockTarget: \"output\",\n mockSource,\n })\n if (fnReturnsPromise) {\n return Promise.resolve(output) as TReturn\n }\n return output as TReturn\n }\n // Same, when the value resolves asynchronously (lazy recorded-output\n // fetch, or an async value function). A synchronous wrapped fn cannot\n // return a Promise its caller can use, so surface it under replay\n // rather than silently mis-typing the result.\n const emitMockAsync = (\n pending: Promise<unknown>,\n mockSource: MockSource,\n ): TReturn => {\n if (!fnReturnsPromise) {\n throw new BitfabError(\n `Cannot mock synchronous span \"${traceFunctionKey}\" with an ` +\n \"asynchronously-resolved value (lazy recorded-output fetch or \" +\n \"an async value function). Make the wrapped function async, or \" +\n 'use mock: \"all\" so recorded outputs are fetched eagerly.',\n )\n }\n return (async () => {\n const output = await pending\n void sendSpan({\n result: output,\n mocked: true,\n mockTarget: \"output\",\n mockSource,\n })\n return output\n })() as TReturn\n }\n // Resolve this span's recorded output. Prefer an inline output when\n // the tree carried one (eager \"all\", or an older server that ignores\n // includeOutputs and returns outputs without an externalSpanId); only\n // lazily fetch when the payload-free tree omitted it. Returns a value\n // or a Promise.\n const resolveRecordedOutput = (): unknown | Promise<unknown> => {\n const hasInlineOutput =\n mockSpan?.output !== undefined ||\n mockSpan?.outputMeta !== undefined\n if (\n !hasInlineOutput &&\n replayCtxForMock.fetchSpanOutput &&\n mockSpan?.externalSpanId\n ) {\n return replayCtxForMock.fetchSpanOutput(mockSpan.externalSpanId)\n }\n if (!mockSpan) {\n // No recorded counterpart at all (e.g. getOriginalOutput on a span\n // the changed code newly introduced).\n return Promise.reject(\n new BitfabError(\n `No recorded span to source output for \"${traceFunctionKey}\".`,\n ),\n )\n }\n let output = mockSpan.output\n if (\n mockSpan.outputMeta !== undefined &&\n mockSpan.outputMeta !== null\n ) {\n output = deserializeValue({\n json: mockSpan.output,\n meta: mockSpan.outputMeta,\n })\n }\n return output\n }\n\n const shouldMockWithBaseStrategy =\n replayCtxForMock.mockStrategy === \"all\" ||\n (replayCtxForMock.mockStrategy === \"marked\" &&\n options.mockOnReplay === true)\n\n // 1) Overrides. A resolver can decline with NO_MOCK_OVERRIDE, which\n // continues to the next override and then the base strategy.\n if (replayCtxForMock.mockOverrides?.length) {\n const nodeMeta: SpanNodeMeta = {\n traceFunctionKey,\n spanName: baseSpanParams.spanName,\n type: options.type ?? \"custom\",\n originalSpanId: mockSpan?.sourceSpanId,\n }\n const overrideCtx = {\n node: nodeMeta,\n inputs: args,\n getOriginalOutput: () => Promise.resolve(resolveRecordedOutput()),\n }\n type OverrideResolution =\n | { matched: true; output: unknown }\n | { matched: false }\n const resolveOverrideFrom = (\n startIndex: number,\n ): OverrideResolution | Promise<OverrideResolution> => {\n for (\n let index = startIndex;\n index < replayCtxForMock.mockOverrides!.length;\n index += 1\n ) {\n const override = replayCtxForMock.mockOverrides![index]\n if (!override?.match(nodeMeta)) {\n continue\n }\n const injected = resolveMockValue(override.value, overrideCtx)\n if (injected instanceof Promise) {\n return injected.then((output) =>\n output === NO_MOCK_OVERRIDE\n ? resolveOverrideFrom(index + 1)\n : { matched: true, output },\n )\n }\n if (injected !== NO_MOCK_OVERRIDE) {\n return { matched: true, output: injected }\n }\n }\n return { matched: false }\n }\n\n const resolution = resolveOverrideFrom(0)\n if (resolution instanceof Promise) {\n if (!fnReturnsPromise) {\n throw new BitfabError(\n `Cannot resolve an asynchronous mock override for synchronous span \"${traceFunctionKey}\". ` +\n \"Make the wrapped function async or return NO_MOCK_OVERRIDE synchronously.\",\n )\n }\n return runWithSpanStack(newStack, async () => {\n const resolved = await resolution\n if (resolved.matched) {\n void sendSpan({\n result: resolved.output,\n mocked: true,\n mockTarget: \"output\",\n mockSource: \"override\",\n })\n return resolved.output\n }\n if (shouldMockWithBaseStrategy && !mockSpan) {\n throw new BitfabError(\n `Replay selected span \"${traceFunctionKey}:${baseSpanParams.spanName}\" for mocking, but recorded occurrence ${callIndex + 1} is unavailable. The real span was not executed.`,\n )\n }\n if (shouldMockWithBaseStrategy) {\n const output = await resolveRecordedOutput()\n void sendSpan({\n result: output,\n mocked: true,\n mockTarget: \"output\",\n mockSource: \"recorded\",\n })\n return output\n }\n return executeWithContext()\n }) as TReturn\n }\n if (resolution.matched) {\n return emitMock(resolution.output, \"override\")\n }\n }\n\n // 2) Base strategy: replay recorded output for mocked spans.\n if (shouldMockWithBaseStrategy && !mockSpan) {\n throw new BitfabError(\n `Replay selected span \"${traceFunctionKey}:${baseSpanParams.spanName}\" for mocking, but recorded occurrence ${callIndex + 1} is unavailable. The real span was not executed.`,\n )\n }\n if (shouldMockWithBaseStrategy) {\n const recorded = resolveRecordedOutput()\n if (recorded instanceof Promise) {\n return emitMockAsync(recorded, \"recorded\")\n }\n return emitMock(recorded, \"recorded\")\n }\n }\n } catch (setupError) {\n // If this call registered root trace state before failing, remove the\n // now-orphaned entry: no span or completion will follow, so leaving it\n // would leak the maps and block that trace id's completion forever.\n if (registeredTraceId) {\n activeTraceStates.delete(registeredTraceId)\n }\n if (setupError instanceof MixedTracingError) {\n throw setupError\n }\n // During replay (a controlled eval), a setup failure must surface, not\n // silently fall through. The setup region includes the mock\n // interception: if a matched mock can't build its output (e.g.\n // deserializeValue on bad outputMeta), swallowing it would run the real\n // function - real side effects, and a skewed mock call counter - which\n // defeats replay. Re-throw so the replay runner records it as that\n // item's error. The never-crash fallback below is for production hosts.\n if (getReplayContext() || inSeedScope()) {\n throw setupError\n }\n // Tracing setup failed; run the user's function untraced so a tracing\n // failure never crashes the host app while preserving its receiver.\n warnOnce(\n `withSpan-setup:${traceFunctionKey}`,\n `tracing setup failed for \"${traceFunctionKey}\"; running it untraced. The function still runs and returns normally; no span is recorded.`,\n )\n return fn.apply(this, args) as TReturn\n }\n\n // Run OUTSIDE the setup try: a throw from the user's own function must\n // propagate unchanged and never be mistaken for a tracing failure (which\n // would double-invoke `fn`).\n return runWithSpanStack(newStack, executeWithContext)\n }\n // Mark the wrapper with its key so replay() can tell wrapped functions\n // from plain callables (which it auto-wraps) and reject key mismatches.\n Object.defineProperty(wrappedFn, \"_bitfabTraceFunctionKey\", {\n value: traceFunctionKey,\n })\n // The wrapper takes rest parameters, so its own `length` is 0 and says\n // nothing about what the traced function requires. Keep the original so\n // seedTrace can check a case against the real signature, mirroring\n // `inspect.unwrap` on the Python side.\n Object.defineProperty(wrappedFn, \"_bitfabWrappedFn\", { value: fn })\n return wrappedFn\n }\n\n /**\n * Create a standard ECMAScript method decorator that records each invocation\n * as a span.\n *\n * It supports instance, static, and private methods; use\n * {@link Bitfab.withSpan} for standalone functions, class fields, and\n * accessors.\n *\n * @example\n * ```typescript\n * const bitfab = new Bitfab({ apiKey: process.env.BITFAB_API_KEY });\n *\n * class OrderService {\n * @bitfab.span(\"order-processing\", { type: \"agent\" })\n * async process(orderId: string) {\n * return { orderId };\n * }\n * }\n * ```\n *\n * @param traceFunctionKey - A string identifier for grouping spans\n * @param options - Span configuration applied to the decorated method\n * @returns A standard ECMAScript method decorator\n */\n span(\n traceFunctionKey: string,\n options: SpanOptions = {},\n ): SpanMethodDecorator {\n return (originalMethod, context) => {\n if (context.kind !== \"method\") {\n throw new BitfabError(\n `Bitfab span decorators can only decorate methods; ${String(context.name)} is a ${context.kind}`,\n )\n }\n\n return this.withSpan(traceFunctionKey, options, originalMethod)\n }\n }\n\n /**\n * Get a detached handle to a previously-created trace, looked up by the\n * canonical Bitfab trace ID.\n *\n * The returned handle is not tied to AsyncLocalStorage - each method sends\n * to the server immediately. Useful for adding context to a trace from a\n * different process or thread than the one that created it.\n *\n * Throws synchronously if `traceId` is not a valid Bitfab trace ID. The\n * server returns 404 if no trace exists with that ID in the org; the failure surfaces as a\n * logged warning (fire-and-forget) or via the awaited promise.\n *\n * Example:\n * ```typescript\n * const trace = client.getTrace(traceId);\n * await trace.addContext({ refund_status: \"approved\" });\n * await trace.setMetadata({ region: \"us-west\" });\n * ```\n */\n getTrace(traceId: string): DetachedTrace {\n validateTraceId(traceId)\n\n return {\n traceId,\n addContext: (context: Record<string, unknown>): Promise<void> => {\n if (!this.shouldRecord()) {\n return Promise.resolve()\n }\n if (typeof context !== \"object\" || context === null) {\n return Promise.resolve()\n }\n return this.httpClient.patchTrace(traceId, {\n appendContexts: [context],\n })\n },\n setMetadata: (metadata: Record<string, unknown>): Promise<void> => {\n if (!this.shouldRecord()) {\n return Promise.resolve()\n }\n if (typeof metadata !== \"object\" || metadata === null) {\n return Promise.resolve()\n }\n return this.httpClient.patchTrace(traceId, { mergeMetadata: metadata })\n },\n setSessionId: (sessionId: string): Promise<void> => {\n if (!this.shouldRecord()) {\n return Promise.resolve()\n }\n if (typeof sessionId !== \"string\" || sessionId.length === 0) {\n return Promise.resolve()\n }\n return this.httpClient.patchTrace(traceId, { setSessionId: sessionId })\n },\n setName: (name: string): Promise<void> => {\n if (!this.shouldRecord()) {\n return Promise.resolve()\n }\n if (typeof name !== \"string\" || name.length === 0) {\n return Promise.resolve()\n }\n return this.httpClient.patchTrace(traceId, { setName: name })\n },\n }\n }\n\n /**\n * Fetch one persisted span from a trace without loading the full trace.\n * Name lookups return the last matching span by default. Pass `occurrence`\n * as `\"first\"` or a zero-based index to select a different match.\n */\n async getTraceSpan(\n traceId: string,\n lookup: SpanLookup,\n ): Promise<CapturedSpan | null> {\n validateTraceId(traceId)\n const hasId = lookup.id !== undefined\n const hasName = lookup.name !== undefined\n if (hasId === hasName) {\n throw new BitfabError(\"Provide exactly one of id or name\")\n }\n if (hasId) {\n validateSpanId(lookup.id)\n } else {\n if (lookup.name.length === 0) {\n throw new BitfabError(\"name must be a non-empty string\")\n }\n const occurrence = lookup.occurrence ?? \"last\"\n if (\n occurrence !== \"first\" &&\n occurrence !== \"last\" &&\n (!Number.isInteger(occurrence) || occurrence < 0)\n ) {\n throw new BitfabError(\n 'occurrence must be \"first\", \"last\", or a non-negative integer',\n )\n }\n }\n return this.httpClient.getTraceSpan(traceId, lookup)\n }\n\n /**\n * Get a function wrapper for a specific trace function key.\n *\n * This provides a fluent API alternative to calling withSpan directly,\n * allowing you to bind the traceFunctionKey once and wrap multiple functions.\n *\n * Example usage:\n * ```typescript\n * const client = new Bitfab({ apiKey: 'your-api-key' });\n *\n * const orderFunc = client.getFunction('order-processing');\n * const tracedProcessOrder = orderFunc.withSpan(processOrder);\n * const tracedValidateOrder = orderFunc.withSpan(validateOrder);\n * ```\n *\n * @param traceFunctionKey - A string identifier for grouping spans\n * @returns A BitfabFunction instance for wrapping functions\n */\n getFunction(traceFunctionKey: string): BitfabFunction {\n return new BitfabFunction(this, traceFunctionKey)\n }\n\n /**\n * Send trace completion when a root span ends.\n * Internal method to record trace completion with end time.\n * Queued on the client's span transport; delivery is the transport's job.\n */\n private sendTraceCompletion(params: {\n traceFunctionKey: string\n traceId: string\n startedAt: string\n endedAt: string\n sessionId?: string\n name?: string\n metadata?: Record<string, unknown>\n contexts?: ContextEntry[]\n testRunId?: string\n inputSourceTraceId?: string\n replayAttempt?: number\n dbSnapshotRef?: DbSnapshotRef\n dropped?: boolean\n ingestionType?: TraceIngestionType\n /**\n * Replay DB branch usage record, present only when a lease was\n * attached to the replay item. Serialized as `db_snapshot_usage` so\n * the server can stamp the trace's metadata at ingest.\n */\n dbSnapshotUsage?: {\n neonBranchId: string\n snapshotTimestamp?: string\n /**\n * The branch's region. Recorded so a duration gap between items can be\n * attributed to a cross-region round trip rather than to the code.\n */\n region?: string\n /** Bitfab trace id of the original trace this replay item pinned to. */\n originalTraceId?: string\n accessed: boolean\n /** Server-measured provisioning timings, echoed back verbatim. */\n timings?: DbBranchTimings\n }\n }): void {\n // Build the raw trace object for the externalTraces endpoint\n const rawTrace: Record<string, unknown> = {\n id: params.traceId,\n started_at: params.startedAt,\n ended_at: params.endedAt,\n }\n\n // Add optional fields to rawData\n if (params.name) {\n rawTrace.name = params.name\n }\n if (params.metadata && Object.keys(params.metadata).length > 0) {\n rawTrace.metadata = params.metadata\n }\n if (params.contexts && params.contexts.length > 0) {\n rawTrace.contexts = params.contexts\n }\n if (params.inputSourceTraceId) {\n rawTrace.input_source_trace_id = params.inputSourceTraceId\n }\n if (params.replayAttempt !== undefined) {\n rawTrace.replay_attempt = params.replayAttempt\n }\n if (params.dbSnapshotRef) {\n rawTrace.db_snapshot_ref = params.dbSnapshotRef\n }\n if (params.ingestionType) {\n rawTrace.ingestion_type = params.ingestionType\n }\n if (params.dbSnapshotUsage) {\n rawTrace.db_snapshot_usage = {\n neon_branch_id: params.dbSnapshotUsage.neonBranchId,\n ...(params.dbSnapshotUsage.snapshotTimestamp && {\n snapshot_timestamp: params.dbSnapshotUsage.snapshotTimestamp,\n }),\n ...(params.dbSnapshotUsage.region && {\n region: params.dbSnapshotUsage.region,\n }),\n ...(params.dbSnapshotUsage.originalTraceId && {\n original_trace_id: params.dbSnapshotUsage.originalTraceId,\n // Deprecated wire alias, kept so this SDK still reports usage\n // against servers that predate the rename.\n source_trace_id: params.dbSnapshotUsage.originalTraceId,\n }),\n accessed: params.dbSnapshotUsage.accessed,\n // Echoed verbatim (camelCase inside) rather than re-cased into this\n // record's snake_case: it is the server's own object coming back, and\n // a translation layer here is one more thing to drift.\n ...(params.dbSnapshotUsage.timings && {\n timings: params.dbSnapshotUsage.timings,\n }),\n }\n }\n\n this.httpClient.sendExternalTrace({\n id: params.traceId,\n type: \"sdk-function\",\n source: \"typescript-sdk-function\",\n traceFunctionKey: params.traceFunctionKey,\n externalTrace: rawTrace,\n completed: true,\n ...(params.dropped && { dropped: true }),\n ...(params.sessionId && { sessionId: params.sessionId }),\n ...(params.testRunId && { testRunId: params.testRunId }),\n })\n }\n\n /**\n * Send a wrapper span from function execution.\n * Internal method to record spans when using withSpan.\n * Queued on the client's span transport; delivery is the transport's job.\n */\n private sendWrapperSpan(params: {\n traceFunctionKey: string\n functionName?: string\n spanName: string\n traceId: string\n spanId: string\n parentSpanId: string | null\n inputs?: unknown[]\n result: unknown\n error?: string\n startedAt: string\n endedAt: string\n spanType: SpanType\n contexts?: ContextEntry[]\n prompt?: string\n testRunId?: string\n inputSourceSpanId?: string\n mocked?: boolean\n mockTarget?: MockTarget\n mockSource?: MockSource\n functionId?: string\n captureContent: boolean\n autoTraceDefinition?: AutoTraceFunctionDefinition\n }): void {\n const serializedInputs = params.captureContent\n ? serializeValue(params.inputs)\n : undefined\n const serializedResult = params.captureContent\n ? serializeValue(params.result)\n : undefined\n\n // Format as an external span with the wrapper format\n const externalSpan: Record<string, unknown> = {\n id: params.spanId,\n trace_id: params.traceId,\n started_at: params.startedAt,\n ended_at: params.endedAt,\n span_data: {\n name: params.spanName,\n type: params.spanType,\n ...(params.functionId !== undefined && {\n function_id: params.functionId,\n content_captured: params.captureContent,\n }),\n ...(params.autoTraceDefinition !== undefined && {\n function_file: params.autoTraceDefinition.file,\n function_line: params.autoTraceDefinition.line,\n function_column: params.autoTraceDefinition.column,\n }),\n ...(serializedInputs !== undefined && {\n input: serializedInputs.json,\n ...(serializedInputs.meta !== undefined && {\n input_meta: serializedInputs.meta,\n }),\n }),\n ...(serializedResult !== undefined && {\n output: serializedResult.json,\n ...(serializedResult.meta !== undefined && {\n output_meta: serializedResult.meta,\n }),\n }),\n ...(params.functionName !== undefined && {\n function_name: params.functionName,\n }),\n ...(params.captureContent &&\n params.error !== undefined && {\n error: params.error,\n error_source: \"code\",\n }),\n ...(params.captureContent &&\n params.contexts &&\n params.contexts.length > 0 && {\n contexts: params.contexts,\n }),\n ...(params.captureContent &&\n params.prompt !== undefined && { prompt: params.prompt }),\n },\n }\n\n // Add parent_id for nested spans\n if (params.parentSpanId) {\n externalSpan.parent_id = params.parentSpanId\n }\n if (params.inputSourceSpanId) {\n externalSpan.input_source_span_id = params.inputSourceSpanId\n }\n\n this.httpClient.sendExternalSpan({\n id: params.spanId,\n traceId: params.traceId,\n type: \"sdk-function\",\n source: \"typescript-sdk-function\",\n sourceTraceId: params.traceId,\n traceFunctionKey: params.traceFunctionKey,\n rawSpan: externalSpan,\n ...(params.testRunId && { testRunId: params.testRunId }),\n ...(params.mocked && { mocked: true }),\n ...(params.mockTarget && { mockTarget: params.mockTarget }),\n ...(params.mockSource && { mockSource: params.mockSource }),\n })\n }\n\n /**\n * Replay historical traces through a function and create a test run.\n *\n * Fetches the last N traces for the given trace function key, re-runs each\n * through the provided function, and returns comparison data.\n *\n * Accepts either a `withSpan`-wrapped function (under the same key) or any\n * plain callable: plain callables are wrapped internally so each replayed\n * invocation records a trace tied to the test run. The plain-callable form\n * is how handler-instrumented workflows (LangGraph/LangChain, Claude Agent\n * SDK) replay - those record traces under a key with no `withSpan`-wrapped\n * root in the app.\n *\n * @param traceFunctionKey - The trace function key to replay\n * @param fn - The function to run recorded inputs through\n * @param options - Optional replay options. When `traceIds` is passed,\n * `limit` is ignored (with a warning): an explicit ID list already\n * determines how many traces replay.\n * @returns ReplayResult with items, testRunId, and testRunUrl\n */\n /**\n * Register a mock override applied to every subsequent `replay` on this\n * client, so downstream real code runs against a value you supply for the\n * matched span. Instance-scoped (no global state); call {@link clearMockOverrides}\n * to reset. Per-call `replay({ mockOverride })` overrides take precedence, and\n * both take precedence over the base `mock` strategy.\n *\n * ```ts\n * // Object form (value is a flat value here)\n * bitfab.registerMockOverride({\n * match: (node) => node.traceFunctionKey === \"classify-intent\",\n * value: { label: \"refund\" },\n * })\n * // Ordered form (equivalent); value may also be a function of the context\n * bitfab.registerMockOverride(\n * (node) => node.traceFunctionKey === \"classify-intent\",\n * ({ inputs }) => ({ label: \"refund\" }),\n * )\n * // Keyed form: the resolver only sees spans for this trace function key.\n * bitfab.registerMockOverride(\"classify-intent\", ({ inputs }) => ({\n * label: String(inputs[0]),\n * }))\n * // Or one resolver for every child span:\n * bitfab.registerMockOverride(({ node }) =>\n * node.traceFunctionKey === \"classify-intent\"\n * ? { label: \"refund\" }\n * : NO_MOCK_OVERRIDE,\n * )\n * ```\n */\n registerMockOverride(override: MockOverride): void\n registerMockOverride(resolver: MockOverrideResolver): void\n registerMockOverride(match: NodeMatcher, value: MockValue): void\n registerMockOverride(\n traceFunctionKey: string,\n override: MockOverride | MockOverrideResolver,\n ): void\n registerMockOverride(\n overrideOrResolverOrMatch:\n | string\n | MockOverride\n | MockOverrideResolver\n | NodeMatcher,\n ...values: [] | [MockValue | MockOverride | MockOverrideResolver]\n ): void {\n let override: MockOverride\n if (typeof overrideOrResolverOrMatch === \"string\") {\n const keyedOverride = values[0]\n if (values.length !== 1 || keyedOverride === undefined) {\n throw new BitfabError(\n \"registerMockOverride(traceFunctionKey, override) requires a resolver function or { match, value } override.\",\n )\n }\n if (typeof keyedOverride === \"function\") {\n override = {\n match: (node) => node.traceFunctionKey === overrideOrResolverOrMatch,\n value: keyedOverride,\n }\n } else if (\n typeof keyedOverride === \"object\" &&\n keyedOverride !== null &&\n \"match\" in keyedOverride &&\n \"value\" in keyedOverride\n ) {\n override = {\n match: (node) =>\n node.traceFunctionKey === overrideOrResolverOrMatch &&\n keyedOverride.match(node),\n value: keyedOverride.value,\n }\n } else {\n throw new BitfabError(\n \"registerMockOverride(traceFunctionKey, override) requires a resolver function or { match, value } override.\",\n )\n }\n } else if (typeof overrideOrResolverOrMatch !== \"function\") {\n override = overrideOrResolverOrMatch\n } else if (values.length === 0) {\n override = { match: () => true, value: overrideOrResolverOrMatch }\n } else {\n override = {\n match: overrideOrResolverOrMatch as NodeMatcher,\n value: values[0],\n }\n }\n this.mockOverrides.push(override)\n }\n\n /** Remove all overrides registered via {@link registerMockOverride}. */\n clearMockOverrides(): void {\n this.mockOverrides.length = 0\n }\n\n seedTrace(traceFunctionKey: string, options: SeedCaseOptions): string\n seedTrace<TArgs extends unknown[], TReturn>(\n traceFunctionKey: string,\n fn: (...args: TArgs) => TReturn,\n options?: SeedRunOptions<TArgs>,\n ): Promise<string>\n seedTrace(\n traceFunctionKey: string,\n optionsOrFn: SeedCaseOptions | ((...args: never[]) => unknown),\n runOptions?: SeedRunOptions<never[]>,\n ): string | Promise<string> {\n if (typeof optionsOrFn === \"function\") {\n return this.seedTraceByRunning(traceFunctionKey, optionsOrFn, runOptions)\n }\n return this.seedTraceFromCase(traceFunctionKey, optionsOrFn)\n }\n\n private seedTraceFromCase(\n traceFunctionKey: string,\n options: SeedCaseOptions,\n ): string {\n const { input } = options\n const fn =\n (options.fn as { _bitfabWrappedFn?: (...args: unknown[]) => unknown })\n ?._bitfabWrappedFn ?? options.fn\n if (fn && input.length < fn.length) {\n throw new BitfabError(\n `Seeded case supplies ${input.length} argument(s) but ${\n fn.name === \"\" ? \"the function\" : fn.name\n } requires ${fn.length}. Fix the case, or omit fn to seed it anyway.`,\n )\n }\n\n const traceId = randomUuid()\n const startedAt = nowIsoTimestamp()\n\n activeTraceStates.set(traceId, {\n traceId,\n startedAt,\n contexts: [],\n ingestionType: \"seeded\",\n ...(options.sessionId !== undefined && { sessionId: options.sessionId }),\n ...(options.name !== undefined && { name: options.name }),\n ...(options.metadata !== undefined && { metadata: options.metadata }),\n })\n\n try {\n this.sendWrapperSpan({\n traceFunctionKey,\n spanName: options.spanName ?? traceFunctionKey,\n traceId,\n spanId: randomUuid(),\n parentSpanId: null,\n inputs: input,\n result: options.expected,\n startedAt,\n endedAt: startedAt,\n spanType: options.spanType ?? \"agent\",\n captureContent: true,\n })\n this.sendTraceCompletion({\n traceFunctionKey,\n traceId,\n startedAt,\n endedAt: startedAt,\n sessionId: options.sessionId,\n name: options.name,\n metadata: options.metadata,\n contexts: [],\n ingestionType: \"seeded\",\n })\n } finally {\n activeTraceStates.delete(traceId)\n }\n\n return traceId\n }\n\n private async seedTraceByRunning(\n traceFunctionKey: string,\n fn: (...args: never[]) => unknown,\n options?: SeedRunOptions<never[]>,\n ): Promise<string> {\n const wrappedKey = (fn as { _bitfabTraceFunctionKey?: string })\n ._bitfabTraceFunctionKey\n let target = fn\n if (wrappedKey === undefined) {\n const seedRootOptions: InternalSpanOptions = {\n name: traceFunctionKey,\n type: \"agent\",\n surface: \"neutral\",\n }\n target = this.withSpan(\n traceFunctionKey,\n seedRootOptions,\n fn as (...args: unknown[]) => unknown,\n ) as (...args: never[]) => unknown\n } else if (wrappedKey !== traceFunctionKey) {\n throw new BitfabError(\n `Function is wrapped with trace function key '${wrappedKey}' but ` +\n `seedTrace was called with '${traceFunctionKey}'. Pass matching ` +\n \"keys, or pass the unwrapped function to seed it under the \" +\n \"explicit key.\",\n )\n }\n\n await seedContextReady\n\n const traceId = randomUuid()\n activeTraceStates.set(traceId, {\n traceId,\n startedAt: nowIsoTimestamp(),\n contexts: [],\n ingestionType: \"seeded\",\n ...(options?.sessionId !== undefined && { sessionId: options.sessionId }),\n ...(options?.name !== undefined && { name: options.name }),\n ...(options?.metadata !== undefined && { metadata: options.metadata }),\n })\n\n const args = (options?.args ?? []) as never[]\n let unrecorded = true\n try {\n await runWithSeedContext({ traceId }, async () => target(...args))\n } finally {\n try {\n const { flushTraces } = await import(\"./http.js\")\n await flushTraces(30_000)\n } finally {\n unrecorded = activeTraceStates.delete(traceId)\n }\n }\n if (unrecorded) {\n throw new BitfabError(\n `seedTrace recorded nothing for '${traceFunctionKey}': the call ` +\n \"finished without a root span. Check that an API key resolves \" +\n \"(BITFAB_API_KEY or apiKey), and that fn is a regular or async \" +\n \"function rather than a generator.\",\n )\n }\n return traceId\n }\n\n async replay<TReturn>(\n traceFunctionKey: string,\n // biome-ignore lint/suspicious/noExplicitAny: replay deserializes inputs from historical data, typed args would be incorrect\n fn: (...args: any[]) => TReturn | Promise<TReturn>,\n options?: ReplayOptions,\n ): Promise<ReplayResult<TReturn>> {\n const wrappedKey = (fn as { _bitfabTraceFunctionKey?: string })\n ._bitfabTraceFunctionKey\n let replayFn = fn\n if (wrappedKey === undefined) {\n // Name the root span after the key (not the callable's name) so it\n // matches the production root span: handler-instrumented roots (Claude\n // Agent SDK, OpenAI Agents) are named after the trace function key, so\n // naming the auto-wrap after fn.name would make the replayed root read\n // differently from the trace it replays.\n const replayRootOptions: InternalSpanOptions = {\n name: traceFunctionKey,\n type: \"agent\",\n surface: \"neutral\",\n }\n replayFn = this.withSpan(traceFunctionKey, replayRootOptions, fn)\n } else if (wrappedKey !== traceFunctionKey) {\n throw new BitfabError(\n `Function is wrapped with trace function key '${wrappedKey}' but ` +\n `replay was called with '${traceFunctionKey}'. Pass matching keys, ` +\n \"or pass the unwrapped function to replay it under the explicit key.\",\n )\n }\n const { replay: doReplay } = await import(\"./replay.js\")\n return doReplay(\n this.httpClient,\n this.serviceUrl,\n traceFunctionKey,\n replayFn,\n options,\n this.mockOverrides,\n )\n }\n}\n\n/**\n * Represents a Bitfab function that can wrap user functions for tracing.\n *\n * This provides a fluent API for binding a traceFunctionKey once and\n * then wrapping multiple functions with that key.\n *\n * Example usage:\n * ```typescript\n * const client = new Bitfab({ apiKey: 'your-api-key' });\n *\n * const orderFunc = client.getFunction('order-processing');\n * const tracedProcessOrder = orderFunc.withSpan(processOrder);\n * const tracedValidateOrder = orderFunc.withSpan(validateOrder);\n * ```\n */\nexport class BitfabFunction {\n constructor(\n private readonly client: Bitfab,\n private readonly traceFunctionKey: string,\n ) {}\n\n /**\n * Wrap a function to automatically create a span for its inputs and outputs.\n *\n * The wrapped function behaves identically to the original, but sends\n * span data to Bitfab in the background after each call.\n *\n * Example usage:\n * ```typescript\n * const orderFunc = client.getFunction('order-processing');\n *\n * // Basic usage (defaults to \"custom\" span type)\n * const tracedProcessOrder = orderFunc.withSpan(processOrder);\n *\n * // With explicit span type\n * const tracedProcessOrder = orderFunc.withSpan({ type: 'function' }, processOrder);\n * ```\n *\n * @param optionsOrFn - Either SpanOptions or the function to wrap\n * @param maybeFn - The function to wrap if options were provided\n * @returns A wrapped function with the same signature that creates spans\n */\n withSpan<TArgs extends unknown[], TReturn>(\n optionsOrFn: SpanOptions | ((...args: TArgs) => TReturn),\n maybeFn?: (...args: TArgs) => TReturn,\n ): (...args: TArgs) => TReturn {\n // Handle overloaded signature\n const options: SpanOptions =\n typeof optionsOrFn === \"function\" ? {} : optionsOrFn\n const fn: (...args: TArgs) => TReturn =\n typeof optionsOrFn === \"function\" ? optionsOrFn : maybeFn!\n\n return this.client.withSpan(this.traceFunctionKey, options, fn)\n }\n\n /**\n * Create a standard ECMAScript method decorator bound to this function key.\n *\n * @example\n * ```typescript\n * const orders = client.getFunction(\"order-processing\");\n *\n * class OrderService {\n * @orders.span({ type: \"agent\" })\n * async process(orderId: string) {\n * return { orderId };\n * }\n * }\n * ```\n *\n * @param options - Span configuration applied to the decorated method\n * @returns A standard ECMAScript method decorator\n */\n span(options: SpanOptions = {}): SpanMethodDecorator {\n return this.client.span(this.traceFunctionKey, options)\n }\n\n /**\n * Get a Vercel AI SDK language-model middleware bound to this function's key.\n *\n * Equivalent to `client.getVercelAiMiddleware(key)` but reuses the key bound\n * on this handle, so an outer `withSpan` root and the middleware-traced model\n * calls share one key without repeating the string. With a matching key, the\n * outer span is the replayable root and the model-call spans nest beneath it.\n *\n * Nesting is captured when the model is called, so keep the\n * `generateText` / `streamText` call inside this handle's `withSpan`; the\n * middleware object itself can be created anywhere.\n *\n * ```typescript\n * const chatTurn = client.getFunction(\"chat-turn\");\n * const runChatTurn = chatTurn.withSpan(\n * { type: \"agent\", finalize: finalizers.aiSdk },\n * (messages) => streamText({ model, messages }),\n * );\n * const model = wrapLanguageModel({\n * model: openai(\"gpt-4o\"),\n * middleware: chatTurn.getVercelAiMiddleware(),\n * });\n * ```\n *\n * @returns A Vercel AI SDK middleware configured for this client and key\n */\n getVercelAiMiddleware() {\n return this.client.getVercelAiMiddleware(this.traceFunctionKey)\n }\n\n /**\n * Get a Claude Agent SDK handler bound to this function's key.\n *\n * Equivalent to `client.getClaudeAgentHandler(key)` but reuses the key bound\n * on this handle, so an outer `withSpan` root and the handler share one key\n * without repeating the string. With a matching key, the outer span is the\n * replayable root and every handler span nests beneath it.\n *\n * Use the handler inside this handle's `withSpan` body so its spans capture\n * the enclosing root; framework calls made with no active span record their\n * own root instead.\n *\n * ```typescript\n * const pipeline = client.getFunction(\"my-agent\");\n * const tracedRun = pipeline.withSpan({ type: \"agent\" }, async (prompt) => {\n * const handler = pipeline.getClaudeAgentHandler();\n * const options = handler.instrumentOptions({ model: \"claude-sonnet-4-6\" });\n * for await (const msg of handler.wrapQuery(query({ prompt, options }))) { ... }\n * });\n * ```\n *\n * @returns A Claude Agent SDK handler configured for this client and key\n */\n getClaudeAgentHandler() {\n return this.client.getClaudeAgentHandler(this.traceFunctionKey)\n }\n\n /**\n * Get a LangGraph/LangChain callback handler bound to this function's key.\n *\n * Equivalent to `client.getLangGraphCallbackHandler(key)` but reuses the key\n * bound on this handle, so an outer `withSpan` root and the handler share one\n * key without repeating the string. With a matching key, the outer span is\n * the replayable root and the LangGraph spans nest beneath it.\n *\n * Use the handler inside this handle's `withSpan` body so its spans capture\n * the enclosing root; framework calls made with no active span record their\n * own root instead.\n *\n * ```typescript\n * const pipeline = client.getFunction(\"my-pipeline\");\n * const tracedRun = pipeline.withSpan({ type: \"agent\" }, async (query) => {\n * const handler = pipeline.getLangGraphCallbackHandler();\n * return agent.invoke({ messages: [...] }, { callbacks: [handler] });\n * });\n * ```\n *\n * @returns A LangGraph/LangChain callback handler for this client and key\n */\n getLangGraphCallbackHandler() {\n return this.client.getLangGraphCallbackHandler(this.traceFunctionKey)\n }\n\n /**\n * Alias of {@link getLangGraphCallbackHandler} - LangChain and LangGraph\n * share one callback system, so the same bound handler serves both.\n *\n * @returns A LangChain callback handler for this client and key\n */\n getLangChainCallbackHandler() {\n return this.client.getLangChainCallbackHandler(this.traceFunctionKey)\n }\n\n /**\n * Get the first-class LangGraph tool replay integration bound to this key.\n *\n * @experimental This API may change before it is stable.\n */\n getLangGraphIntegration(options?: LangGraphIntegrationOptions) {\n return this.client.getLangGraphIntegration(this.traceFunctionKey, options)\n }\n\n /**\n * Wrap a BAML client method to automatically capture prompt and LLM metadata.\n * Delegates to the parent client's wrapBAML method.\n *\n * Unlike the other methods on this handle, `wrapBAML` does NOT use the bound\n * key: it opens no span of its own. It enriches the *current* span (via\n * `getCurrentSpan().setPrompt()` / `addContext()`), so call it inside a\n * function wrapped by this handle's `withSpan` - the bound key keys that\n * wrapper, and the BAML prompt/metadata attach to it.\n *\n * @param methodOrClient - Either a BAML method (uses constructor bamlClient) or the BAML client instance\n * @param maybeMethodOrOptions - The BAML method when the first argument is a client, or WrapBAMLOptions when the first argument is the method\n * @param maybeOptions - WrapBAMLOptions when using the two-argument (client, method) form\n * @returns An async function with the same signature that instruments the BAML call\n */\n wrapBAML<TArgs extends unknown[], TReturn>(\n methodOrClient: unknown,\n maybeMethodOrOptions?:\n | ((...args: TArgs) => Promise<TReturn>)\n | WrapBAMLOptions,\n maybeOptions?: WrapBAMLOptions,\n ): WrappedBamlFn<TArgs, TReturn> {\n return this.client.wrapBAML(\n methodOrClient,\n maybeMethodOrOptions,\n maybeOptions,\n )\n }\n}\n","import {\n type AsyncLocalStorageLike,\n createAsyncLocalStorage,\n} from \"./asyncStorage.js\"\n\nexport interface AutoTraceFunctionDefinition {\n id: string\n name: string\n file: string\n line: number\n column: number\n async?: boolean\n wrapper?: boolean\n}\n\nexport interface AutoTraceNodeConfiguration {\n functionName: string\n name?: string\n type?: \"llm\" | \"agent\" | \"function\" | \"guardrail\" | \"handoff\" | \"custom\"\n capture: boolean\n testRunId?: string\n mockOnReplay?: boolean\n // biome-ignore lint/suspicious/noExplicitAny: node finalizers receive the configured function's result, whose type is owned by the caller\n finalize?: (result: any) => unknown | Promise<unknown>\n}\n\nexport interface AutoTraceContext {\n invoke<T>(\n definition: AutoTraceFunctionDefinition,\n inputs: unknown[],\n fn: () => T,\n depth: number,\n nodeConfiguration?: AutoTraceNodeConfiguration,\n ): T\n}\n\ninterface AutoTraceScope {\n context: AutoTraceContext\n depth: number\n nodeConfiguration?: AutoTraceNodeConfiguration\n}\n\ninterface AutoTraceState {\n storage: AsyncLocalStorageLike<AutoTraceScope> | null\n browserScope: AutoTraceScope | undefined\n capturePolicies: WeakMap<object, Map<string, ReadonlySet<string>>>\n activeRoots: number\n}\n\ninterface AutoTraceGlobal {\n __bitfabAutoTraceStateV3?: AutoTraceState\n}\n\ninterface AutoTraceAsyncGenerator {\n next(value?: unknown): Promise<IteratorResult<unknown, unknown>>\n return(value?: unknown): Promise<IteratorResult<unknown, unknown>>\n throw(error?: unknown): Promise<IteratorResult<unknown, unknown>>\n [Symbol.asyncIterator](): AutoTraceAsyncGenerator\n}\n\nconst autoTraceGlobal = globalThis as unknown as AutoTraceGlobal\nconst autoTraceState: AutoTraceState =\n autoTraceGlobal.__bitfabAutoTraceStateV3 ?? {\n storage: null,\n browserScope: undefined,\n capturePolicies: new WeakMap(),\n activeRoots: 0,\n }\nautoTraceGlobal.__bitfabAutoTraceStateV3 = autoTraceState\n\nfunction initializeAutoTraceStorage(): void {\n autoTraceState.storage ??= createAsyncLocalStorage<AutoTraceScope>()\n}\n\nexport function runWithAutoTraceContext<T>(\n context: AutoTraceContext,\n fn: () => T,\n depth = 0,\n): T {\n initializeAutoTraceStorage()\n const scope = { context, depth }\n if (autoTraceState.storage) {\n return autoTraceState.storage.run(scope, fn)\n }\n\n const previous = autoTraceState.browserScope\n autoTraceState.browserScope = scope\n try {\n return fn()\n } finally {\n autoTraceState.browserScope = previous\n }\n}\n\nexport function runWithAutoTraceNodeConfiguration<T>(\n nodeConfiguration: AutoTraceNodeConfiguration,\n fn: () => T,\n): T {\n const scope = currentAutoTraceScope()\n if (!scope) {\n return fn()\n }\n\n const configuredScope = { ...scope, nodeConfiguration }\n let result: T\n if (autoTraceState.storage) {\n result = autoTraceState.storage.run(configuredScope, fn)\n } else {\n const previous = autoTraceState.browserScope\n autoTraceState.browserScope = configuredScope\n try {\n result = fn()\n } finally {\n autoTraceState.browserScope = previous\n }\n }\n\n if (isAutoTraceAsyncGenerator(result)) {\n return wrapAutoTraceNodeAsyncGenerator(nodeConfiguration, result) as T\n }\n return result\n}\n\nexport function runWithAutoTraceRootContext<T>(\n context: AutoTraceContext,\n fn: () => T,\n): T {\n autoTraceState.activeRoots += 1\n let result: T\n try {\n result = runWithAutoTraceContext(context, fn)\n } catch (error) {\n autoTraceState.activeRoots -= 1\n throw error\n }\n\n if (isAutoTraceAsyncGenerator(result)) {\n autoTraceState.activeRoots -= 1\n return wrapAutoTraceAsyncGenerator(context, result) as T\n }\n\n if (result instanceof Promise) {\n return result.finally(() => {\n autoTraceState.activeRoots -= 1\n }) as T\n }\n\n autoTraceState.activeRoots -= 1\n return result\n}\n\nfunction isAutoTraceAsyncGenerator(\n value: unknown,\n): value is AutoTraceAsyncGenerator {\n if (value === null || typeof value !== \"object\") {\n return false\n }\n const candidate = value as Record<PropertyKey, unknown>\n return (\n typeof candidate.next === \"function\" &&\n typeof candidate.return === \"function\" &&\n typeof candidate.throw === \"function\" &&\n typeof candidate[Symbol.asyncIterator] === \"function\"\n )\n}\n\nfunction wrapAutoTraceAsyncGenerator(\n context: AutoTraceContext,\n source: AutoTraceAsyncGenerator,\n): AutoTraceAsyncGenerator {\n const step = (\n method: \"next\" | \"return\" | \"throw\",\n value?: unknown,\n ): Promise<IteratorResult<unknown, unknown>> =>\n runWithAutoTraceRootContext(context, () => source[method](value))\n const wrapped: AutoTraceAsyncGenerator = {\n next: (value) => step(\"next\", value),\n return: (value) => step(\"return\", value),\n throw: (error) => step(\"throw\", error),\n [Symbol.asyncIterator]: () => wrapped,\n }\n return wrapped\n}\n\nfunction wrapAutoTraceNodeAsyncGenerator(\n nodeConfiguration: AutoTraceNodeConfiguration,\n source: AutoTraceAsyncGenerator,\n): AutoTraceAsyncGenerator {\n const step = (\n method: \"next\" | \"return\" | \"throw\",\n value?: unknown,\n ): Promise<IteratorResult<unknown, unknown>> =>\n runWithAutoTraceNodeConfiguration(nodeConfiguration, () =>\n source[method](value),\n )\n const wrapped: AutoTraceAsyncGenerator = {\n next: (value) => step(\"next\", value),\n return: (value) => step(\"return\", value),\n throw: (error) => step(\"throw\", error),\n [Symbol.asyncIterator]: () => wrapped,\n }\n return wrapped\n}\n\nexport function __bitfabAutoSpan<T>(\n definition: AutoTraceFunctionDefinition,\n inputs: unknown[],\n fn: () => T,\n): T {\n const scope = currentAutoTraceScope()\n if (!scope) {\n return fn()\n }\n const nameParts = definition.name.split(\".\")\n const simpleName = nameParts[nameParts.length - 1]\n const nodeConfiguration =\n simpleName === scope.nodeConfiguration?.functionName\n ? scope.nodeConfiguration\n : undefined\n return scope.context.invoke(\n definition,\n inputs,\n fn,\n scope.depth,\n nodeConfiguration,\n )\n}\n\n/**\n * Preserve a function's original call arguments for transform cases where\n * parameter bindings discard them, such as destructured arrow parameters.\n *\n * This helper is internal transform/runtime protocol. The proxy preserves the\n * target's callability, arity, async identity, and non-constructibility while\n * only allocating a trace closure beneath an active automatic trace root.\n *\n * @experimental The automatic tracing protocol may change.\n */\nexport function __bitfabAutoWrap<T extends (...args: never[]) => unknown>(\n definition: AutoTraceFunctionDefinition,\n fn: T,\n): T {\n if (fn.name === \"\") {\n const nameParts = definition.name.split(\".\")\n const inferredName = nameParts[nameParts.length - 1]\n if (inferredName !== undefined) {\n Object.defineProperty(fn, \"name\", {\n configurable: true,\n value: inferredName,\n })\n }\n }\n\n const target = fn as unknown as (...args: unknown[]) => unknown\n return new Proxy(target, {\n apply(callTarget, thisArg, args) {\n if (!__bitfabAutoTraceActive()) {\n return Reflect.apply(callTarget, thisArg, args)\n }\n return __bitfabAutoSpan(definition, args, () =>\n Reflect.apply(callTarget, thisArg, args),\n )\n },\n }) as unknown as T\n}\n\n/**\n * Return whether the current call is inside an automatic trace root.\n *\n * Build transforms use this before allocating function metadata, captured\n * inputs, or an invocation closure. It is internal transform/runtime protocol,\n * not a supported application API.\n *\n * @experimental The automatic tracing protocol may change.\n */\nexport function __bitfabAutoTraceActive(): boolean {\n if (autoTraceState.activeRoots === 0) {\n return false\n }\n return currentAutoTraceScope() !== undefined\n}\n\nfunction currentAutoTraceScope(): AutoTraceScope | undefined {\n initializeAutoTraceStorage()\n return autoTraceState.storage?.getStore() ?? autoTraceState.browserScope\n}\n\nexport function __setBitfabAutoTraceCapturePolicy(\n client: object,\n traceFunctionKey: string,\n functionIds: Iterable<string> | undefined,\n): void {\n const policies = autoTraceState.capturePolicies.get(client) ?? new Map()\n if (functionIds === undefined) {\n policies.delete(traceFunctionKey)\n if (policies.size === 0) {\n autoTraceState.capturePolicies.delete(client)\n }\n return\n }\n policies.set(traceFunctionKey, new Set(functionIds))\n autoTraceState.capturePolicies.set(client, policies)\n}\n\nexport function getAutoTraceCapturePolicy(\n client: object,\n traceFunctionKey: string,\n): ReadonlySet<string> | undefined {\n return autoTraceState.capturePolicies.get(client)?.get(traceFunctionKey)\n}\n","/**\n * Import an OPTIONAL peer dependency without breaking a consumer's bundler.\n *\n * Optional peers (declared in this package's `peerDependenciesMeta` with\n * `optional: true` - e.g. `@openai/agents`, `@boundaryml/baml`) are absent by\n * design for most consumers: someone who only uses the Vercel AI integration\n * never installs `@openai/agents`, and someone who never calls `Bitfab.call()`\n * never installs `@boundaryml/baml`.\n *\n * A plain `import(\"@openai/agents\")` leaves a static, literal specifier in the\n * built SDK. A consumer's bundler (webpack, Turbopack, Vite, Rollup, esbuild)\n * statically analyses that specifier and tries to resolve it at *build* time,\n * failing the whole build with \"Module not found: Can't resolve\n * '@openai/agents'\" even though that code path never runs for that consumer.\n * Wrapping the import in try/catch is not enough: only webpack >= 5.90.2 treats\n * that as optional, and Turbopack/Vite/older webpack do not.\n *\n * The robust, bundler-agnostic fix is to keep the specifier out of static\n * analysis entirely. The caller passes the specifier as parts that are joined\n * at runtime, so no bundler can see a literal module name to resolve. The\n * `webpackIgnore` / `@vite-ignore` magic comments are belt-and-suspenders for\n * bundlers that still inspect the (now non-literal) request. This mirrors the\n * technique already used for `node:async_hooks` in `asyncStorage.ts`.\n *\n * The import stays a native runtime `import()`: it resolves from `node_modules`\n * when the peer IS installed, and throws an ordinary module-not-found error\n * only when the feature is actually used without its peer installed - which is\n * the correct behaviour (the caller opted into an integration whose peer they\n * chose not to install).\n *\n * @param specifierParts - The package specifier split so it is reconstructed at\n * runtime, never appearing as a literal (e.g. `[\"@openai\", \"agents\"]` ->\n * `\"@openai/agents\"`).\n */\nexport function importOptionalPeer<T = unknown>(\n specifierParts: readonly string[],\n): Promise<T> {\n // Reconstructed at runtime so no bundler sees a literal specifier to resolve.\n const specifier = specifierParts.join(\"/\")\n return import(\n /* webpackIgnore: true */ /* @vite-ignore */ specifier\n ) as Promise<T>\n}\n","/**\n * BAML execution utilities for the Bitfab TypeScript SDK.\n * This module provides functions to execute BAML prompts dynamically on the client side.\n */\n\nimport { importOptionalPeer } from \"./optionalPeer.js\"\n\ntype BamlModule = typeof import(\"@boundaryml/baml\")\n\nlet cachedBaml: BamlModule | null = null\n\nasync function loadBaml(): Promise<BamlModule> {\n if (cachedBaml) {\n return cachedBaml\n }\n try {\n // Reconstructed specifier (see importOptionalPeer): keeps a consumer's\n // bundler from trying to resolve `@boundaryml/baml` at build time when it\n // is not installed (it is an optional peer, only needed for Bitfab.call()).\n cachedBaml = await importOptionalPeer<BamlModule>([\"@boundaryml\", \"baml\"])\n return cachedBaml\n } catch {\n throw new Error(\n \"@boundaryml/baml is required for Bitfab.call(). Install it with: npm install @boundaryml/baml\",\n )\n }\n}\n\n/**\n * Provider definition from the server.\n */\nexport interface ProviderDefinition {\n provider: string\n apiKeyEnv: string\n models: Array<{\n model: string\n description: string\n }>\n}\n\n/**\n * Result of a BAML function execution with raw collector data.\n */\nexport interface BamlExecutionResult {\n /** The parsed result of the function */\n result: unknown\n /** Raw collector data for the server to parse */\n rawCollector: Record<string, unknown> | null\n}\n\n/**\n * Capitalize first letter of a string.\n */\nfunction capitalize(str: string): string {\n return str.charAt(0).toUpperCase() + str.slice(1)\n}\n\n/**\n * Convert provider name to PascalCase.\n * e.g., \"openai\" -> \"OpenAI\", \"anthropic\" -> \"Anthropic\"\n */\nfunction formatProvider(provider: string): string {\n const providerMap: Record<string, string> = {\n openai: \"OpenAI\",\n anthropic: \"Anthropic\",\n google: \"Google\",\n }\n return providerMap[provider] ?? capitalize(provider)\n}\n\n/**\n * Convert a model name to a valid BAML identifier part.\n * e.g., \"gpt-5-mini\" -> \"GPT5_mini\", \"gpt-4.1\" -> \"GPT4_1\"\n */\nfunction formatModel(model: string): string {\n return model\n .replace(/^gpt-/, \"GPT\") // gpt- prefix -> GPT\n .replace(/\\./g, \"_\") // dots -> underscore\n .replace(/-/g, \"_\") // hyphens -> underscore\n}\n\n/**\n * Generate the BAML client name from provider and model.\n * e.g., \"openai\" + \"gpt-4.1-mini\" -> \"OpenAI_GPT4_1_mini\"\n */\nexport function getClientName(provider: string, model: string): string {\n return `${formatProvider(provider)}_${formatModel(model)}`\n}\n\n/**\n * Generates BAML client definition strings.\n * BamlRuntime.fromFiles requires clients to be defined in source for parsing.\n */\nfunction generateClientDefinitions(providers: ProviderDefinition[]): string {\n const definitions: string[] = []\n\n for (const providerDef of providers) {\n for (const model of providerDef.models) {\n const clientName = getClientName(providerDef.provider, model.model)\n const temperatureOption = supportsTemperatureZero(\n providerDef.provider,\n model.model,\n )\n ? \"\\n temperature 0\"\n : \"\"\n definitions.push(`client<llm> ${clientName} {\n provider ${providerDef.provider}\n options {\n model \"${model.model}\"\n api_key env.${providerDef.apiKeyEnv}${temperatureOption}\n }\n}`)\n }\n }\n\n return definitions.join(\"\\n\\n\")\n}\n\nfunction supportsTemperatureZero(provider: string, model: string): boolean {\n return (\n provider === \"openai\" &&\n (model.startsWith(\"gpt-4.1\") || model.startsWith(\"gpt-4o\"))\n )\n}\n\n/**\n * Prepends the default client definitions to a BAML source if it doesn't already define them.\n */\nfunction withDefaultClients(\n bamlSource: string,\n providers: ProviderDefinition[],\n): string {\n const hasDefaultClient = bamlSource.includes(\"client<llm> OpenAI_\")\n if (hasDefaultClient) {\n return bamlSource\n }\n const defaultClients = generateClientDefinitions(providers)\n return `${defaultClients}\\n\\n${bamlSource}`\n}\n\n/**\n * Extracts the first function name from BAML source code.\n */\nfunction extractFunctionName(bamlSource: string): string | null {\n const match = bamlSource.match(/function\\s+(\\w+)\\s*\\(/)\n return match?.[1] ?? null\n}\n\n/**\n * Parameter type information extracted from BAML function signature.\n */\nexport interface BamlParameterType {\n name: string\n type: string\n isOptional: boolean\n}\n\n/**\n * Extracts function parameter names and types from BAML source code.\n * Used to properly coerce inputs based on expected types.\n */\nexport function extractFunctionParameters(\n bamlSource: string,\n): BamlParameterType[] {\n const functionMatch = bamlSource.match(/function\\s+\\w+\\s*\\(([^)]*)\\)\\s*->/)\n if (!functionMatch) {\n return []\n }\n\n const paramsString = functionMatch[1].trim()\n if (!paramsString) {\n return []\n }\n\n const params: BamlParameterType[] = []\n const paramParts = splitParameters(paramsString)\n\n for (const part of paramParts) {\n const trimmed = part.trim()\n if (!trimmed) {\n continue\n }\n\n const paramMatch = trimmed.match(/^(\\w+)\\s*:\\s*(.+)$/)\n if (paramMatch) {\n const name = paramMatch[1]\n let type = paramMatch[2].trim()\n const isOptional = type.endsWith(\"?\")\n if (isOptional) {\n type = type.slice(0, -1)\n }\n params.push({ name, type, isOptional })\n }\n }\n\n return params\n}\n\n/**\n * Split parameter string by commas, respecting nested angle brackets.\n */\nfunction splitParameters(paramsString: string): string[] {\n const parts: string[] = []\n let current = \"\"\n let depth = 0\n\n for (const char of paramsString) {\n if (char === \"<\") {\n depth++\n current += char\n } else if (char === \">\") {\n depth--\n current += char\n } else if (char === \",\" && depth === 0) {\n parts.push(current)\n current = \"\"\n } else {\n current += char\n }\n }\n\n if (current.trim()) {\n parts.push(current)\n }\n\n return parts\n}\n\n/**\n * Coerce a single string value to the expected BAML type.\n * Returns the coerced value, or the original string if coercion fails.\n */\nfunction coerceToType(value: string, expectedType: string): unknown {\n // String type - keep as is\n if (expectedType === \"string\") {\n return value\n }\n\n // Integer type\n if (expectedType === \"int\") {\n const parsed = Number.parseInt(value, 10)\n if (!Number.isNaN(parsed)) {\n return parsed\n }\n return value\n }\n\n // Float type\n if (expectedType === \"float\") {\n const parsed = Number.parseFloat(value)\n if (!Number.isNaN(parsed)) {\n return parsed\n }\n return value\n }\n\n // Boolean type\n if (expectedType === \"bool\") {\n const lower = value.toLowerCase()\n if (lower === \"true\") {\n return true\n }\n if (lower === \"false\") {\n return false\n }\n return value\n }\n\n // Array types (e.g., string[], int[])\n if (expectedType.endsWith(\"[]\")) {\n try {\n const parsed = JSON.parse(value)\n if (Array.isArray(parsed)) {\n return parsed\n }\n } catch {\n // Not valid JSON array\n }\n return value\n }\n\n // Complex types (objects, classes, maps) - try JSON parse\n try {\n return JSON.parse(value)\n } catch {\n return value\n }\n}\n\n/**\n * Coerces input values from strings to their appropriate types based on expected BAML types.\n * Actively coerces to the expected type (int, float, bool, etc.) rather than just avoiding\n * unintended conversions.\n */\nfunction coerceInputs(\n inputs: Record<string, unknown>,\n expectedTypes: Map<string, string>,\n): Record<string, unknown> {\n const coerced: Record<string, unknown> = {}\n\n for (const [key, value] of Object.entries(inputs)) {\n if (typeof value === \"string\") {\n const expectedType = expectedTypes.get(key)\n\n if (expectedType) {\n coerced[key] = coerceToType(value, expectedType)\n } else {\n // No expected type info - keep as string\n coerced[key] = value\n }\n } else {\n coerced[key] = value\n }\n }\n\n return coerced\n}\n\n/**\n * Recursively convert an object to a JSON-serializable structure.\n * Similar to Python's _obj_to_dict function.\n */\nfunction objToDict(obj: unknown, depth = 0, maxDepth = 5): unknown {\n if (depth > maxDepth) {\n return `<max depth reached: ${typeof obj}>`\n }\n\n // Handle primitives\n if (\n obj === null ||\n obj === undefined ||\n typeof obj === \"string\" ||\n typeof obj === \"number\" ||\n typeof obj === \"boolean\"\n ) {\n return obj\n }\n\n // Handle arrays\n if (Array.isArray(obj)) {\n return obj.map((item) => objToDict(item, depth + 1, maxDepth))\n }\n\n // Handle plain objects and class instances\n if (typeof obj === \"object\") {\n const result: Record<string, unknown> = {}\n\n // Add type information for non-plain objects\n if (obj.constructor && obj.constructor.name !== \"Object\") {\n result.__type__ = obj.constructor.name\n }\n\n // Extract all enumerable properties\n for (const key of Object.keys(obj)) {\n if (key.startsWith(\"_\")) {\n continue // Skip private properties\n }\n\n try {\n const value = (obj as Record<string, unknown>)[key]\n\n // Skip functions\n if (typeof value === \"function\") {\n continue\n }\n\n result[key] = objToDict(value, depth + 1, maxDepth)\n } catch (error) {\n result[key] =\n `<error: ${error instanceof Error ? error.message : String(error)}>`\n }\n }\n\n // Also try to get non-enumerable properties from the prototype\n // This helps capture getters and computed properties\n try {\n const proto = Object.getPrototypeOf(obj)\n if (proto && proto !== Object.prototype) {\n const descriptors = Object.getOwnPropertyDescriptors(proto)\n for (const [key, descriptor] of Object.entries(descriptors)) {\n if (key.startsWith(\"_\") || key === \"constructor\" || key in result) {\n continue\n }\n\n // Try to get the value if it has a getter\n if (descriptor.get) {\n try {\n const value = (obj as Record<string, unknown>)[key]\n if (typeof value !== \"function\") {\n result[key] = objToDict(value, depth + 1, maxDepth)\n }\n } catch {\n // Getter might throw or be inaccessible\n }\n }\n }\n }\n } catch {\n // Prototype inspection might fail\n }\n\n return result\n }\n\n // Fallback for other types\n return String(obj)\n}\n\n/**\n * Serialize the BAML Collector to a JSON-serializable structure.\n * Recursively extracts all properties from the Collector for server-side parsing.\n */\nfunction serializeCollector(\n collector: unknown,\n): Record<string, unknown> | null {\n try {\n return objToDict(collector, 0, 5) as Record<string, unknown>\n } catch (_error) {\n // Silently ignore serialization failures\n return null\n }\n}\n\n/**\n * Allowed environment variable keys for LLM providers.\n * Only these keys will be passed to the BAML runtime.\n */\nconst ALLOWED_ENV_KEYS = [\"OPENAI_API_KEY\"] as const\n\n/**\n * Type for allowed environment variables.\n * Only OPENAI_API_KEY is currently supported.\n */\nexport type AllowedEnvVars = {\n OPENAI_API_KEY?: string\n}\n\n/**\n * Filters environment variables to only include allowed keys.\n * This prevents accidentally passing sensitive environment variables to the BAML runtime.\n */\nfunction filterEnvVars(envVars: AllowedEnvVars): Record<string, string> {\n const filtered: Record<string, string> = {}\n for (const key of ALLOWED_ENV_KEYS) {\n const value = envVars[key]\n if (value) {\n filtered[key] = value\n }\n }\n return filtered\n}\n\n/**\n * Runs the BAML function with the given inputs using the BAML runtime directly.\n * No file generation or subprocess spawning needed.\n *\n * @param bamlSource - The BAML source code containing the function\n * @param inputs - Named arguments to pass to the function\n * @param providers - Available provider definitions\n * @param envVars - Environment variables for API keys (only OPENAI_API_KEY is allowed)\n * @returns The result and execution metadata of the BAML function call\n */\nexport async function runFunctionWithBaml(\n bamlSource: string,\n inputs: Record<string, unknown>,\n providers: ProviderDefinition[],\n envVars: AllowedEnvVars,\n): Promise<BamlExecutionResult> {\n const { BamlRuntime, Collector } = await loadBaml()\n\n // Extract function name from the BAML source\n const functionName = extractFunctionName(bamlSource)\n if (!functionName) {\n throw new Error(\"No function found in BAML source\")\n }\n\n // Add default client definitions (runtime needs them for parsing)\n const fullSource = withDefaultClients(bamlSource, providers)\n\n // Filter env vars to only allowed keys\n const filteredEnvVars = filterEnvVars(envVars)\n\n // Create runtime from source with env vars\n const runtime = BamlRuntime.fromFiles(\n \"/tmp/baml_runtime\",\n { \"source.baml\": fullSource },\n filteredEnvVars,\n )\n\n // Create context manager\n const ctx = runtime.createContextManager()\n\n // Create collector to capture execution metadata\n const collector = new Collector(\"bitfab-collector\")\n\n // Extract expected parameter types from BAML source\n const params = extractFunctionParameters(bamlSource)\n const expectedTypes = new Map(params.map((p) => [p.name, p.type]))\n\n // Coerce inputs from strings to proper types based on BAML signature\n const args = coerceInputs(inputs, expectedTypes)\n\n // Call the function with collector\n const functionResult = await runtime.callFunction(\n functionName,\n args,\n ctx,\n null, // TypeBuilder\n null, // ClientRegistry\n [collector], // Collectors - capture execution data\n {}, // Tags\n filteredEnvVars,\n )\n\n if (!functionResult.isOk()) {\n throw new Error(\"BAML function execution failed\")\n }\n\n // Serialize the collector to a dict for the server to parse\n const rawCollector = serializeCollector(collector)\n\n return {\n result: functionResult.parsed(false),\n rawCollector,\n }\n}\n","import { MixedTracingError } from \"./errors.js\"\n\nexport type CaptureSurface = \"opt-in\" | \"opt-out\"\n\nexport type SurfaceRequest = CaptureSurface | \"inherit\" | \"neutral\"\n\nexport const DEFAULT_SURFACE: CaptureSurface = \"opt-in\"\n\nconst SURFACE_API: Record<CaptureSurface, string> = {\n \"opt-in\": \"withSpan()\",\n \"opt-out\": \"withTrace()\",\n}\n\nconst MIXED_SURFACE_REMEDY: Record<CaptureSurface, string> = {\n \"opt-in\":\n \"Inside a withTrace/trace subtree, configure a discovered call with node()/withNode() instead, or trace this workflow with withSpan() only.\",\n \"opt-out\":\n \"Wrap the caller with withTrace()/trace() as well, or wrap this function with withSpan().\",\n}\n\nexport function resolveSurface(\n requested: SurfaceRequest,\n parentSurface: CaptureSurface | undefined,\n): CaptureSurface | undefined {\n if (requested === \"neutral\") {\n return undefined\n }\n if (requested === \"inherit\") {\n return parentSurface ?? DEFAULT_SURFACE\n }\n return requested\n}\n\nexport function mixedTracingError(\n enteredApi: string,\n entered: CaptureSurface,\n enclosing: CaptureSurface,\n traceFunctionKey?: string,\n): MixedTracingError {\n const subject =\n traceFunctionKey === undefined ? \"\" : ` for \"${traceFunctionKey}\"`\n return new MixedTracingError(\n `opt-in and opt-out tracing can't be mixed in one call stack: ${enteredApi} (${entered})${subject} was entered inside a ${SURFACE_API[enclosing]} call (${enclosing}). ${MIXED_SURFACE_REMEDY[entered]}`,\n )\n}\n\nexport function assertSurfacesCompatible(\n requested: SurfaceRequest,\n resolved: CaptureSurface | undefined,\n parentSurface: CaptureSurface | undefined,\n traceFunctionKey: string,\n): void {\n if (requested === \"inherit\" || requested === \"neutral\") {\n return\n }\n if (resolved === undefined || parentSurface === undefined) {\n return\n }\n if (parentSurface === resolved) {\n return\n }\n throw mixedTracingError(\n SURFACE_API[resolved],\n resolved,\n parentSurface,\n traceFunctionKey,\n )\n}\n","import type { HttpClient } from \"./http.js\"\n\nexport interface DatasetGraderRef {\n id: string\n name: string | null\n}\n\nexport interface Dataset {\n id: string\n traceFunctionKey: string\n name: string\n description: string | null\n traceCount: number\n graders: DatasetGraderRef[]\n createdAt: string\n updatedAt: string\n}\n\nexport interface SaveDatasetParams {\n traceFunctionKey: string\n name: string\n description?: string\n}\n\nexport interface SaveDatasetResult {\n dataset: Dataset\n created: boolean\n}\n\nexport interface ListDatasetsParams {\n traceFunctionKey?: string\n}\n\nexport interface DatasetTraceIds {\n datasetId: string\n traceIds: string[]\n}\n\nexport interface AddDatasetTracesResult {\n dataset: Dataset\n addedTraceIds: string[]\n alreadyPresentTraceIds: string[]\n skippedTraceIds: string[]\n}\n\nexport interface RemoveDatasetTracesResult {\n dataset: Dataset\n removedTraceIds: string[]\n notPresentTraceIds: string[]\n}\n\nexport interface AddDatasetGradersResult {\n dataset: Dataset\n addedGraderIds: string[]\n alreadyAssignedGraderIds: string[]\n skippedGraderIds: string[]\n}\n\nexport interface RemoveDatasetGradersResult {\n dataset: Dataset\n removedGraderIds: string[]\n notAssignedGraderIds: string[]\n}\n\nexport type GraderRerunStatus = \"pending\" | \"running\" | \"completed\" | \"errored\"\n\nexport interface GraderRerunProgress {\n completedTraces: number\n totalTraces: number\n graderCount: number\n}\n\nexport interface GraderRerunResult {\n tracesGraded: number\n gradersRun: number\n}\n\nexport interface GraderRerun {\n id: string\n status: GraderRerunStatus\n graderIds: string[]\n progress: GraderRerunProgress | null\n result: GraderRerunResult | null\n error: string | null\n createdAt: string\n updatedAt: string\n}\n\nexport interface RerunGradersOptions {\n graderIds?: string[]\n wait?: boolean\n timeoutMs?: number\n pollIntervalMs?: number\n}\n\nexport interface RerunGradersResult {\n run: GraderRerun\n joinedExisting: boolean\n}\n\nconst DEFAULT_RERUN_TIMEOUT_MS = 90_000\nconst DEFAULT_RERUN_POLL_INTERVAL_MS = 1_000\nconst TERMINAL_RERUN_STATUSES: ReadonlySet<GraderRerunStatus> = new Set([\n \"completed\",\n \"errored\",\n])\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\nfunction datasetPath(datasetId: string, suffix = \"\"): string {\n return `/api/sdk/datasets/${encodeURIComponent(datasetId)}${suffix}`\n}\n\n/**\n * Dataset operations for the authenticated organization, reached as\n * `client.datasets`. A dataset is a named bucket of traces scoped to one trace\n * function. Experiments replay against it and its graders score its members.\n */\nexport class DatasetsClient {\n constructor(private readonly httpClient: HttpClient) {}\n\n /**\n * Create a dataset, or update the one already named this way under the same\n * trace function. `created` reports which happened. An omitted description\n * leaves an existing one untouched.\n */\n async save(params: SaveDatasetParams): Promise<SaveDatasetResult> {\n return this.httpClient.request<SaveDatasetResult>(\"/api/sdk/datasets\", {\n traceFunctionKey: params.traceFunctionKey,\n name: params.name,\n ...(params.description === undefined\n ? {}\n : { description: params.description }),\n })\n }\n\n /**\n * List datasets, scoped to one trace function when `traceFunctionKey` is\n * given and organization-wide otherwise.\n */\n async list(params: ListDatasetsParams = {}): Promise<Dataset[]> {\n const query =\n params.traceFunctionKey === undefined\n ? \"\"\n : `?traceFunctionKey=${encodeURIComponent(params.traceFunctionKey)}`\n const response = await this.httpClient.get<{ datasets: Dataset[] }>(\n `/api/sdk/datasets${query}`,\n )\n return response.datasets\n }\n\n /** Fetch one dataset by id. Rejects with a 404 `BitfabError` when it is not in this organization. */\n async get(datasetId: string): Promise<Dataset> {\n const response = await this.httpClient.get<{ dataset: Dataset }>(\n datasetPath(datasetId),\n )\n return response.dataset\n }\n\n /** The ids of every trace in the dataset, the same membership a replay with `datasetId` selects. */\n async listTraces(datasetId: string): Promise<DatasetTraceIds> {\n return this.httpClient.get<DatasetTraceIds>(\n datasetPath(datasetId, \"/traces\"),\n )\n }\n\n /**\n * Add traces to the dataset (1 to 100 ids per call). Traces outside the\n * organization or under another trace function are reported in\n * `skippedTraceIds` rather than failing the call.\n */\n async addTraces(\n datasetId: string,\n traceIds: string[],\n ): Promise<AddDatasetTracesResult> {\n return this.httpClient.request<AddDatasetTracesResult>(\n datasetPath(datasetId, \"/traces\"),\n { traceIds },\n )\n }\n\n /** Remove traces from the dataset. The traces themselves are never deleted. */\n async removeTraces(\n datasetId: string,\n traceIds: string[],\n ): Promise<RemoveDatasetTracesResult> {\n return this.httpClient.request<RemoveDatasetTracesResult>(\n datasetPath(datasetId, \"/removeTraces\"),\n { traceIds },\n )\n }\n\n /**\n * Assign graders to the dataset (1 to 100 ids per call). Graders outside the\n * organization or under another trace function are reported in\n * `skippedGraderIds` rather than failing the call.\n */\n async addGraders(\n datasetId: string,\n graderIds: string[],\n ): Promise<AddDatasetGradersResult> {\n return this.httpClient.request<AddDatasetGradersResult>(\n datasetPath(datasetId, \"/graders\"),\n { graderIds },\n )\n }\n\n /** Unassign graders from the dataset. */\n async removeGraders(\n datasetId: string,\n graderIds: string[],\n ): Promise<RemoveDatasetGradersResult> {\n return this.httpClient.request<RemoveDatasetGradersResult>(\n datasetPath(datasetId, \"/removeGraders\"),\n { graderIds },\n )\n }\n\n /**\n * Re-run graders over every trace in the dataset. Defaults to every assigned\n * grader; an unassigned id is rejected. Waits for the run to finish (up to\n * `timeoutMs`, default 90s) unless `wait` is `false`, and returns the last\n * run state seen either way. A request matching an in-flight run joins it.\n */\n async rerunGraders(\n datasetId: string,\n options: RerunGradersOptions = {},\n ): Promise<RerunGradersResult> {\n const started = await this.httpClient.request<RerunGradersResult>(\n datasetPath(datasetId, \"/rerunGraders\"),\n options.graderIds === undefined ? {} : { graderIds: options.graderIds },\n )\n if (options.wait === false) {\n return started\n }\n\n const deadline =\n Date.now() + (options.timeoutMs ?? DEFAULT_RERUN_TIMEOUT_MS)\n const interval = options.pollIntervalMs ?? DEFAULT_RERUN_POLL_INTERVAL_MS\n let run = started.run\n while (!TERMINAL_RERUN_STATUSES.has(run.status) && Date.now() < deadline) {\n await sleep(interval)\n run = (await this.getGraderRerun(datasetId, run.id)) ?? run\n }\n return { run, joinedExisting: started.joinedExisting }\n }\n\n /**\n * The dataset's active grader re-run, or the run named by `runId`. Returns\n * `null` when nothing is active or the run does not belong to this dataset.\n */\n async getGraderRerun(\n datasetId: string,\n runId?: string,\n ): Promise<GraderRerun | null> {\n const query =\n runId === undefined ? \"\" : `?runId=${encodeURIComponent(runId)}`\n const response = await this.httpClient.get<{ run: GraderRerun | null }>(\n datasetPath(datasetId, `/rerunGraders${query}`),\n )\n return response.run\n }\n}\n","/**\n * Per-trace database snapshot ref capture.\n *\n * Every root span carries a `DbSnapshotRef` that pins the DB state at trace\n * open by wall-clock timestamp. Capturing the timestamp is free (no IO) and\n * harmless, so it happens on every trace regardless of configuration: that\n * lets any trace be replayed against a historical branch later. A `provider`\n * is attached only when the customer configured `dbSnapshot`; when absent it\n * is resolved at replay time. The Bitfab service uses the timestamp to\n * materialize an ephemeral branch from `customer-main`.\n */\n\nimport { BitfabError } from \"./errors.js\"\n\n// TODO: add more providers as resolvers are built (ardent, dolt, gfs, ...).\nexport const SUPPORTED_PROVIDERS = [\"neon\"] as const\n\nexport type DbSnapshotProvider = (typeof SUPPORTED_PROVIDERS)[number]\n\nexport interface DbSnapshotConfig {\n /** Discriminator for the server-side resolver. */\n provider: DbSnapshotProvider\n}\n\nexport interface DbSnapshotRef {\n /**\n * The wall-clock ISO timestamp the SDK observed immediately before\n * invoking the wrapped function. The name encodes its provenance:\n * SDK-observed, wall clock (not monotonic), captured before user code\n * began executing. Always present.\n */\n sdkWallClockBeforeFn: string\n /**\n * The configured provider for server-side branch resolution. Only set when\n * the customer configured `dbSnapshot`; otherwise the provider is resolved\n * at replay time.\n */\n provider?: DbSnapshotProvider\n}\n\nexport function validateDbSnapshotConfig(config: DbSnapshotConfig): void {\n if (!SUPPORTED_PROVIDERS.includes(config.provider)) {\n throw new BitfabError(\n `dbSnapshot.provider \"${config.provider}\" is not supported. Supported providers: ${SUPPORTED_PROVIDERS.join(\", \")}.`,\n )\n }\n}\n\n/**\n * Build a snapshot ref for one trace. Synchronous, no IO. Always stores the\n * wall clock the SDK observed immediately before invoking the wrapped\n * function; the resolver uses that as the Neon snapshot timestamp. The\n * `provider` is included only when `dbSnapshot` was configured (`config`\n * present); otherwise it is resolved at replay time.\n */\nexport function buildSnapshotRef(\n config: DbSnapshotConfig | undefined,\n sdkWallClockBeforeFn: string,\n): DbSnapshotRef {\n return {\n sdkWallClockBeforeFn,\n ...(config && { provider: config.provider }),\n }\n}\n","/**\n * LangGraph/LangChain callback handler for Bitfab tracing.\n *\n * Hooks into LangGraph's callback system to capture graph node execution,\n * LLM calls, and tool invocations as Bitfab spans, without requiring users\n * to wrap their functions with withSpan (which fails on non-serializable args).\n *\n * Duck-typed to match LangChain.js's BaseCallbackHandler interface.\n * No @langchain/core dependency required.\n */\n\nimport { DEFAULT_SERVICE_URL } from \"./constants.js\"\nimport { type ApiKeyInput, HttpClient } from \"./http.js\"\nimport {\n finalizeSpanPayload,\n finalizeTracePayload,\n} from \"./processorPayload.js\"\nimport { randomUuid } from \"./randomUuid.js\"\nimport { toJsonSafeReport } from \"./serialize.js\"\nimport { nowIsoTimestamp } from \"./timestamp.js\"\n\nexport interface ActiveSpanContext {\n traceId: string\n spanId: string\n}\n\ninterface SpanInfo {\n id: string\n spanId: string\n traceId: string\n rootRunId: string\n parentId: string | null\n startedAt: string\n endedAt?: string\n name: string\n type: string\n input?: unknown\n output?: unknown\n error?: string\n contexts: Array<Record<string, unknown>>\n model?: string\n hidden?: boolean\n // Type names of input/output values that could only be captured as\n // placeholders. Carried to the send boundary so finalizeSpanPayload can mark\n // the span non-replayable.\n dropped?: string[]\n}\n\ninterface InvocationState {\n traceId: string\n activeContext: ActiveSpanContext | null\n rootRunId: string\n}\n\nconst LANGSMITH_HIDDEN_TAG = \"langsmith:hidden\"\n\nconst CHAIN_RUN_TYPES = new Set([\"chain\", \"parser\", \"prompt\"])\n\nconst LANGGRAPH_METADATA_KEYS = [\n \"langgraph_step\",\n \"langgraph_node\",\n \"langgraph_triggers\",\n \"langgraph_path\",\n \"langgraph_checkpoint_ns\",\n] as const\n\nfunction nowIso(): string {\n return nowIsoTimestamp()\n}\n\nfunction normalizeChainStartArgs(\n parentRunIdOrRunType?: string,\n runTypeOrRunName?: string,\n runNameOrParentRunId?: string,\n): { parentRunId?: string; runName?: string } {\n if (parentRunIdOrRunType && CHAIN_RUN_TYPES.has(parentRunIdOrRunType)) {\n return {\n parentRunId: runNameOrParentRunId,\n runName: runTypeOrRunName,\n }\n }\n\n return {\n parentRunId: parentRunIdOrRunType,\n runName: runNameOrParentRunId,\n }\n}\n\nfunction convertMessage(message: unknown): Record<string, unknown> {\n if (typeof message !== \"object\" || message === null) {\n return { role: \"unknown\", content: String(message) }\n }\n\n const msg = message as Record<string, unknown>\n\n if (typeof msg.toDict === \"function\") {\n return (msg as { toDict(): Record<string, unknown> }).toDict()\n }\n\n const typeToRole: Record<string, string> = {\n human: \"user\",\n ai: \"assistant\",\n system: \"system\",\n tool: \"tool\",\n function: \"function\",\n }\n\n const result: Record<string, unknown> = {}\n\n const msgType = msg._getType\n ? String((msg as { _getType(): string })._getType())\n : (msg.type as string | undefined)\n\n result.role =\n (msgType ? typeToRole[msgType] : undefined) ?? msg.role ?? \"unknown\"\n result.content = msg.content ?? \"\"\n\n if (msg.tool_calls) {\n result.tool_calls = msg.tool_calls\n }\n if (msg.tool_call_id) {\n result.tool_call_id = msg.tool_call_id\n }\n if (msg.name) {\n result.name = msg.name\n }\n\n return result\n}\n\nfunction extractModelName(\n serialized: Record<string, unknown> | undefined,\n metadata: Record<string, unknown> | undefined,\n): string | undefined {\n if (serialized) {\n const kwargs = serialized.kwargs as Record<string, unknown> | undefined\n if (kwargs) {\n const model = kwargs.model_name ?? kwargs.model ?? kwargs.model_id\n if (model) {\n return String(model)\n }\n }\n }\n if (metadata) {\n const lsModel = metadata.ls_model_name\n if (lsModel) {\n return String(lsModel)\n }\n }\n return undefined\n}\n\ninterface NormalizedUsage {\n inputTokens: number | null\n outputTokens: number | null\n totalTokens: number | null\n cachedInputTokens: number | null\n}\n\nfunction asTokenCount(value: unknown): number | null {\n return typeof value === \"number\" && Number.isFinite(value) ? value : null\n}\n\n/**\n * Normalize a provider-reported token-usage dict into Bitfab's span fields.\n *\n * Handles, in priority order:\n * - Anthropic native (`input_tokens` EXCLUDES cache reads/creation, so they\n * are added back to get the true prompt size)\n * - OpenAI native (`prompt_tokens` / `completion_tokens`, snake or camel case)\n * - Google Gemini / Vertex native (`prompt_token_count` / `candidates_token_count`)\n * - LangChain normalized `usage_metadata` (`input_tokens` / `output_tokens` /\n * `total_tokens` with `input_token_details.cache_read`)\n *\n * Returns null when the value carries no recognizable token counts. Never\n * estimates: only provider-reported numbers are returned.\n */\nfunction normalizeTokenUsage(raw: unknown): NormalizedUsage | null {\n if (typeof raw !== \"object\" || raw === null || Array.isArray(raw)) {\n return null\n }\n const u = raw as Record<string, unknown>\n\n // Anthropic native: input_tokens excludes cached reads and cache writes.\n if (\"cache_read_input_tokens\" in u || \"cache_creation_input_tokens\" in u) {\n const cacheRead = asTokenCount(u.cache_read_input_tokens)\n const cacheCreation = asTokenCount(u.cache_creation_input_tokens)\n const baseInput = asTokenCount(u.input_tokens)\n const outputTokens = asTokenCount(u.output_tokens)\n if (\n cacheRead === null &&\n cacheCreation === null &&\n baseInput === null &&\n outputTokens === null\n ) {\n return null\n }\n const inputTokens =\n (baseInput ?? 0) + (cacheRead ?? 0) + (cacheCreation ?? 0)\n return {\n inputTokens,\n outputTokens,\n totalTokens: inputTokens + (outputTokens ?? 0),\n cachedInputTokens: cacheRead,\n }\n }\n\n // OpenAI native (snake_case) and LangChain.js legacy llmOutput (camelCase).\n if (\n \"prompt_tokens\" in u ||\n \"completion_tokens\" in u ||\n \"promptTokens\" in u ||\n \"completionTokens\" in u\n ) {\n const promptDetails = (u.prompt_tokens_details ?? {}) as Record<\n string,\n unknown\n >\n return withAnyTokenCount({\n inputTokens:\n asTokenCount(u.prompt_tokens) ?? asTokenCount(u.promptTokens),\n outputTokens:\n asTokenCount(u.completion_tokens) ?? asTokenCount(u.completionTokens),\n totalTokens: asTokenCount(u.total_tokens) ?? asTokenCount(u.totalTokens),\n cachedInputTokens: asTokenCount(promptDetails.cached_tokens),\n })\n }\n\n // Google Gemini / Vertex native.\n if (\"prompt_token_count\" in u || \"candidates_token_count\" in u) {\n return withAnyTokenCount({\n inputTokens: asTokenCount(u.prompt_token_count),\n outputTokens: asTokenCount(u.candidates_token_count),\n totalTokens: asTokenCount(u.total_token_count),\n cachedInputTokens: asTokenCount(u.cached_content_token_count),\n })\n }\n\n // LangChain normalized usage_metadata (also plain Anthropic without cache keys).\n if (\"input_tokens\" in u || \"output_tokens\" in u) {\n const inputDetails = (u.input_token_details ?? {}) as Record<\n string,\n unknown\n >\n const inputTokens = asTokenCount(u.input_tokens)\n const outputTokens = asTokenCount(u.output_tokens)\n let totalTokens = asTokenCount(u.total_tokens)\n if (totalTokens === null && inputTokens !== null && outputTokens !== null) {\n totalTokens = inputTokens + outputTokens\n }\n return withAnyTokenCount({\n inputTokens,\n outputTokens,\n totalTokens,\n cachedInputTokens: asTokenCount(inputDetails.cache_read),\n })\n }\n\n return null\n}\n\n/**\n * A recognizable usage shape whose values are all null/non-numeric carries no\n * usage. Returning null lets extraction fall through to the next source\n * (response_metadata, then legacy llm_output) instead of blocking it.\n */\nfunction withAnyTokenCount(usage: NormalizedUsage): NormalizedUsage | null {\n const hasCount =\n usage.inputTokens !== null ||\n usage.outputTokens !== null ||\n usage.totalTokens !== null ||\n usage.cachedInputTokens !== null\n return hasCount ? usage : null\n}\n\nfunction addUsage(totals: NormalizedUsage, usage: NormalizedUsage): void {\n for (const key of [\n \"inputTokens\",\n \"outputTokens\",\n \"totalTokens\",\n \"cachedInputTokens\",\n ] as const) {\n const value = usage[key]\n if (value !== null) {\n totals[key] = (totals[key] ?? 0) + value\n }\n }\n}\n\n/**\n * Extract usage from each generation's message: the standardized\n * `usage_metadata` (set by modern LangChain chat models, including the final\n * aggregated chunk of streaming runs), falling back to provider-native\n * `response_metadata`. Sums across generations when a result has several.\n */\nfunction usageFromGenerations(\n generations: unknown[][] | undefined,\n): NormalizedUsage | null {\n if (!generations?.length) {\n return null\n }\n const totals: NormalizedUsage = {\n inputTokens: null,\n outputTokens: null,\n totalTokens: null,\n cachedInputTokens: null,\n }\n let found = false\n for (const batch of generations) {\n if (!Array.isArray(batch)) {\n continue\n }\n for (const gen of batch) {\n const msg = (gen as Record<string, unknown> | null)?.message as\n | Record<string, unknown>\n | undefined\n if (!msg || typeof msg !== \"object\") {\n continue\n }\n const responseMetadata = msg.response_metadata as\n | Record<string, unknown>\n | undefined\n const usage =\n normalizeTokenUsage(msg.usage_metadata) ??\n normalizeTokenUsage(responseMetadata?.token_usage) ??\n normalizeTokenUsage(responseMetadata?.usage) ??\n normalizeTokenUsage(responseMetadata?.tokenUsage)\n if (!usage) {\n continue\n }\n found = true\n addUsage(totals, usage)\n }\n }\n return found ? totals : null\n}\n\n/**\n * Extract token usage from an LLM result.\n *\n * Resolution order: per-generation `message.usage_metadata` (normalized,\n * provider-agnostic), then `message.response_metadata` token usage, then the\n * legacy `llmOutput.tokenUsage` / `token_usage` / `usage` location. Fields\n * with no provider-reported value are omitted; nothing is ever estimated.\n */\nfunction extractUsage(\n output: Record<string, unknown>,\n): Record<string, unknown> {\n const generations = output.generations as unknown[][] | undefined\n const llmOutput = (output.llmOutput ?? output.llm_output) as\n | Record<string, unknown>\n | undefined\n\n const normalized =\n usageFromGenerations(generations) ??\n normalizeTokenUsage(llmOutput?.tokenUsage) ??\n normalizeTokenUsage(llmOutput?.token_usage) ??\n normalizeTokenUsage(llmOutput?.usage)\n\n const usage: Record<string, unknown> = {}\n if (!normalized) {\n return usage\n }\n if (normalized.inputTokens !== null) {\n usage.inputTokens = normalized.inputTokens\n }\n if (normalized.outputTokens !== null) {\n usage.outputTokens = normalized.outputTokens\n }\n if (normalized.totalTokens !== null) {\n usage.totalTokens = normalized.totalTokens\n }\n if (normalized.cachedInputTokens !== null) {\n usage.cachedInputTokens = normalized.cachedInputTokens\n }\n\n return usage\n}\n\nfunction extractLangGraphMetadata(\n metadata: Record<string, unknown> | undefined,\n): Record<string, unknown> {\n if (!metadata) {\n return {}\n }\n const result: Record<string, unknown> = {}\n for (const key of LANGGRAPH_METADATA_KEYS) {\n if (key in metadata) {\n result[key] = metadata[key]\n }\n }\n return result\n}\n\n/**\n * LangChain/LangGraph callback handler that sends traces to Bitfab.\n *\n * Duck-typed to match LangChain.js's BaseCallbackHandler, so no\n * `@langchain/core` dependency is required. Pass as a callback:\n *\n * ```typescript\n * const handler = bitfab.getLangGraphCallbackHandler(\"my-agent\");\n * const result = await agent.invoke(\n * { messages: [...] },\n * { callbacks: [handler] },\n * );\n * ```\n */\nexport class BitfabLangGraphCallbackHandler {\n name = \"BitfabLangGraphCallbackHandler\"\n\n ignoreRetry = true\n // Retriever callbacks ARE captured (retriever queries -> function spans).\n ignoreRetriever = false\n ignoreCustomEvent = true\n\n private readonly httpClient: HttpClient\n private readonly ownsHttpClient: boolean\n private readonly traceFunctionKey: string\n private readonly getActiveSpanContext: (() => ActiveSpanContext | null) | null\n private readonly captureTools: boolean\n\n private runToSpan: Map<string, SpanInfo> = new Map()\n private invocations: Map<string, InvocationState> = new Map()\n\n constructor(config: {\n apiKey?: ApiKeyInput\n traceFunctionKey: string\n serviceUrl?: string\n timeout?: number\n getActiveSpanContext?: () => ActiveSpanContext | null\n /** Whether callback tool events should emit spans. Defaults to true. */\n captureTools?: boolean\n /**\n * The owning `Bitfab` client's HTTP client. Supplied by\n * `getLangGraphCallbackHandler()` so this handler shares that client's\n * single span-transport worker instead of starting a second one.\n * @internal\n */\n _httpClient?: HttpClient\n }) {\n this.ownsHttpClient = config._httpClient === undefined\n this.httpClient =\n config._httpClient ??\n new HttpClient({\n apiKey: config.apiKey,\n serviceUrl: config.serviceUrl ?? DEFAULT_SERVICE_URL,\n timeout: config.timeout ?? 10000,\n })\n this.traceFunctionKey = config.traceFunctionKey\n this.getActiveSpanContext = config.getActiveSpanContext ?? null\n this.captureTools = config.captureTools ?? true\n }\n\n /**\n * Flush and release the span transport this handler started. A no-op when\n * the handler borrowed a `Bitfab` client's HTTP client: that client's\n * `close()` owns the worker's lifetime.\n */\n async close(timeoutMs?: number): Promise<boolean> {\n return this.ownsHttpClient ? this.httpClient.close(timeoutMs) : true\n }\n\n // ── lifecycle helpers ──────────────────────────────────────────\n\n private startSpan(\n runId: string,\n parentRunId: string | undefined,\n name: string,\n spanType: string,\n inputData?: unknown,\n metadata?: Record<string, unknown>,\n tags?: string[],\n ): SpanInfo {\n // If we have a tracked parent, inherit its invocation. Otherwise this\n // callback is the root of a fresh invocation: capture the outer Bitfab\n // span context now so concurrent invocations don't overwrite each other.\n const parentSpan = parentRunId ? this.runToSpan.get(parentRunId) : undefined\n const willHide = tags?.includes(LANGSMITH_HIDDEN_TAG) === true\n\n let invocation: InvocationState\n let effectiveParentId: string | null\n let isRootInvocation = false\n if (parentSpan) {\n const existing = this.invocations.get(parentSpan.rootRunId)\n if (existing) {\n invocation = existing\n } else {\n invocation = {\n traceId: parentSpan.traceId,\n activeContext: null,\n rootRunId: parentSpan.rootRunId,\n }\n this.invocations.set(invocation.rootRunId, invocation)\n }\n // Hidden callbacks stay local for parent resolution. Walk visible spans\n // to the nearest submitted ancestor so the stored tree has no orphan.\n if (!willHide) {\n let resolved: SpanInfo | undefined = parentSpan\n while (resolved?.hidden === true) {\n resolved = resolved.parentId\n ? this.runToSpan.get(resolved.parentId)\n : undefined\n }\n effectiveParentId = resolved\n ? resolved.spanId\n : (invocation.activeContext?.spanId ?? null)\n } else {\n effectiveParentId = parentRunId ?? null\n }\n } else {\n const activeContext = this.getActiveSpanContext?.() ?? null\n invocation = {\n traceId: activeContext ? activeContext.traceId : randomUuid(),\n activeContext,\n rootRunId: runId,\n }\n this.invocations.set(runId, invocation)\n effectiveParentId = activeContext?.spanId ?? null\n isRootInvocation = true\n }\n\n const lgMetadata = extractLangGraphMetadata(metadata)\n const contexts: Array<Record<string, unknown>> =\n Object.keys(lgMetadata).length > 0 ? [lgMetadata] : []\n\n const { safe: safeInput, dropped: inputDropped } =\n toJsonSafeReport(inputData)\n const spanInfo: SpanInfo = {\n id: randomUuid(),\n spanId: runId,\n traceId: invocation.traceId,\n rootRunId: invocation.rootRunId,\n parentId: effectiveParentId,\n startedAt: nowIso(),\n name,\n type: spanType,\n input: safeInput,\n contexts,\n }\n if (inputDropped.length > 0) {\n spanInfo.dropped = [...inputDropped]\n }\n if (willHide) {\n spanInfo.hidden = true\n }\n this.runToSpan.set(runId, spanInfo)\n if (isRootInvocation) {\n this.sendTraceStart(spanInfo)\n }\n return spanInfo\n }\n\n private completeSpan(\n runId: string,\n output?: unknown,\n error?: string,\n extraContexts?: Record<string, unknown>,\n ): void {\n const spanInfo = this.runToSpan.get(runId)\n if (!spanInfo) {\n return\n }\n this.runToSpan.delete(runId)\n\n spanInfo.endedAt = nowIso()\n const { safe: safeOutput, dropped: outputDropped } =\n toJsonSafeReport(output)\n spanInfo.output = safeOutput\n if (outputDropped.length > 0) {\n spanInfo.dropped = [...(spanInfo.dropped ?? []), ...outputDropped]\n }\n if (error !== undefined) {\n spanInfo.error = error\n }\n\n if (extraContexts && Object.keys(extraContexts).length > 0) {\n spanInfo.contexts.push(extraContexts)\n }\n\n if (spanInfo.hidden !== true) {\n this.sendSpan(spanInfo)\n }\n\n if (runId === spanInfo.rootRunId) {\n const invocation = this.invocations.get(runId)\n this.sendTraceCompletion(spanInfo, invocation?.activeContext ?? null)\n this.invocations.delete(runId)\n }\n }\n\n private sendSpan(spanInfo: SpanInfo): void {\n const spanData: Record<string, unknown> = {\n name: spanInfo.name,\n type: spanInfo.type,\n }\n if (spanInfo.input !== undefined) {\n spanData.input = spanInfo.input\n }\n if (spanInfo.output !== undefined) {\n spanData.output = spanInfo.output\n }\n if (spanInfo.error !== undefined) {\n spanData.error = spanInfo.error\n }\n if (spanInfo.contexts.length > 0) {\n spanData.contexts = spanInfo.contexts\n }\n const rawSpan: Record<string, unknown> = {\n id: spanInfo.spanId,\n trace_id: spanInfo.traceId,\n started_at: spanInfo.startedAt,\n ended_at: spanInfo.endedAt ?? nowIso(),\n span_data: spanData,\n }\n if (spanInfo.parentId !== null) {\n rawSpan.parent_id = spanInfo.parentId\n }\n\n const payload: Record<string, unknown> = {\n id: spanInfo.id,\n traceId: spanInfo.traceId,\n type: \"sdk-function\",\n source: \"typescript-sdk-langgraph\",\n traceFunctionKey: this.traceFunctionKey,\n sourceTraceId: spanInfo.traceId,\n rawSpan,\n }\n\n // Sanitize the whole span and mark a lossy capture non-replayable.\n // spanInfo.dropped carries losses from the capture-time input/output\n // snapshot above.\n const finalized = finalizeSpanPayload(payload, spanInfo.dropped)\n\n try {\n this.httpClient.sendExternalSpan(finalized)\n } catch {\n // Never crash the host app\n }\n }\n\n private sendTraceCompletion(\n rootSpan: SpanInfo,\n activeContext: ActiveSpanContext | null,\n ): void {\n const completed = activeContext === null\n\n const traceData: Record<string, unknown> = {\n id: rootSpan.traceId,\n type: \"sdk-function\",\n source: \"typescript-sdk-langgraph\",\n traceFunctionKey: this.traceFunctionKey,\n externalTrace: {\n id: rootSpan.traceId,\n started_at: rootSpan.startedAt,\n ended_at: rootSpan.endedAt ?? nowIso(),\n },\n completed,\n }\n\n const finalized = finalizeTracePayload(traceData)\n\n try {\n this.httpClient.sendExternalTrace(finalized)\n } catch {\n // Never crash the host app\n }\n }\n\n private sendTraceStart(rootSpan: SpanInfo): void {\n const traceData: Record<string, unknown> = {\n id: rootSpan.traceId,\n type: \"sdk-function\",\n source: \"typescript-sdk-langgraph\",\n traceFunctionKey: this.traceFunctionKey,\n externalTrace: {\n id: rootSpan.traceId,\n started_at: rootSpan.startedAt,\n },\n completed: false,\n }\n\n const finalized = finalizeTracePayload(traceData)\n\n try {\n this.httpClient.sendExternalTrace(finalized)\n } catch {\n // Never crash the host app\n }\n }\n\n // ── chain callbacks (graph nodes) ─────────────────────────────\n\n async handleChainStart(\n chain: Record<string, unknown> | null | undefined,\n inputs: Record<string, unknown>,\n runId: string,\n parentRunIdOrRunType?: string,\n tags?: string[],\n metadata?: Record<string, unknown>,\n runTypeOrRunName?: string,\n runNameOrParentRunId?: string,\n ): Promise<void> {\n try {\n const { parentRunId, runName } = normalizeChainStartArgs(\n parentRunIdOrRunType,\n runTypeOrRunName,\n runNameOrParentRunId,\n )\n const serialized = chain ?? {}\n const idArr = serialized.id as string[] | undefined\n const name =\n runName ??\n (serialized.name as string) ??\n idArr?.[idArr.length - 1] ??\n \"chain\"\n this.startSpan(\n runId,\n parentRunId,\n String(name),\n \"agent\",\n inputs,\n metadata,\n tags,\n )\n } catch {\n // Never crash the host app\n }\n }\n\n async handleChainEnd(\n outputs: Record<string, unknown>,\n runId: string,\n ): Promise<void> {\n try {\n this.completeSpan(runId, outputs)\n } catch {\n // Never crash the host app\n }\n }\n\n async handleChainError(error: unknown, runId: string): Promise<void> {\n try {\n const errorObj = error as { constructor?: { name?: string } }\n if (errorObj?.constructor?.name === \"GraphBubbleUp\") {\n this.completeSpan(runId, undefined, undefined)\n return\n }\n this.completeSpan(\n runId,\n undefined,\n error instanceof Error ? error.message : String(error),\n )\n } catch {\n // Never crash the host app\n }\n }\n\n // ── LLM callbacks ─────────────────────────────────────────────\n\n async handleChatModelStart(\n llm: Record<string, unknown> | null | undefined,\n messages: unknown[][],\n runId: string,\n parentRunId?: string,\n _extraParams?: Record<string, unknown>,\n tags?: string[],\n metadata?: Record<string, unknown>,\n runName?: string,\n ): Promise<void> {\n try {\n const serialized = llm ?? {}\n const model = extractModelName(serialized, metadata)\n const idArr = serialized.id as string[] | undefined\n const name = runName ?? model ?? idArr?.[idArr.length - 1] ?? \"llm\"\n const converted = messages.map((batch) => batch.map(convertMessage))\n\n const spanInfo = this.startSpan(\n runId,\n parentRunId,\n String(name),\n \"llm\",\n converted,\n metadata,\n tags,\n )\n spanInfo.model = model\n } catch {\n // Never crash the host app\n }\n }\n\n async handleLLMStart(\n llm: Record<string, unknown> | null | undefined,\n prompts: string[],\n runId: string,\n parentRunId?: string,\n _extraParams?: Record<string, unknown>,\n tags?: string[],\n metadata?: Record<string, unknown>,\n runName?: string,\n ): Promise<void> {\n try {\n const serialized = llm ?? {}\n const model = extractModelName(serialized, metadata)\n const idArr = serialized.id as string[] | undefined\n const name = runName ?? model ?? idArr?.[idArr.length - 1] ?? \"llm\"\n\n const spanInfo = this.startSpan(\n runId,\n parentRunId,\n String(name),\n \"llm\",\n prompts,\n metadata,\n tags,\n )\n spanInfo.model = model\n } catch {\n // Never crash the host app\n }\n }\n\n async handleLLMEnd(\n output: Record<string, unknown>,\n runId: string,\n ): Promise<void> {\n try {\n let llmOutput: unknown\n const generations = output.generations as unknown[][] | undefined\n if (generations?.length && generations[generations.length - 1]?.length) {\n const gen = generations[generations.length - 1][\n generations[generations.length - 1].length - 1\n ] as Record<string, unknown>\n const msg = gen.message as Record<string, unknown> | undefined\n llmOutput = msg ? convertMessage(msg) : (gen.text ?? String(gen))\n }\n\n const usage = extractUsage(output)\n const spanInfo = this.runToSpan.get(runId)\n const model = spanInfo?.model\n\n const llmContext: Record<string, unknown> = {}\n if (model) {\n llmContext.model = model\n }\n Object.assign(llmContext, usage)\n\n this.completeSpan(\n runId,\n llmOutput,\n undefined,\n Object.keys(llmContext).length > 0 ? llmContext : undefined,\n )\n } catch {\n // Never crash the host app\n }\n }\n\n async handleLLMError(error: unknown, runId: string): Promise<void> {\n try {\n this.completeSpan(\n runId,\n undefined,\n error instanceof Error ? error.message : String(error),\n )\n } catch {\n // Never crash the host app\n }\n }\n\n async handleLLMNewToken(): Promise<void> {\n // Intentionally empty: per-token events are not traced. Usage for\n // streaming runs is captured in handleLLMEnd from the final aggregated\n // chunk's usage_metadata / response_metadata.\n }\n\n // ── tool callbacks ────────────────────────────────────────────\n\n async handleToolStart(\n tool: Record<string, unknown> | null | undefined,\n input: string,\n runId: string,\n parentRunId?: string,\n tags?: string[],\n metadata?: Record<string, unknown>,\n runName?: string,\n ): Promise<void> {\n if (!this.captureTools) {\n return\n }\n try {\n const serialized = tool ?? {}\n const name = runName ?? (serialized.name as string) ?? \"tool\"\n this.startSpan(\n runId,\n parentRunId,\n String(name),\n \"function\",\n input,\n metadata,\n tags,\n )\n } catch {\n // Never crash the host app\n }\n }\n\n async handleToolEnd(output: unknown, runId: string): Promise<void> {\n if (!this.captureTools) {\n return\n }\n try {\n this.completeSpan(runId, output)\n } catch {\n // Never crash the host app\n }\n }\n\n async handleToolError(error: unknown, runId: string): Promise<void> {\n if (!this.captureTools) {\n return\n }\n try {\n this.completeSpan(\n runId,\n undefined,\n error instanceof Error ? error.message : String(error),\n )\n } catch {\n // Never crash the host app\n }\n }\n\n // ── retriever callbacks ───────────────────────────────────────\n\n async handleRetrieverStart(\n retriever: Record<string, unknown> | null | undefined,\n query: string,\n runId: string,\n parentRunId?: string,\n tags?: string[],\n metadata?: Record<string, unknown>,\n runName?: string,\n ): Promise<void> {\n try {\n const serialized = retriever ?? {}\n const name = runName ?? (serialized.name as string) ?? \"retriever\"\n this.startSpan(\n runId,\n parentRunId,\n String(name),\n \"function\",\n query,\n metadata,\n tags,\n )\n } catch {\n // Never crash the host app\n }\n }\n\n async handleRetrieverEnd(documents: unknown, runId: string): Promise<void> {\n try {\n this.completeSpan(runId, documents)\n } catch {\n // Never crash the host app\n }\n }\n\n async handleRetrieverError(error: unknown, runId: string): Promise<void> {\n try {\n this.completeSpan(\n runId,\n undefined,\n error instanceof Error ? error.message : String(error),\n )\n } catch {\n // Never crash the host app\n }\n }\n}\n","import { BitfabError } from \"./http.js\"\nimport type { BitfabLangGraphCallbackHandler } from \"./langgraph.js\"\nimport { importOptionalPeer } from \"./optionalPeer.js\"\nimport { getReplayContext } from \"./replayContext.js\"\n\nconst TOOL_RESULT_TAG = \"__bitfabLangGraphToolResult\"\n\ntype ToolMessageContent = string | Array<Record<string, unknown>>\n\ninterface ToolMessageFields {\n content: ToolMessageContent\n tool_call_id: string\n name?: string\n id?: string\n status?: \"success\" | \"error\"\n artifact?: unknown\n metadata?: Record<string, unknown>\n additional_kwargs?: Record<string, unknown>\n response_metadata?: Record<string, unknown>\n}\n\ninterface ToolMessageConstructor {\n new (fields: ToolMessageFields): unknown\n}\n\ninterface CommandConstructor {\n new (fields: {\n graph?: string\n update?: unknown\n resume?: unknown\n goto?: unknown\n }): unknown\n}\n\ninterface LangChainCoreRuntime {\n ToolMessage: ToolMessageConstructor\n}\n\ninterface LangGraphRuntime {\n Command: CommandConstructor\n}\n\ninterface SpanClient {\n withSpan<TArgs extends unknown[], TReturn>(\n traceFunctionKey: string,\n options: {\n name?: string\n type?: \"agent\" | \"function\"\n captureWhen?: \"always\" | \"nested\"\n mockOnReplay?: boolean\n finalize?: (result: unknown) => unknown | Promise<unknown>\n surface?: \"inherit\"\n },\n fn: (...args: TArgs) => TReturn,\n ): (...args: TArgs) => TReturn\n}\n\ninterface LangGraphTool {\n readonly name?: string\n invoke(input: unknown, ...rest: unknown[]): unknown\n}\n\ninterface ConfiguredLangGraphRunnable<TInput, TConfig, TReturn> {\n invoke(input: TInput, config?: TConfig): TReturn\n}\n\ninterface LangGraphRunnable<TInput, TConfig, TReturn> {\n withConfig(config: {\n callbacks: unknown[]\n }): ConfiguredLangGraphRunnable<TInput, TConfig, TReturn>\n}\n\ninterface EncodedToolMessage extends Record<string, unknown> {\n [TOOL_RESULT_TAG]: \"tool-message\"\n content: ToolMessageContent\n}\n\ninterface EncodedCommand extends Record<string, unknown> {\n [TOOL_RESULT_TAG]: \"command\"\n graph?: string\n update?: unknown\n resume?: unknown\n goto?: unknown\n}\n\ntype EncodedToolResult = EncodedToolMessage | EncodedCommand\n\n/**\n * Options for first-class LangGraph ToolNode replay interception.\n *\n * @experimental This API may change before it is stable.\n */\nexport interface LangGraphIntegrationOptions {\n /**\n * Tools marked for recorded-output mocking under replay's default\n * `mock: \"marked\"` strategy. Defaults to every wrapped tool. Pass a list to\n * mark only those tool names, or `false` to require `mock: \"all\"` or an\n * override.\n */\n mockToolsOnReplay?: boolean | readonly string[]\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null\n}\n\nfunction isToolMessage(value: unknown): value is Record<string, unknown> & {\n content: ToolMessageContent\n} {\n return (\n isRecord(value) &&\n value.lc_direct_tool_output === true &&\n value.type === \"tool\" &&\n (typeof value.content === \"string\" || Array.isArray(value.content))\n )\n}\n\nfunction isCommand(value: unknown): value is Record<string, unknown> {\n return isRecord(value) && value.lg_name === \"Command\"\n}\n\nfunction encodeNested(value: unknown): unknown {\n if (isToolMessage(value) || isCommand(value)) {\n return encodeNativeToolResult(value)\n }\n if (Array.isArray(value)) {\n return value.map(encodeNested)\n }\n if (isRecord(value)) {\n return Object.fromEntries(\n Object.entries(value).map(([key, entry]) => [key, encodeNested(entry)]),\n )\n }\n return value\n}\n\nfunction encodeNativeToolResult(value: unknown): EncodedToolResult {\n if (isToolMessage(value)) {\n return {\n [TOOL_RESULT_TAG]: \"tool-message\",\n content: value.content,\n name: typeof value.name === \"string\" ? value.name : undefined,\n id: typeof value.id === \"string\" ? value.id : undefined,\n status:\n value.status === \"success\" || value.status === \"error\"\n ? value.status\n : undefined,\n artifact: encodeNested(value.artifact),\n metadata: encodeNested(value.metadata),\n additionalKwargs: encodeNested(value.additional_kwargs),\n responseMetadata: encodeNested(value.response_metadata),\n }\n }\n\n return {\n [TOOL_RESULT_TAG]: \"command\",\n graph:\n isRecord(value) && typeof value.graph === \"string\"\n ? value.graph\n : undefined,\n update: isRecord(value) ? encodeNested(value.update) : undefined,\n resume: isRecord(value) ? encodeNested(value.resume) : undefined,\n goto: isRecord(value) ? encodeNested(value.goto) : undefined,\n }\n}\n\nfunction finalizeToolResult(value: unknown): unknown {\n return isToolMessage(value) || isCommand(value)\n ? encodeNativeToolResult(value)\n : value\n}\n\nfunction isEncodedToolResult(value: unknown): value is EncodedToolResult {\n return isRecord(value) && typeof value[TOOL_RESULT_TAG] === \"string\"\n}\n\nasync function loadLangChainCore(): Promise<LangChainCoreRuntime> {\n try {\n return await importOptionalPeer<LangChainCoreRuntime>([\n \"@langchain\",\n \"core\",\n \"messages\",\n ])\n } catch {\n throw new BitfabError(\n \"LangGraph tool replay requires @langchain/core. Install @langchain/langgraph before using getLangGraphIntegration().\",\n \"https://docs.bitfab.ai/frameworks/langgraph\",\n )\n }\n}\n\nasync function loadLangGraph(): Promise<LangGraphRuntime> {\n try {\n return await importOptionalPeer<LangGraphRuntime>([\n \"@langchain\",\n \"langgraph\",\n ])\n } catch {\n throw new BitfabError(\n \"Replaying a LangGraph Command requires @langchain/langgraph.\",\n \"https://docs.bitfab.ai/frameworks/langgraph\",\n )\n }\n}\n\nasync function reviveNested(\n value: unknown,\n toolCallId: string,\n): Promise<unknown> {\n if (isEncodedToolResult(value)) {\n return reviveToolResult(value, toolCallId)\n }\n if (Array.isArray(value)) {\n return Promise.all(value.map((entry) => reviveNested(entry, toolCallId)))\n }\n if (isRecord(value)) {\n const entries = await Promise.all(\n Object.entries(value).map(async ([key, entry]) => [\n key,\n await reviveNested(entry, toolCallId),\n ]),\n )\n return Object.fromEntries(entries)\n }\n return value\n}\n\nasync function reviveToolResult(\n value: EncodedToolResult,\n toolCallId: string,\n): Promise<unknown> {\n if (value[TOOL_RESULT_TAG] === \"tool-message\") {\n const { ToolMessage } = await loadLangChainCore()\n return new ToolMessage({\n content: value.content,\n tool_call_id: toolCallId,\n ...(typeof value.name === \"string\" && { name: value.name }),\n ...(typeof value.id === \"string\" && { id: value.id }),\n ...((value.status === \"success\" || value.status === \"error\") && {\n status: value.status,\n }),\n ...(value.artifact !== undefined && {\n artifact: await reviveNested(value.artifact, toolCallId),\n }),\n ...(isRecord(value.metadata) && {\n metadata: await reviveNested(value.metadata, toolCallId),\n }),\n ...(isRecord(value.additionalKwargs) && {\n additional_kwargs: await reviveNested(\n value.additionalKwargs,\n toolCallId,\n ),\n }),\n ...(isRecord(value.responseMetadata) && {\n response_metadata: await reviveNested(\n value.responseMetadata,\n toolCallId,\n ),\n }),\n } as ToolMessageFields)\n }\n\n const { Command } = await loadLangGraph()\n return new Command({\n ...(typeof value.graph === \"string\" && { graph: value.graph }),\n ...(value.update !== undefined && {\n update: await reviveNested(value.update, toolCallId),\n }),\n ...(value.resume !== undefined && {\n resume: await reviveNested(value.resume, toolCallId),\n }),\n ...(value.goto !== undefined && {\n goto: await reviveNested(value.goto, toolCallId),\n }),\n })\n}\n\n/**\n * First-class LangGraph integration for callback tracing and replayable\n * `ToolNode` tools.\n *\n * @experimental This API may change before it is stable.\n */\nexport class BitfabLangGraphIntegration {\n /** Callback handler for the compiled graph's invocation config. */\n // biome-ignore lint/suspicious/noExplicitAny: avoids leaking an optional peer's declarations into every SDK consumer\n readonly callbackHandler: any\n\n private readonly client: SpanClient\n private readonly traceFunctionKey: string\n private readonly mockToolsOnReplay: boolean | readonly string[]\n\n constructor(config: {\n client: SpanClient\n traceFunctionKey: string\n callbackHandler: BitfabLangGraphCallbackHandler\n options?: LangGraphIntegrationOptions\n }) {\n this.client = config.client\n this.traceFunctionKey = config.traceFunctionKey\n this.callbackHandler = config.callbackHandler\n this.mockToolsOnReplay = config.options?.mockToolsOnReplay ?? true\n }\n\n /**\n * Wrap tools before passing the same returned array to both\n * `model.bindTools()` and `new ToolNode()`. Each invocation becomes an\n * independently mockable child span.\n */\n wrapTools<T extends readonly LangGraphTool[]>(tools: T): T {\n return tools.map((tool) => this.wrapTool(tool)) as unknown as T\n }\n\n /**\n * Create the normal graph entry point. The returned function adds Bitfab's\n * callback handler, preserves invocation config, and records only the graph\n * input as the replayable root input.\n *\n * @experimental This API may change before it is stable.\n */\n createInvoker<TInput, TConfig, TReturn>(\n graph: LangGraphRunnable<TInput, TConfig, TReturn>,\n ): (input: TInput, config?: TConfig) => TReturn {\n const configuredGraph = graph.withConfig({\n callbacks: [this.callbackHandler],\n })\n\n return (input, config) => {\n const invoke = this.wrapInvoke((rootInput: TInput) =>\n configuredGraph.invoke(rootInput, config),\n )\n return invoke(input)\n }\n }\n\n private wrapTool<T extends LangGraphTool>(tool: T): T {\n const toolName = tool.name\n if (typeof toolName !== \"string\" || toolName.length === 0) {\n throw new BitfabError(\n \"LangGraph replayable tools must have a name.\",\n \"https://docs.bitfab.ai/frameworks/langgraph\",\n )\n }\n\n const mockToolsOnReplay = this.mockToolsOnReplay\n const shouldMock =\n typeof mockToolsOnReplay === \"boolean\"\n ? mockToolsOnReplay\n : mockToolsOnReplay.includes(toolName)\n const originalInvoke = tool.invoke.bind(tool)\n\n return new Proxy(tool, {\n get: (target, property) => {\n if (property === \"invoke\") {\n return async (input: unknown, ...rest: unknown[]) => {\n const toolCallId =\n isRecord(input) && typeof input.id === \"string\" ? input.id : \"\"\n const args = isRecord(input) && \"args\" in input ? input.args : input\n this.assertReplayToolResultExists(toolName, shouldMock)\n const execute = this.client.withSpan(\n this.traceFunctionKey,\n {\n name: toolName,\n type: \"function\",\n captureWhen: \"nested\",\n mockOnReplay: shouldMock,\n finalize: finalizeToolResult,\n surface: \"inherit\",\n },\n async (_args: unknown) => await originalInvoke(input, ...rest),\n )\n const result = await execute(args)\n return isEncodedToolResult(result)\n ? await reviveToolResult(result, toolCallId)\n : result\n }\n }\n\n const value = Reflect.get(target, property, target)\n return typeof value === \"function\" ? value.bind(target) : value\n },\n })\n }\n\n private assertReplayToolResultExists(\n toolName: string,\n shouldMock: boolean,\n ): void {\n const replayContext = getReplayContext()\n if (!replayContext?.mockTree) {\n return\n }\n\n const counterKey = `${this.traceFunctionKey}:${toolName}`\n const callIndex = replayContext.callCounters?.get(counterKey) ?? 0\n const mockSpan = replayContext.mockTree.spans.get(\n `${counterKey}:${callIndex}`,\n )\n const hasMatchingOverride = replayContext.mockOverrides?.some((override) =>\n override.match({\n traceFunctionKey: this.traceFunctionKey,\n spanName: toolName,\n type: \"function\",\n originalSpanId: mockSpan?.sourceSpanId,\n }),\n )\n const expectsRecordedOutput =\n replayContext.mockStrategy === \"all\" ||\n (replayContext.mockStrategy === \"marked\" && shouldMock)\n\n if (hasMatchingOverride !== true && expectsRecordedOutput && !mockSpan) {\n throw new BitfabError(\n `No recorded LangGraph tool result for \"${toolName}\" at call ${callIndex + 1}; refusing to execute the live tool during replay.`,\n \"https://docs.bitfab.ai/frameworks/langgraph\",\n )\n }\n }\n\n /** Wrap the function that invokes the compiled graph as the replay root. */\n wrapInvoke<TArgs extends unknown[], TReturn>(\n fn: (...args: TArgs) => TReturn,\n ): (...args: TArgs) => TReturn {\n return this.client.withSpan(\n this.traceFunctionKey,\n { name: this.traceFunctionKey, type: \"agent\", surface: \"inherit\" },\n fn,\n )\n }\n}\n","/**\n * OpenAI Agents SDK handler for Bitfab tracing.\n *\n * The OpenAI Agents SDK is instrumented in two layers:\n *\n * 1. A process-wide `TracingProcessor` (see `getOpenAiTracingProcessor` /\n * `BitfabOpenAITracingProcessor`) registered once with `addTraceProcessor`.\n * It captures everything *inside* a run - LLM calls, tool calls, handoffs -\n * as Bitfab spans.\n * 2. This handler's `wrapRun`, which owns the *root*. The processor never sees\n * the caller's input (the SDK's trace events don't carry it), so a\n * processor-only run records a root span with an empty input and is not\n * replayable. `wrapRun` is a thin drop-in for `run()` that opens a\n * `withSpan` root carrying the input and final output, so the run is\n * replayable with no hand-written `withSpan`. The processor's spans nest\n * underneath it automatically (it remaps onto the active span context).\n *\n * When `wrapRun` runs inside an enclosing Bitfab span (the replay auto-wrap, or\n * a caller's own `withSpan`), that span is already the replayable root: the\n * handler skips opening a second one and lets the processor nest the run's spans\n * under the existing root. This mirrors the Claude Agent SDK and LangGraph\n * handlers, which no-op their root span under an enclosing span, and keeps a\n * replayed run's span tree identical to the original (no doubled root agent\n * span).\n *\n * Use both together: register the processor once at startup, then call\n * `handler.wrapRun(agent, input)` instead of `run(agent, input)`.\n */\n\nimport { importOptionalPeer } from \"./optionalPeer.js\"\n\n// Local structural stand-ins for the OpenAI Agents SDK types this handler\n// touches. Declared here so neither this module nor the SDK's published `.d.ts`\n// references `@openai/agents` (an optional peer most consumers never install):\n// a top-level `import ... from \"@openai/agents\"` in the shipped types breaks a\n// consumer's `tsc` under `skipLibCheck: false` even when they never use this\n// handler. The stand-ins are deliberately loose supersets, so a consumer's real\n// `Agent` / run input is still assignable when they DO call `wrapRun`. The\n// concrete `@openai/agents` types enter only inside the function body (via\n// `importOptionalPeer<typeof import(\"@openai/agents\")>`), which the declaration\n// output erases.\n\n// biome-ignore lint/suspicious/noExplicitAny: structural stand-in for the agent SDK's `Agent<any, any>`\ntype AgentLike = any\n\n// The run input union `run()` accepts: a prompt string, a list of input items,\n// or a serialized run state. Items/state are opaque here (we only forward them).\ntype RunInput = string | unknown[] | Record<string, unknown>\n\n// The run options `run()` accepts; only `stream` is read by this handler.\ntype RunOptions = {\n stream?: boolean\n} & Record<string, unknown>\n\n// What this handler reads off a run result: streamed runs expose `completed`,\n// both variants expose `finalOutput`.\ntype RunResultLike = {\n finalOutput?: unknown\n completed?: Promise<void>\n}\n\n// The exact span options this handler passes to `withSpan`. Declared locally\n// (a structural subset of the client's `SpanOptions`, so the bound `withSpan`\n// is assignable) rather than imported from client.ts - that would create an\n// import cycle, since client.ts imports this handler. Mirrors how the other\n// framework handlers stay free of any client import.\ntype RootSpanOptions = {\n type: \"agent\"\n finalize: (result: unknown) => unknown | Promise<unknown>\n surface: \"inherit\"\n}\n\n// The subset of the Bitfab client this handler needs: a bound `withSpan`.\ntype WithSpanFn = <TArgs extends unknown[], TReturn>(\n traceFunctionKey: string,\n options: RootSpanOptions,\n fn: (...args: TArgs) => TReturn,\n) => (...args: TArgs) => TReturn\n\n// Returns the active Bitfab span context (or null) so wrapRun can detect an\n// enclosing span and skip opening its own root. Only nullness is read, so the\n// context shape is left opaque (avoids importing SpanContext from client.ts,\n// which would create an import cycle).\ntype GetActiveSpanContextFn = () => unknown | null\n\n/**\n * OpenAI Agents SDK handler that records a replayable root span around a run.\n *\n * ```typescript\n * import { Bitfab } from \"@bitfab/sdk\";\n * import { addTraceProcessor, Agent, run } from \"@openai/agents\";\n *\n * const bitfab = new Bitfab({ apiKey: \"...\" });\n * addTraceProcessor(bitfab.getOpenAiTracingProcessor()); // captures internals\n *\n * const agent = new Agent({ name: \"Researcher\", instructions: \"...\" });\n * const handler = bitfab.getOpenAiAgentHandler(\"research-topic\");\n *\n * // Swap run(agent, input) -> handler.wrapRun(agent, input)\n * const result = await handler.wrapRun(agent, \"Find X\");\n * return result.finalOutput;\n * ```\n */\nexport class BitfabOpenAIAgentHandler {\n private readonly traceFunctionKey: string\n private readonly withSpanFn: WithSpanFn\n private readonly getActiveSpanContext?: GetActiveSpanContextFn\n\n constructor(config: {\n traceFunctionKey: string\n withSpan: WithSpanFn\n getActiveSpanContext?: GetActiveSpanContextFn\n }) {\n this.traceFunctionKey = config.traceFunctionKey\n this.withSpanFn = config.withSpan\n this.getActiveSpanContext = config.getActiveSpanContext\n }\n\n /**\n * Drop-in replacement for the OpenAI Agents SDK's `run()` that records a\n * replayable root `agent` span.\n *\n * The `input` is captured as the root span's input (as a single positional\n * argument, so `replay(key, fn)` re-feeds it), and the run's `finalOutput`\n * is recorded as the root output. For streaming runs (`{ stream: true }`),\n * the result is handed back immediately and the final output is recorded\n * once the stream completes - first-byte latency is untouched.\n *\n * The process-wide tracing processor (`getOpenAiTracingProcessor`) must still\n * be registered: it captures the LLM/tool/handoff spans that nest beneath\n * this root.\n */\n async wrapRun(\n agent: AgentLike,\n input: RunInput,\n options?: RunOptions,\n ): Promise<RunResultLike> {\n // Dynamic import keeps `@openai/agents` an optional peer dependency and\n // matches the SDK's browser-safe import rules (no static Node/agent SDK\n // imports). Callers of this handler necessarily have the package installed.\n // Routed through `importOptionalPeer` so the specifier never appears as a\n // literal - otherwise a consumer's bundler tries to resolve `@openai/agents`\n // at build time and fails even when they never use this handler.\n const { run } = await importOptionalPeer<typeof import(\"@openai/agents\")>([\n \"@openai\",\n \"agents\",\n ])\n\n // The local stand-in types are looser than `run()`'s real parameters, so\n // cast at the call boundary. These casts live in the function body, which\n // the declaration output erases, so no `@openai/agents` reference leaks\n // into the published `.d.ts`.\n type RunInputArg = Parameters<typeof run>[1]\n type RunOptionsArg = Parameters<typeof run>[2]\n\n // An enclosing span is already the replayable root: run directly and let the\n // processor nest the run's spans under it, instead of opening (and doubling)\n // a second root agent span. Covers the replay auto-wrap and a caller's own\n // withSpan; mirrors the Claude Agent SDK and LangGraph handlers.\n if (this.getActiveSpanContext?.() != null) {\n return run(\n agent,\n input as RunInputArg,\n options as RunOptionsArg,\n ) as Promise<RunResultLike>\n }\n\n const isStreaming = options?.stream === true\n\n // The recorded output is the run's final answer, not the (non-serializable)\n // result object. `finalize` records it without disturbing the caller's\n // return value; for streaming it also waits for the stream to drain so the\n // final output is present before the span is recorded.\n const finalize = async (result: unknown): Promise<unknown> => {\n const res = result as RunResultLike | null\n if (isStreaming && res?.completed) {\n try {\n await res.completed\n } catch {\n // Stream errors surface to the caller; the span still records what\n // final output is available rather than crashing finalize.\n }\n }\n return res?.finalOutput\n }\n\n const options_: RootSpanOptions = {\n type: \"agent\",\n finalize,\n surface: \"inherit\",\n }\n\n // Wrap a function that TAKES the input as its argument and call it with the\n // input, so withSpan records `[input]` as the root span input. run() runs\n // inside the withSpan context, so the tracing processor's onTraceStart sees\n // this root and nests the run's internal spans beneath it.\n const traced = this.withSpanFn(\n this.traceFunctionKey,\n options_,\n (agentInput: RunInput) =>\n run(\n agent,\n agentInput as RunInputArg,\n options as RunOptionsArg,\n ) as Promise<RunResultLike>,\n )\n\n return traced(input)\n }\n}\n","/**\n * The database branch a single replay item runs against.\n *\n * `getCurrentReplayBranch()` hands you one inside a replayed function when the\n * source trace carried a DB snapshot reference and the Bitfab service resolved\n * a branch from it. Outside a replay item, or when no branch was resolved, that\n * accessor returns null and your code keeps reading `process.env.DATABASE_URL`\n * the normal way.\n *\n * Immutable and scoped to one item: the accessor builds it from the replay\n * AsyncLocalStorage context, so parallel replay items each see their own branch\n * and no lease state lives on a long-lived object.\n *\n * Internally the resolved per-item state is a `DbBranchLease` (see\n * replayContext.ts), the SDK/server protocol term. Its useful fields are\n * exposed directly here so customer code never sees the word.\n */\n\nimport type { DbBranchLease, ReplayContext } from \"./replayContext.js\"\n\nexport class ReplayBranch implements Omit<DbBranchLease, \"databaseUrl\"> {\n /** The provider's own id for this branch, e.g. for correlating with its console. */\n declare readonly neonBranchId: string\n /** Env var name the customer's app reads, e.g. `DATABASE_URL`. */\n declare readonly envKey: string\n /** When this branch's URL stops being valid. ISO-8601. */\n declare readonly expiresAt: string\n /**\n * The instant this branch is pinned to: the source trace's wall clock, read\n * just before the traced function ran. Compare it against the trace you meant\n * to replay to confirm the branch is the right point in history.\n */\n declare readonly snapshotTimestamp?: string\n /** Deep link to the branch in the provider console, if available. */\n declare readonly providerConsoleUrl?: string\n /**\n * True if the branch is read-only. Use it to skip write operations during\n * replay when the provider returned a read-only lease.\n */\n declare readonly readOnly?: boolean\n /**\n * The branch's region, e.g. `aws-us-east-1`. A compute runs in its project's\n * region, so a replay runner elsewhere pays that round trip on every query.\n */\n declare readonly region?: string\n /** The historical trace ID that produced the input for this replay item. */\n declare readonly traceId: string\n\n // Genuine JS private fields, not TypeScript `private`: these must be\n // non-enumerable so neither the connection string nor the whole replay\n // context can ride along into a log line or a serialized payload.\n readonly #url: string\n readonly #context: ReplayContext\n\n /** @internal Built by `getCurrentReplayBranch()`; never constructed by callers. */\n constructor(lease: DbBranchLease, traceId: string, context: ReplayContext) {\n // Copy the lease wholesale minus the connection string, so a field the\n // server starts sending reaches customer code without an SDK release.\n // Everything here must stay a plain data property: `databaseUrl` is the\n // only member allowed to mark the branch as accessed.\n //\n // defineProperty, not Object.assign: assignment runs setters, so a lease\n // carrying a `__proto__` key would swap this object's prototype and leave\n // `databaseUrl` returning undefined, which reads as \"no branch\" and sends\n // the replay to the live database.\n const { databaseUrl, ...exposed } = lease\n for (const [key, value] of Object.entries(exposed)) {\n Object.defineProperty(this, key, {\n value,\n enumerable: true,\n configurable: true,\n })\n }\n Object.defineProperty(this, \"traceId\", {\n value: traceId,\n enumerable: true,\n configurable: true,\n })\n this.#url = databaseUrl\n this.#context = context\n }\n\n /**\n * Connection string for this item's branch. Point your database client at it\n * instead of the live database for the duration of the replayed call.\n *\n * Reading it records on the trace that the replayed code obtained the branch\n * URL, which is what separates \"a branch was provisioned\" from \"the branch\n * was actually used\". The other fields inspect the lease without exposing the\n * connection string, so they deliberately do not record anything. That is\n * also why this is a getter and not a plain field: the URL is absent from\n * `JSON.stringify(branch)` and from logging the object.\n */\n get databaseUrl(): string {\n this.#context.dbSnapshotAccessed = true\n return this.#url\n }\n}\n","import {\n type AsyncLocalStorageLike,\n asyncStorageReady,\n createAsyncLocalStorage,\n} from \"./asyncStorage.js\"\n\nexport interface SeedContext {\n traceId: string\n}\n\nlet seedContextStorage: AsyncLocalStorageLike<SeedContext | null> | null = null\nconst SEED_CONTEXT_STORAGE_SYMBOL = Symbol.for(\"bitfab.seedContextStorage\")\n\nexport const seedContextReady: Promise<void> = asyncStorageReady.then(() => {\n const shared = globalThis as typeof globalThis & Record<symbol, unknown>\n const existing = shared[SEED_CONTEXT_STORAGE_SYMBOL] as\n | AsyncLocalStorageLike<SeedContext | null>\n | undefined\n if (existing) {\n seedContextStorage = existing\n return\n }\n const created = createAsyncLocalStorage<SeedContext | null>()\n if (created) {\n shared[SEED_CONTEXT_STORAGE_SYMBOL] = created\n seedContextStorage = created\n }\n})\n\nexport function getSeedContext(): SeedContext | null {\n return seedContextStorage?.getStore() ?? null\n}\n\nexport function inSeedScope(): boolean {\n return getSeedContext() !== null\n}\n\nexport function runWithSeedContext<T>(ctx: SeedContext, fn: () => T): T {\n if (seedContextStorage) {\n return seedContextStorage.run(ctx, fn)\n }\n return fn()\n}\n","/**\n * Tracing utilities for external trace submission to Bitfab.\n *\n * This module provides utilities for sending external traces (e.g., from OpenAI API calls)\n * to Bitfab for monitoring and analysis.\n */\n\nimport { DEFAULT_SERVICE_URL } from \"./constants.js\"\nimport { type ApiKeyInput, HttpClient } from \"./http.js\"\nimport { finalizeSpanPayload } from \"./processorPayload.js\"\nimport { randomUuid } from \"./randomUuid.js\"\n\n// Minimal structural shapes of the OpenAI Agents SDK's `Trace` and `Span`,\n// declared locally so neither this module nor the SDK's published `.d.ts`\n// references `@openai/agents` - an optional peer many consumers never install.\n// We only touch the fields below; the real SDK objects are structural\n// supersets, so a consumer's `addTraceProcessor(processor)` still type-checks.\ninterface Trace {\n traceId: string\n toJSON(): unknown\n}\n\n// biome-ignore lint/suspicious/noExplicitAny: mirrors the agent SDK's `Span<any>`\ninterface Span<_T = any> {\n traceId?: string\n toJSON(): unknown\n spanData?: {\n type?: string\n _input?: unknown\n _response?: unknown\n } | null\n}\n\nexport interface TraceResponse {\n traceId: string\n status: \"success\"\n}\n\nexport interface ActiveSpanContext {\n traceId: string\n spanId: string\n}\n\n/**\n * TracingProcessor interface from OpenAI Agents SDK v0.3.7\n */\nexport interface TracingProcessor {\n onTraceStart(trace: Trace): Promise<void>\n onTraceEnd(trace: Trace): Promise<void>\n // biome-ignore lint/suspicious/noExplicitAny: OpenAI Agents SDK uses any for span data\n onSpanStart(span: Span<any>): Promise<void>\n // biome-ignore lint/suspicious/noExplicitAny: OpenAI Agents SDK uses any for span data\n onSpanEnd(span: Span<any>): Promise<void>\n forceFlush(): Promise<void>\n shutdown(timeout?: number): Promise<void>\n}\n\n/**\n * Tracing processor for OpenAI Agents SDK integration.\n *\n * Implements the TracingProcessor interface from the OpenAI Agents SDK to\n * automatically capture traces and spans and send them to Bitfab for\n * monitoring and analysis.\n *\n * Example usage:\n * ```typescript\n * import { Bitfab } from 'bitfab';\n * import { addTraceProcessor } from '@openai/agents';\n *\n * const client = new Bitfab({ apiKey: 'your-api-key' });\n * const processor = client.getOpenAiTracingProcessor();\n * addTraceProcessor(processor);\n * ```\n */\nexport class BitfabOpenAITracingProcessor implements TracingProcessor {\n private readonly httpClient: HttpClient\n private readonly ownsHttpClient: boolean\n private activeTraces: Record<string, Trace> = {}\n private readonly getActiveSpanContext: (() => ActiveSpanContext | null) | null\n private activeSpanMappings: Record<string, ActiveSpanContext> = {}\n private canonicalTraceIds: Record<string, string> = {}\n\n private getCanonicalTraceId(sourceTraceId: string): string {\n const existing = this.canonicalTraceIds[sourceTraceId]\n if (existing) {\n return existing\n }\n\n const created = randomUuid()\n this.canonicalTraceIds[sourceTraceId] = created\n return created\n }\n\n /**\n * Initialize the tracing processor.\n *\n * @param config - Configuration options\n */\n constructor(config: {\n apiKey?: ApiKeyInput\n serviceUrl?: string\n timeout?: number\n getActiveSpanContext?: () => ActiveSpanContext | null\n /**\n * The owning `Bitfab` client's HTTP client. Supplied by\n * `getOpenAiTracingProcessor()` so this processor shares that client's\n * single span-transport worker instead of starting a second one.\n * @internal\n */\n _httpClient?: HttpClient\n }) {\n this.ownsHttpClient = config._httpClient === undefined\n this.httpClient =\n config._httpClient ??\n new HttpClient({\n apiKey: config.apiKey,\n serviceUrl: config.serviceUrl ?? DEFAULT_SERVICE_URL,\n timeout: config.timeout ?? 10000,\n })\n this.getActiveSpanContext = config.getActiveSpanContext ?? null\n }\n\n /**\n * Flush and release the span transport this processor started. A no-op when\n * the processor borrowed a `Bitfab` client's HTTP client: that client's\n * `close()` owns the worker's lifetime.\n */\n async close(timeoutMs?: number): Promise<boolean> {\n return this.ownsHttpClient ? this.httpClient.close(timeoutMs) : true\n }\n\n /**\n * Called when a trace is started.\n * If there's an active withSpan context, the trace ID is remapped to the\n * outer trace and sent to pre-create the external_traces row on the server.\n */\n async onTraceStart(trace: Trace): Promise<void> {\n this.activeTraces[trace.traceId] = trace\n\n const activeContext = this.getActiveSpanContext?.()\n if (activeContext) {\n this.activeSpanMappings[trace.traceId] = activeContext\n }\n\n const canonicalTraceId =\n activeContext?.traceId ?? this.getCanonicalTraceId(trace.traceId)\n this.canonicalTraceIds[trace.traceId] = canonicalTraceId\n\n this.sendTrace(trace, {\n id: canonicalTraceId,\n sourceTraceId: activeContext?.traceId,\n })\n }\n\n /**\n * Called when a trace is ended.\n * If mapped to a withSpan trace, sends with remapped ID and completed=false\n * since the parent withSpan handles completion.\n */\n async onTraceEnd(trace: Trace): Promise<void> {\n const mapping = this.activeSpanMappings[trace.traceId]\n\n this.sendTrace(trace, {\n completed: mapping === undefined,\n id: mapping?.traceId ?? this.getCanonicalTraceId(trace.traceId),\n sourceTraceId: mapping?.traceId,\n })\n\n delete this.activeSpanMappings[trace.traceId]\n delete this.canonicalTraceIds[trace.traceId]\n delete this.activeTraces[trace.traceId]\n }\n\n /**\n * Called when a span is started. Span payloads are authoritative completed\n * snapshots, so start notifications do not cross the transport boundary.\n */\n // biome-ignore lint/suspicious/noExplicitAny: OpenAI Agents SDK uses any for span data\n async onSpanStart(_span: Span<any>): Promise<void> {}\n\n /**\n * Called when a span is ended.\n *\n * Send the finalized span snapshot to Bitfab for complete trace capture.\n */\n // biome-ignore lint/suspicious/noExplicitAny: OpenAI Agents SDK uses any for span data\n async onSpanEnd(span: Span<any>): Promise<void> {\n // Send the completed span to Bitfab (fire-and-forget).\n this.sendSpan(span)\n }\n\n /**\n * Called when a trace is being flushed.\n */\n async forceFlush(): Promise<void> {\n // Spans now enter a buffered transport, so this is no longer a no-op: the\n // agent SDK's own flush would otherwise return while Bitfab spans sit\n // queued, and a run that flushes then exits would lose them.\n await this.httpClient.waitForPendingRequests()\n }\n\n /**\n * Called when the trace processor is shutting down.\n */\n async shutdown(timeout?: number): Promise<void> {\n this.activeTraces = {}\n this.activeSpanMappings = {}\n this.canonicalTraceIds = {}\n // A directly constructed processor owns its transport worker and no\n // Bitfab client will ever close it, so this is its only release point.\n // A borrowed client's worker is left alone (see close()).\n await this.close(timeout)\n }\n\n /**\n * Send trace to Bitfab API (fire-and-forget).\n * When traceIdOverride is provided, the trace ID is remapped to link\n * the OpenAI trace into an outer withSpan trace.\n */\n private sendTrace(\n trace: Trace,\n options: {\n completed?: boolean\n id?: string\n sourceTraceId?: string\n } = {},\n ): void {\n try {\n const traceData = trace.toJSON() as Record<string, unknown>\n if (options.sourceTraceId) {\n traceData.id = options.sourceTraceId\n }\n\n this.httpClient.sendExternalTrace({\n ...(options.id && { id: options.id }),\n type: \"openai\",\n source: \"typescript-sdk-openai-tracing\",\n externalTrace: traceData,\n completed: options.completed ?? false,\n })\n } catch {\n // Silently ignore - never crash the host app\n }\n }\n\n /**\n * Export span to JSON object, collecting any errors.\n */\n private exportSpan(\n // biome-ignore lint/suspicious/noExplicitAny: OpenAI Agents SDK uses any for span data\n span: Span<any>,\n ): [\n Record<string, unknown>,\n Array<{ source: string; step: string; error: string }>,\n ] {\n const errors: Array<{ source: string; step: string; error: string }> = []\n let serializedSpan: Record<string, unknown>\n\n try {\n const jsonResult = span.toJSON()\n if (typeof jsonResult !== \"object\" || jsonResult === null) {\n errors.push({\n source: \"sdk\",\n step: \"span.toJSON()\",\n error: `Returned unexpected type: ${typeof jsonResult}`,\n })\n serializedSpan = {}\n } else {\n serializedSpan = jsonResult as Record<string, unknown>\n }\n } catch (error) {\n errors.push({\n source: \"sdk\",\n step: \"span.toJSON()\",\n error: error instanceof Error ? error.message : String(error),\n })\n serializedSpan = {}\n }\n\n if (!serializedSpan.span_data) {\n serializedSpan.span_data = {} as Record<string, unknown>\n }\n\n return [serializedSpan, errors]\n }\n\n /**\n * Extract and add input/response to serialized span, updating errors list.\n */\n private extractSpanInputResponse(\n // biome-ignore lint/suspicious/noExplicitAny: OpenAI Agents SDK uses any for span data\n span: Span<any>,\n serializedSpan: Record<string, unknown>,\n errors: Array<{ source: string; step: string; error: string }>,\n ): void {\n // Only ResponseSpanData hides its content from toJSON(): the SDK's\n // removePrivateFields strips its _input/_response, so we recover them here.\n // Every other span type (function, generation, agent, custom, ...) already\n // carries its data in span_data, so writing here would clobber a real input\n // with an empty placeholder. Gate strictly to response spans, and only set a\n // field when the value is actually present (never stamp []/null).\n if (span.spanData?.type !== \"response\") {\n return\n }\n\n const spanData = serializedSpan.span_data as Record<string, unknown>\n\n try {\n const input = span.spanData?._input\n if (input !== undefined) {\n spanData.input = input\n }\n } catch (error) {\n errors.push({\n source: \"sdk\",\n step: \"access_input\",\n error: error instanceof Error ? error.message : String(error),\n })\n }\n\n try {\n const response = span.spanData?._response\n if (response !== undefined) {\n spanData.response = response\n }\n } catch (error) {\n errors.push({\n source: \"sdk\",\n step: \"access_response\",\n error: error instanceof Error ? error.message : String(error),\n })\n }\n }\n\n /**\n * If the span's trace is mapped to a withSpan trace, rewrite trace_id and parent_id.\n */\n private applySpanOverrides(\n serializedSpan: Record<string, unknown>,\n traceId: string,\n ): void {\n const mapping = this.activeSpanMappings[traceId]\n if (mapping) {\n serializedSpan.trace_id = mapping.traceId\n if (!serializedSpan.parent_id) {\n serializedSpan.parent_id = mapping.spanId\n }\n }\n }\n\n /**\n * Build span payload for the external spans API.\n */\n private buildSpanPayload(\n serializedSpan: Record<string, unknown>,\n errors: Array<{ source: string; step: string; error: string }>,\n ): Record<string, unknown> {\n const payload: Record<string, unknown> = {\n id: randomUuid(),\n type: \"openai\",\n source: \"typescript-sdk-openai-tracing\",\n sourceTraceId: serializedSpan.trace_id ?? \"unknown\",\n rawSpan: serializedSpan,\n }\n\n if (errors.length > 0) {\n payload.errors = errors\n }\n\n // Sanitize the whole span (the raw OpenAI span_data is otherwise shipped\n // unsanitized, relying only on the http-layer net) and mark a lossy capture\n // non-replayable, merging with the SDK-level errors collected above.\n return finalizeSpanPayload(payload)\n }\n\n /**\n * Send span to Bitfab API (fire-and-forget).\n * If the span belongs to a trace mapped to a withSpan trace, the trace_id\n * and parent_id are rewritten to link the span into the withSpan tree.\n */\n private sendSpan(\n // biome-ignore lint/suspicious/noExplicitAny: OpenAI Agents SDK uses any for span data\n span: Span<any>,\n ): void {\n const errors: Array<{ source: string; step: string; error: string }> = []\n const [serializedSpan, exportErrors] = this.exportSpan(span)\n errors.push(...exportErrors)\n\n this.extractSpanInputResponse(span, serializedSpan, errors)\n\n this.applySpanOverrides(serializedSpan, span.traceId ?? \"\")\n\n const payload = this.buildSpanPayload(serializedSpan, errors)\n const canonicalTraceId = span.traceId\n ? this.getCanonicalTraceId(span.traceId)\n : undefined\n if (canonicalTraceId) {\n payload.traceId = canonicalTraceId\n }\n\n this.httpClient.sendExternalSpan(payload)\n }\n}\n","/**\n * Vercel AI SDK integration for Bitfab tracing.\n *\n * The Vercel AI SDK (`ai`) routes every `generateText` / `streamText` /\n * `generateObject` / `streamObject` call through a language model. Bitfab hooks\n * that model with a *language-model middleware* (`wrapLanguageModel`), so each\n * model call is captured as a keyed `llm` span with no hand-written `withSpan`:\n *\n * ```typescript\n * import { Bitfab } from \"@bitfab/sdk\";\n * import { wrapLanguageModel, streamText } from \"ai\";\n * import { openai } from \"@ai-sdk/openai\";\n *\n * const bitfab = new Bitfab({ apiKey: \"...\" });\n *\n * const model = wrapLanguageModel({\n * model: openai(\"gpt-4o\"),\n * middleware: bitfab.getVercelAiMiddleware(\"chat-turn\"),\n * });\n *\n * const result = streamText({ model, messages });\n * return result.toUIMessageStreamResponse(); // live stream untouched\n * ```\n *\n * The span records the call parameters (the prompt/messages) as its input and a\n * serializable summary (`{ text, toolCalls, usage, finishReason }`) as its\n * output. Streaming is handled by passing the model's stream through a\n * transform that accumulates the assembled text/usage as the caller consumes\n * it: the live stream is handed back unchanged (first-byte latency untouched)\n * and the span is finalized once the stream completes.\n *\n * The middleware is fully duck-typed (no static or dynamic `ai` import), so it\n * adds no dependency and is browser-safe. It works with `ai` v5 and v6.\n */\n\n// The exact span options this middleware passes to `withSpan`. Declared locally\n// (a structural subset of the client's `SpanOptions`, so the bound `withSpan`\n// is assignable) rather than imported from client.ts - that would create an\n// import cycle, since client.ts imports this handler. Mirrors how the other\n// framework handlers stay free of any client import.\ntype LlmSpanOptions = {\n type: \"llm\"\n finalize: (result: unknown) => unknown | Promise<unknown>\n surface: \"inherit\"\n}\n\n// The subset of the Bitfab client this middleware needs: a bound `withSpan`.\ntype WithSpanFn = <TArgs extends unknown[], TReturn>(\n traceFunctionKey: string,\n options: LlmSpanOptions,\n fn: (...args: TArgs) => TReturn,\n) => (...args: TArgs) => TReturn\n\n/**\n * Duck-typed subset of the Vercel AI SDK language-model call parameters. The\n * only field we read for the span input is `prompt` (the messages), but the\n * whole object is recorded so the call is reconstructable on replay.\n */\nexport interface VercelCallParams {\n prompt?: unknown\n [key: string]: unknown\n}\n\n/** A content part of a non-streaming `doGenerate` result. */\ninterface VercelContentPart {\n type: string\n text?: string\n toolCallId?: string\n toolName?: string\n // v3 names tool arguments `input`; v5/v2 used `args`.\n input?: unknown\n args?: unknown\n}\n\n/** Duck-typed subset of a non-streaming `doGenerate` result. */\nexport interface VercelGenerateResult {\n content?: VercelContentPart[]\n // Some providers expose a flattened `text`; prefer it when present.\n text?: string\n usage?: unknown\n finishReason?: unknown\n [key: string]: unknown\n}\n\n/** Duck-typed subset of a single streaming part from `doStream`. */\ninterface VercelStreamPart {\n type: string\n // v3 text-delta carries `delta`; v2 carried `textDelta`.\n delta?: string\n textDelta?: string\n toolCallId?: string\n toolName?: string\n input?: unknown\n args?: unknown\n usage?: unknown\n finishReason?: unknown\n}\n\n/** Duck-typed subset of a streaming `doStream` result. */\nexport interface VercelStreamResult {\n stream: ReadableStream<VercelStreamPart>\n [key: string]: unknown\n}\n\ninterface MiddlewareCall<TResult> {\n doGenerate: () => PromiseLike<VercelGenerateResult>\n doStream: () => PromiseLike<VercelStreamResult>\n params: VercelCallParams\n model: unknown\n __result?: TResult\n}\n\n/**\n * The structural shape of a Vercel AI SDK language-model middleware. Matches\n * `LanguageModelV3Middleware` from `@ai-sdk/provider` without importing it, so\n * the SDK stays dependency-free. `wrapLanguageModel` only reads the method\n * fields (it ignores `specificationVersion`), so this object drops straight in.\n */\nexport interface BitfabLanguageModelMiddleware {\n specificationVersion: \"v3\"\n // The wrap methods hand the provider's own result straight back (only the\n // span output is derived from it), so the return is typed `any` to stay\n // assignable to `LanguageModelV{2,3}Middleware` across AI SDK majors - the\n // SDK's strict result types (which require `warnings`, `content`, etc.) are a\n // superset of the duck-typed subset declared here. Implementation returns the\n // precise `VercelGenerateResult` / `VercelStreamResult` shapes.\n wrapGenerate: (\n options: MiddlewareCall<VercelGenerateResult>,\n // biome-ignore lint/suspicious/noExplicitAny: passthrough of the provider result; see note above\n ) => Promise<any>\n wrapStream: (\n options: MiddlewareCall<VercelStreamResult>,\n // biome-ignore lint/suspicious/noExplicitAny: passthrough of the provider result; see note above\n ) => Promise<any>\n}\n\n/** The provider/model that served a call (e.g. `{ provider, modelId }`). */\ntype ModelLabel = { provider?: string; modelId?: string }\n\n/** The serializable summary recorded as a model call's span output. */\ntype CallSummary = {\n text: string\n toolCalls?: unknown[]\n usage?: unknown\n finishReason?: unknown\n // Which provider/model actually served this call. Invaluable when a single\n // wrapped key spans multiple providers (e.g. a Claude-primary, GPT-4o-fallback\n // setup) so each span shows who answered.\n model?: ModelLabel\n}\n\n/** Read `{ provider, modelId }` off an AI SDK language model, defensively. */\nfunction modelLabel(model: unknown): ModelLabel | undefined {\n if (!model || typeof model !== \"object\") {\n return undefined\n }\n const m = model as { provider?: unknown; modelId?: unknown }\n const provider = typeof m.provider === \"string\" ? m.provider : undefined\n const modelId = typeof m.modelId === \"string\" ? m.modelId : undefined\n if (provider == null && modelId == null) {\n return undefined\n }\n return { provider, modelId }\n}\n\n/** Collapse a non-streaming generate result into a serializable span output. */\nfunction summarizeGenerate(\n result: VercelGenerateResult,\n model: ModelLabel | undefined,\n): CallSummary {\n const content = Array.isArray(result.content) ? result.content : []\n const text =\n typeof result.text === \"string\"\n ? result.text\n : content\n .filter((p) => p.type === \"text\" && typeof p.text === \"string\")\n .map((p) => p.text)\n .join(\"\")\n const toolCalls = content\n .filter((p) => p.type === \"tool-call\")\n .map((p) => ({\n toolCallId: p.toolCallId,\n toolName: p.toolName,\n input: p.input ?? p.args,\n }))\n const summary: CallSummary = {\n text,\n toolCalls: toolCalls.length > 0 ? toolCalls : undefined,\n usage: result.usage,\n finishReason: result.finishReason,\n }\n if (model) {\n summary.model = model\n }\n return summary\n}\n\n/**\n * A pass-through transform that accumulates the assembled text, tool calls, and\n * final usage from a model's stream, resolving `onComplete` with that summary\n * once the stream finishes. Parts are enqueued unchanged so the caller's stream\n * is untouched; capture errors are swallowed so tracing never breaks the stream.\n */\nfunction accumulateStream(\n onComplete: (summary: CallSummary) => void,\n model: ModelLabel | undefined,\n): TransformStream<VercelStreamPart, VercelStreamPart> {\n let text = \"\"\n const toolCalls: unknown[] = []\n let usage: unknown\n let finishReason: unknown\n let completed = false\n const complete = (): void => {\n if (completed) {\n return\n }\n completed = true\n const summary: CallSummary = {\n text,\n toolCalls: toolCalls.length > 0 ? toolCalls : undefined,\n usage,\n finishReason,\n }\n if (model) {\n summary.model = model\n }\n onComplete(summary)\n }\n return new TransformStream<VercelStreamPart, VercelStreamPart>({\n transform(part, controller) {\n try {\n if (part?.type === \"text-delta\") {\n text += part.delta ?? part.textDelta ?? \"\"\n } else if (part?.type === \"tool-call\") {\n toolCalls.push({\n toolCallId: part.toolCallId,\n toolName: part.toolName,\n input: part.input ?? part.args,\n })\n } else if (part?.type === \"finish\") {\n usage = part.usage\n finishReason = part.finishReason\n // The `finish` part is the stream's last meaningful event; resolve\n // the span output as soon as it passes rather than waiting for the\n // reader to close the stream.\n complete()\n }\n } catch {\n // Never let span capture break the caller's stream.\n }\n controller.enqueue(part)\n },\n flush() {\n // Fallback when a provider omits an explicit `finish` part.\n complete()\n },\n })\n}\n\n/**\n * Vercel AI SDK middleware that records each language-model call as a keyed\n * `llm` span. Obtain it from {@link BitfabClient.getVercelAiMiddleware} rather\n * than constructing it directly.\n */\nexport class BitfabVercelAiHandler {\n private readonly traceFunctionKey: string\n private readonly withSpanFn: WithSpanFn\n\n constructor(config: { traceFunctionKey: string; withSpan: WithSpanFn }) {\n this.traceFunctionKey = config.traceFunctionKey\n this.withSpanFn = config.withSpan\n }\n\n /** The `wrapLanguageModel` middleware object for this trace function key. */\n get middleware(): BitfabLanguageModelMiddleware {\n const key = this.traceFunctionKey\n const withSpan = this.withSpanFn\n return {\n specificationVersion: \"v3\",\n wrapGenerate: async ({ doGenerate, params, model }) => {\n const label = modelLabel(model)\n // Wrap a function that TAKES the call params as its argument and call it\n // with them, so withSpan records `[params]` (the prompt/settings) as the\n // span input. `finalize` records the serializable summary as the output\n // while the raw result is returned to the AI SDK unchanged.\n const traced = withSpan<\n [VercelCallParams],\n Promise<VercelGenerateResult>\n >(\n key,\n {\n type: \"llm\",\n finalize: (result) =>\n summarizeGenerate((result ?? {}) as VercelGenerateResult, label),\n surface: \"inherit\",\n },\n () => doGenerate() as Promise<VercelGenerateResult>,\n )\n return traced(params)\n },\n wrapStream: async ({ doStream, params, model }) => {\n const label = modelLabel(model)\n let resolveSummary: (summary: CallSummary) => void = () => {}\n const summary = new Promise<CallSummary>((resolve) => {\n resolveSummary = resolve\n })\n const traced = withSpan<\n [VercelCallParams],\n Promise<VercelStreamResult>\n >(\n key,\n // The wrapped fn returns immediately with the live stream, so the span\n // output cannot be read from the return value. `finalize` instead\n // awaits the summary the accumulator resolves once the stream drains.\n { type: \"llm\", finalize: () => summary, surface: \"inherit\" },\n async () => {\n const result = await doStream()\n const stream = result.stream.pipeThrough(\n accumulateStream(resolveSummary, label),\n )\n return { ...result, stream }\n },\n )\n return traced(params)\n },\n }\n }\n}\n","/**\n * Bitfab client for provider-based API calls.\n */\n\nexport type {\n AllowedEnvVars,\n BamlExecutionResult,\n ProviderDefinition,\n} from \"./baml.js\"\nexport { BitfabClaudeAgentHandler } from \"./claudeAgentSdk.js\"\nexport type {\n BitfabConfig,\n CaptureSurface,\n CaptureWhen,\n CurrentSpan,\n CurrentTrace,\n DetachedTrace,\n NodeMethodDecorator,\n NodeOptions,\n SeedCaseOptions,\n SeedRunOptions,\n SpanMethodDecorator,\n SpanMethodDecoratorContext,\n SpanOptions,\n SpanType,\n WrapBAMLOptions,\n WrappedBamlFn,\n} from \"./client.js\"\nexport {\n Bitfab,\n BitfabError,\n BitfabFunction,\n getCurrentReplayBranch,\n getCurrentSpan,\n getCurrentTrace,\n MixedTracingError,\n} from \"./client.js\"\nexport { __version__, DEFAULT_SERVICE_URL } from \"./constants.js\"\nexport type {\n AddDatasetGradersResult,\n AddDatasetTracesResult,\n Dataset,\n DatasetGraderRef,\n DatasetTraceIds,\n GraderRerun,\n GraderRerunProgress,\n GraderRerunResult,\n GraderRerunStatus,\n ListDatasetsParams,\n RemoveDatasetGradersResult,\n RemoveDatasetTracesResult,\n RerunGradersOptions,\n RerunGradersResult,\n SaveDatasetParams,\n SaveDatasetResult,\n} from \"./datasets.js\"\nexport { DatasetsClient } from \"./datasets.js\"\nexport type {\n DbSnapshotConfig,\n DbSnapshotProvider,\n DbSnapshotRef,\n} from \"./dbSnapshot.js\"\nexport { SUPPORTED_PROVIDERS } from \"./dbSnapshot.js\"\nexport { finalizers } from \"./finalizers.js\"\nexport type {\n CapturedSpan,\n SpanLookup,\n SpanOccurrence,\n} from \"./http.js\"\nexport { flushTraces, HttpClient } from \"./http.js\"\nexport {\n BitfabLangGraphCallbackHandler,\n BitfabLangGraphCallbackHandler as BitfabLangChainCallbackHandler,\n} from \"./langgraph.js\"\nexport {\n BitfabLangGraphIntegration,\n type LangGraphIntegrationOptions,\n} from \"./langgraphIntegration.js\"\nexport type {\n MockOverride,\n MockOverrideCtx,\n MockOverrideInput,\n MockOverrideResolver,\n MockValue,\n NodeMatcher,\n SpanNodeMeta,\n} from \"./mockOverride.js\"\nexport { NO_MOCK_OVERRIDE } from \"./mockOverride.js\"\nexport { BitfabOpenAIAgentHandler } from \"./openaiAgentSdk.js\"\nexport type {\n AdaptContext,\n AdaptInputsFn,\n CodeChangeFile,\n DbBranchOptions,\n MockStrategy,\n ReplayItem,\n ReplayItemFinishProgress,\n ReplayItemStartProgress,\n ReplayOptions,\n ReplayProgress,\n ReplayProgressItem,\n ReplayResult,\n TokenUsage,\n TraceIngestionType,\n TraceOutline,\n TraceOutlineSpan,\n TraceOutlineSpanError,\n} from \"./replay.js\"\nexport {\n BITFAB_PROGRESS_PREFIX,\n DbBranchReplayError,\n ReplayError,\n reportReplayProgress,\n serializeReplayResult,\n} from \"./replay.js\"\nexport type { ReplayBranch } from \"./replayBranch.js\"\nexport type { DbBranchTimings } from \"./replayContext.js\"\nexport type {\n ReplayOptionsFactory,\n ReplayRegistration,\n ReplayRegistry,\n ReplayRegistryContext,\n ReplayRegistryOptions,\n SeedCase,\n SeedResult,\n} from \"./replayRegistry.js\"\nexport {\n defineReplayRegistry,\n seedFromRegistry,\n} from \"./replayRegistry.js\"\nexport type {\n ActiveSpanContext,\n TraceResponse,\n TracingProcessor,\n} from \"./tracing.js\"\nexport { BitfabOpenAITracingProcessor } from \"./tracing.js\"\nexport type {\n BitfabLanguageModelMiddleware,\n VercelCallParams,\n VercelGenerateResult,\n VercelStreamResult,\n} from \"./vercelAiSdk.js\"\nexport { BitfabVercelAiHandler } from \"./vercelAiSdk.js\"\n","/**\n * Prebuilt `finalize` helpers for `withSpan({ finalize }, fn)`.\n *\n * A streaming function returns a live stream object that the caller consumes\n * directly (SSE, a UI message stream). `withSpan` hands that object back\n * unchanged; a `finalize` function tells it what serializable view to record\n * as the span output instead of the raw, non-serializable stream.\n */\n\n/**\n * Duck-typed subset of the Vercel AI SDK `streamText` / `streamObject`\n * result. Each field is exposed as a promise that resolves once the stream\n * finishes; reading them does not consume the live stream (the AI SDK tees\n * internally), so the caller's own consumption is unaffected. We avoid a\n * hard dependency on `ai` by matching structurally.\n */\ninterface AiSdkStreamResultLike {\n text?: Promise<string> | string\n usage?: Promise<unknown> | unknown\n totalUsage?: Promise<unknown> | unknown\n finishReason?: Promise<unknown> | unknown\n toolCalls?: Promise<unknown> | unknown\n toolResults?: Promise<unknown> | unknown\n reasoningText?: Promise<string> | string\n}\n\n/** Await a value that may be a promise, swallowing rejection to `undefined`. */\nasync function settle<T>(\n value: Promise<T> | T | undefined,\n): Promise<T | undefined> {\n try {\n return await value\n } catch {\n return undefined\n }\n}\n\n/**\n * Drain a Vercel AI SDK streaming result into a serializable, replayable\n * span output: `{ text, usage, finishReason, toolCalls, toolResults }`.\n *\n * Pass it straight to `withSpan`:\n *\n * ```ts\n * import { finalizers } from \"@bitfab/sdk\"\n *\n * const traced = bitfab.withSpan(\n * \"chat-turn\",\n * { type: \"agent\", finalize: finalizers.aiSdk },\n * () => streamText({ model, messages }),\n * )\n * const result = traced() // caller still gets the live StreamTextResult\n * return result.toUIMessageStreamResponse()\n * ```\n *\n * Never throws: any field that is absent or rejects is recorded as\n * `undefined` so finalize never drops the span.\n */\nasync function aiSdk(result: unknown): Promise<Record<string, unknown>> {\n const r = (result ?? {}) as AiSdkStreamResultLike\n const [text, usage, totalUsage, finishReason, toolCalls, toolResults] =\n await Promise.all([\n settle(r.text),\n settle(r.usage),\n settle(r.totalUsage),\n settle(r.finishReason),\n settle(r.toolCalls),\n settle(r.toolResults),\n ])\n return {\n text,\n usage: totalUsage ?? usage,\n finishReason,\n toolCalls,\n toolResults,\n }\n}\n\n/**\n * Collect a `ReadableStream`'s chunks into an array for the span output,\n * via a `tee()` so the caller's branch is untouched. The caller MUST use\n * the returned stream, not the original, since a stream can only be read\n * once:\n *\n * ```ts\n * let live: ReadableStream\n * const traced = bitfab.withSpan(\n * \"render\",\n * { finalize: (r) => finalizers.readableStream(r, (s) => { live = s }) },\n * () => makeReadableStream(),\n * )\n * traced()\n * return new Response(live!)\n * ```\n *\n * Prefer `aiSdk` for the Vercel AI SDK, whose result tees internally and\n * needs no caller rewiring.\n */\nasync function readableStream(\n stream: ReadableStream,\n onLive: (live: ReadableStream) => void,\n): Promise<{ chunks: unknown[] }> {\n const [live, copy] = stream.tee()\n onLive(live)\n const chunks: unknown[] = []\n const reader = copy.getReader()\n try {\n for (;;) {\n const { done, value } = await reader.read()\n if (done) {\n break\n }\n chunks.push(value)\n }\n } catch {\n // Never let span capture crash the host app.\n }\n return { chunks }\n}\n\nexport const finalizers = {\n aiSdk,\n readableStream,\n}\n","import type { Bitfab } from \"./client.js\"\nimport { BitfabError } from \"./errors.js\"\nimport {\n type CodeChangeFile,\n ReplayError,\n type ReplayItem,\n type ReplayOptions,\n type ReplayResult,\n reportReplayProgress,\n serializeReplayResult,\n} from \"./replay.js\"\n\ntype ReplayFunction = (\n // biome-ignore lint/suspicious/noExplicitAny: replay functions receive historical arguments\n ...args: any[]\n) => unknown | Promise<unknown>\n\nexport type ReplayRegistryOptions = Omit<\n ReplayOptions,\n \"onItemStart\" | \"onItemFinish\" | \"onProgress\"\n>\n\nexport interface ReplayRegistryContext {\n /** Values supplied through `--params` and repeated `--param name=value`. */\n params: Readonly<Record<string, unknown>>\n}\n\nexport type ReplayOptionsFactory = (\n context: ReplayRegistryContext,\n) => ReplayRegistryOptions | Promise<ReplayRegistryOptions>\n\nexport interface ReplayRegistration {\n /** Client instance used by the production traced function. */\n client: Bitfab\n /** The exact traced function production calls. */\n fn: ReplayFunction\n /**\n * Required for handler-instrumented or otherwise plain callables. Omit for a\n * `withSpan`-wrapped function and the registry reads the wrapper's key.\n */\n traceFunctionKey?: string\n /**\n * Per-function replay behavior and defaults. Put executable configuration\n * such as `mockOverride` and `adaptInputs` here; command-line values override\n * overlapping scalar defaults such as `mock` and `maxConcurrency`.\n */\n options?: ReplayRegistryOptions\n /** Build executable replay behavior from caller-supplied CLI parameters. */\n optionsFactory?: ReplayOptionsFactory\n}\n\nexport type ReplayRegistry = Record<string, ReplayRegistration>\n\n/**\n * Define the project-owned list of replayable functions.\n *\n * The registry is deliberately data-only: the SDK owns the replay CLI, so an\n * SDK upgrade can add replay features without regenerating the project file.\n */\nexport function defineReplayRegistry<TRegistry extends ReplayRegistry>(\n registry: TRegistry,\n): TRegistry {\n return registry\n}\n\nexport interface ReplayCliIo {\n stdout?: (line: string) => void\n stderr?: (line: string) => void\n readFile?: (path: string) => Promise<string>\n}\n\ninterface ReplayCliArgs {\n pipeline: string\n limit?: number\n attempts?: number\n traceIds?: string[]\n name?: string\n maxConcurrency?: number\n codeChangePath?: string\n experimentGroupId?: string\n datasetId?: string\n graderIds?: string[]\n mock?: \"none\" | \"all\" | \"marked\"\n dbBranch?: boolean\n noCodeChange?: boolean\n dryRun?: boolean\n paramsPath?: string\n params: string[]\n}\n\ninterface CodeChange {\n description: string\n files: CodeChangeFile[]\n}\n\nconst VALUE_FLAGS = new Set([\n \"--limit\",\n \"--attempts\",\n \"--trace-ids\",\n \"--name\",\n \"--concurrency\",\n \"--max-concurrency\",\n \"--code-change\",\n \"--experiment-group-id\",\n \"--dataset-id\",\n \"--grader-ids\",\n \"--mock\",\n \"--param\",\n \"--params\",\n])\n\nconst BOOLEAN_FLAGS = new Set([\n \"--db-branch\",\n \"--no-db-branch\",\n \"--no-code-change\",\n \"--dry-run\",\n])\n\nconst HELP_FLAGS = new Set([\"--help\", \"-h\"])\n\nconst MAX_ATTEMPTS = 100\n\nfunction usage(registry: ReplayRegistry): string {\n return `Usage: bitfab-replay --registry <path> <${Object.keys(registry).join(\"|\")}> [options]\\n\\nOptions:\\n --limit N\\n --attempts N (replay each trace N times in this run, max ${MAX_ATTEMPTS})\\n --trace-ids id1,id2\\n --name NAME\\n --concurrency N, --max-concurrency N\\n --code-change PATH, --no-code-change\\n --experiment-group-id UUID\\n --dataset-id UUID\\n --grader-ids id1,id2\\n --mock none|all|marked\\n --db-branch, --no-db-branch\\n --dry-run (resolve inputs, run nothing)\\n --params PATH\\n --param name=value (repeatable)\\n -h, --help`\n}\n\nexport class ReplayCliHelp extends Error {}\n\n/** One case to seed, in the shape `--seed` reads from JSON or JSONL. */\nexport interface SeedCase {\n /** Arguments spread into the registered function at replay. */\n input: unknown[]\n /** The output this case should produce. */\n expected?: unknown\n /** Recorded on the trace, for tracing a seeded case back to its source row. */\n metadata?: Record<string, unknown>\n sessionId?: string\n}\n\nexport interface SeedResult {\n pipeline: string\n traceFunctionKey: string\n traceIds: string[]\n}\n\nfunction parseSeedCases(raw: string, path: string, run: boolean): SeedCase[] {\n const trimmed = raw.trim()\n if (trimmed.length === 0) {\n throw new BitfabError(`Seed file '${path}' is empty.`)\n }\n const values: unknown[] = trimmed.startsWith(\"[\")\n ? (JSON.parse(trimmed) as unknown[])\n : trimmed\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter((line) => line.length > 0)\n .map((line) => JSON.parse(line) as unknown)\n\n return values.map((value, index) => {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n throw new BitfabError(\n `Seed case ${index} in '${path}' must be an object with an \"input\" array.`,\n )\n }\n const { input } = value as { input?: unknown }\n if (!Array.isArray(input)) {\n throw new BitfabError(\n `Seed case ${index} in '${path}' is missing an \"input\" array. Wrap a single argument as [arg].`,\n )\n }\n if (run && \"expected\" in value) {\n throw new BitfabError(\n `Seed case ${index} in '${path}' carries \"expected\", which --run does not record: the case is run once and its output is what the run produced. Remove the field, or drop --run to record the case without running it.`,\n )\n }\n return value as SeedCase\n })\n}\n\n/**\n * Seed cases through an already-registered pipeline.\n *\n * The registration is the whole point: it already holds the client, the exact\n * function production calls, and the trace function key replay selects by, so\n * a seeded case is guaranteed to line up with the replay that will read it.\n * Passing the registered function to `seedTrace` also means a case that cannot\n * supply its required arguments is rejected here rather than at replay.\n */\nexport async function seedFromRegistry(\n registry: ReplayRegistry,\n pipeline: string,\n cases: readonly SeedCase[],\n options: { run?: boolean } = {},\n): Promise<SeedResult> {\n const registration = registry[pipeline]\n if (registration === undefined) {\n throw new BitfabError(\n `Unknown pipeline '${pipeline}'. Registered: ${Object.keys(registry).join(\", \")}`,\n )\n }\n const traceFunctionKey = resolveTraceFunctionKey(registration)\n if (options.run === true) {\n const traceIds: string[] = []\n for (const seedCase of cases) {\n traceIds.push(\n await registration.client.seedTrace(traceFunctionKey, registration.fn, {\n args: seedCase.input,\n metadata: seedCase.metadata,\n sessionId: seedCase.sessionId,\n }),\n )\n }\n return { pipeline, traceFunctionKey, traceIds }\n }\n const traceIds = cases.map((seedCase) =>\n registration.client.seedTrace(traceFunctionKey, {\n input: seedCase.input,\n expected: seedCase.expected,\n fn: registration.fn,\n metadata: seedCase.metadata,\n sessionId: seedCase.sessionId,\n }),\n )\n const { flushTraces } = await import(\"./http.js\")\n await flushTraces(30_000)\n return { pipeline, traceFunctionKey, traceIds }\n}\n\nconst SEED_USAGE =\n 'Usage: bitfab-replay --registry <path> <pipeline> --seed <cases.jsonl> [--run]\\n\\nEach case is a JSON object with an \"input\" array, plus optional \"expected\", \"metadata\", and \"sessionId\". A JSON array of those objects works too.\\n\\nWithout --run, each case is written as a trace directly: \"input\" becomes the root span input and \"expected\" its output, and nothing executes.\\n\\nWith --run, each case is run once through the registered function with capture off and the execution is recorded, so the output is what the run produced. Cases carrying \"expected\" are rejected.'\n\nexport async function runSeedCli(\n registry: ReplayRegistry,\n argv: readonly string[],\n io: ReplayCliIo = {},\n): Promise<SeedResult> {\n const stdout = io.stdout ?? console.log\n const stderr = io.stderr ?? console.error\n if (argv.some((value) => HELP_FLAGS.has(value))) {\n throw new ReplayCliHelp(SEED_USAGE)\n }\n const pipeline = argv[0]\n if (pipeline === undefined || registry[pipeline] === undefined) {\n throw new BitfabError(SEED_USAGE)\n }\n const seedIndex = argv.indexOf(\"--seed\")\n const casesPath = argv[seedIndex + 1]\n if (casesPath === undefined || casesPath.startsWith(\"--\")) {\n throw new BitfabError(\"--seed requires a path to a cases file.\")\n }\n const run = argv.includes(\"--run\")\n const readFile = io.readFile ?? defaultReadFile\n const cases = parseSeedCases(await readFile(casesPath), casesPath, run)\n\n stderr(\n run\n ? `[seed] Running ${cases.length} case(s) through \"${pipeline}\"...`\n : `[seed] Seeding ${cases.length} case(s) into \"${pipeline}\"...`,\n )\n const result = await seedFromRegistry(registry, pipeline, cases, { run })\n stderr(\n `[seed] ${run ? \"Recorded\" : \"Wrote\"} ${result.traceIds.length} trace(s) for \"${result.traceFunctionKey}\". Replay them with --trace-ids ${result.traceIds.slice(0, 3).join(\",\")}${result.traceIds.length > 3 ? \",...\" : \"\"}`,\n )\n stdout(JSON.stringify(result, null, 2))\n return result\n}\n\nfunction requirePositiveInteger(\n flag: string,\n raw: string,\n max?: number,\n): number {\n const value = Number(raw)\n if (!Number.isInteger(value) || value < 1) {\n throw new BitfabError(\n `${flag} must be a positive integer (received '${raw}').`,\n )\n }\n if (max !== undefined && value > max) {\n throw new BitfabError(`${flag} must be at most ${max} (received '${raw}').`)\n }\n return value\n}\n\nfunction commaSeparated(flag: string, raw: string): string[] {\n const values = raw\n .split(\",\")\n .map((value) => value.trim())\n .filter((value) => value.length > 0)\n if (values.length === 0) {\n throw new BitfabError(`${flag} must contain at least one value.`)\n }\n return values\n}\n\nfunction parseReplayCliArgs(\n registry: ReplayRegistry,\n argv: readonly string[],\n): ReplayCliArgs {\n if (argv.some((value) => HELP_FLAGS.has(value))) {\n throw new ReplayCliHelp(usage(registry))\n }\n const pipeline = argv[0]\n if (pipeline === undefined || registry[pipeline] === undefined) {\n throw new BitfabError(usage(registry))\n }\n\n const parsed: ReplayCliArgs = { pipeline, params: [] }\n for (let index = 1; index < argv.length; index += 1) {\n const flag = argv[index]\n if (BOOLEAN_FLAGS.has(flag)) {\n switch (flag) {\n case \"--db-branch\":\n if (parsed.dbBranch === false) {\n throw new BitfabError(\n \"--db-branch and --no-db-branch cannot be used together.\",\n )\n }\n parsed.dbBranch = true\n break\n case \"--no-db-branch\":\n if (parsed.dbBranch === true) {\n throw new BitfabError(\n \"--db-branch and --no-db-branch cannot be used together.\",\n )\n }\n parsed.dbBranch = false\n break\n case \"--no-code-change\":\n parsed.noCodeChange = true\n break\n case \"--dry-run\":\n parsed.dryRun = true\n break\n }\n continue\n }\n if (!VALUE_FLAGS.has(flag)) {\n throw new BitfabError(\n `Unknown replay option '${flag}'.\\n${usage(registry)}`,\n )\n }\n const raw = argv[index + 1]\n if (raw === undefined || raw.startsWith(\"--\")) {\n throw new BitfabError(`${flag} requires a value.`)\n }\n index += 1\n\n switch (flag) {\n case \"--limit\":\n parsed.limit = requirePositiveInteger(flag, raw)\n break\n case \"--attempts\":\n parsed.attempts = requirePositiveInteger(flag, raw, MAX_ATTEMPTS)\n break\n case \"--trace-ids\":\n parsed.traceIds = commaSeparated(flag, raw)\n break\n case \"--name\":\n parsed.name = raw\n break\n case \"--concurrency\":\n case \"--max-concurrency\":\n parsed.maxConcurrency = requirePositiveInteger(flag, raw)\n break\n case \"--code-change\":\n parsed.codeChangePath = raw\n break\n case \"--experiment-group-id\":\n parsed.experimentGroupId = raw\n break\n case \"--dataset-id\":\n parsed.datasetId = raw\n break\n case \"--grader-ids\":\n parsed.graderIds = commaSeparated(flag, raw)\n break\n case \"--mock\":\n if (raw !== \"none\" && raw !== \"all\" && raw !== \"marked\") {\n throw new BitfabError(\n `--mock must be one of: none, all, marked (received '${raw}').`,\n )\n }\n parsed.mock = raw\n break\n case \"--params\":\n parsed.paramsPath = raw\n break\n case \"--param\":\n parsed.params.push(raw)\n break\n }\n }\n if (parsed.traceIds !== undefined && parsed.datasetId !== undefined) {\n throw new BitfabError(\n \"--trace-ids and --dataset-id select different replay sources and cannot be used together.\",\n )\n }\n if (parsed.codeChangePath !== undefined && parsed.noCodeChange === true) {\n throw new BitfabError(\n \"--code-change and --no-code-change cannot be used together.\",\n )\n }\n return parsed\n}\n\nfunction resolveTraceFunctionKey(registration: ReplayRegistration): string {\n const wrappedKey = (\n registration.fn as ReplayFunction & {\n _bitfabTraceFunctionKey?: string\n }\n )._bitfabTraceFunctionKey\n const key = registration.traceFunctionKey ?? wrappedKey\n if (key === undefined) {\n throw new BitfabError(\n \"Replay registry entry uses a plain function. Set traceFunctionKey to the key its production handler records.\",\n )\n }\n return key\n}\n\nasync function defaultReadFile(path: string): Promise<string> {\n const fs = await import(\"node:fs/promises\").catch(() => null)\n if (fs === null) {\n throw new BitfabError(\n \"--code-change requires a runtime that can read local files.\",\n )\n }\n return fs.readFile(path, \"utf8\")\n}\n\nasync function loadCodeChange(\n path: string | undefined,\n readFile: (path: string) => Promise<string>,\n): Promise<CodeChange | undefined> {\n if (path === undefined) {\n return undefined\n }\n const value = JSON.parse(await readFile(path)) as Partial<CodeChange>\n if (typeof value.description !== \"string\" || !Array.isArray(value.files)) {\n throw new BitfabError(\n `Invalid --code-change file '${path}': expected { description, files }.`,\n )\n }\n return { description: value.description, files: value.files }\n}\n\nfunction parseParameter(raw: string): [string, unknown] {\n const separator = raw.indexOf(\"=\")\n const key = raw.slice(0, separator).trim()\n if (separator < 1 || key.length === 0) {\n throw new BitfabError(\n `Invalid --param '${raw}': expected a non-empty name=value pair.`,\n )\n }\n const value = raw.slice(separator + 1)\n try {\n return [key, JSON.parse(value) as unknown]\n } catch {\n return [key, value]\n }\n}\n\nasync function loadParameters(\n path: string | undefined,\n rawParameters: readonly string[],\n readFile: (path: string) => Promise<string>,\n): Promise<Record<string, unknown>> {\n let params: Record<string, unknown> = {}\n if (path !== undefined) {\n const value = JSON.parse(await readFile(path)) as unknown\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n throw new BitfabError(\n `Invalid --params file '${path}': expected a JSON object.`,\n )\n }\n params = { ...(value as Record<string, unknown>) }\n }\n for (const raw of rawParameters) {\n const [key, value] = parseParameter(raw)\n params[key] = value\n }\n return params\n}\n\nfunction valuesEqual(left: unknown, right: unknown): boolean {\n try {\n return JSON.stringify(left) === JSON.stringify(right)\n } catch {\n return Object.is(left, right)\n }\n}\n\nfunction renderSummary(\n pipeline: string,\n result: ReplayResult<unknown>,\n stderr: (line: string) => void,\n): void {\n let same = 0\n let changed = 0\n let matched = 0\n let missed = 0\n let errors = 0\n\n for (const item of result.items) {\n if (item.error !== null) {\n errors += 1\n continue\n }\n const equal = valuesEqual(item.result, item.originalOutput)\n if (item.ingestionType === \"seeded\") {\n if (equal) {\n matched += 1\n } else {\n missed += 1\n }\n } else if (equal) {\n same += 1\n } else {\n changed += 1\n }\n }\n\n stderr(\"\\n─── Summary ───\")\n stderr(` Pipeline: ${pipeline}`)\n stderr(` Replayed: ${result.items.length}`)\n if (result.attempts > 1) {\n stderr(` Attempts: ${result.attempts}`)\n }\n if (same > 0 || changed > 0 || matched + missed === 0) {\n stderr(` Same: ${same}`)\n stderr(` Changed: ${changed}`)\n }\n if (matched > 0 || missed > 0) {\n stderr(` Matched expected: ${matched}`)\n stderr(` Missed expected: ${missed}`)\n }\n if (errors > 0) {\n stderr(` Errors: ${errors}`)\n }\n stderr(`\\n ${result.testRunUrl}`)\n}\n\nfunction renderDryRun(\n pipeline: string,\n result: ReplayResult<unknown>,\n stderr: (line: string) => void,\n): void {\n stderr(\"\\n─── Dry run ───\")\n stderr(` Pipeline: ${pipeline}`)\n stderr(` Resolved: ${result.items.length} (nothing was executed)`)\n for (const item of result.items) {\n stderr(`\\n ${item.originalTraceId}`)\n stderr(` args: ${safeJson(item.input)}`)\n }\n stderr(`\\n ${result.testRunUrl}`)\n}\n\nfunction safeJson(value: unknown): string {\n try {\n return JSON.stringify(value) ?? String(value)\n } catch {\n return String(value)\n }\n}\n\nfunction reportReplayError(\n error: ReplayError,\n stderr: (line: string) => void,\n): void {\n for (const item of error.items as ReplayItem<unknown>[]) {\n stderr(\n `${item.originalTraceId}: ${String(item.traceError ?? item.replayError ?? item.error)}`,\n )\n }\n}\n\n/**\n * Run the SDK-owned replay command against a project-owned registry.\n *\n * The installed `bitfab-replay` executable calls this after loading the\n * registry passed through `--registry`. The SDK owns every common flag,\n * lifecycle callback, and output contract.\n */\nexport async function runReplayCli(\n registry: ReplayRegistry,\n argv: readonly string[] = typeof process === \"undefined\"\n ? []\n : process.argv.slice(2),\n io: ReplayCliIo = {},\n): Promise<ReplayResult<unknown>> {\n const stdout = io.stdout ?? console.log\n const stderr = io.stderr ?? console.error\n const args = parseReplayCliArgs(registry, argv)\n const registration = registry[args.pipeline]\n const traceFunctionKey = resolveTraceFunctionKey(registration)\n const readFile = io.readFile ?? defaultReadFile\n const params = await loadParameters(args.paramsPath, args.params, readFile)\n const dynamicOptions = await registration.optionsFactory?.({ params })\n const registrationOptions: ReplayRegistryOptions = {\n ...registration.options,\n ...dynamicOptions,\n }\n if (\n registrationOptions.traceIds !== undefined &&\n registrationOptions.datasetId !== undefined\n ) {\n throw new BitfabError(\n \"Replay registry options traceIds and datasetId select different sources and cannot be used together.\",\n )\n }\n const codeChange = await loadCodeChange(args.codeChangePath, readFile)\n\n const options: ReplayOptions = {\n ...registrationOptions,\n ...(args.name === undefined ? {} : { name: args.name }),\n ...(args.attempts === undefined ? {} : { attempts: args.attempts }),\n ...(args.maxConcurrency === undefined\n ? {}\n : { maxConcurrency: args.maxConcurrency }),\n ...(args.experimentGroupId === undefined\n ? {}\n : { experimentGroupId: args.experimentGroupId }),\n ...(args.datasetId === undefined ? {} : { datasetId: args.datasetId }),\n ...(args.graderIds === undefined ? {} : { graderIds: args.graderIds }),\n ...(args.mock === undefined ? {} : { mock: args.mock }),\n ...(args.dbBranch === undefined\n ? {}\n : {\n dbBranch:\n args.dbBranch &&\n registrationOptions.dbBranch !== undefined &&\n registrationOptions.dbBranch !== false\n ? registrationOptions.dbBranch\n : args.dbBranch,\n }),\n ...(args.noCodeChange === true\n ? { codeChangeDescription: null, codeChangeFiles: null }\n : {}),\n ...(args.dryRun === true ? { dryRun: true } : {}),\n ...(codeChange === undefined\n ? {}\n : {\n codeChangeDescription: codeChange.description,\n codeChangeFiles: codeChange.files,\n }),\n onItemStart: reportReplayProgress,\n onItemFinish: reportReplayProgress,\n }\n\n if (args.traceIds !== undefined) {\n options.traceIds = args.traceIds\n options.datasetId = undefined\n options.limit = undefined\n } else if (args.datasetId !== undefined) {\n options.traceIds = undefined\n options.limit = undefined\n } else if (args.limit !== undefined) {\n options.traceIds = undefined\n options.datasetId = undefined\n options.limit = args.limit\n } else if (\n registrationOptions.traceIds !== undefined ||\n registrationOptions.datasetId !== undefined\n ) {\n options.limit = undefined\n } else {\n options.limit = registrationOptions.limit ?? 10\n }\n\n const attemptsSuffix =\n options.attempts !== undefined && options.attempts > 1\n ? ` (${options.attempts} attempts each)`\n : \"\"\n stderr(\n `[replay] ${args.dryRun === true ? \"Resolving inputs for\" : \"Replaying\"} ${options.traceIds?.length ?? options.limit ?? \"dataset\"} traces from \"${traceFunctionKey}\"${attemptsSuffix}...`,\n )\n\n try {\n const result = await registration.client.replay(\n traceFunctionKey,\n registration.fn,\n options,\n )\n if (args.dryRun === true) {\n renderDryRun(args.pipeline, result, stderr)\n } else {\n renderSummary(args.pipeline, result, stderr)\n }\n stdout(serializeReplayResult(result))\n // A command that selected nothing did nothing, so it must not exit 0. This\n // is the shape an unseeded corpus takes: `--limit 10` against a trace\n // function with no traces reads as a clean run rather than as no run.\n if (result.items.length === 0) {\n throw new BitfabError(\n `No traces matched \"${traceFunctionKey}\", so nothing was replayed. Seed cases with --seed, or capture a trace first.`,\n )\n }\n return result\n } catch (error) {\n if (error instanceof ReplayError) {\n reportReplayError(error, stderr)\n }\n throw error\n }\n}\n"],"mappings":"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","names":["isRecord","DEFAULT_LIFECYCLE_TIMEOUT_MS","superjson","error","mapWithConcurrency","_context","nowIso","asTokenCount","extractUsage","readEnv","readEnv","method","flushTraces","traceIds","flushTraces"]}