@bitfab/sdk 0.26.0 → 0.26.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/{chunk-GCAJN5I7.js → chunk-SJFOTDP3.js} +2 -2
- package/dist/{chunk-GCAJN5I7.js.map → chunk-SJFOTDP3.js.map} +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/node.cjs +1 -1
- package/dist/node.cjs.map +1 -1
- package/dist/node.js +1 -1
- package/package.json +2 -2
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/errors.ts","../src/warnOnce.ts","../src/randomUuid.ts","../src/serialize.ts","../src/asyncStorage.ts","../src/replayContext.ts","../src/replay.ts","../src/index.ts","../src/version.generated.ts","../src/constants.ts","../src/http.ts","../src/unrefTimer.ts","../src/claudeAgentSdk.ts","../src/client.ts","../src/optionalPeer.ts","../src/baml.ts","../src/dbSnapshot.ts","../src/langgraph.ts","../src/openaiAgentSdk.ts","../src/replayEnvironment.ts","../src/tracing.ts","../src/vercelAiSdk.ts","../src/finalizers.ts"],"sourcesContent":["/**\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 super(message)\n this.name = \"BitfabError\"\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 * 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 * 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 { 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 serialized payload size. superjson can succeed on values like SDK\n// client instances (OpenAI, etc.) and produce hundreds of KB to MB of useless\n// internal state. Anything beyond this is replaced with a stub so the span\n// still ships and the trace isn't dropped server-side.\nconst MAX_SERIALIZED_BYTES = 512_000\n\n// A higher cap for the framework-capture path (toJsonSafe). Agent/graph states\n// (LangGraph, Claude Agent SDK) are legitimately larger than a single\n// function's args/return, so this ceiling preserves real detail while still\n// bounding the payload so the wire-side JSON.stringify can't blow up or get the\n// span rejected server-side.\nconst MAX_FRAMEWORK_SERIALIZED_BYTES = 2_000_000\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 const safe = toJsonSafeInner(value, 0, new WeakSet())\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 return `<unserializable: too_large_${size}_bytes>`\n }\n } catch {\n // Keep the recursed value; the http-layer sanitizer is the final backstop.\n }\n return safe\n}\n\nfunction toJsonSafeInner(\n value: unknown,\n depth: number,\n seen: WeakSet<object>,\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 return `<${className}>`\n }\n\n // Non-object composites (bigint, function, symbol) stringify directly.\n if (typeof value !== \"object\") {\n try {\n return String(value)\n } catch {\n return `<${className}>`\n }\n }\n\n if (seen.has(value as object)) {\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) => toJsonSafeInner(item, depth + 1, seen))\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 )\n } catch {\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)\n }\n }\n result = obj\n } catch {\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 * 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 * 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\"\n\n/** A single span entry in the mock tree with its historical output. */\nexport interface MockSpan {\n sourceSpanId: 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 `ReplayEnvironment`, 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\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 * `ReplayEnvironment.traceId`) should expose, since it's the ID the\n * customer sees in the Bitfab dashboard.\n */\n sourceBitfabTraceId?: string\n mockTree?: MockTree\n callCounters?: Map<string, number>\n mockStrategy?: \"none\" | \"all\" | \"marked\"\n dbBranchLease?: DbBranchLease\n /**\n * Set to true by `ReplayEnvironment` the first time customer code\n * actually obtains `databaseUrl` for this item (via the getter or\n * `snapshot()`). 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 * Any future consumption path that hands the URL to customer code by\n * other means (e.g. a process-isolated runner writing an env overlay)\n * must also set this.\n */\n dbSnapshotAccessed?: boolean\n /**\n * Collector for the replay item's trace-persistence work. When present,\n * the root span's send path pushes a promise that resolves only after\n * every span upload AND the trace completion have been sent (registered\n * synchronously at send time, so the replay runner can await it after\n * the wrapped fn resolves). This is what lets replay guarantee traces\n * are persisted server-side before `completeReplay` builds the\n * trace-ID mapping. Absent outside replay, where sends stay\n * fire-and-forget.\n */\n pendingPersistence?: Promise<unknown>[]\n}\n\nlet replayContextStorage: AsyncLocalStorageLike<ReplayContext | null> | null =\n null\n\nexport const replayContextReady: Promise<void> = asyncStorageReady.then(() => {\n replayContextStorage = createAsyncLocalStorage<ReplayContext | null>()\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 * 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 type { DbSnapshotRef } from \"./dbSnapshot.js\"\nimport { BitfabError } from \"./errors.js\"\nimport type {\n CodeChangeFile,\n HttpClient,\n SpanTreeNode,\n TokenUsage,\n} from \"./http.js\"\nimport { randomUuid } from \"./randomUuid.js\"\nimport type { DbBranchLease, MockTree } from \"./replayContext.js\"\nimport { replayContextReady, runWithReplayContext } from \"./replayContext.js\"\nimport type { ReplayEnvironment } from \"./replayEnvironment.js\"\nimport { deserializeValue } from \"./serialize.js\"\n\nexport type MockStrategy = \"none\" | \"all\" | \"marked\"\n\nexport interface ReplayOptions {\n /**\n * Maximum number of traces to replay (1-100, default 5). Ignored when\n * `traceIds` is passed (with a warning): an explicit ID list already\n * determines how many traces replay.\n */\n limit?: number\n /** Optional list of specific trace IDs to replay (max 100). */\n traceIds?: 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 */\n codeChangeDescription?: string\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`).\n */\n codeChangeFiles?: CodeChangeFile[]\n /**\n * Mock strategy for child spans during replay.\n * - \"none\": everything runs real code (default)\n * - \"all\": every child withSpan returns historical output\n * - \"marked\": only spans tagged with { mockOnReplay: true } in SpanOptions are mocked\n */\n mock?: MockStrategy\n /**\n * Per-trace environment. When the source trace carries a DB branching\n * snapshot, the SDK populates `environment.databaseUrl` before invoking\n * `fn` for that item and resets it after. Customer code reads from the\n * environment to pick up the per-trace branch URL.\n */\n environment?: ReplayEnvironment\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. When 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 * 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 * 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 settles, 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 onProgress?: (progress: ReplayProgress) => void\n}\n\n/** Running totals reported to {@link ReplayOptions.onProgress} as replay proceeds. */\nexport interface ReplayProgress {\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 ran the function without throwing. */\n succeeded: number\n /** Of the completed items, how many threw (their `item.error` is set). */\n errored: number\n}\n\n/** Per-trace context passed to {@link ReplayOptions.adaptInputs}. */\nexport interface AdaptContext {\n /** Bitfab trace ID of the historical trace being replayed. */\n traceId: string\n /** External span ID the recorded inputs were read from. */\n sourceSpanId: string\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 /** Trace ID of the new trace created during replay. */\n traceId: string | null\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 /** The original output from the historical trace. */\n originalOutput: unknown\n /** Error message if the function threw, or null on success. */\n error: string | null\n /** Original trace duration in milliseconds, or null if timestamps are missing. */\n durationMs: number | 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. This is the \"new\" side of a token delta: compare it against\n * the original trace's recorded usage to see how the code change moved cost.\n * Matches what Studio's experiments view shows.\n */\n tokens: TokenUsage | null\n /** Model name from the original trace, or null if not captured. */\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\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}\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<\n string,\n { sourceSpanId: string; output: unknown; outputMeta?: unknown }\n >()\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\n const counterKey = `${key}:${name}`\n const index = counters.get(counterKey) ?? 0\n counters.set(counterKey, index + 1)\n spans.set(`${counterKey}:${index}`, {\n sourceSpanId: node.sourceSpanId,\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 traceId: string\n externalSpanId: string\n durationMs: number | null\n model: string | null\n dbSnapshotRef?: DbSnapshotRef\n dbBranchLease?: DbBranchLease\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 environment: ReplayEnvironment | undefined,\n adaptInputs:\n | ((inputs: unknown[], ctx: AdaptContext) => unknown[])\n | undefined,\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 `environment`,\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\n // no snapshot ref, or whose resolve failed server-side, arrive without\n // a lease; `env.active` will be `false` for those.\n const lease = environment ? serverItem.dbBranchLease : undefined\n\n let inputs: unknown[] = []\n let originalOutput: unknown\n let result: TReturn | undefined\n let error: string | null = null\n const replayedTraceId = randomUuid()\n // Collects the root span's full persistence chain (span uploads + trace\n // completion). Awaited below so this item's trace is on the server before\n // replay() calls completeReplay — otherwise the server's trace-ID mapping\n // races the uploads and item.traceId nulls out.\n const pendingPersistence: Promise<unknown>[] = []\n\n try {\n const span = await httpClient.getExternalSpan(serverItem.externalSpanId)\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 inputs = adaptInputs(inputs, {\n traceId: serverItem.traceId,\n sourceSpanId: serverItem.externalSpanId,\n })\n }\n\n // Build mock tree when mocking is active\n let mockTree: MockTree | undefined\n if (mockStrategy === \"all\" || mockStrategy === \"marked\") {\n const treeResponse = await httpClient.getSpanTree(\n serverItem.externalSpanId,\n )\n mockTree = buildMockTree(treeResponse.root)\n }\n\n const maybePromise = runWithReplayContext(\n {\n testRunId,\n traceId: replayedTraceId,\n inputSourceSpanId: span.id,\n inputSourceTraceId: span.externalTraceId,\n sourceBitfabTraceId: serverItem.traceId,\n mockTree,\n callCounters: mockTree ? new Map() : undefined,\n mockStrategy,\n dbBranchLease: lease,\n pendingPersistence,\n },\n () => fn(...inputs),\n )\n result = maybePromise instanceof Promise ? await maybePromise : maybePromise\n } catch (e) {\n error = e instanceof Error ? e.message : String(e)\n } finally {\n // Wait for this item's trace (spans + completion) to be fully persisted\n // before the item resolves. Runs on the error path too — a throwing fn\n // still emits a root span whose trace must land before completeReplay.\n await Promise.allSettled(pendingPersistence)\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 return {\n traceId: replayedTraceId,\n input: inputs,\n result,\n originalOutput,\n error,\n durationMs: serverItem.durationMs ?? null,\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: serverItem.model ?? null,\n dbSnapshotRef: serverItem.dbSnapshotRef ?? null,\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,\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 const result = await tasks[index]()\n results[index] = result\n 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): 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?.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\n await replayContextReady\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?.codeChangeDescription,\n options?.codeChangeFiles,\n options?.environment !== undefined, // includeDbBranchLease\n options?.experimentGroupId,\n options?.datasetId,\n )\n\n const mockStrategy: MockStrategy = options?.mock ?? \"none\"\n const maxConcurrency = options?.maxConcurrency ?? 10\n\n const tasks = serverItems.map(\n (serverItem) => () =>\n processItem(\n httpClient,\n serverItem,\n fn,\n testRunId,\n mockStrategy,\n options?.environment,\n options?.adaptInputs,\n ),\n )\n const total = tasks.length\n let completed = 0\n let succeeded = 0\n let errored = 0\n const resultItems = await mapWithConcurrency(\n tasks,\n maxConcurrency,\n options?.onProgress\n ? (item) => {\n completed += 1\n if (item.error === null) {\n succeeded += 1\n } else {\n errored += 1\n }\n try {\n options?.onProgress?.({ completed, total, succeeded, errored })\n } catch {\n // Progress UI must never crash the replay run.\n }\n }\n : undefined,\n )\n\n // Every item awaited its own trace persistence (spans + completion) in\n // processItem, so all replay traces are on the server by now — no flush\n // needed, and completeReplay's trace-ID mapping is deterministic.\n // completeReplay failures propagate: a missing mapping means verdicts\n // can't be persisted, which callers must hear about loudly.\n const completeResult = await httpClient.completeReplay(testRunId)\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 if (serverTraceIds === undefined) {\n // Older servers don't return the mapping. Preserve the legacy\n // null-traceId behavior but say why.\n try {\n console.warn(\n \"Bitfab: server did not return replay trace IDs; item.traceId will be null (server upgrade required for verdict persistence)\",\n )\n } catch {\n // Never crash the host app\n }\n for (const item of resultItems) {\n item.traceId = null\n }\n } else {\n // Map each item's locally-generated trace ID to the server's trace row\n // ID. A completed item with no mapping means its trace was sent but the\n // server has no record — a null traceId blocks verdict persistence and\n // the Studio experiments view downstream, so this must never be silent.\n //\n // Severity splits on scope:\n // - ALL completed items missing → systemic (the replayed function isn't\n // wrapped with withSpan, or uploads are wholesale broken). Throw; the\n // run's results are unusable for persistence and silence here is the\n // exact bug this guarantee exists to prevent.\n // - SOME completed items missing → per-item upload failure (transient\n // network blip, one oversized payload). Null those items and log an\n // unmissable error, but return the run — callers can persist verdicts\n // for the items that landed instead of losing all the compute.\n const missing: string[] = []\n let completedCount = 0\n for (const item of resultItems) {\n if (item.traceId) {\n const mapped = serverTraceIds[item.traceId]\n if (item.error === null) {\n completedCount += 1\n if (mapped === undefined) {\n missing.push(item.traceId)\n }\n }\n // Pull this item's replayed-run tokens by its server trace id, before\n // item.traceId is overwritten with that id below.\n if (mapped !== undefined) {\n item.tokens = replayTokens?.[mapped] ?? null\n }\n item.traceId = mapped ?? null\n }\n }\n if (missing.length > 0) {\n const serverCount =\n completeResult.traceCount !== undefined\n ? ` The server persisted ${completeResult.traceCount} trace(s) for this run.`\n : \"\"\n if (missing.length === completedCount) {\n throw 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 }\n try {\n console.error(\n `Bitfab: server has no persisted trace for ${missing.length} of ${completedCount} completed replay item(s) (testRunId ${testRunId}).${serverCount} ` +\n `Their traceId is null and verdicts cannot be persisted for them. Missing: ${missing.join(\", \")}`,\n )\n } catch {\n // Never crash the host app\n }\n }\n }\n\n return {\n items: resultItems,\n testRunId,\n testRunUrl: `${serviceUrl}${testRunUrl}`,\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 CurrentSpan,\n CurrentTrace,\n DetachedTrace,\n SpanOptions,\n SpanType,\n WrapBAMLOptions,\n WrappedBamlFn,\n} from \"./client.js\"\nexport {\n Bitfab,\n BitfabError,\n BitfabFunction,\n getCurrentSpan,\n getCurrentTrace,\n} from \"./client.js\"\nexport { __version__, DEFAULT_SERVICE_URL } from \"./constants.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 { flushTraces } from \"./http.js\"\nexport {\n BitfabLangGraphCallbackHandler,\n BitfabLangGraphCallbackHandler as BitfabLangChainCallbackHandler,\n} from \"./langgraph.js\"\nexport { BitfabOpenAIAgentHandler } from \"./openaiAgentSdk.js\"\nexport type {\n AdaptContext,\n AdaptInputsFn,\n CodeChangeFile,\n MockStrategy,\n ReplayItem,\n ReplayOptions,\n ReplayProgress,\n ReplayResult,\n TokenUsage,\n} from \"./replay.js\"\nexport type { ReplayEnvironmentSnapshot } from \"./replayEnvironment.js\"\nexport { ReplayEnvironment } from \"./replayEnvironment.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 * Auto-generated version file.\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.26.0\"\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 { __version__ } from \"./version.generated.js\"\n","/**\n * HTTP client utilities for Bitfab API requests.\n *\n * This module provides:\n * - HttpClient class for making API requests\n * - awaitOnExit helper for fire-and-forget operations that must complete before process exit\n */\n\nimport { __version__ } from \"./constants.js\"\nimport type { DbSnapshotRef } from \"./dbSnapshot.js\"\nimport { BitfabError } from \"./errors.js\"\nimport type { DbBranchLease } from \"./replayContext.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 }\n\n/**\n * JSON-encode a request body without ever throwing on a stray value.\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} {\n try {\n return { body: JSON.stringify(payload), dropped: [] }\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 return {\n body: JSON.stringify({ error: `payload_serialize_failed: ${message}` }),\n dropped,\n }\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 if (\n dropped.length > 0 &&\n typeof sanitized === \"object\" &&\n sanitized !== null &&\n !Array.isArray(sanitized)\n ) {\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 { body: JSON.stringify(sanitized), dropped }\n }\n}\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 to prevent it from being garbage collected.\n * The promise will be removed from tracking when it completes (success or failure).\n * Useful for fire-and-forget operations that need to complete before process exit.\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 all pending fire-and-forget operations (spans, traces) to complete.\n * Useful in tests and scripts to ensure all data has been sent before asserting or exiting.\n *\n * @param timeoutMs - Maximum time to wait in milliseconds (default: 5000)\n */\nexport async function flushTraces(timeoutMs: number = 5000): Promise<void> {\n if (pendingTracePromises.size === 0) {\n return\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 await Promise.race([\n Promise.allSettled(Array.from(pendingTracePromises)),\n new Promise<void>((resolve) => {\n timer = setTimeout(resolve, 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)\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 (pendingTracePromises.size > 0 && !isFlushing) {\n isFlushing = true\n // Wait for all pending traces to complete\n // This keeps the event loop alive until promises resolve\n Promise.allSettled(\n Array.from(pendingTracePromises).map((p) =>\n p.catch(() => {\n // Silently ignore individual trace failures\n }),\n ),\n )\n .then(() => {\n isFlushing = false\n })\n .catch(() => {\n isFlushing = false\n })\n }\n })\n}\n\nexport interface HttpClientConfig {\n apiKey?: string\n serviceUrl: string\n timeout?: number\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 */\nexport class HttpClient {\n private readonly apiKey: string | undefined\n private readonly serviceUrl: string\n private readonly timeout: number\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 * 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 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 // 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\n try {\n const response = await fetch(url, {\n method,\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${this.apiKey}`,\n },\n 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 )\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 /**\n * Send an internal trace (from BAML execution).\n * Fire-and-forget with awaitOnExit - doesn't block the caller.\n */\n sendInternalTrace(\n functionId: string,\n payload: Record<string, unknown>,\n ): void {\n void awaitOnExit(\n this.request(`/api/sdk/functions/${functionId}/traces`, {\n ...payload,\n sdkVersion: __version__,\n }),\n ).catch((error) => {\n try {\n console.error(\"Bitfab: Failed to create trace:\", error)\n } catch {}\n })\n }\n\n /**\n * Send an external span (from withSpan wrapper or OpenAI tracing).\n * Fire-and-forget with awaitOnExit - doesn't block the caller.\n * Returns the tracked promise so callers can optionally await it.\n */\n sendExternalSpan(payload: Record<string, unknown>): Promise<unknown> {\n return awaitOnExit(\n this.request(\"/api/sdk/externalSpans\", {\n ...payload,\n sdkVersion: __version__,\n }),\n ).catch((error) => {\n try {\n console.error(\"Bitfab: Failed to create external span:\", error)\n } catch {}\n })\n }\n\n /**\n * Send an external trace (from OpenAI tracing).\n * Fire-and-forget with awaitOnExit - doesn't block the caller.\n * Returns the tracked promise so callers can optionally await it\n * (the replay path does, so trace completions are persisted before\n * `completeReplay` builds the trace-ID mapping).\n */\n sendExternalTrace(payload: Record<string, unknown>): Promise<unknown> {\n return awaitOnExit(\n this.request(\"/api/sdk/externalTraces\", {\n ...payload,\n sdkVersion: __version__,\n }),\n ).catch((error) => {\n try {\n console.error(\"Bitfab: Failed to create external trace:\", error)\n } catch {}\n })\n }\n\n /**\n * Partial update of an existing external trace identified by sourceTraceId.\n * Used by the detached `client.getTrace(id)` handle. Fire-and-forget;\n * returns a tracked promise that callers may optionally await.\n */\n patchTrace(\n sourceTraceId: string,\n payload: {\n appendContexts?: Record<string, unknown>[]\n mergeMetadata?: Record<string, unknown>\n setSessionId?: string\n },\n ): Promise<unknown> {\n const endpoint = `/api/sdk/externalTraces/${encodeURIComponent(sourceTraceId)}`\n return awaitOnExit(\n this.request(endpoint, payload, { method: \"PATCH\" }),\n ).catch((error) => {\n try {\n console.error(\"Bitfab: Failed to patch trace:\", error)\n } catch {}\n })\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 codeChangeDescription?: string,\n codeChangeFiles?: CodeChangeFile[],\n includeDbBranchLease?: boolean,\n experimentGroupId?: string,\n datasetId?: string,\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 (codeChangeDescription !== undefined) {\n payload.codeChangeDescription = codeChangeDescription\n }\n if (codeChangeFiles !== undefined) {\n payload.codeChangeFiles = codeChangeFiles\n }\n if (includeDbBranchLease) {\n payload.includeDbBranchLease = true\n }\n if (experimentGroupId !== undefined) {\n payload.experimentGroupId = experimentGroupId\n }\n if (datasetId !== undefined) {\n payload.datasetId = datasetId\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.\n // Use a generous timeout to cover the worst case; otherwise the SDK\n // would time out before a healthy server finished.\n const timeout = includeDbBranchLease ? 180_000 : 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 */\n async getExternalSpan(spanId: string): Promise<ExternalSpanResponse> {\n const url = `${this.serviceUrl}/api/sdk/externalSpans/${spanId}`\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.apiKey}` },\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 async getSpanTree(externalSpanId: string): Promise<SpanTreeResponse> {\n const url = `${this.serviceUrl}/api/sdk/replay/spanTree/${externalSpanId}`\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.apiKey}` },\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 * 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: 30_000 },\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 dbSnapshotRef: DbSnapshotRef,\n ): Promise<{ lease: DbBranchLease }> {\n return this.request<{ lease: DbBranchLease }>(\n \"/api/sdk/replay/resolveDbBranchLease\",\n { testRunId, traceId, dbSnapshotRef },\n { timeout: 90_000 },\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 items: Array<{\n traceId: string\n externalSpanId: 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 `ReplayEnvironment`. Absent until the resolver lands.\n */\n dbBranchLease?: DbBranchLease\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 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 sourceSpanId: string\n traceFunctionKey: string\n spanName: string\n type: string\n output: unknown\n outputMeta?: unknown\n children: SpanTreeNode[]\n}\n\nexport interface SpanTreeResponse {\n root: SpanTreeNode\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 * 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 { HttpClient } from \"./http.js\"\nimport { randomUuid } from \"./randomUuid.js\"\nimport { toJsonSafe } from \"./serialize.js\"\n\nexport interface ActiveSpanContext {\n traceId: string\n spanId: string\n}\n\ninterface SpanInfo {\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}\n\nfunction nowIso(): string {\n return new Date().toISOString()\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 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?: string\n traceFunctionKey: string\n serviceUrl?: string\n timeout?: number\n getActiveSpanContext?: () => ActiveSpanContext | null\n }) {\n this.httpClient = 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 // ── 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 const spanInfo: SpanInfo = {\n spanId,\n traceId,\n parentId: parentId ?? null,\n startedAt: nowIso(),\n name,\n type: spanType,\n input: safeSerialize(inputData),\n contexts: [],\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 spanInfo.output = safeSerialize(output)\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 type: \"sdk-function\",\n source: \"typescript-sdk-claude-agent-sdk\",\n traceFunctionKey: this.traceFunctionKey,\n sourceTraceId: spanInfo.traceId,\n rawSpan,\n }\n\n try {\n this.httpClient.sendExternalSpan(payload)\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 workflow_name: this.traceFunctionKey,\n }\n\n if (metadata) {\n externalTrace.metadata = metadata\n }\n\n const traceData: Record<string, unknown> = {\n type: \"sdk-function\",\n source: \"typescript-sdk-claude-agent-sdk\",\n traceFunctionKey: this.traceFunctionKey,\n externalTrace,\n completed,\n }\n\n try {\n this.httpClient.sendExternalTrace(traceData)\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 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 * 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 type AllowedEnvVars,\n type ProviderDefinition,\n runFunctionWithBaml,\n} from \"./baml.js\"\nimport { BitfabClaudeAgentHandler } from \"./claudeAgentSdk.js\"\nimport { DEFAULT_SERVICE_URL } from \"./constants.js\"\nimport type { DbSnapshotConfig, DbSnapshotRef } from \"./dbSnapshot.js\"\nimport { buildSnapshotRef, validateDbSnapshotConfig } from \"./dbSnapshot.js\"\nimport { BitfabError, HttpClient } from \"./http.js\"\nimport { BitfabLangGraphCallbackHandler } from \"./langgraph.js\"\nimport { BitfabOpenAIAgentHandler } from \"./openaiAgentSdk.js\"\nimport { importOptionalPeer } from \"./optionalPeer.js\"\nimport { randomUuid } from \"./randomUuid.js\"\nimport type { ReplayOptions, ReplayResult } from \"./replay.js\"\nimport { getReplayContext } from \"./replayContext.js\"\nimport { ReplayEnvironment } from \"./replayEnvironment.js\"\nimport { deserializeValue, serializeValue } from \"./serialize.js\"\nimport { BitfabOpenAITracingProcessor } from \"./tracing.js\"\nimport { unrefTimer } from \"./unrefTimer.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 metadata?: Record<string, unknown>\n contexts: ContextEntry[]\n startedAt: string\n testRunId?: string\n inputSourceTraceId?: string\n dbSnapshotRef?: DbSnapshotRef\n}\n\n// Span context for tracking nested spans\ninterface SpanContext {\n traceId: string\n spanId: string\n contexts: ContextEntry[]\n prompt?: string\n}\n\n// Global map to track active trace states\nconst activeTraceStates = new Map<string, TraceState>()\nconst pendingSpanPromises = new Map<string, Promise<unknown>[]>()\n\nlet asyncLocalStorage: AsyncLocalStorageLike<SpanContext[]> | null = null\n\nconst asyncLocalStorageReady: Promise<void> = asyncStorageReady.then(() => {\n asyncLocalStorage = createAsyncLocalStorage<SpanContext[]>()\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 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 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 * caller-supplied id (the same id passed when the trace was started).\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 caller-supplied 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 * Returns a promise that the caller may await for confirmation, or ignore\n * to fire-and-forget. The pending request is tracked so `flushTraces()`\n * waits for it.\n */\n addContext(context: Record<string, unknown>): Promise<unknown>\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.\n */\n setMetadata(metadata: Record<string, unknown>): Promise<unknown>\n /**\n * Set the sessionId for this trace. Replaces any existing sessionId.\n */\n setSessionId(sessionId: string): Promise<unknown>\n}\n\nconst TRACE_ID_PATTERN = /^[a-zA-Z0-9_\\-.:]+$/\nconst TRACE_ID_MAX_LENGTH = 256\n\nfunction validateTraceId(traceId: string): void {\n if (typeof traceId !== \"string\" || traceId.length === 0) {\n throw new BitfabError(\"traceId is required and must be a non-empty string\")\n }\n if (traceId.length > TRACE_ID_MAX_LENGTH) {\n throw new BitfabError(\n `traceId must be ${TRACE_ID_MAX_LENGTH} characters or fewer`,\n )\n }\n if (!TRACE_ID_PATTERN.test(traceId)) {\n throw new BitfabError(\n `traceId may only contain letters, digits, \"_\", \"-\", \".\", \":\"`,\n )\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 /**\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\n// No-op implementations for when called outside a span context\nconst noOpSpan: CurrentSpan = {\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 setMetadata(): void {\n // No-op\n },\n addContext(): 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 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 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: new Date().toISOString(),\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 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 }\n}\n\nexport interface BitfabConfig {\n /** The API key for Bitfab API authentication. When undefined or empty, tracing is disabled. */\n apiKey?: string\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 /** Whether the client is enabled. Defaults to true. When false, withSpan returns the original function unwrapped. */\n enabled?: 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 * 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 * 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.\n */\n mockOnReplay?: boolean\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\ninterface FunctionVersionResponse {\n id: string\n name: string\n versionId: string\n versionNumber: number | null\n prompt: string\n providers: ProviderDefinition[]\n}\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 /**\n * Per-trace environment for `replay({ environment })`. Construct one,\n * pass it to replay, and read `env.databaseUrl` inside the replayed\n * function to pick up the per-trace branch URL.\n */\n static readonly ReplayEnvironment = ReplayEnvironment\n\n private readonly apiKey: string | undefined\n private readonly serviceUrl: string\n private readonly timeout: number\n private readonly envVars: AllowedEnvVars\n private readonly enabled: boolean\n private readonly httpClient: HttpClient\n private readonly bamlClient: unknown\n private readonly dbSnapshot: DbSnapshotConfig | undefined\n\n /**\n * Initialize the Bitfab client.\n *\n * @param config - Configuration options for the client\n */\n constructor(config: BitfabConfig) {\n this.apiKey = config.apiKey\n this.serviceUrl = config.serviceUrl ?? DEFAULT_SERVICE_URL\n this.timeout = config.timeout ?? 120000\n this.envVars = config.envVars ?? {}\n const enabled = config.enabled ?? true\n if (enabled && (!config.apiKey || config.apiKey.trim() === \"\")) {\n console.warn(\n \"Bitfab: apiKey is empty — tracing is disabled. Provide a valid API key to enable tracing.\",\n )\n this.enabled = false\n } else {\n this.enabled = enabled\n }\n this.bamlClient = config.bamlClient ?? null\n if (config.dbSnapshot) {\n validateDbSnapshotConfig(config.dbSnapshot)\n }\n this.dbSnapshot = config.dbSnapshot\n this.httpClient = new HttpClient({\n apiKey: this.apiKey,\n serviceUrl: this.serviceUrl,\n timeout: this.timeout,\n })\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 apiKey: this.apiKey,\n serviceUrl: this.serviceUrl,\n getActiveSpanContext: () => {\n const stack = getSpanStack()\n return stack[stack.length - 1] ?? null\n },\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.apiKey,\n traceFunctionKey,\n serviceUrl: this.serviceUrl,\n getActiveSpanContext: () => {\n const stack = getSpanStack()\n return stack[stack.length - 1] ?? null\n },\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 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.apiKey,\n traceFunctionKey,\n serviceUrl: this.serviceUrl,\n getActiveSpanContext: () => {\n const stack = getSpanStack()\n return stack[stack.length - 1] ?? null\n },\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 if (!this.enabled) {\n const fn = typeof optionsOrFn === \"function\" ? optionsOrFn : maybeFn!\n return fn\n }\n\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 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 // 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 // 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 traceId =\n parentContext?.traceId ?? replayCtxForTraceId?.traceId ?? randomUuid()\n const spanId = randomUuid()\n const parentSpanId = parentContext?.spanId ?? null\n const isRootSpan = parentSpanId === null\n\n // Create new context for this span with empty contexts array\n const newContext: SpanContext = { traceId, spanId, contexts: [] }\n newStack = [...currentStack, newContext]\n\n // Capture inputs and start time\n const inputs = args\n const startedAt = new Date().toISOString()\n\n // Register trace state for root spans\n if (isRootSpan && !activeTraceStates.has(traceId)) {\n const replayCtxAtRoot = getReplayContext()\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 ...(replayCtxAtRoot?.testRunId && {\n testRunId: replayCtxAtRoot.testRunId,\n }),\n ...(replayCtxAtRoot?.inputSourceTraceId && {\n inputSourceTraceId: replayCtxAtRoot.inputSourceTraceId,\n }),\n dbSnapshotRef,\n })\n pendingSpanPromises.set(traceId, [])\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 }\n\n // Helper to send span and (for root spans) await all pending spans\n // before sending the trace completion signal.\n // Wrapped in try/catch so span errors never crash the host app.\n const sendSpan = async (\n params: { result: unknown; error?: string },\n spanOpts?: { skipPersistenceRegistration?: boolean },\n ) => {\n // In replay, persistence is correctness: the replay runner must not\n // call `completeReplay` until this trace's spans AND completion are\n // on the server, or the trace-ID mapping comes back empty and every\n // item.traceId nulls out. Register a persistence promise into the\n // replay context SYNCHRONOUSLY (before the first await below), so\n // it is visible to the runner by the time the wrapped fn's promise\n // resolves. Outside replay this is a no-op and sends stay\n // fire-and-forget.\n // `skipPersistenceRegistration` is set when a deferred `finalize`\n // path already registered the persistence promise synchronously\n // (sendSpan here runs later, after finalize resolves); it still\n // performs the full awaited persistence below, it just must not push\n // a second, late promise the runner may never see.\n const replayCtx = getReplayContext()\n const persistenceCollector = isRootSpan\n ? replayCtx?.pendingPersistence\n : undefined\n let resolvePersistence: (() => void) | undefined\n if (persistenceCollector && !spanOpts?.skipPersistenceRegistration) {\n persistenceCollector.push(\n new Promise<void>((resolve) => {\n resolvePersistence = resolve\n }),\n )\n }\n try {\n const endedAt = new Date().toISOString()\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 const spanPromise = self.sendWrapperSpan({\n ...baseSpanParams,\n ...params,\n contexts: newContext.contexts,\n prompt: newContext.prompt,\n endedAt,\n ...(replayCtx?.testRunId && { testRunId: replayCtx.testRunId }),\n ...(replayCtx?.inputSourceSpanId && {\n inputSourceSpanId: replayCtx.inputSourceSpanId,\n }),\n })\n\n // For root spans, await all pending span requests then send trace completion\n if (isRootSpan) {\n const pending = pendingSpanPromises.get(traceId) ?? []\n pending.push(spanPromise)\n if (persistenceCollector) {\n // Replay: wait for every span upload in full. The underlying\n // requests carry their own HTTP timeouts, so this is bounded.\n await Promise.allSettled(pending)\n } else {\n // Production: never hold the host app hostage on uploads. Clear\n // and unref the race timer so a resolved race never leaves a\n // dangling timeout holding the Node event loop open (which would\n // delay process exit, freeze a serverless function, or hang a\n // test runner for up to 5s after the last traced call).\n let raceTimer: ReturnType<typeof setTimeout> | undefined\n try {\n await Promise.race([\n Promise.allSettled(pending),\n new Promise((resolve) => {\n raceTimer = setTimeout(resolve, 5000)\n unrefTimer(raceTimer)\n }),\n ])\n } finally {\n if (raceTimer) {\n clearTimeout(raceTimer)\n }\n }\n }\n pendingSpanPromises.delete(traceId)\n\n const traceState = activeTraceStates.get(traceId)\n const completionPromise = self.sendTraceCompletion({\n traceFunctionKey,\n traceId,\n startedAt: traceState?.startedAt ?? startedAt,\n endedAt,\n sessionId: traceState?.sessionId,\n metadata: traceState?.metadata,\n contexts: traceState?.contexts ?? [],\n testRunId: traceState?.testRunId,\n inputSourceTraceId: traceState?.inputSourceTraceId,\n dbSnapshotRef: traceState?.dbSnapshotRef,\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 sourceTraceId: replayCtx.sourceBitfabTraceId,\n accessed: replayCtx.dbSnapshotAccessed === true,\n },\n }),\n })\n activeTraceStates.delete(traceId)\n if (persistenceCollector) {\n await completionPromise\n }\n } else {\n // Non-root spans: track the promise for the root to await later\n const pending = pendingSpanPromises.get(traceId)\n if (pending) {\n pending.push(spanPromise)\n } else {\n pendingSpanPromises.set(traceId, [spanPromise])\n }\n }\n } catch {\n // Silently ignore — user's result/exception takes priority\n } finally {\n resolvePersistence?.()\n }\n }\n\n // Mock interception: if a mock tree is present and this is not the\n // root span, check whether this child span should return historical\n // output instead of executing real code. The lookup key matches the\n // shape buildMockTree builds: `${traceFunctionKey}:${spanName}:${idx}`\n // with callIndex 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 shouldMock =\n replayCtxForMock.mockStrategy === \"all\" ||\n (replayCtxForMock.mockStrategy === \"marked\" &&\n options.mockOnReplay === true)\n\n if (shouldMock) {\n const mockKey = `${counterKey}:${callIndex}`\n const mockSpan = replayCtxForMock.mockTree.spans.get(mockKey)\n if (mockSpan) {\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 // Send a span recording the mocked output, then return it.\n // Match the wrapped fn's call shape: if it returns a Promise,\n // return a resolved Promise so `.then()` callers don't crash on\n // a raw value. (`await rawValue` already works either way, but a\n // sync `Promise.resolve(...).then(...)` consumer would not.)\n // Detected once at wrap time via fnReturnsPromise so non-async\n // functions that return Promises (e.g.\n // `function getData() { return fetch(...) }`) are handled too.\n void sendSpan({ result: output })\n if (fnReturnsPromise) {\n return Promise.resolve(output) as TReturn\n }\n return output as TReturn\n }\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 // The finalize -> sendSpan upload is deferred (we await finalize\n // first), but replay registers root persistence SYNCHRONOUSLY inside\n // sendSpan so the runner can await it before completing the item.\n // Because the deferred chain hasn't called sendSpan yet when the\n // wrapped fn's promise resolves, register the persistence promise\n // here, synchronously, and resolve it once the upload finishes.\n // Otherwise replay awaits an empty pendingPersistence and nulls out\n // the streaming root's trace ID. sendSpan is told to skip its own\n // (now-redundant) registration.\n const replayCtx = getReplayContext()\n const persistenceCollector = isRootSpan\n ? replayCtx?.pendingPersistence\n : undefined\n let resolvePersistence: (() => void) | undefined\n if (persistenceCollector) {\n persistenceCollector.push(\n new Promise<void>((resolve) => {\n resolvePersistence = resolve\n }),\n )\n }\n void Promise.resolve()\n .then(() => options.finalize!(result))\n .then((output) =>\n sendSpan(\n { result: output },\n { skipPersistenceRegistration: true },\n ),\n )\n .catch((error: unknown) =>\n sendSpan(\n {\n result: undefined,\n error:\n error instanceof Error\n ? `finalize failed: ${error.message}`\n : `finalize failed: ${String(error)}`,\n },\n { skipPersistenceRegistration: true },\n ),\n )\n .finally(() => resolvePersistence?.())\n } else {\n void sendSpan({ result })\n }\n }\n\n // Execute function within new span context\n executeWithContext = (): TReturn => {\n const result = fn(...args)\n\n // Check if result is a Promise (async function)\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 // Async generator: keep the span open across iteration so child\n // spans created inside the generator body nest under it. (finalize\n // does not apply here — generator output is captured automatically.)\n if (isAsyncGenerator(result)) {\n return wrapAsyncGenerator(result, newStack, sendSpan) as TReturn\n }\n\n // Sync function - create span in background. A sync function can\n // still return a live stream object (e.g. AI SDK `streamText`), so\n // finalize is honored here too.\n recordSpan(result)\n return result\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 pendingSpanPromises.delete(registeredTraceId)\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()) {\n throw setupError\n }\n // Tracing setup failed; run the user's function untraced so a tracing\n // failure never crashes the host app. Call exactly as the traced path\n // does (`fn(...args)`, no receiver) so `this`-binding stays consistent.\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(...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 return wrappedFn\n }\n\n /**\n * Get a detached handle to a previously-created trace, looked up by the\n * caller-supplied id (the same id passed at trace creation).\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 malformed (empty, too long, or\n * contains characters outside `[a-zA-Z0-9_\\-.:]`). Server returns 404 if\n * 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(\"order_abc_123\");\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<unknown> => {\n if (!this.enabled) {\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<unknown> => {\n if (!this.enabled) {\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<unknown> => {\n if (!this.enabled) {\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 }\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 * Fire-and-forget - sends to externalTraces endpoint via httpClient.\n */\n private sendTraceCompletion(params: {\n traceFunctionKey: string\n traceId: string\n startedAt: string\n endedAt: string\n sessionId?: string\n metadata?: Record<string, unknown>\n contexts?: ContextEntry[]\n testRunId?: string\n inputSourceTraceId?: string\n dbSnapshotRef?: DbSnapshotRef\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 sourceTraceId?: string\n accessed: boolean\n }\n }): Promise<unknown> {\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 workflow_name: params.traceFunctionKey,\n }\n\n // Add optional fields to rawData\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.dbSnapshotRef) {\n rawTrace.db_snapshot_ref = params.dbSnapshotRef\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.sourceTraceId && {\n source_trace_id: params.dbSnapshotUsage.sourceTraceId,\n }),\n accessed: params.dbSnapshotUsage.accessed,\n }\n }\n\n return this.httpClient.sendExternalTrace({\n type: \"sdk-function\",\n source: \"typescript-sdk-function\",\n traceFunctionKey: params.traceFunctionKey,\n externalTrace: rawTrace,\n completed: 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 * Fire-and-forget - sends to externalSpans endpoint via httpClient.\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 }): Promise<unknown> {\n // Serialize inputs and result with superjson for type preservation\n const serializedInputs = serializeValue(params.inputs)\n const serializedResult = serializeValue(params.result)\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 input: serializedInputs.json,\n output: serializedResult.json,\n // Include superjson meta for type preservation\n ...(serializedInputs.meta !== undefined && {\n input_meta: serializedInputs.meta,\n }),\n ...(serializedResult.meta !== undefined && {\n output_meta: serializedResult.meta,\n }),\n ...(params.functionName !== undefined && {\n function_name: params.functionName,\n }),\n ...(params.error !== undefined && {\n error: params.error,\n error_source: \"code\",\n }),\n ...(params.contexts &&\n params.contexts.length > 0 && {\n contexts: params.contexts,\n }),\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 return this.httpClient.sendExternalSpan({\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 })\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 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 replayFn = this.withSpan(\n traceFunctionKey,\n { name: traceFunctionKey, type: \"agent\" },\n fn,\n )\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 )\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 * 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 * 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","/**\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 definitions.push(`client<llm> ${clientName} {\n provider ${providerDef.provider}\n options {\n model \"${model.model}\"\n api_key env.${providerDef.apiKeyEnv}\n }\n}`)\n }\n }\n\n return definitions.join(\"\\n\\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","/**\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 { HttpClient } from \"./http.js\"\nimport { randomUuid } from \"./randomUuid.js\"\nimport { toJsonSafe } from \"./serialize.js\"\n\nexport interface ActiveSpanContext {\n traceId: string\n spanId: string\n}\n\ninterface SpanInfo {\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}\n\ninterface InvocationState {\n traceId: string\n activeContext: ActiveSpanContext | null\n rootRunId: string\n}\n\nconst LANGSMITH_HIDDEN_TAG = \"langsmith:hidden\"\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 new Date().toISOString()\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 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 traceFunctionKey: string\n private readonly getActiveSpanContext: (() => ActiveSpanContext | null) | null\n\n private runToSpan: Map<string, SpanInfo> = new Map()\n private invocations: Map<string, InvocationState> = new Map()\n\n constructor(config: {\n apiKey?: string\n traceFunctionKey: string\n serviceUrl?: string\n timeout?: number\n getActiveSpanContext?: () => ActiveSpanContext | null\n }) {\n this.httpClient = 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\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 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 // If this visible span's parent is hidden, walk up to the nearest\n // visible ancestor so the server can drop hidden spans without leaving\n // the visible child as an 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 }\n\n const lgMetadata = extractLangGraphMetadata(metadata)\n const contexts: Array<Record<string, unknown>> =\n Object.keys(lgMetadata).length > 0 ? [lgMetadata] : []\n\n const spanInfo: SpanInfo = {\n spanId: runId,\n traceId: invocation.traceId,\n rootRunId: invocation.rootRunId,\n parentId: effectiveParentId,\n startedAt: nowIso(),\n name,\n type: spanType,\n input: safeSerialize(inputData),\n contexts,\n }\n if (willHide) {\n spanInfo.hidden = true\n }\n this.runToSpan.set(runId, spanInfo)\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 spanInfo.output = safeSerialize(output)\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 this.sendSpan(spanInfo)\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 if (spanInfo.hidden) {\n spanData.hidden = true\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 type: \"sdk-function\",\n source: \"typescript-sdk-langgraph\",\n traceFunctionKey: this.traceFunctionKey,\n sourceTraceId: spanInfo.traceId,\n rawSpan,\n }\n\n try {\n this.httpClient.sendExternalSpan(payload)\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 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 workflow_name: this.traceFunctionKey,\n },\n completed,\n }\n\n try {\n this.httpClient.sendExternalTrace(traceData)\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>,\n inputs: Record<string, unknown>,\n runId: string,\n parentRunId?: string,\n tags?: string[],\n metadata?: Record<string, unknown>,\n ): Promise<void> {\n try {\n const idArr = chain.id as string[] | undefined\n const name =\n (chain.name as string) ?? idArr?.[idArr.length - 1] ?? \"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>,\n messages: unknown[][],\n runId: string,\n parentRunId?: string,\n _extraParams?: Record<string, unknown>,\n tags?: string[],\n metadata?: Record<string, unknown>,\n ): Promise<void> {\n try {\n const model = extractModelName(llm, metadata)\n const idArr = llm.id as string[] | undefined\n const name = 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>,\n prompts: string[],\n runId: string,\n parentRunId?: string,\n _extraParams?: Record<string, unknown>,\n tags?: string[],\n metadata?: Record<string, unknown>,\n ): Promise<void> {\n try {\n const model = extractModelName(llm, metadata)\n const idArr = llm.id as string[] | undefined\n const name = 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>,\n input: string,\n runId: string,\n parentRunId?: string,\n tags?: string[],\n metadata?: Record<string, unknown>,\n ): Promise<void> {\n try {\n const name = (tool.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 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 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>,\n query: string,\n runId: string,\n parentRunId?: string,\n tags?: string[],\n metadata?: Record<string, unknown>,\n ): Promise<void> {\n try {\n const name = (retriever.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","/**\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}\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 = { type: \"agent\", finalize }\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 * Per-trace environment exposed to customer code during replay.\n *\n * The customer instantiates one `ReplayEnvironment` and passes it to\n * `bitfab.replay({ environment })`. Inside the replayed function they read\n * `env.databaseUrl` (and friends) to pick up the per-trace branch URL the\n * Bitfab service resolved from the source trace's snapshot reference.\n *\n * Outside replay, accessing `env.databaseUrl` throws. Customer code uses\n * the env only on the replay path; live request code keeps reading\n * `process.env.DATABASE_URL` the normal way.\n *\n * Concurrency-safe: getters resolve through the replay AsyncLocalStorage\n * context, so each in-flight replay item sees its own per-trace values\n * even when the SDK runs items in parallel.\n *\n * Internally, the resolved per-item state is a `DbBranchLease` (see\n * replayContext.ts) — that's the SDK ↔ server protocol term. We expose\n * its useful fields directly here so customer code never sees the word.\n */\n\nimport { getReplayContext } from \"./replayContext.js\"\n\nexport interface ReplayEnvironmentSnapshot {\n databaseUrl: string\n expiresAt: string\n providerConsoleUrl?: string\n readOnly?: boolean\n traceId: string\n}\n\nexport class ReplayEnvironment {\n /**\n * The per-trace branch URL for the item currently being replayed.\n * Throws if read outside a replay item.\n */\n get databaseUrl(): string {\n const snapshot = this.require()\n this.markAccessed()\n return snapshot.databaseUrl\n }\n\n /** When the per-trace branch URL stops being valid. ISO-8601. */\n get expiresAt(): string {\n return this.require().expiresAt\n }\n\n /** Deep link to the branch in the provider console, if available. */\n get providerConsoleUrl(): string | undefined {\n return this.require().providerConsoleUrl\n }\n\n /**\n * True if the branch is read-only. Customer code can use this to skip\n * write operations during replay when the provider returned a read-only\n * lease.\n */\n get readOnly(): boolean | undefined {\n return this.require().readOnly\n }\n\n /** The historical trace ID that produced the input for this replay item. */\n get traceId(): string {\n return this.require().traceId\n }\n\n /** True when read inside a replay item that has a resolved branch. */\n get active(): boolean {\n return this.read() !== null\n }\n\n /** Non-throwing variant for callers that handle the inactive case. */\n snapshot(): ReplayEnvironmentSnapshot | null {\n const snapshot = this.read()\n if (snapshot) {\n this.markAccessed()\n }\n return snapshot\n }\n\n /**\n * Record on the replay context that customer code obtained the branch\n * URL. Only `databaseUrl` and `snapshot()` count — `active`, `readOnly`\n * and friends inspect the lease without exposing the connection string,\n * so they don't prove the replayed code could have connected to the\n * branch.\n */\n private markAccessed(): void {\n const ctx = getReplayContext()\n if (ctx?.dbBranchLease) {\n ctx.dbSnapshotAccessed = true\n }\n }\n\n private read(): ReplayEnvironmentSnapshot | 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),\n // not the external_traces.id. Fall back to the external ID only if the\n // Bitfab ID is somehow absent — keeps replays from external sources\n // working until the source-system path is fully wired.\n const traceId = ctx.sourceBitfabTraceId ?? ctx.inputSourceTraceId\n if (!traceId) {\n return null\n }\n const lease = ctx.dbBranchLease\n return {\n databaseUrl: lease.databaseUrl,\n expiresAt: lease.expiresAt,\n providerConsoleUrl: lease.providerConsoleUrl,\n readOnly: lease.readOnly,\n traceId,\n }\n }\n\n private require(): ReplayEnvironmentSnapshot {\n const snapshot = this.read()\n if (!snapshot) {\n throw new Error(\n \"ReplayEnvironment accessed outside of a replay item. Pass it to bitfab.replay({ environment }) and only read it inside the replayed function.\",\n )\n }\n return snapshot\n }\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 { HttpClient } from \"./http.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 activeTraces: Record<string, Trace> = {}\n private readonly getActiveSpanContext: (() => ActiveSpanContext | null) | null\n private activeSpanMappings: Record<string, ActiveSpanContext> = {}\n\n /**\n * Initialize the tracing processor.\n *\n * @param config - Configuration options\n */\n constructor(config: {\n apiKey?: string\n serviceUrl?: string\n timeout?: number\n getActiveSpanContext?: () => ActiveSpanContext | null\n }) {\n this.httpClient = 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 * 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 this.sendTrace(trace, activeContext ? { id: activeContext.traceId } : {})\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(\n trace,\n mapping ? { id: mapping.traceId } : { completed: true },\n )\n\n delete this.activeSpanMappings[trace.traceId]\n delete this.activeTraces[trace.traceId]\n }\n\n /**\n * Called when a span is started.\n */\n // biome-ignore lint/suspicious/noExplicitAny: OpenAI Agents SDK uses any for span data\n async onSpanStart(span: Span<any>): Promise<void> {\n // Send the span to Bitfab (fire-and-forget)\n this.sendSpan(span)\n }\n\n /**\n * Called when a span is ended.\n *\n * Send all spans 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 span to Bitfab again to capture updates (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 // No buffering, so nothing to flush\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 }\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 overrides: { completed?: boolean; id?: string } = {},\n ): void {\n try {\n const { completed, ...traceOverrides } = overrides\n const traceData = trace.toJSON() as Record<string, unknown>\n Object.assign(traceData, traceOverrides)\n\n this.httpClient.sendExternalTrace({\n type: \"openai\",\n source: \"typescript-sdk-openai-tracing\",\n externalTrace: traceData,\n completed: 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 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 return 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\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}\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 },\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 },\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 * 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"],"mappings":"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","names":["superjson","nowIso","safeSerialize","asTokenCount","extractUsage","method","fn"]}
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/warnOnce.ts","../src/randomUuid.ts","../src/serialize.ts","../src/asyncStorage.ts","../src/replayContext.ts","../src/replay.ts","../src/index.ts","../src/version.generated.ts","../src/constants.ts","../src/http.ts","../src/unrefTimer.ts","../src/claudeAgentSdk.ts","../src/client.ts","../src/optionalPeer.ts","../src/baml.ts","../src/dbSnapshot.ts","../src/langgraph.ts","../src/openaiAgentSdk.ts","../src/replayEnvironment.ts","../src/tracing.ts","../src/vercelAiSdk.ts","../src/finalizers.ts"],"sourcesContent":["/**\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 super(message)\n this.name = \"BitfabError\"\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 * 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 * 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 { 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 serialized payload size. superjson can succeed on values like SDK\n// client instances (OpenAI, etc.) and produce hundreds of KB to MB of useless\n// internal state. Anything beyond this is replaced with a stub so the span\n// still ships and the trace isn't dropped server-side.\nconst MAX_SERIALIZED_BYTES = 512_000\n\n// A higher cap for the framework-capture path (toJsonSafe). Agent/graph states\n// (LangGraph, Claude Agent SDK) are legitimately larger than a single\n// function's args/return, so this ceiling preserves real detail while still\n// bounding the payload so the wire-side JSON.stringify can't blow up or get the\n// span rejected server-side.\nconst MAX_FRAMEWORK_SERIALIZED_BYTES = 2_000_000\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 const safe = toJsonSafeInner(value, 0, new WeakSet())\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 return `<unserializable: too_large_${size}_bytes>`\n }\n } catch {\n // Keep the recursed value; the http-layer sanitizer is the final backstop.\n }\n return safe\n}\n\nfunction toJsonSafeInner(\n value: unknown,\n depth: number,\n seen: WeakSet<object>,\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 return `<${className}>`\n }\n\n // Non-object composites (bigint, function, symbol) stringify directly.\n if (typeof value !== \"object\") {\n try {\n return String(value)\n } catch {\n return `<${className}>`\n }\n }\n\n if (seen.has(value as object)) {\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) => toJsonSafeInner(item, depth + 1, seen))\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 )\n } catch {\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)\n }\n }\n result = obj\n } catch {\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 * 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 * 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\"\n\n/** A single span entry in the mock tree with its historical output. */\nexport interface MockSpan {\n sourceSpanId: 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 `ReplayEnvironment`, 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\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 * `ReplayEnvironment.traceId`) should expose, since it's the ID the\n * customer sees in the Bitfab dashboard.\n */\n sourceBitfabTraceId?: string\n mockTree?: MockTree\n callCounters?: Map<string, number>\n mockStrategy?: \"none\" | \"all\" | \"marked\"\n dbBranchLease?: DbBranchLease\n /**\n * Set to true by `ReplayEnvironment` the first time customer code\n * actually obtains `databaseUrl` for this item (via the getter or\n * `snapshot()`). 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 * Any future consumption path that hands the URL to customer code by\n * other means (e.g. a process-isolated runner writing an env overlay)\n * must also set this.\n */\n dbSnapshotAccessed?: boolean\n /**\n * Collector for the replay item's trace-persistence work. When present,\n * the root span's send path pushes a promise that resolves only after\n * every span upload AND the trace completion have been sent (registered\n * synchronously at send time, so the replay runner can await it after\n * the wrapped fn resolves). This is what lets replay guarantee traces\n * are persisted server-side before `completeReplay` builds the\n * trace-ID mapping. Absent outside replay, where sends stay\n * fire-and-forget.\n */\n pendingPersistence?: Promise<unknown>[]\n}\n\nlet replayContextStorage: AsyncLocalStorageLike<ReplayContext | null> | null =\n null\n\nexport const replayContextReady: Promise<void> = asyncStorageReady.then(() => {\n replayContextStorage = createAsyncLocalStorage<ReplayContext | null>()\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 * 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 type { DbSnapshotRef } from \"./dbSnapshot.js\"\nimport { BitfabError } from \"./errors.js\"\nimport type {\n CodeChangeFile,\n HttpClient,\n SpanTreeNode,\n TokenUsage,\n} from \"./http.js\"\nimport { randomUuid } from \"./randomUuid.js\"\nimport type { DbBranchLease, MockTree } from \"./replayContext.js\"\nimport { replayContextReady, runWithReplayContext } from \"./replayContext.js\"\nimport type { ReplayEnvironment } from \"./replayEnvironment.js\"\nimport { deserializeValue } from \"./serialize.js\"\n\nexport type MockStrategy = \"none\" | \"all\" | \"marked\"\n\nexport interface ReplayOptions {\n /**\n * Maximum number of traces to replay (1-100, default 5). Ignored when\n * `traceIds` is passed (with a warning): an explicit ID list already\n * determines how many traces replay.\n */\n limit?: number\n /** Optional list of specific trace IDs to replay (max 100). */\n traceIds?: 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 */\n codeChangeDescription?: string\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`).\n */\n codeChangeFiles?: CodeChangeFile[]\n /**\n * Mock strategy for child spans during replay.\n * - \"none\": everything runs real code (default)\n * - \"all\": every child withSpan returns historical output\n * - \"marked\": only spans tagged with { mockOnReplay: true } in SpanOptions are mocked\n */\n mock?: MockStrategy\n /**\n * Per-trace environment. When the source trace carries a DB branching\n * snapshot, the SDK populates `environment.databaseUrl` before invoking\n * `fn` for that item and resets it after. Customer code reads from the\n * environment to pick up the per-trace branch URL.\n */\n environment?: ReplayEnvironment\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. When 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 * 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 * 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 settles, 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 onProgress?: (progress: ReplayProgress) => void\n}\n\n/** Running totals reported to {@link ReplayOptions.onProgress} as replay proceeds. */\nexport interface ReplayProgress {\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 ran the function without throwing. */\n succeeded: number\n /** Of the completed items, how many threw (their `item.error` is set). */\n errored: number\n}\n\n/** Per-trace context passed to {@link ReplayOptions.adaptInputs}. */\nexport interface AdaptContext {\n /** Bitfab trace ID of the historical trace being replayed. */\n traceId: string\n /** External span ID the recorded inputs were read from. */\n sourceSpanId: string\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 /** Trace ID of the new trace created during replay. */\n traceId: string | null\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 /** The original output from the historical trace. */\n originalOutput: unknown\n /** Error message if the function threw, or null on success. */\n error: string | null\n /** Original trace duration in milliseconds, or null if timestamps are missing. */\n durationMs: number | 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. This is the \"new\" side of a token delta: compare it against\n * the original trace's recorded usage to see how the code change moved cost.\n * Matches what Studio's experiments view shows.\n */\n tokens: TokenUsage | null\n /** Model name from the original trace, or null if not captured. */\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\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}\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<\n string,\n { sourceSpanId: string; output: unknown; outputMeta?: unknown }\n >()\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\n const counterKey = `${key}:${name}`\n const index = counters.get(counterKey) ?? 0\n counters.set(counterKey, index + 1)\n spans.set(`${counterKey}:${index}`, {\n sourceSpanId: node.sourceSpanId,\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 traceId: string\n externalSpanId: string\n durationMs: number | null\n model: string | null\n dbSnapshotRef?: DbSnapshotRef\n dbBranchLease?: DbBranchLease\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 environment: ReplayEnvironment | undefined,\n adaptInputs:\n | ((inputs: unknown[], ctx: AdaptContext) => unknown[])\n | undefined,\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 `environment`,\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\n // no snapshot ref, or whose resolve failed server-side, arrive without\n // a lease; `env.active` will be `false` for those.\n const lease = environment ? serverItem.dbBranchLease : undefined\n\n let inputs: unknown[] = []\n let originalOutput: unknown\n let result: TReturn | undefined\n let error: string | null = null\n const replayedTraceId = randomUuid()\n // Collects the root span's full persistence chain (span uploads + trace\n // completion). Awaited below so this item's trace is on the server before\n // replay() calls completeReplay — otherwise the server's trace-ID mapping\n // races the uploads and item.traceId nulls out.\n const pendingPersistence: Promise<unknown>[] = []\n\n try {\n const span = await httpClient.getExternalSpan(serverItem.externalSpanId)\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 inputs = adaptInputs(inputs, {\n traceId: serverItem.traceId,\n sourceSpanId: serverItem.externalSpanId,\n })\n }\n\n // Build mock tree when mocking is active\n let mockTree: MockTree | undefined\n if (mockStrategy === \"all\" || mockStrategy === \"marked\") {\n const treeResponse = await httpClient.getSpanTree(\n serverItem.externalSpanId,\n )\n mockTree = buildMockTree(treeResponse.root)\n }\n\n const maybePromise = runWithReplayContext(\n {\n testRunId,\n traceId: replayedTraceId,\n inputSourceSpanId: span.id,\n inputSourceTraceId: span.externalTraceId,\n sourceBitfabTraceId: serverItem.traceId,\n mockTree,\n callCounters: mockTree ? new Map() : undefined,\n mockStrategy,\n dbBranchLease: lease,\n pendingPersistence,\n },\n () => fn(...inputs),\n )\n result = maybePromise instanceof Promise ? await maybePromise : maybePromise\n } catch (e) {\n error = e instanceof Error ? e.message : String(e)\n } finally {\n // Wait for this item's trace (spans + completion) to be fully persisted\n // before the item resolves. Runs on the error path too — a throwing fn\n // still emits a root span whose trace must land before completeReplay.\n await Promise.allSettled(pendingPersistence)\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 return {\n traceId: replayedTraceId,\n input: inputs,\n result,\n originalOutput,\n error,\n durationMs: serverItem.durationMs ?? null,\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: serverItem.model ?? null,\n dbSnapshotRef: serverItem.dbSnapshotRef ?? null,\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,\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 const result = await tasks[index]()\n results[index] = result\n 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): 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?.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\n await replayContextReady\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?.codeChangeDescription,\n options?.codeChangeFiles,\n options?.environment !== undefined, // includeDbBranchLease\n options?.experimentGroupId,\n options?.datasetId,\n )\n\n const mockStrategy: MockStrategy = options?.mock ?? \"none\"\n const maxConcurrency = options?.maxConcurrency ?? 10\n\n const tasks = serverItems.map(\n (serverItem) => () =>\n processItem(\n httpClient,\n serverItem,\n fn,\n testRunId,\n mockStrategy,\n options?.environment,\n options?.adaptInputs,\n ),\n )\n const total = tasks.length\n let completed = 0\n let succeeded = 0\n let errored = 0\n const resultItems = await mapWithConcurrency(\n tasks,\n maxConcurrency,\n options?.onProgress\n ? (item) => {\n completed += 1\n if (item.error === null) {\n succeeded += 1\n } else {\n errored += 1\n }\n try {\n options?.onProgress?.({ completed, total, succeeded, errored })\n } catch {\n // Progress UI must never crash the replay run.\n }\n }\n : undefined,\n )\n\n // Every item awaited its own trace persistence (spans + completion) in\n // processItem, so all replay traces are on the server by now — no flush\n // needed, and completeReplay's trace-ID mapping is deterministic.\n // completeReplay failures propagate: a missing mapping means verdicts\n // can't be persisted, which callers must hear about loudly.\n const completeResult = await httpClient.completeReplay(testRunId)\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 if (serverTraceIds === undefined) {\n // Older servers don't return the mapping. Preserve the legacy\n // null-traceId behavior but say why.\n try {\n console.warn(\n \"Bitfab: server did not return replay trace IDs; item.traceId will be null (server upgrade required for verdict persistence)\",\n )\n } catch {\n // Never crash the host app\n }\n for (const item of resultItems) {\n item.traceId = null\n }\n } else {\n // Map each item's locally-generated trace ID to the server's trace row\n // ID. A completed item with no mapping means its trace was sent but the\n // server has no record — a null traceId blocks verdict persistence and\n // the Studio experiments view downstream, so this must never be silent.\n //\n // Severity splits on scope:\n // - ALL completed items missing → systemic (the replayed function isn't\n // wrapped with withSpan, or uploads are wholesale broken). Throw; the\n // run's results are unusable for persistence and silence here is the\n // exact bug this guarantee exists to prevent.\n // - SOME completed items missing → per-item upload failure (transient\n // network blip, one oversized payload). Null those items and log an\n // unmissable error, but return the run — callers can persist verdicts\n // for the items that landed instead of losing all the compute.\n const missing: string[] = []\n let completedCount = 0\n for (const item of resultItems) {\n if (item.traceId) {\n const mapped = serverTraceIds[item.traceId]\n if (item.error === null) {\n completedCount += 1\n if (mapped === undefined) {\n missing.push(item.traceId)\n }\n }\n // Pull this item's replayed-run tokens by its server trace id, before\n // item.traceId is overwritten with that id below.\n if (mapped !== undefined) {\n item.tokens = replayTokens?.[mapped] ?? null\n }\n item.traceId = mapped ?? null\n }\n }\n if (missing.length > 0) {\n const serverCount =\n completeResult.traceCount !== undefined\n ? ` The server persisted ${completeResult.traceCount} trace(s) for this run.`\n : \"\"\n if (missing.length === completedCount) {\n throw 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 }\n try {\n console.error(\n `Bitfab: server has no persisted trace for ${missing.length} of ${completedCount} completed replay item(s) (testRunId ${testRunId}).${serverCount} ` +\n `Their traceId is null and verdicts cannot be persisted for them. Missing: ${missing.join(\", \")}`,\n )\n } catch {\n // Never crash the host app\n }\n }\n }\n\n return {\n items: resultItems,\n testRunId,\n testRunUrl: `${serviceUrl}${testRunUrl}`,\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 CurrentSpan,\n CurrentTrace,\n DetachedTrace,\n SpanOptions,\n SpanType,\n WrapBAMLOptions,\n WrappedBamlFn,\n} from \"./client.js\"\nexport {\n Bitfab,\n BitfabError,\n BitfabFunction,\n getCurrentSpan,\n getCurrentTrace,\n} from \"./client.js\"\nexport { __version__, DEFAULT_SERVICE_URL } from \"./constants.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 { flushTraces } from \"./http.js\"\nexport {\n BitfabLangGraphCallbackHandler,\n BitfabLangGraphCallbackHandler as BitfabLangChainCallbackHandler,\n} from \"./langgraph.js\"\nexport { BitfabOpenAIAgentHandler } from \"./openaiAgentSdk.js\"\nexport type {\n AdaptContext,\n AdaptInputsFn,\n CodeChangeFile,\n MockStrategy,\n ReplayItem,\n ReplayOptions,\n ReplayProgress,\n ReplayResult,\n TokenUsage,\n} from \"./replay.js\"\nexport type { ReplayEnvironmentSnapshot } from \"./replayEnvironment.js\"\nexport { ReplayEnvironment } from \"./replayEnvironment.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 * Auto-generated version file.\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.26.1\"\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 { __version__ } from \"./version.generated.js\"\n","/**\n * HTTP client utilities for Bitfab API requests.\n *\n * This module provides:\n * - HttpClient class for making API requests\n * - awaitOnExit helper for fire-and-forget operations that must complete before process exit\n */\n\nimport { __version__ } from \"./constants.js\"\nimport type { DbSnapshotRef } from \"./dbSnapshot.js\"\nimport { BitfabError } from \"./errors.js\"\nimport type { DbBranchLease } from \"./replayContext.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 }\n\n/**\n * JSON-encode a request body without ever throwing on a stray value.\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} {\n try {\n return { body: JSON.stringify(payload), dropped: [] }\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 return {\n body: JSON.stringify({ error: `payload_serialize_failed: ${message}` }),\n dropped,\n }\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 if (\n dropped.length > 0 &&\n typeof sanitized === \"object\" &&\n sanitized !== null &&\n !Array.isArray(sanitized)\n ) {\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 { body: JSON.stringify(sanitized), dropped }\n }\n}\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 to prevent it from being garbage collected.\n * The promise will be removed from tracking when it completes (success or failure).\n * Useful for fire-and-forget operations that need to complete before process exit.\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 all pending fire-and-forget operations (spans, traces) to complete.\n * Useful in tests and scripts to ensure all data has been sent before asserting or exiting.\n *\n * @param timeoutMs - Maximum time to wait in milliseconds (default: 5000)\n */\nexport async function flushTraces(timeoutMs: number = 5000): Promise<void> {\n if (pendingTracePromises.size === 0) {\n return\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 await Promise.race([\n Promise.allSettled(Array.from(pendingTracePromises)),\n new Promise<void>((resolve) => {\n timer = setTimeout(resolve, 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)\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 (pendingTracePromises.size > 0 && !isFlushing) {\n isFlushing = true\n // Wait for all pending traces to complete\n // This keeps the event loop alive until promises resolve\n Promise.allSettled(\n Array.from(pendingTracePromises).map((p) =>\n p.catch(() => {\n // Silently ignore individual trace failures\n }),\n ),\n )\n .then(() => {\n isFlushing = false\n })\n .catch(() => {\n isFlushing = false\n })\n }\n })\n}\n\nexport interface HttpClientConfig {\n apiKey?: string\n serviceUrl: string\n timeout?: number\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 */\nexport class HttpClient {\n private readonly apiKey: string | undefined\n private readonly serviceUrl: string\n private readonly timeout: number\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 * 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 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 // 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\n try {\n const response = await fetch(url, {\n method,\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${this.apiKey}`,\n },\n 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 )\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 /**\n * Send an internal trace (from BAML execution).\n * Fire-and-forget with awaitOnExit - doesn't block the caller.\n */\n sendInternalTrace(\n functionId: string,\n payload: Record<string, unknown>,\n ): void {\n void awaitOnExit(\n this.request(`/api/sdk/functions/${functionId}/traces`, {\n ...payload,\n sdkVersion: __version__,\n }),\n ).catch((error) => {\n try {\n console.error(\"Bitfab: Failed to create trace:\", error)\n } catch {}\n })\n }\n\n /**\n * Send an external span (from withSpan wrapper or OpenAI tracing).\n * Fire-and-forget with awaitOnExit - doesn't block the caller.\n * Returns the tracked promise so callers can optionally await it.\n */\n sendExternalSpan(payload: Record<string, unknown>): Promise<unknown> {\n return awaitOnExit(\n this.request(\"/api/sdk/externalSpans\", {\n ...payload,\n sdkVersion: __version__,\n }),\n ).catch((error) => {\n try {\n console.error(\"Bitfab: Failed to create external span:\", error)\n } catch {}\n })\n }\n\n /**\n * Send an external trace (from OpenAI tracing).\n * Fire-and-forget with awaitOnExit - doesn't block the caller.\n * Returns the tracked promise so callers can optionally await it\n * (the replay path does, so trace completions are persisted before\n * `completeReplay` builds the trace-ID mapping).\n */\n sendExternalTrace(payload: Record<string, unknown>): Promise<unknown> {\n return awaitOnExit(\n this.request(\"/api/sdk/externalTraces\", {\n ...payload,\n sdkVersion: __version__,\n }),\n ).catch((error) => {\n try {\n console.error(\"Bitfab: Failed to create external trace:\", error)\n } catch {}\n })\n }\n\n /**\n * Partial update of an existing external trace identified by sourceTraceId.\n * Used by the detached `client.getTrace(id)` handle. Fire-and-forget;\n * returns a tracked promise that callers may optionally await.\n */\n patchTrace(\n sourceTraceId: string,\n payload: {\n appendContexts?: Record<string, unknown>[]\n mergeMetadata?: Record<string, unknown>\n setSessionId?: string\n },\n ): Promise<unknown> {\n const endpoint = `/api/sdk/externalTraces/${encodeURIComponent(sourceTraceId)}`\n return awaitOnExit(\n this.request(endpoint, payload, { method: \"PATCH\" }),\n ).catch((error) => {\n try {\n console.error(\"Bitfab: Failed to patch trace:\", error)\n } catch {}\n })\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 codeChangeDescription?: string,\n codeChangeFiles?: CodeChangeFile[],\n includeDbBranchLease?: boolean,\n experimentGroupId?: string,\n datasetId?: string,\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 (codeChangeDescription !== undefined) {\n payload.codeChangeDescription = codeChangeDescription\n }\n if (codeChangeFiles !== undefined) {\n payload.codeChangeFiles = codeChangeFiles\n }\n if (includeDbBranchLease) {\n payload.includeDbBranchLease = true\n }\n if (experimentGroupId !== undefined) {\n payload.experimentGroupId = experimentGroupId\n }\n if (datasetId !== undefined) {\n payload.datasetId = datasetId\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.\n // Use a generous timeout to cover the worst case; otherwise the SDK\n // would time out before a healthy server finished.\n const timeout = includeDbBranchLease ? 180_000 : 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 */\n async getExternalSpan(spanId: string): Promise<ExternalSpanResponse> {\n const url = `${this.serviceUrl}/api/sdk/externalSpans/${spanId}`\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.apiKey}` },\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 async getSpanTree(externalSpanId: string): Promise<SpanTreeResponse> {\n const url = `${this.serviceUrl}/api/sdk/replay/spanTree/${externalSpanId}`\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.apiKey}` },\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 * 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: 30_000 },\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 dbSnapshotRef: DbSnapshotRef,\n ): Promise<{ lease: DbBranchLease }> {\n return this.request<{ lease: DbBranchLease }>(\n \"/api/sdk/replay/resolveDbBranchLease\",\n { testRunId, traceId, dbSnapshotRef },\n { timeout: 90_000 },\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 items: Array<{\n traceId: string\n externalSpanId: 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 `ReplayEnvironment`. Absent until the resolver lands.\n */\n dbBranchLease?: DbBranchLease\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 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 sourceSpanId: string\n traceFunctionKey: string\n spanName: string\n type: string\n output: unknown\n outputMeta?: unknown\n children: SpanTreeNode[]\n}\n\nexport interface SpanTreeResponse {\n root: SpanTreeNode\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 * 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 { HttpClient } from \"./http.js\"\nimport { randomUuid } from \"./randomUuid.js\"\nimport { toJsonSafe } from \"./serialize.js\"\n\nexport interface ActiveSpanContext {\n traceId: string\n spanId: string\n}\n\ninterface SpanInfo {\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}\n\nfunction nowIso(): string {\n return new Date().toISOString()\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 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?: string\n traceFunctionKey: string\n serviceUrl?: string\n timeout?: number\n getActiveSpanContext?: () => ActiveSpanContext | null\n }) {\n this.httpClient = 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 // ── 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 const spanInfo: SpanInfo = {\n spanId,\n traceId,\n parentId: parentId ?? null,\n startedAt: nowIso(),\n name,\n type: spanType,\n input: safeSerialize(inputData),\n contexts: [],\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 spanInfo.output = safeSerialize(output)\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 type: \"sdk-function\",\n source: \"typescript-sdk-claude-agent-sdk\",\n traceFunctionKey: this.traceFunctionKey,\n sourceTraceId: spanInfo.traceId,\n rawSpan,\n }\n\n try {\n this.httpClient.sendExternalSpan(payload)\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 workflow_name: this.traceFunctionKey,\n }\n\n if (metadata) {\n externalTrace.metadata = metadata\n }\n\n const traceData: Record<string, unknown> = {\n type: \"sdk-function\",\n source: \"typescript-sdk-claude-agent-sdk\",\n traceFunctionKey: this.traceFunctionKey,\n externalTrace,\n completed,\n }\n\n try {\n this.httpClient.sendExternalTrace(traceData)\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 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 * 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 type AllowedEnvVars,\n type ProviderDefinition,\n runFunctionWithBaml,\n} from \"./baml.js\"\nimport { BitfabClaudeAgentHandler } from \"./claudeAgentSdk.js\"\nimport { DEFAULT_SERVICE_URL } from \"./constants.js\"\nimport type { DbSnapshotConfig, DbSnapshotRef } from \"./dbSnapshot.js\"\nimport { buildSnapshotRef, validateDbSnapshotConfig } from \"./dbSnapshot.js\"\nimport { BitfabError, HttpClient } from \"./http.js\"\nimport { BitfabLangGraphCallbackHandler } from \"./langgraph.js\"\nimport { BitfabOpenAIAgentHandler } from \"./openaiAgentSdk.js\"\nimport { importOptionalPeer } from \"./optionalPeer.js\"\nimport { randomUuid } from \"./randomUuid.js\"\nimport type { ReplayOptions, ReplayResult } from \"./replay.js\"\nimport { getReplayContext } from \"./replayContext.js\"\nimport { ReplayEnvironment } from \"./replayEnvironment.js\"\nimport { deserializeValue, serializeValue } from \"./serialize.js\"\nimport { BitfabOpenAITracingProcessor } from \"./tracing.js\"\nimport { unrefTimer } from \"./unrefTimer.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 metadata?: Record<string, unknown>\n contexts: ContextEntry[]\n startedAt: string\n testRunId?: string\n inputSourceTraceId?: string\n dbSnapshotRef?: DbSnapshotRef\n}\n\n// Span context for tracking nested spans\ninterface SpanContext {\n traceId: string\n spanId: string\n contexts: ContextEntry[]\n prompt?: string\n}\n\n// Global map to track active trace states\nconst activeTraceStates = new Map<string, TraceState>()\nconst pendingSpanPromises = new Map<string, Promise<unknown>[]>()\n\nlet asyncLocalStorage: AsyncLocalStorageLike<SpanContext[]> | null = null\n\nconst asyncLocalStorageReady: Promise<void> = asyncStorageReady.then(() => {\n asyncLocalStorage = createAsyncLocalStorage<SpanContext[]>()\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 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 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 * caller-supplied id (the same id passed when the trace was started).\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 caller-supplied 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 * Returns a promise that the caller may await for confirmation, or ignore\n * to fire-and-forget. The pending request is tracked so `flushTraces()`\n * waits for it.\n */\n addContext(context: Record<string, unknown>): Promise<unknown>\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.\n */\n setMetadata(metadata: Record<string, unknown>): Promise<unknown>\n /**\n * Set the sessionId for this trace. Replaces any existing sessionId.\n */\n setSessionId(sessionId: string): Promise<unknown>\n}\n\nconst TRACE_ID_PATTERN = /^[a-zA-Z0-9_\\-.:]+$/\nconst TRACE_ID_MAX_LENGTH = 256\n\nfunction validateTraceId(traceId: string): void {\n if (typeof traceId !== \"string\" || traceId.length === 0) {\n throw new BitfabError(\"traceId is required and must be a non-empty string\")\n }\n if (traceId.length > TRACE_ID_MAX_LENGTH) {\n throw new BitfabError(\n `traceId must be ${TRACE_ID_MAX_LENGTH} characters or fewer`,\n )\n }\n if (!TRACE_ID_PATTERN.test(traceId)) {\n throw new BitfabError(\n `traceId may only contain letters, digits, \"_\", \"-\", \".\", \":\"`,\n )\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 /**\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\n// No-op implementations for when called outside a span context\nconst noOpSpan: CurrentSpan = {\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 setMetadata(): void {\n // No-op\n },\n addContext(): 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 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 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: new Date().toISOString(),\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 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 }\n}\n\nexport interface BitfabConfig {\n /** The API key for Bitfab API authentication. When undefined or empty, tracing is disabled. */\n apiKey?: string\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 /** Whether the client is enabled. Defaults to true. When false, withSpan returns the original function unwrapped. */\n enabled?: 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 * 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 * 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.\n */\n mockOnReplay?: boolean\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\ninterface FunctionVersionResponse {\n id: string\n name: string\n versionId: string\n versionNumber: number | null\n prompt: string\n providers: ProviderDefinition[]\n}\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 /**\n * Per-trace environment for `replay({ environment })`. Construct one,\n * pass it to replay, and read `env.databaseUrl` inside the replayed\n * function to pick up the per-trace branch URL.\n */\n static readonly ReplayEnvironment = ReplayEnvironment\n\n private readonly apiKey: string | undefined\n private readonly serviceUrl: string\n private readonly timeout: number\n private readonly envVars: AllowedEnvVars\n private readonly enabled: boolean\n private readonly httpClient: HttpClient\n private readonly bamlClient: unknown\n private readonly dbSnapshot: DbSnapshotConfig | undefined\n\n /**\n * Initialize the Bitfab client.\n *\n * @param config - Configuration options for the client\n */\n constructor(config: BitfabConfig) {\n this.apiKey = config.apiKey\n this.serviceUrl = config.serviceUrl ?? DEFAULT_SERVICE_URL\n this.timeout = config.timeout ?? 120000\n this.envVars = config.envVars ?? {}\n const enabled = config.enabled ?? true\n if (enabled && (!config.apiKey || config.apiKey.trim() === \"\")) {\n console.warn(\n \"Bitfab: apiKey is empty — tracing is disabled. Provide a valid API key to enable tracing.\",\n )\n this.enabled = false\n } else {\n this.enabled = enabled\n }\n this.bamlClient = config.bamlClient ?? null\n if (config.dbSnapshot) {\n validateDbSnapshotConfig(config.dbSnapshot)\n }\n this.dbSnapshot = config.dbSnapshot\n this.httpClient = new HttpClient({\n apiKey: this.apiKey,\n serviceUrl: this.serviceUrl,\n timeout: this.timeout,\n })\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 apiKey: this.apiKey,\n serviceUrl: this.serviceUrl,\n getActiveSpanContext: () => {\n const stack = getSpanStack()\n return stack[stack.length - 1] ?? null\n },\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.apiKey,\n traceFunctionKey,\n serviceUrl: this.serviceUrl,\n getActiveSpanContext: () => {\n const stack = getSpanStack()\n return stack[stack.length - 1] ?? null\n },\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 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.apiKey,\n traceFunctionKey,\n serviceUrl: this.serviceUrl,\n getActiveSpanContext: () => {\n const stack = getSpanStack()\n return stack[stack.length - 1] ?? null\n },\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 if (!this.enabled) {\n const fn = typeof optionsOrFn === \"function\" ? optionsOrFn : maybeFn!\n return fn\n }\n\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 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 // 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 // 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 traceId =\n parentContext?.traceId ?? replayCtxForTraceId?.traceId ?? randomUuid()\n const spanId = randomUuid()\n const parentSpanId = parentContext?.spanId ?? null\n const isRootSpan = parentSpanId === null\n\n // Create new context for this span with empty contexts array\n const newContext: SpanContext = { traceId, spanId, contexts: [] }\n newStack = [...currentStack, newContext]\n\n // Capture inputs and start time\n const inputs = args\n const startedAt = new Date().toISOString()\n\n // Register trace state for root spans\n if (isRootSpan && !activeTraceStates.has(traceId)) {\n const replayCtxAtRoot = getReplayContext()\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 ...(replayCtxAtRoot?.testRunId && {\n testRunId: replayCtxAtRoot.testRunId,\n }),\n ...(replayCtxAtRoot?.inputSourceTraceId && {\n inputSourceTraceId: replayCtxAtRoot.inputSourceTraceId,\n }),\n dbSnapshotRef,\n })\n pendingSpanPromises.set(traceId, [])\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 }\n\n // Helper to send span and (for root spans) await all pending spans\n // before sending the trace completion signal.\n // Wrapped in try/catch so span errors never crash the host app.\n const sendSpan = async (\n params: { result: unknown; error?: string },\n spanOpts?: { skipPersistenceRegistration?: boolean },\n ) => {\n // In replay, persistence is correctness: the replay runner must not\n // call `completeReplay` until this trace's spans AND completion are\n // on the server, or the trace-ID mapping comes back empty and every\n // item.traceId nulls out. Register a persistence promise into the\n // replay context SYNCHRONOUSLY (before the first await below), so\n // it is visible to the runner by the time the wrapped fn's promise\n // resolves. Outside replay this is a no-op and sends stay\n // fire-and-forget.\n // `skipPersistenceRegistration` is set when a deferred `finalize`\n // path already registered the persistence promise synchronously\n // (sendSpan here runs later, after finalize resolves); it still\n // performs the full awaited persistence below, it just must not push\n // a second, late promise the runner may never see.\n const replayCtx = getReplayContext()\n const persistenceCollector = isRootSpan\n ? replayCtx?.pendingPersistence\n : undefined\n let resolvePersistence: (() => void) | undefined\n if (persistenceCollector && !spanOpts?.skipPersistenceRegistration) {\n persistenceCollector.push(\n new Promise<void>((resolve) => {\n resolvePersistence = resolve\n }),\n )\n }\n try {\n const endedAt = new Date().toISOString()\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 const spanPromise = self.sendWrapperSpan({\n ...baseSpanParams,\n ...params,\n contexts: newContext.contexts,\n prompt: newContext.prompt,\n endedAt,\n ...(replayCtx?.testRunId && { testRunId: replayCtx.testRunId }),\n ...(replayCtx?.inputSourceSpanId && {\n inputSourceSpanId: replayCtx.inputSourceSpanId,\n }),\n })\n\n // For root spans, await all pending span requests then send trace completion\n if (isRootSpan) {\n const pending = pendingSpanPromises.get(traceId) ?? []\n pending.push(spanPromise)\n if (persistenceCollector) {\n // Replay: wait for every span upload in full. The underlying\n // requests carry their own HTTP timeouts, so this is bounded.\n await Promise.allSettled(pending)\n } else {\n // Production: never hold the host app hostage on uploads. Clear\n // and unref the race timer so a resolved race never leaves a\n // dangling timeout holding the Node event loop open (which would\n // delay process exit, freeze a serverless function, or hang a\n // test runner for up to 5s after the last traced call).\n let raceTimer: ReturnType<typeof setTimeout> | undefined\n try {\n await Promise.race([\n Promise.allSettled(pending),\n new Promise((resolve) => {\n raceTimer = setTimeout(resolve, 5000)\n unrefTimer(raceTimer)\n }),\n ])\n } finally {\n if (raceTimer) {\n clearTimeout(raceTimer)\n }\n }\n }\n pendingSpanPromises.delete(traceId)\n\n const traceState = activeTraceStates.get(traceId)\n const completionPromise = self.sendTraceCompletion({\n traceFunctionKey,\n traceId,\n startedAt: traceState?.startedAt ?? startedAt,\n endedAt,\n sessionId: traceState?.sessionId,\n metadata: traceState?.metadata,\n contexts: traceState?.contexts ?? [],\n testRunId: traceState?.testRunId,\n inputSourceTraceId: traceState?.inputSourceTraceId,\n dbSnapshotRef: traceState?.dbSnapshotRef,\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 sourceTraceId: replayCtx.sourceBitfabTraceId,\n accessed: replayCtx.dbSnapshotAccessed === true,\n },\n }),\n })\n activeTraceStates.delete(traceId)\n if (persistenceCollector) {\n await completionPromise\n }\n } else {\n // Non-root spans: track the promise for the root to await later\n const pending = pendingSpanPromises.get(traceId)\n if (pending) {\n pending.push(spanPromise)\n } else {\n pendingSpanPromises.set(traceId, [spanPromise])\n }\n }\n } catch {\n // Silently ignore — user's result/exception takes priority\n } finally {\n resolvePersistence?.()\n }\n }\n\n // Mock interception: if a mock tree is present and this is not the\n // root span, check whether this child span should return historical\n // output instead of executing real code. The lookup key matches the\n // shape buildMockTree builds: `${traceFunctionKey}:${spanName}:${idx}`\n // with callIndex 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 shouldMock =\n replayCtxForMock.mockStrategy === \"all\" ||\n (replayCtxForMock.mockStrategy === \"marked\" &&\n options.mockOnReplay === true)\n\n if (shouldMock) {\n const mockKey = `${counterKey}:${callIndex}`\n const mockSpan = replayCtxForMock.mockTree.spans.get(mockKey)\n if (mockSpan) {\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 // Send a span recording the mocked output, then return it.\n // Match the wrapped fn's call shape: if it returns a Promise,\n // return a resolved Promise so `.then()` callers don't crash on\n // a raw value. (`await rawValue` already works either way, but a\n // sync `Promise.resolve(...).then(...)` consumer would not.)\n // Detected once at wrap time via fnReturnsPromise so non-async\n // functions that return Promises (e.g.\n // `function getData() { return fetch(...) }`) are handled too.\n void sendSpan({ result: output })\n if (fnReturnsPromise) {\n return Promise.resolve(output) as TReturn\n }\n return output as TReturn\n }\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 // The finalize -> sendSpan upload is deferred (we await finalize\n // first), but replay registers root persistence SYNCHRONOUSLY inside\n // sendSpan so the runner can await it before completing the item.\n // Because the deferred chain hasn't called sendSpan yet when the\n // wrapped fn's promise resolves, register the persistence promise\n // here, synchronously, and resolve it once the upload finishes.\n // Otherwise replay awaits an empty pendingPersistence and nulls out\n // the streaming root's trace ID. sendSpan is told to skip its own\n // (now-redundant) registration.\n const replayCtx = getReplayContext()\n const persistenceCollector = isRootSpan\n ? replayCtx?.pendingPersistence\n : undefined\n let resolvePersistence: (() => void) | undefined\n if (persistenceCollector) {\n persistenceCollector.push(\n new Promise<void>((resolve) => {\n resolvePersistence = resolve\n }),\n )\n }\n void Promise.resolve()\n .then(() => options.finalize!(result))\n .then((output) =>\n sendSpan(\n { result: output },\n { skipPersistenceRegistration: true },\n ),\n )\n .catch((error: unknown) =>\n sendSpan(\n {\n result: undefined,\n error:\n error instanceof Error\n ? `finalize failed: ${error.message}`\n : `finalize failed: ${String(error)}`,\n },\n { skipPersistenceRegistration: true },\n ),\n )\n .finally(() => resolvePersistence?.())\n } else {\n void sendSpan({ result })\n }\n }\n\n // Execute function within new span context\n executeWithContext = (): TReturn => {\n const result = fn(...args)\n\n // Check if result is a Promise (async function)\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 // Async generator: keep the span open across iteration so child\n // spans created inside the generator body nest under it. (finalize\n // does not apply here — generator output is captured automatically.)\n if (isAsyncGenerator(result)) {\n return wrapAsyncGenerator(result, newStack, sendSpan) as TReturn\n }\n\n // Sync function - create span in background. A sync function can\n // still return a live stream object (e.g. AI SDK `streamText`), so\n // finalize is honored here too.\n recordSpan(result)\n return result\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 pendingSpanPromises.delete(registeredTraceId)\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()) {\n throw setupError\n }\n // Tracing setup failed; run the user's function untraced so a tracing\n // failure never crashes the host app. Call exactly as the traced path\n // does (`fn(...args)`, no receiver) so `this`-binding stays consistent.\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(...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 return wrappedFn\n }\n\n /**\n * Get a detached handle to a previously-created trace, looked up by the\n * caller-supplied id (the same id passed at trace creation).\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 malformed (empty, too long, or\n * contains characters outside `[a-zA-Z0-9_\\-.:]`). Server returns 404 if\n * 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(\"order_abc_123\");\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<unknown> => {\n if (!this.enabled) {\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<unknown> => {\n if (!this.enabled) {\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<unknown> => {\n if (!this.enabled) {\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 }\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 * Fire-and-forget - sends to externalTraces endpoint via httpClient.\n */\n private sendTraceCompletion(params: {\n traceFunctionKey: string\n traceId: string\n startedAt: string\n endedAt: string\n sessionId?: string\n metadata?: Record<string, unknown>\n contexts?: ContextEntry[]\n testRunId?: string\n inputSourceTraceId?: string\n dbSnapshotRef?: DbSnapshotRef\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 sourceTraceId?: string\n accessed: boolean\n }\n }): Promise<unknown> {\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 workflow_name: params.traceFunctionKey,\n }\n\n // Add optional fields to rawData\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.dbSnapshotRef) {\n rawTrace.db_snapshot_ref = params.dbSnapshotRef\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.sourceTraceId && {\n source_trace_id: params.dbSnapshotUsage.sourceTraceId,\n }),\n accessed: params.dbSnapshotUsage.accessed,\n }\n }\n\n return this.httpClient.sendExternalTrace({\n type: \"sdk-function\",\n source: \"typescript-sdk-function\",\n traceFunctionKey: params.traceFunctionKey,\n externalTrace: rawTrace,\n completed: 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 * Fire-and-forget - sends to externalSpans endpoint via httpClient.\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 }): Promise<unknown> {\n // Serialize inputs and result with superjson for type preservation\n const serializedInputs = serializeValue(params.inputs)\n const serializedResult = serializeValue(params.result)\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 input: serializedInputs.json,\n output: serializedResult.json,\n // Include superjson meta for type preservation\n ...(serializedInputs.meta !== undefined && {\n input_meta: serializedInputs.meta,\n }),\n ...(serializedResult.meta !== undefined && {\n output_meta: serializedResult.meta,\n }),\n ...(params.functionName !== undefined && {\n function_name: params.functionName,\n }),\n ...(params.error !== undefined && {\n error: params.error,\n error_source: \"code\",\n }),\n ...(params.contexts &&\n params.contexts.length > 0 && {\n contexts: params.contexts,\n }),\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 return this.httpClient.sendExternalSpan({\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 })\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 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 replayFn = this.withSpan(\n traceFunctionKey,\n { name: traceFunctionKey, type: \"agent\" },\n fn,\n )\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 )\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 * 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 * 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","/**\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 definitions.push(`client<llm> ${clientName} {\n provider ${providerDef.provider}\n options {\n model \"${model.model}\"\n api_key env.${providerDef.apiKeyEnv}\n }\n}`)\n }\n }\n\n return definitions.join(\"\\n\\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","/**\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 { HttpClient } from \"./http.js\"\nimport { randomUuid } from \"./randomUuid.js\"\nimport { toJsonSafe } from \"./serialize.js\"\n\nexport interface ActiveSpanContext {\n traceId: string\n spanId: string\n}\n\ninterface SpanInfo {\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}\n\ninterface InvocationState {\n traceId: string\n activeContext: ActiveSpanContext | null\n rootRunId: string\n}\n\nconst LANGSMITH_HIDDEN_TAG = \"langsmith:hidden\"\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 new Date().toISOString()\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 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 traceFunctionKey: string\n private readonly getActiveSpanContext: (() => ActiveSpanContext | null) | null\n\n private runToSpan: Map<string, SpanInfo> = new Map()\n private invocations: Map<string, InvocationState> = new Map()\n\n constructor(config: {\n apiKey?: string\n traceFunctionKey: string\n serviceUrl?: string\n timeout?: number\n getActiveSpanContext?: () => ActiveSpanContext | null\n }) {\n this.httpClient = 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\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 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 // If this visible span's parent is hidden, walk up to the nearest\n // visible ancestor so the server can drop hidden spans without leaving\n // the visible child as an 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 }\n\n const lgMetadata = extractLangGraphMetadata(metadata)\n const contexts: Array<Record<string, unknown>> =\n Object.keys(lgMetadata).length > 0 ? [lgMetadata] : []\n\n const spanInfo: SpanInfo = {\n spanId: runId,\n traceId: invocation.traceId,\n rootRunId: invocation.rootRunId,\n parentId: effectiveParentId,\n startedAt: nowIso(),\n name,\n type: spanType,\n input: safeSerialize(inputData),\n contexts,\n }\n if (willHide) {\n spanInfo.hidden = true\n }\n this.runToSpan.set(runId, spanInfo)\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 spanInfo.output = safeSerialize(output)\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 this.sendSpan(spanInfo)\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 if (spanInfo.hidden) {\n spanData.hidden = true\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 type: \"sdk-function\",\n source: \"typescript-sdk-langgraph\",\n traceFunctionKey: this.traceFunctionKey,\n sourceTraceId: spanInfo.traceId,\n rawSpan,\n }\n\n try {\n this.httpClient.sendExternalSpan(payload)\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 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 workflow_name: this.traceFunctionKey,\n },\n completed,\n }\n\n try {\n this.httpClient.sendExternalTrace(traceData)\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>,\n inputs: Record<string, unknown>,\n runId: string,\n parentRunId?: string,\n tags?: string[],\n metadata?: Record<string, unknown>,\n ): Promise<void> {\n try {\n const idArr = chain.id as string[] | undefined\n const name =\n (chain.name as string) ?? idArr?.[idArr.length - 1] ?? \"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>,\n messages: unknown[][],\n runId: string,\n parentRunId?: string,\n _extraParams?: Record<string, unknown>,\n tags?: string[],\n metadata?: Record<string, unknown>,\n ): Promise<void> {\n try {\n const model = extractModelName(llm, metadata)\n const idArr = llm.id as string[] | undefined\n const name = 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>,\n prompts: string[],\n runId: string,\n parentRunId?: string,\n _extraParams?: Record<string, unknown>,\n tags?: string[],\n metadata?: Record<string, unknown>,\n ): Promise<void> {\n try {\n const model = extractModelName(llm, metadata)\n const idArr = llm.id as string[] | undefined\n const name = 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>,\n input: string,\n runId: string,\n parentRunId?: string,\n tags?: string[],\n metadata?: Record<string, unknown>,\n ): Promise<void> {\n try {\n const name = (tool.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 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 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>,\n query: string,\n runId: string,\n parentRunId?: string,\n tags?: string[],\n metadata?: Record<string, unknown>,\n ): Promise<void> {\n try {\n const name = (retriever.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","/**\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}\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 = { type: \"agent\", finalize }\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 * Per-trace environment exposed to customer code during replay.\n *\n * The customer instantiates one `ReplayEnvironment` and passes it to\n * `bitfab.replay({ environment })`. Inside the replayed function they read\n * `env.databaseUrl` (and friends) to pick up the per-trace branch URL the\n * Bitfab service resolved from the source trace's snapshot reference.\n *\n * Outside replay, accessing `env.databaseUrl` throws. Customer code uses\n * the env only on the replay path; live request code keeps reading\n * `process.env.DATABASE_URL` the normal way.\n *\n * Concurrency-safe: getters resolve through the replay AsyncLocalStorage\n * context, so each in-flight replay item sees its own per-trace values\n * even when the SDK runs items in parallel.\n *\n * Internally, the resolved per-item state is a `DbBranchLease` (see\n * replayContext.ts) — that's the SDK ↔ server protocol term. We expose\n * its useful fields directly here so customer code never sees the word.\n */\n\nimport { getReplayContext } from \"./replayContext.js\"\n\nexport interface ReplayEnvironmentSnapshot {\n databaseUrl: string\n expiresAt: string\n providerConsoleUrl?: string\n readOnly?: boolean\n traceId: string\n}\n\nexport class ReplayEnvironment {\n /**\n * The per-trace branch URL for the item currently being replayed.\n * Throws if read outside a replay item.\n */\n get databaseUrl(): string {\n const snapshot = this.require()\n this.markAccessed()\n return snapshot.databaseUrl\n }\n\n /** When the per-trace branch URL stops being valid. ISO-8601. */\n get expiresAt(): string {\n return this.require().expiresAt\n }\n\n /** Deep link to the branch in the provider console, if available. */\n get providerConsoleUrl(): string | undefined {\n return this.require().providerConsoleUrl\n }\n\n /**\n * True if the branch is read-only. Customer code can use this to skip\n * write operations during replay when the provider returned a read-only\n * lease.\n */\n get readOnly(): boolean | undefined {\n return this.require().readOnly\n }\n\n /** The historical trace ID that produced the input for this replay item. */\n get traceId(): string {\n return this.require().traceId\n }\n\n /** True when read inside a replay item that has a resolved branch. */\n get active(): boolean {\n return this.read() !== null\n }\n\n /** Non-throwing variant for callers that handle the inactive case. */\n snapshot(): ReplayEnvironmentSnapshot | null {\n const snapshot = this.read()\n if (snapshot) {\n this.markAccessed()\n }\n return snapshot\n }\n\n /**\n * Record on the replay context that customer code obtained the branch\n * URL. Only `databaseUrl` and `snapshot()` count — `active`, `readOnly`\n * and friends inspect the lease without exposing the connection string,\n * so they don't prove the replayed code could have connected to the\n * branch.\n */\n private markAccessed(): void {\n const ctx = getReplayContext()\n if (ctx?.dbBranchLease) {\n ctx.dbSnapshotAccessed = true\n }\n }\n\n private read(): ReplayEnvironmentSnapshot | 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),\n // not the external_traces.id. Fall back to the external ID only if the\n // Bitfab ID is somehow absent — keeps replays from external sources\n // working until the source-system path is fully wired.\n const traceId = ctx.sourceBitfabTraceId ?? ctx.inputSourceTraceId\n if (!traceId) {\n return null\n }\n const lease = ctx.dbBranchLease\n return {\n databaseUrl: lease.databaseUrl,\n expiresAt: lease.expiresAt,\n providerConsoleUrl: lease.providerConsoleUrl,\n readOnly: lease.readOnly,\n traceId,\n }\n }\n\n private require(): ReplayEnvironmentSnapshot {\n const snapshot = this.read()\n if (!snapshot) {\n throw new Error(\n \"ReplayEnvironment accessed outside of a replay item. Pass it to bitfab.replay({ environment }) and only read it inside the replayed function.\",\n )\n }\n return snapshot\n }\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 { HttpClient } from \"./http.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 activeTraces: Record<string, Trace> = {}\n private readonly getActiveSpanContext: (() => ActiveSpanContext | null) | null\n private activeSpanMappings: Record<string, ActiveSpanContext> = {}\n\n /**\n * Initialize the tracing processor.\n *\n * @param config - Configuration options\n */\n constructor(config: {\n apiKey?: string\n serviceUrl?: string\n timeout?: number\n getActiveSpanContext?: () => ActiveSpanContext | null\n }) {\n this.httpClient = 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 * 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 this.sendTrace(trace, activeContext ? { id: activeContext.traceId } : {})\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(\n trace,\n mapping ? { id: mapping.traceId } : { completed: true },\n )\n\n delete this.activeSpanMappings[trace.traceId]\n delete this.activeTraces[trace.traceId]\n }\n\n /**\n * Called when a span is started.\n */\n // biome-ignore lint/suspicious/noExplicitAny: OpenAI Agents SDK uses any for span data\n async onSpanStart(span: Span<any>): Promise<void> {\n // Send the span to Bitfab (fire-and-forget)\n this.sendSpan(span)\n }\n\n /**\n * Called when a span is ended.\n *\n * Send all spans 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 span to Bitfab again to capture updates (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 // No buffering, so nothing to flush\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 }\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 overrides: { completed?: boolean; id?: string } = {},\n ): void {\n try {\n const { completed, ...traceOverrides } = overrides\n const traceData = trace.toJSON() as Record<string, unknown>\n Object.assign(traceData, traceOverrides)\n\n this.httpClient.sendExternalTrace({\n type: \"openai\",\n source: \"typescript-sdk-openai-tracing\",\n externalTrace: traceData,\n completed: 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 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 return 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\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}\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 },\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 },\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 * 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"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,IAMa;AANb;AAAA;AAAA;AAMO,IAAM,cAAN,cAA0B,MAAM;AAAA,MACrC,YACE,SACgB,KAChB;AACA,cAAM,OAAO;AAFG;AAGhB,aAAK,OAAO;AAAA,MACd;AAAA,IACF;AAAA;AAAA;;;ACEO,SAAS,SAAS,KAAa,SAAuB;AAC3D,MAAI,OAAO,IAAI,GAAG,GAAG;AACnB;AAAA,EACF;AACA,SAAO,IAAI,GAAG;AACd,MAAI;AACF,YAAQ,KAAK,YAAY,OAAO,EAAE;AAAA,EACpC,QAAQ;AAAA,EAER;AACF;AA1BA,IAcM;AAdN;AAAA;AAAA;AAcA,IAAM,SAAS,oBAAI,IAAY;AAAA;AAAA;;;ACGxB,SAAS,aAAqB;AACnC,QAAM,eACJ,WACA;AACF,MAAI,OAAO,cAAc,eAAe,YAAY;AAClD,QAAI;AACF,aAAO,aAAa,WAAW;AAAA,IACjC,QAAQ;AAAA,IAER;AAAA,EACF;AACA;AAAA,IACE;AAAA,IACA;AAAA,EACF;AACA,SAAO,eAAe;AACxB;AAMA,SAAS,iBAAyB;AAChC,SAAO,uCAAuC,QAAQ,SAAS,CAAC,SAAS;AACvE,UAAM,OAAQ,KAAK,OAAO,IAAI,KAAM;AACpC,UAAM,QAAQ,SAAS,MAAM,OAAQ,OAAO,IAAO;AACnD,WAAO,MAAM,SAAS,EAAE;AAAA,EAC1B,CAAC;AACH;AA7CA;AAAA;AAAA;AAeA;AAAA;AAAA;;;ACqBA,SAAS,cAAc,OAAwB;AAC7C,MAAI;AACF,UAAM,WAAY,OAA+C,aAC7D;AACJ,QAAI,YAAY,aAAa,UAAU;AACrC,aAAO;AAAA,IACT;AAAA,EACF,QAAQ;AAAA,EAER;AACA,SAAO,OAAO;AAChB;AAEA,SAAS,mBAAmB,OAAgB,QAAiC;AAG3E;AAAA,IACE,aAAa,OAAO,QAAQ,QAAQ,GAAG,CAAC;AAAA,IACxC,qDAAqD,MAAM;AAAA,EAC7D;AACA,MAAI;AACJ,MAAI;AACF,cAAU,oBAAoB,cAAc,KAAK,CAAC,KAAK,MAAM;AAAA,EAC/D,QAAQ;AACN,cAAU,oBAAoB,MAAM;AAAA,EACtC;AACA,SAAO,EAAE,MAAM,QAAQ;AACzB;AA+BO,SAAS,eAAe,OAAiC;AAC9D,MAAI;AACF,UAAM,EAAE,MAAM,KAAK,IAAI,iBAAAA,QAAU,UAAU,KAAK;AAEhD,QAAI;AACJ,QAAI;AACF,aAAO,KAAK,UAAU,IAAI,EAAE;AAAA,IAC9B,QAAQ;AACN,aAAO,mBAAmB,OAAO,kCAAkC;AAAA,IACrE;AACA,QAAI,OAAO,sBAAsB;AAC/B,aAAO,mBAAmB,OAAO,aAAa,IAAI,QAAQ;AAAA,IAC5D;AAEA,WAAO,OAAO,EAAE,MAAM,KAAK,IAAI,EAAE,KAAK;AAAA,EACxC,QAAQ;AACN,QAAI;AACF,aAAO,EAAE,MAAM,KAAK,MAAM,KAAK,UAAU,KAAK,CAAC,EAAE;AAAA,IACnD,QAAQ;AACN,aAAO,mBAAmB,OAAO,uBAAuB;AAAA,IAC1D;AAAA,EACF;AACF;AAeO,SAAS,iBAAiB,YAAsC;AACrE,MAAI,WAAW,SAAS,QAAW;AAEjC,WAAO,WAAW;AAAA,EACpB;AAKA,SAAO,iBAAAA,QAAU,YAAY;AAAA,IAC3B,MAAM,WAAW;AAAA,IACjB,MAAM,WAAW;AAAA,EACnB,CAAC;AACH;AAkBO,SAAS,WAAW,OAAyB;AAClD,QAAM,OAAO,gBAAgB,OAAO,GAAG,oBAAI,QAAQ,CAAC;AAQpD,MAAI;AACF,UAAM,OAAO,KAAK,UAAU,IAAI,GAAG,UAAU;AAC7C,QAAI,OAAO,gCAAgC;AACzC;AAAA,QACE;AAAA,QACA,gCAAgC,8BAA8B;AAAA,MAChE;AACA,aAAO,8BAA8B,IAAI;AAAA,IAC3C;AAAA,EACF,QAAQ;AAAA,EAER;AACA,SAAO;AACT;AAEA,SAAS,gBACP,OACA,OACA,MACS;AACT,MAAI,UAAU,QAAQ,UAAU,QAAW;AACzC,WAAO;AAAA,EACT;AACA,MACE,OAAO,UAAU,YACjB,OAAO,UAAU,YACjB,OAAO,UAAU,WACjB;AACA,WAAO;AAAA,EACT;AAEA,QAAM,YACH,OAA+C,aAAa,QAC7D,OAAO;AACT,MAAI,QAAQ,gBAAgB;AAC1B,WAAO,IAAI,SAAS;AAAA,EACtB;AAGA,MAAI,OAAO,UAAU,UAAU;AAC7B,QAAI;AACF,aAAO,OAAO,KAAK;AAAA,IACrB,QAAQ;AACN,aAAO,IAAI,SAAS;AAAA,IACtB;AAAA,EACF;AAEA,MAAI,KAAK,IAAI,KAAe,GAAG;AAC7B,WAAO,UAAU,SAAS;AAAA,EAC5B;AACA,OAAK,IAAI,KAAe;AAExB,MAAI;AACJ,MAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,aAAS,MAAM,IAAI,CAAC,SAAS,gBAAgB,MAAM,QAAQ,GAAG,IAAI,CAAC;AAAA,EACrE,WAAW,OAAQ,MAAkC,WAAW,YAAY;AAI1E,QAAI;AACF,eAAS;AAAA,QACN,MAAgC,OAAO;AAAA,QACxC,QAAQ;AAAA,QACR;AAAA,MACF;AAAA,IACF,QAAQ;AACN,eAAS,IAAI,SAAS;AAAA,IACxB;AAAA,EACF,OAAO;AACL,QAAI;AACF,YAAM,MAA+B,CAAC;AACtC,iBAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,KAAK,GAAG;AAC1C,YAAI,CAAC,EAAE,WAAW,GAAG,GAAG;AACtB,cAAI,CAAC,IAAI,gBAAgB,GAAG,QAAQ,GAAG,IAAI;AAAA,QAC7C;AAAA,MACF;AACA,eAAS;AAAA,IACX,QAAQ;AACN,eAAS,IAAI,SAAS;AAAA,IACxB;AAAA,EACF;AAMA,OAAK,OAAO,KAAe;AAC3B,SAAO;AACT;AAnQA,IAQA,kBAmBM,sBAOA,gCAgHA;AAlJN;AAAA;AAAA;AAQA,uBAAsB;AACtB;AAkBA,IAAM,uBAAuB;AAO7B,IAAM,iCAAiC;AAgHvC,IAAM,iBAAiB;AAAA;AAAA;;;ACnGhB,SAAS,+BACd,KACM;AACN,MAAI,CAAC,wBAAwB;AAC3B,6BAAyB;AAAA,EAC3B;AACA,aAAW;AACb;AA2CO,SAAS,yBAAkC;AAChD,SAAO;AACT;AAEO,SAAS,0BAA8D;AAC5E,SAAO,yBACF,IAAI,uBAAuB,IAC5B;AACN;AAzGA,IAmCI,wBAEA,UAqCS;AA1Eb;AAAA;AAAA;AAmCA,IAAI,yBACF;AACF,IAAI,WAAW;AAqCR,IAAM,qBACX,OAAO,YAAY,eAAe,QAAQ,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA,MAKhD;AAAA;AAAA,QAEE,CAAC,QAAQ,aAAa,EAAE,KAAK,GAAG;AAAA,QAE/B;AAAA,QACC,CAAC,QAEK;AACJ,yCAA+B,IAAI,iBAAiB;AAAA,QACtD;AAAA,MACF,EACC,MAAM,MAAM;AAAA,MAAC,CAAC;AAAA,QACjB,QAAQ,QAAQ,GACpB,KAAK,MAAM;AACX,iBAAW;AAAA,IACb,CAAC;AAAA;AAAA;;;ACeM,SAAS,mBAAyC;AACvD,SAAO,sBAAsB,SAAS,KAAK;AAC7C;AAGO,SAAS,qBAAwB,KAAoB,IAAgB;AAC1E,MAAI,sBAAsB;AACxB,WAAO,qBAAqB,IAAI,KAAK,EAAE;AAAA,EACzC;AACA,SAAO,GAAG;AACZ;AAxHA,IAsGI,sBAGS;AAzGb;AAAA;AAAA;AASA;AA6FA,IAAI,uBACF;AAEK,IAAM,qBAAoC,kBAAkB,KAAK,MAAM;AAC5E,6BAAuB,wBAA8C;AAAA,IACvE,CAAC;AAAA;AAAA;;;AC3GD;AAAA;AAAA;AAAA;AA4LA,SAAS,kBAAkB,UAA8C;AACvE,QAAM,YAAY,SAAS;AAC3B,QAAM,WAAW,SAAS;AAG1B,MAAI,cAAc,UAAa,cAAc,MAAM;AACjD,UAAM,eAAe,iBAAiB,EAAE,MAAM,UAAU,MAAM,UAAU,CAAC;AACzE,QAAI,MAAM,QAAQ,YAAY,GAAG;AAC/B,aAAO;AAAA,IACT;AACA,WAAO,iBAAiB,UAAa,iBAAiB,OAClD,CAAC,YAAY,IACb,CAAC;AAAA,EACP;AAGA,MAAI,MAAM,QAAQ,QAAQ,GAAG;AAC3B,WAAO;AAAA,EACT;AACA,SAAO,aAAa,UAAa,aAAa,OAAO,CAAC,QAAQ,IAAI,CAAC;AACrE;AAKA,SAAS,kBAAkB,UAA4C;AACrE,QAAM,aAAa,SAAS;AAC5B,QAAM,YAAY,SAAS;AAE3B,MAAI,eAAe,UAAa,eAAe,MAAM;AACnD,WAAO,iBAAiB,EAAE,MAAM,WAAW,MAAM,WAAW,CAAC;AAAA,EAC/D;AAEA,SAAO;AACT;AAuBA,SAAS,cAAc,UAAkC;AACvD,QAAM,QAAQ,oBAAI,IAGhB;AACF,QAAM,WAAW,oBAAI,IAAoB;AAEzC,WAAS,KAAK,MAA0B;AACtC,UAAM,MAAM,KAAK;AACjB,QAAI,KAAK;AACP,YAAM,OAAO,KAAK;AAClB,YAAM,aAAa,GAAG,GAAG,IAAI,IAAI;AACjC,YAAM,QAAQ,SAAS,IAAI,UAAU,KAAK;AAC1C,eAAS,IAAI,YAAY,QAAQ,CAAC;AAClC,YAAM,IAAI,GAAG,UAAU,IAAI,KAAK,IAAI;AAAA,QAClC,cAAc,KAAK;AAAA,QACnB,QAAQ,KAAK;AAAA,QACb,YAAY,KAAK;AAAA,MACnB,CAAC;AAAA,IACH;AACA,eAAW,SAAS,KAAK,UAAU;AACjC,WAAK,KAAK;AAAA,IACZ;AAAA,EACF;AAEA,aAAW,SAAS,SAAS,UAAU;AACrC,SAAK,KAAK;AAAA,EACZ;AAEA,SAAO,EAAE,MAAM;AACjB;AAMA,eAAe,YACb,YACA,YASA,IACA,WACA,cACA,aACA,aAG8B;AAS9B,QAAM,QAAQ,cAAc,WAAW,gBAAgB;AAEvD,MAAI,SAAoB,CAAC;AACzB,MAAI;AACJ,MAAI;AACJ,MAAI,QAAuB;AAC3B,QAAM,kBAAkB,WAAW;AAKnC,QAAM,qBAAyC,CAAC;AAEhD,MAAI;AACF,UAAM,OAAO,MAAM,WAAW,gBAAgB,WAAW,cAAc;AACvE,UAAM,WAAY,KAAK,SAAS,aAAa,CAAC;AAE9C,aAAS,kBAAkB,QAAQ;AACnC,qBAAiB,kBAAkB,QAAQ;AAK3C,QAAI,aAAa;AACf,eAAS,YAAY,QAAQ;AAAA,QAC3B,SAAS,WAAW;AAAA,QACpB,cAAc,WAAW;AAAA,MAC3B,CAAC;AAAA,IACH;AAGA,QAAI;AACJ,QAAI,iBAAiB,SAAS,iBAAiB,UAAU;AACvD,YAAM,eAAe,MAAM,WAAW;AAAA,QACpC,WAAW;AAAA,MACb;AACA,iBAAW,cAAc,aAAa,IAAI;AAAA,IAC5C;AAEA,UAAM,eAAe;AAAA,MACnB;AAAA,QACE;AAAA,QACA,SAAS;AAAA,QACT,mBAAmB,KAAK;AAAA,QACxB,oBAAoB,KAAK;AAAA,QACzB,qBAAqB,WAAW;AAAA,QAChC;AAAA,QACA,cAAc,WAAW,oBAAI,IAAI,IAAI;AAAA,QACrC;AAAA,QACA,eAAe;AAAA,QACf;AAAA,MACF;AAAA,MACA,MAAM,GAAG,GAAG,MAAM;AAAA,IACpB;AACA,aAAS,wBAAwB,UAAU,MAAM,eAAe;AAAA,EAClE,SAAS,GAAG;AACV,YAAQ,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC;AAAA,EACnD,UAAE;AAIA,UAAM,QAAQ,WAAW,kBAAkB;AAC3C,QAAI,OAAO;AACT,UAAI;AACF,cAAM,WAAW,qBAAqB,MAAM,YAAY;AAAA,MAC1D,SAAS,GAAG;AACV,YAAI;AACF,kBAAQ;AAAA,YACN,uCAAuC,MAAM,YAAY,iCACvD,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC,CAC3C;AAAA,UACF;AAAA,QACF,QAAQ;AAAA,QAER;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,SAAS;AAAA,IACT,OAAO;AAAA,IACP;AAAA,IACA;AAAA,IACA;AAAA,IACA,YAAY,WAAW,cAAc;AAAA;AAAA;AAAA;AAAA,IAIrC,QAAQ;AAAA,IACR,OAAO,WAAW,SAAS;AAAA,IAC3B,eAAe,WAAW,iBAAiB;AAAA,EAC7C;AACF;AAMA,eAAe,mBACb,OACA,gBACA,WACc;AACd,QAAM,UAAe,IAAI,MAAM,MAAM,MAAM;AAC3C,MAAI,YAAY;AAEhB,iBAAe,SAAwB;AACrC,WAAO,YAAY,MAAM,QAAQ;AAC/B,YAAM,QAAQ;AACd,YAAM,SAAS,MAAM,MAAM,KAAK,EAAE;AAClC,cAAQ,KAAK,IAAI;AACjB,kBAAY,QAAQ,KAAK;AAAA,IAC3B;AAAA,EACF;AAEA,QAAM,UAAU,MAAM;AAAA,IACpB,EAAE,QAAQ,KAAK,IAAI,gBAAgB,MAAM,MAAM,EAAE;AAAA,IACjD,MAAM,OAAO;AAAA,EACf;AACA,QAAM,QAAQ,IAAI,OAAO;AACzB,SAAO;AACT;AAOA,eAAsB,OACpB,YACA,YACA,kBAEA,IACA,SACgC;AAChC,MAAI,SAAS,aAAa,QAAW;AACnC,QAAI,QAAQ,SAAS,WAAW,GAAG;AACjC,YAAM,IAAI,YAAY,8CAA8C;AAAA,IACtE;AACA,QAAI,QAAQ,SAAS,SAAS,KAAK;AACjC,YAAM,IAAI;AAAA,QACR,2DAA2D,QAAQ,SAAS,MAAM;AAAA,MACpF;AAAA,IACF;AAAA,EACF;AACA,MAAI,SAAS,UAAU,UAAa,SAAS,aAAa,QAAW;AACnE,QAAI;AACF,cAAQ;AAAA,QACN;AAAA,MACF;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,QAAM;AAEN,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA,OAAO;AAAA,EACT,IAAI,MAAM,WAAW;AAAA,IACnB;AAAA;AAAA;AAAA,IAGA,SAAS,WAAW,SAAa,SAAS,SAAS;AAAA,IACnD,SAAS;AAAA,IACT,SAAS;AAAA,IACT,SAAS;AAAA,IACT,SAAS,gBAAgB;AAAA;AAAA,IACzB,SAAS;AAAA,IACT,SAAS;AAAA,EACX;AAEA,QAAM,eAA6B,SAAS,QAAQ;AACpD,QAAM,iBAAiB,SAAS,kBAAkB;AAElD,QAAM,QAAQ,YAAY;AAAA,IACxB,CAAC,eAAe,MACd;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,SAAS;AAAA,MACT,SAAS;AAAA,IACX;AAAA,EACJ;AACA,QAAM,QAAQ,MAAM;AACpB,MAAI,YAAY;AAChB,MAAI,YAAY;AAChB,MAAI,UAAU;AACd,QAAM,cAAc,MAAM;AAAA,IACxB;AAAA,IACA;AAAA,IACA,SAAS,aACL,CAAC,SAAS;AACR,mBAAa;AACb,UAAI,KAAK,UAAU,MAAM;AACvB,qBAAa;AAAA,MACf,OAAO;AACL,mBAAW;AAAA,MACb;AACA,UAAI;AACF,iBAAS,aAAa,EAAE,WAAW,OAAO,WAAW,QAAQ,CAAC;AAAA,MAChE,QAAQ;AAAA,MAER;AAAA,IACF,IACA;AAAA,EACN;AAOA,QAAM,iBAAiB,MAAM,WAAW,eAAe,SAAS;AAChE,QAAM,iBAAiB,eAAe;AAGtC,QAAM,eAAe,eAAe;AAEpC,MAAI,mBAAmB,QAAW;AAGhC,QAAI;AACF,cAAQ;AAAA,QACN;AAAA,MACF;AAAA,IACF,QAAQ;AAAA,IAER;AACA,eAAW,QAAQ,aAAa;AAC9B,WAAK,UAAU;AAAA,IACjB;AAAA,EACF,OAAO;AAeL,UAAM,UAAoB,CAAC;AAC3B,QAAI,iBAAiB;AACrB,eAAW,QAAQ,aAAa;AAC9B,UAAI,KAAK,SAAS;AAChB,cAAM,SAAS,eAAe,KAAK,OAAO;AAC1C,YAAI,KAAK,UAAU,MAAM;AACvB,4BAAkB;AAClB,cAAI,WAAW,QAAW;AACxB,oBAAQ,KAAK,KAAK,OAAO;AAAA,UAC3B;AAAA,QACF;AAGA,YAAI,WAAW,QAAW;AACxB,eAAK,SAAS,eAAe,MAAM,KAAK;AAAA,QAC1C;AACA,aAAK,UAAU,UAAU;AAAA,MAC3B;AAAA,IACF;AACA,QAAI,QAAQ,SAAS,GAAG;AACtB,YAAM,cACJ,eAAe,eAAe,SAC1B,yBAAyB,eAAe,UAAU,4BAClD;AACN,UAAI,QAAQ,WAAW,gBAAgB;AACrC,cAAM,IAAI;AAAA,UACR,yEAAyE,cAAc,iCAAiC,SAAS,KAAK,WAAW;AAAA,QAEnJ;AAAA,MACF;AACA,UAAI;AACF,gBAAQ;AAAA,UACN,6CAA6C,QAAQ,MAAM,OAAO,cAAc,wCAAwC,SAAS,KAAK,WAAW,8EAClE,QAAQ,KAAK,IAAI,CAAC;AAAA,QACnG;AAAA,MACF,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,OAAO;AAAA,IACP;AAAA,IACA,YAAY,GAAG,UAAU,GAAG,UAAU;AAAA,EACxC;AACF;AAhmBA;AAAA;AAAA;AAUA;AAOA;AAEA;AAEA;AAAA;AAAA;;;ACrBA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACSO,IAAM,cAAc;;;ACFpB,IAAM,sBAAsB;;;ACGnC;;;ACAO,SAAS,WAAW,OAA4C;AACrE,QAAM,SAAS;AACf,MAAI,OAAO,OAAO,UAAU,YAAY;AACtC,WAAO,MAAM;AAAA,EACf;AACF;;;ADFA;AAqBO,SAAS,qBAAqB,SAGnC;AACA,MAAI;AACF,WAAO,EAAE,MAAM,KAAK,UAAU,OAAO,GAAG,SAAS,CAAC,EAAE;AAAA,EACtD,QAAQ;AACN,UAAM,UAAoB,CAAC;AAK3B,UAAM,WAAW,CAAC,OAAgB,SAAmC;AACnE,YAAM,IAAI,OAAO;AACjB,UACE,UAAU,QACV,MAAM,YACN,MAAM,YACN,MAAM,WACN;AACA,eAAO;AAAA,MACT;AACA,UAAI,MAAM,UAAU;AAClB,gBAAQ,KAAK,QAAQ;AACrB,eAAO;AAAA,MACT;AACA,UAAI,MAAM,YAAY;AACpB,cAAM,OAAQ,MAA4B,QAAQ;AAClD,gBAAQ,KAAK,IAAI;AACjB,eAAO,oBAAoB,IAAI;AAAA,MACjC;AACA,UAAI,MAAM,UAAU;AAClB,gBAAQ,KAAK,QAAQ;AACrB,eAAO;AAAA,MACT;AACA,UAAI,MAAM,UAAU;AAClB,eAAO;AAAA,MACT;AACA,YAAM,MAAM;AACZ,YAAM,YACH,IAA4C,aAAa,QAC1D;AACF,UAAI,KAAK,IAAI,GAAG,GAAG;AACjB,gBAAQ,KAAK,SAAS;AACtB,eAAO,WAAW,SAAS;AAAA,MAC7B;AACA,WAAK,IAAI,GAAG;AACZ,UAAI;AACJ,UAAI,MAAM,QAAQ,GAAG,GAAG;AACtB,iBAAS,IAAI,IAAI,CAAC,SAAS,SAAS,MAAM,IAAI,CAAC;AAAA,MACjD,WAAW,OAAQ,IAA6B,WAAW,YAAY;AACrE,YAAI;AACF,mBAAS,SAAU,IAA8B,OAAO,GAAG,IAAI;AAAA,QACjE,QAAQ;AACN,kBAAQ,KAAK,SAAS;AACtB,mBAAS,oBAAoB,SAAS;AAAA,QACxC;AAAA,MACF,OAAO;AACL,YAAI;AACF,gBAAM,MAA+B,CAAC;AACtC,qBAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,GAAG,GAAG;AACxC,gBAAI,CAAC,IAAI,SAAS,GAAG,IAAI;AAAA,UAC3B;AACA,mBAAS;AAAA,QACX,QAAQ;AAIN;AAAA,YACE;AAAA,YACA;AAAA,UACF;AACA,kBAAQ,KAAK,SAAS;AACtB,mBAAS,oBAAoB,SAAS;AAAA,QACxC;AAAA,MACF;AACA,WAAK,OAAO,GAAG;AACf,aAAO;AAAA,IACT;AACA,QAAI;AACJ,QAAI;AACF,kBAAY,SAAS,SAAS,oBAAI,QAAQ,CAAC;AAAA,IAC7C,SAAS,OAAO;AAEd,YAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,aAAO;AAAA,QACL,MAAM,KAAK,UAAU,EAAE,OAAO,6BAA6B,OAAO,GAAG,CAAC;AAAA,QACtE;AAAA,MACF;AAAA,IACF;AAIA,QACE,QAAQ,SAAS,KACjB,OAAO,cAAc,YACrB,cAAc,QACd,CAAC,MAAM,QAAQ,SAAS,GACxB;AACA,YAAM,MAAM;AACZ,YAAM,WAAW,MAAM,QAAQ,IAAI,MAAM,IAAI,IAAI,SAAS,CAAC;AAC3D,UAAI,SAAS;AAAA,QACX,GAAG;AAAA,QACH;AAAA,UACE,QAAQ;AAAA,UACR,MAAM;AAAA,UACN,OAAO,sCAAsC;AAAA,YAC3C,GAAG,IAAI,IAAI,OAAO;AAAA,UACpB,EAAE,KAAK,IAAI,CAAC;AAAA,QACd;AAAA,MACF;AAAA,IACF;AACA,WAAO,EAAE,MAAM,KAAK,UAAU,SAAS,GAAG,QAAQ;AAAA,EACpD;AACF;AAIA,IAAM,uBAAuB,oBAAI,IAAsB;AAUhD,SAAS,YAAe,SAAiC;AAC9D,uBAAqB,IAAI,OAAO;AAGhC,OAAK,QACF,QAAQ,MAAM;AACb,yBAAqB,OAAO,OAAO;AAAA,EACrC,CAAC,EACA,MAAM,MAAM;AAAA,EAEb,CAAC;AACH,SAAO;AACT;AAQA,eAAsB,YAAY,YAAoB,KAAqB;AACzE,MAAI,qBAAqB,SAAS,GAAG;AACnC;AAAA,EACF;AAGA,MAAI;AACJ,MAAI;AACF,UAAM,QAAQ,KAAK;AAAA,MACjB,QAAQ,WAAW,MAAM,KAAK,oBAAoB,CAAC;AAAA,MACnD,IAAI,QAAc,CAAC,YAAY;AAC7B,gBAAQ,WAAW,SAAS,SAAS;AACrC,mBAAW,KAAK;AAAA,MAClB,CAAC;AAAA,IACH,CAAC;AAAA,EACH,UAAE;AACA,QAAI,OAAO;AACT,mBAAa,KAAK;AAAA,IACpB;AAAA,EACF;AACF;AAIA,IACE,OAAO,YAAY,eACnB,QAAQ,YAAY,QACpB,QAAQ,SAAS,QAAQ,MACzB;AACA,MAAI,aAAa;AACjB,UAAQ,GAAG,cAAc,MAAM;AAC7B,QAAI,qBAAqB,OAAO,KAAK,CAAC,YAAY;AAChD,mBAAa;AAGb,cAAQ;AAAA,QACN,MAAM,KAAK,oBAAoB,EAAE;AAAA,UAAI,CAAC,MACpC,EAAE,MAAM,MAAM;AAAA,UAEd,CAAC;AAAA,QACH;AAAA,MACF,EACG,KAAK,MAAM;AACV,qBAAa;AAAA,MACf,CAAC,EACA,MAAM,MAAM;AACX,qBAAa;AAAA,MACf,CAAC;AAAA,IACL;AAAA,EACF,CAAC;AACH;AAcO,IAAM,aAAN,MAAiB;AAAA,EAKtB,YAAY,QAA0B;AACpC,SAAK,SAAS,OAAO;AACrB,SAAK,aAAa,OAAO;AACzB,SAAK,UAAU,OAAO,WAAW;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,QACJ,UACA,SACA,SACY;AACZ,UAAM,MAAM,GAAG,KAAK,UAAU,GAAG,QAAQ;AACzC,UAAM,UAAU,SAAS,WAAW,KAAK;AACzC,UAAM,SAAS,SAAS,UAAU;AAElC,UAAM,aAAa,IAAI,gBAAgB;AACvC,UAAM,YAAY,WAAW,MAAM,WAAW,MAAM,GAAG,OAAO;AAO9D,UAAM,EAAE,MAAM,QAAQ,IAAI,qBAAqB,OAAO;AACtD,QAAI,QAAQ,SAAS,GAAG;AACtB,UAAI;AACF,gBAAQ;AAAA,UACN,2BAA2B,QAAQ,SAAS,QAAQ,MAAM,+BAC1B,CAAC,GAAG,IAAI,IAAI,OAAO,CAAC,EAAE,KAAK,IAAI,CAAC;AAAA,QAIlE;AAAA,MACF,QAAQ;AAAA,MAAC;AAAA,IACX;AAEA,QAAI;AACF,YAAM,WAAW,MAAM,MAAM,KAAK;AAAA,QAChC;AAAA,QACA,SAAS;AAAA,UACP,gBAAgB;AAAA,UAChB,eAAe,UAAU,KAAK,MAAM;AAAA,QACtC;AAAA,QACA;AAAA,QACA,QAAQ,WAAW;AAAA,MACrB,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,YAAY,MAAM,SAAS,KAAK;AACtC,cAAM,IAAI;AAAA,UACR,QAAQ,SAAS,MAAM,KAAK,UAAU,MAAM,GAAG,GAAG,CAAC;AAAA,QACrD;AAAA,MACF;AAEA,YAAM,SAAS,MAAM,SAAS,KAAK;AAGnC,UAAI,OAAO,OAAO;AAChB,YAAI,OAAO,KAAK;AACd,gBAAM,IAAI;AAAA,YACR,GAAG,OAAO,KAAK,qBAAqB,KAAK,UAAU,GAAG,OAAO,GAAG;AAAA,YAChE,OAAO;AAAA,UACT;AAAA,QACF;AACA,cAAM,IAAI,YAAY,OAAO,KAAK;AAAA,MACpC;AAEA,aAAO;AAAA,IACT,SAAS,OAAO;AACd,UAAI,iBAAiB,aAAa;AAChC,cAAM;AAAA,MACR;AACA,UAAI,iBAAiB,OAAO;AAC1B,YAAI,MAAM,SAAS,cAAc;AAC/B,gBAAM,IAAI,YAAY,2BAA2B,OAAO,IAAI;AAAA,QAC9D;AACA,cAAM,IAAI,YAAY,MAAM,OAAO;AAAA,MACrC;AACA,YAAM,IAAI,YAAY,wBAAwB;AAAA,IAChD,UAAE;AACA,mBAAa,SAAS;AAAA,IACxB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,eAAkB,MAA0B;AAChD,WAAO,KAAK,QAAW,6BAA6B,EAAE,KAAK,CAAC;AAAA,EAC9D;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,kBACE,YACA,SACM;AACN,SAAK;AAAA,MACH,KAAK,QAAQ,sBAAsB,UAAU,WAAW;AAAA,QACtD,GAAG;AAAA,QACH,YAAY;AAAA,MACd,CAAC;AAAA,IACH,EAAE,MAAM,CAAC,UAAU;AACjB,UAAI;AACF,gBAAQ,MAAM,mCAAmC,KAAK;AAAA,MACxD,QAAQ;AAAA,MAAC;AAAA,IACX,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,iBAAiB,SAAoD;AACnE,WAAO;AAAA,MACL,KAAK,QAAQ,0BAA0B;AAAA,QACrC,GAAG;AAAA,QACH,YAAY;AAAA,MACd,CAAC;AAAA,IACH,EAAE,MAAM,CAAC,UAAU;AACjB,UAAI;AACF,gBAAQ,MAAM,2CAA2C,KAAK;AAAA,MAChE,QAAQ;AAAA,MAAC;AAAA,IACX,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,kBAAkB,SAAoD;AACpE,WAAO;AAAA,MACL,KAAK,QAAQ,2BAA2B;AAAA,QACtC,GAAG;AAAA,QACH,YAAY;AAAA,MACd,CAAC;AAAA,IACH,EAAE,MAAM,CAAC,UAAU;AACjB,UAAI;AACF,gBAAQ,MAAM,4CAA4C,KAAK;AAAA,MACjE,QAAQ;AAAA,MAAC;AAAA,IACX,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,WACE,eACA,SAKkB;AAClB,UAAM,WAAW,2BAA2B,mBAAmB,aAAa,CAAC;AAC7E,WAAO;AAAA,MACL,KAAK,QAAQ,UAAU,SAAS,EAAE,QAAQ,QAAQ,CAAC;AAAA,IACrD,EAAE,MAAM,CAAC,UAAU;AACjB,UAAI;AACF,gBAAQ,MAAM,kCAAkC,KAAK;AAAA,MACvD,QAAQ;AAAA,MAAC;AAAA,IACX,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,YACJ,kBACA,OACA,UACA,uBACA,iBACA,sBACA,mBACA,WAC8B;AAG9B,UAAM,UAAmC,EAAE,iBAAiB;AAC5D,QAAI,UAAU,QAAW;AACvB,cAAQ,QAAQ;AAAA,IAClB;AACA,QAAI,UAAU;AACZ,cAAQ,WAAW;AAAA,IACrB;AACA,QAAI,0BAA0B,QAAW;AACvC,cAAQ,wBAAwB;AAAA,IAClC;AACA,QAAI,oBAAoB,QAAW;AACjC,cAAQ,kBAAkB;AAAA,IAC5B;AACA,QAAI,sBAAsB;AACxB,cAAQ,uBAAuB;AAAA,IACjC;AACA,QAAI,sBAAsB,QAAW;AACnC,cAAQ,oBAAoB;AAAA,IAC9B;AACA,QAAI,cAAc,QAAW;AAC3B,cAAQ,YAAY;AAAA,IACtB;AAKA,UAAM,UAAU,uBAAuB,OAAU;AACjD,WAAO,KAAK,QAA6B,yBAAyB,SAAS;AAAA,MACzE;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,gBAAgB,QAA+C;AACnE,UAAM,MAAM,GAAG,KAAK,UAAU,0BAA0B,MAAM;AAC9D,UAAM,aAAa,IAAI,gBAAgB;AACvC,UAAM,YAAY,WAAW,MAAM,WAAW,MAAM,GAAG,GAAM;AAE7D,QAAI;AACF,YAAM,WAAW,MAAM,MAAM,KAAK;AAAA,QAChC,QAAQ;AAAA,QACR,SAAS,EAAE,eAAe,UAAU,KAAK,MAAM,GAAG;AAAA,QAClD,QAAQ,WAAW;AAAA,MACrB,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,YAAY,MAAM,SAAS,KAAK;AACtC,cAAM,IAAI;AAAA,UACR,QAAQ,SAAS,MAAM,KAAK,UAAU,MAAM,GAAG,GAAG,CAAC;AAAA,QACrD;AAAA,MACF;AAEA,aAAQ,MAAM,SAAS,KAAK;AAAA,IAC9B,SAAS,OAAO;AACd,UAAI,iBAAiB,aAAa;AAChC,cAAM;AAAA,MACR;AACA,UAAI,iBAAiB,OAAO;AAC1B,YAAI,MAAM,SAAS,cAAc;AAC/B,gBAAM,IAAI,YAAY,iCAAiC;AAAA,QACzD;AACA,cAAM,IAAI,YAAY,MAAM,OAAO;AAAA,MACrC;AACA,YAAM,IAAI,YAAY,wBAAwB;AAAA,IAChD,UAAE;AACA,mBAAa,SAAS;AAAA,IACxB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,YAAY,gBAAmD;AACnE,UAAM,MAAM,GAAG,KAAK,UAAU,4BAA4B,cAAc;AACxE,UAAM,aAAa,IAAI,gBAAgB;AACvC,UAAM,YAAY,WAAW,MAAM,WAAW,MAAM,GAAG,GAAM;AAE7D,QAAI;AACF,YAAM,WAAW,MAAM,MAAM,KAAK;AAAA,QAChC,QAAQ;AAAA,QACR,SAAS,EAAE,eAAe,UAAU,KAAK,MAAM,GAAG;AAAA,QAClD,QAAQ,WAAW;AAAA,MACrB,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,YAAY,MAAM,SAAS,KAAK;AACtC,cAAM,IAAI;AAAA,UACR,QAAQ,SAAS,MAAM,KAAK,UAAU,MAAM,GAAG,GAAG,CAAC;AAAA,QACrD;AAAA,MACF;AAEA,aAAQ,MAAM,SAAS,KAAK;AAAA,IAC9B,SAAS,OAAO;AACd,UAAI,iBAAiB,aAAa;AAChC,cAAM;AAAA,MACR;AACA,UAAI,iBAAiB,OAAO;AAC1B,YAAI,MAAM,SAAS,cAAc;AAC/B,gBAAM,IAAI,YAAY,iCAAiC;AAAA,QACzD;AACA,cAAM,IAAI,YAAY,MAAM,OAAO;AAAA,MACrC;AACA,YAAM,IAAI,YAAY,wBAAwB;AAAA,IAChD,UAAE;AACA,mBAAa,SAAS;AAAA,IACxB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,eAAe,WAAoD;AACvE,WAAO,KAAK;AAAA,MACV;AAAA,MACA,EAAE,UAAU;AAAA,MACZ,EAAE,SAAS,IAAO;AAAA,IACpB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,qBACJ,WACA,SACA,eACmC;AACnC,WAAO,KAAK;AAAA,MACV;AAAA,MACA,EAAE,WAAW,SAAS,cAAc;AAAA,MACpC,EAAE,SAAS,IAAO;AAAA,IACpB;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,qBAAqB,cAAqC;AAC9D,UAAM,KAAK;AAAA,MACT;AAAA,MACA,EAAE,aAAa;AAAA,MACf,EAAE,SAAS,IAAO;AAAA,IACpB;AAAA,EACF;AACF;;;AE3kBA;AACA;AAqBA,SAAS,SAAiB;AACxB,UAAO,oBAAI,KAAK,GAAE,YAAY;AAChC;AAIA,IAAM,gBAAgB;AAEtB,SAAS,qBACP,SACgC;AAChC,MAAI,CAAC,MAAM,QAAQ,OAAO,GAAG;AAC3B,WAAO,CAAC;AAAA,EACV;AACA,SAAO,QAAQ,IAAI,CAAC,UAAU,cAAc,KAAK,CAA4B;AAC/E;AAEA,SAAS,aAAa,KAA6B;AACjD,SAAO,OAAO,QAAQ,YAAY,OAAO,SAAS,GAAG,IAAI,MAAM;AACjE;AAEA,SAAS,aACP,SACyB;AACzB,QAAM,YAAqC,CAAC;AAC5C,QAAM,QAAQ,QAAQ;AACtB,MAAI,CAAC,OAAO;AACV,WAAO;AAAA,EACT;AAOA,QAAM,YAAY,aAAa,MAAM,YAAY;AACjD,QAAM,YAAY,aAAa,MAAM,uBAAuB;AAC5D,QAAM,gBAAgB,aAAa,MAAM,2BAA2B;AACpE,MAAI,cAAc,QAAQ,cAAc,QAAQ,kBAAkB,MAAM;AACtE,cAAU,eACP,aAAa,MAAM,aAAa,MAAM,iBAAiB;AAAA,EAC5D;AAEA,QAAM,SAAS,aAAa,MAAM,aAAa;AAC/C,MAAI,WAAW,MAAM;AACnB,cAAU,eAAe;AAAA,EAC3B;AACA,MAAI,cAAc,MAAM;AACtB,cAAU,kBAAkB;AAAA,EAC9B;AACA,MAAI,kBAAkB,MAAM;AAC1B,cAAU,sBAAsB;AAAA,EAClC;AAEA,SAAO;AACT;AAsCO,IAAM,2BAAN,MAA+B;AAAA,EAoCpC,YAAY,QAMT;AApCH;AAAA,SAAQ,YAAmC,oBAAI,IAAI;AACnD,SAAQ,UAAyB;AACjC,SAAQ,aAA4B;AACpC,SAAQ,gBAA0C;AAClD,SAAQ,iBAAgC;AAGxC;AAAA,SAAQ,sBAAsD,CAAC;AAC/D,SAAQ,kBAAkD,CAAC;AAC3D,SAAQ,mBAAkC;AAC1C,SAAQ,sBAAqC;AAC7C,SAAQ,oBAAoD,CAAC;AAC7D,SAAQ,kBAAiC;AACzC,SAAQ,kBAA2C,CAAC;AACpD,SAAQ,sBAAqC;AAC7C,SAAQ,4BAA4D,CAAC;AAGrE;AAAA,SAAQ,sBAA2C,oBAAI,IAAI;AAQ3D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAQ,eAAe;AAWrB,SAAK,aAAa,IAAI,WAAW;AAAA,MAC/B,QAAQ,OAAO;AAAA,MACf,YAAY,OAAO,cAAc;AAAA,MACjC,SAAS,OAAO,WAAW;AAAA,IAC7B,CAAC;AACD,SAAK,mBAAmB,OAAO;AAC/B,SAAK,uBAAuB,OAAO,wBAAwB;AAG3D,SAAK,iBAAiB,KAAK,eAAe,KAAK,IAAI;AACnD,SAAK,kBAAkB,KAAK,gBAAgB,KAAK,IAAI;AACrD,SAAK,yBAAyB,KAAK,uBAAuB,KAAK,IAAI;AACnE,SAAK,oBAAoB,KAAK,kBAAkB,KAAK,IAAI;AACzD,SAAK,mBAAmB,KAAK,iBAAiB,KAAK,IAAI;AAAA,EACzD;AAAA;AAAA,EAIQ,cAAsB;AAC5B,QAAI,KAAK,YAAY,MAAM;AACzB,aAAO,KAAK;AAAA,IACd;AAEA,SAAK,gBAAgB,KAAK,uBAAuB,KAAK;AAEtD,QAAI,KAAK,eAAe;AACtB,WAAK,UAAU,KAAK,cAAc;AAAA,IACpC,OAAO;AACL,WAAK,UAAU,WAAW;AAAA,IAC5B;AAEA,SAAK,iBAAiB,OAAO;AAC7B,WAAO,KAAK;AAAA,EACd;AAAA,EAEQ,YAAY,SAAiC;AACnD,QAAI,SAAS;AACX,YAAM,iBAAiB,KAAK,oBAAoB,IAAI,OAAO;AAC3D,UAAI,gBAAgB;AAClB,eAAO;AAAA,MACT;AAAA,IACF;AAIA,WAAO,KAAK,cAAc,KAAK,eAAe,UAAU;AAAA,EAC1D;AAAA;AAAA;AAAA;AAAA,EAKQ,qBAA2B;AACjC,QAAI,CAAC,KAAK,gBAAgB,KAAK,eAAe,MAAM;AAClD;AAAA,IACF;AACA,SAAK,YAAY;AACjB,QAAI,KAAK,kBAAkB,MAAM;AAC/B;AAAA,IACF;AACA,UAAM,SAAS,WAAW;AAC1B,SAAK,UAAU,QAAQ,KAAK,kBAAkB,SAAS,KAAK,WAAW,IAAI;AAC3E,SAAK,aAAa;AAAA,EACpB;AAAA,EAEQ,mBAAyB;AAC/B,QAAI,KAAK,eAAe,MAAM;AAC5B;AAAA,IACF;AACA,UAAM,SAAS,KAAK;AACpB,SAAK,aAAa;AAClB,SAAK,aAAa,QAAQ,KAAK,UAAU;AAAA,EAC3C;AAAA;AAAA,EAIQ,UACN,QACA,MACA,UACA,WACA,UACU;AACV,UAAM,UAAU,KAAK,YAAY;AAEjC,UAAM,WAAqB;AAAA,MACzB;AAAA,MACA;AAAA,MACA,UAAU,YAAY;AAAA,MACtB,WAAW,OAAO;AAAA,MAClB;AAAA,MACA,MAAM;AAAA,MACN,OAAO,cAAc,SAAS;AAAA,MAC9B,UAAU,CAAC;AAAA,IACb;AACA,SAAK,UAAU,IAAI,QAAQ,QAAQ;AACnC,WAAO;AAAA,EACT;AAAA,EAEQ,aACN,QACA,QACA,OACA,eACM;AACN,UAAM,WAAW,KAAK,UAAU,IAAI,MAAM;AAC1C,QAAI,CAAC,UAAU;AACb;AAAA,IACF;AACA,SAAK,UAAU,OAAO,MAAM;AAE5B,aAAS,UAAU,OAAO;AAC1B,aAAS,SAAS,cAAc,MAAM;AACtC,QAAI,UAAU,QAAW;AACvB,eAAS,QAAQ;AAAA,IACnB;AAEA,QAAI,eAAe;AACjB,eAAS,SAAS,KAAK,aAAa;AAAA,IACtC;AAEA,SAAK,SAAS,QAAQ;AAAA,EACxB;AAAA,EAEQ,SAAS,UAA0B;AACzC,UAAM,WAAoC;AAAA,MACxC,MAAM,SAAS;AAAA,MACf,MAAM,SAAS;AAAA,IACjB;AACA,QAAI,SAAS,UAAU,QAAW;AAChC,eAAS,QAAQ,SAAS;AAAA,IAC5B;AACA,QAAI,SAAS,WAAW,QAAW;AACjC,eAAS,SAAS,SAAS;AAAA,IAC7B;AACA,QAAI,SAAS,UAAU,QAAW;AAChC,eAAS,QAAQ,SAAS;AAAA,IAC5B;AACA,QAAI,SAAS,SAAS,SAAS,GAAG;AAChC,eAAS,WAAW,SAAS;AAAA,IAC/B;AAEA,UAAM,UAAmC;AAAA,MACvC,IAAI,SAAS;AAAA,MACb,UAAU,SAAS;AAAA,MACnB,YAAY,SAAS;AAAA,MACrB,UAAU,SAAS,WAAW,OAAO;AAAA,MACrC,WAAW;AAAA,IACb;AACA,QAAI,SAAS,aAAa,MAAM;AAC9B,cAAQ,YAAY,SAAS;AAAA,IAC/B;AAEA,UAAM,UAAmC;AAAA,MACvC,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,kBAAkB,KAAK;AAAA,MACvB,eAAe,SAAS;AAAA,MACxB;AAAA,IACF;AAEA,QAAI;AACF,WAAK,WAAW,iBAAiB,OAAO;AAAA,IAC1C,QAAQ;AAAA,IAER;AAAA,EACF;AAAA,EAEQ,oBACN,SACA,UACM;AACN,QAAI,KAAK,YAAY,MAAM;AACzB;AAAA,IACF;AAEA,UAAM,YAAY,KAAK,kBAAkB;AACzC,UAAM,UAAU,KAAK;AAGrB,SAAK,UAAU;AAEf,UAAM,gBAAyC;AAAA,MAC7C,IAAI;AAAA,MACJ,YAAY,KAAK,kBAAkB,OAAO;AAAA,MAC1C,UAAU,WAAW,OAAO;AAAA,MAC5B,eAAe,KAAK;AAAA,IACtB;AAEA,QAAI,UAAU;AACZ,oBAAc,WAAW;AAAA,IAC3B;AAEA,UAAM,YAAqC;AAAA,MACzC,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,kBAAkB,KAAK;AAAA,MACvB;AAAA,MACA;AAAA,IACF;AAEA,QAAI;AACF,WAAK,WAAW,kBAAkB,SAAS;AAAA,IAC7C,QAAQ;AAAA,IAER;AAAA,EACF;AAAA;AAAA,EAIA,MAAc,eAEZ,WACA,WACA,UACkC;AAClC,QAAI;AACF,YAAM,MAAO,UAAU,eAA0B,aAAa,WAAW;AACzE,YAAM,WAAY,UAAU,aAAwB;AACpD,YAAM,YAAY,UAAU,cAAc,CAAC;AAC3C,YAAM,UAAU,UAAU;AAC1B,YAAM,WAAW,KAAK,YAAY,OAAO;AAEzC,WAAK,UAAU,KAAK,UAAU,YAAY,WAAW,QAAQ;AAAA,IAC/D,QAAQ;AAAA,IAER;AACA,WAAO,CAAC;AAAA,EACV;AAAA,EAEA,MAAc,gBAEZ,WACA,WACA,UACkC;AAClC,QAAI;AACF,YAAM,MAAO,UAAU,eAA0B,aAAa;AAC9D,YAAM,eAAe,UAAU;AAC/B,WAAK,aAAa,KAAK,YAAY;AAAA,IACrC,QAAQ;AAAA,IAER;AACA,WAAO,CAAC;AAAA,EACV;AAAA,EAEA,MAAc,uBAEZ,WACA,WACA,UACkC;AAClC,QAAI;AACF,YAAM,MAAO,UAAU,eAA0B,aAAa;AAC9D,YAAM,QAAQ,OAAO,UAAU,SAAS,eAAe;AACvD,WAAK,aAAa,KAAK,QAAW,KAAK;AAAA,IACzC,QAAQ;AAAA,IAER;AACA,WAAO,CAAC;AAAA,EACV;AAAA,EAEA,MAAc,kBAEZ,WACA,YACA,UACkC;AAClC,QAAI;AACF,YAAM,UAAW,UAAU,YAAuB,WAAW;AAC7D,YAAM,YAAa,UAAU,cAAyB;AACtD,YAAM,WAAW,KAAK,YAAY;AAElC,YAAM,SAAS,WAAW;AAC1B,WAAK,oBAAoB,IAAI,SAAS,MAAM;AAE5C,WAAK;AAAA,QACH;AAAA,QACA,UAAU,SAAS;AAAA,QACnB;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF,QAAQ;AAAA,IAER;AACA,WAAO,CAAC;AAAA,EACV;AAAA,EAEA,MAAc,iBAEZ,WACA,YACA,UACkC;AAClC,QAAI;AACF,YAAM,UAAW,UAAU,YAAuB;AAClD,YAAM,SAAS,KAAK,oBAAoB,IAAI,OAAO;AACnD,UAAI,QAAQ;AACV,aAAK,oBAAoB,OAAO,OAAO;AACvC,aAAK,aAAa,MAAM;AAAA,MAC1B;AAAA,IACF,QAAQ;AAAA,IAER;AACA,WAAO,CAAC;AAAA,EACV;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,kBAAqD,SAAe;AAIlE,UAAM,QAAoB,QAAQ,SAAuB,CAAC;AAC1D,QAAI,CAAC,QAAQ,OAAO;AAClB;AAAC,MAAC,QAAoC,QAAQ;AAAA,IAChD;AAEA,UAAM,aAA4C;AAAA,MAChD,CAAC,cAAc,KAAK,cAAc;AAAA,MAClC,CAAC,eAAe,KAAK,eAAe;AAAA,MACpC,CAAC,sBAAsB,KAAK,sBAAsB;AAAA,MAClD,CAAC,iBAAiB,KAAK,iBAAiB;AAAA,MACxC,CAAC,gBAAgB,KAAK,gBAAgB;AAAA,IACxC;AAEA,eAAW,CAAC,OAAO,QAAQ,KAAK,YAAY;AAC1C,UAAI,CAAC,MAAM,KAAK,GAAG;AACjB,cAAM,KAAK,IAAI,CAAC;AAAA,MAClB;AACA,YAAM,KAAK,EAAE,KAAK,EAAE,SAAS,MAAM,OAAO,CAAC,QAAQ,EAAE,CAAC;AAAA,IACxD;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,OAAO,aACL,QACA,MACwB;AACxB,SAAK,aAAa,IAAI;AACtB,WAAO,KAAK,cAAc,MAAM;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBA,OAAO,UACL,QACA,MACwB;AACxB,SAAK,aAAa,IAAI;AACtB,WAAO,KAAK,cAAc,MAAM;AAAA,EAClC;AAAA,EAEQ,aAAa,MAAkC;AAKrD,QAAI,QAAQ,KAAK,UAAU,QAAW;AACpC,WAAK,eAAe;AACpB,WAAK,YAAY,KAAK;AAAA,IACxB,OAAO;AACL,WAAK,eAAe;AACpB,WAAK,YAAY;AAAA,IACnB;AACA,SAAK,aAAa;AAAA,EACpB;AAAA;AAAA,EAIA,OAAe,cACb,QACwB;AACxB,QAAI;AACF,WAAK,mBAAmB;AACxB,uBAAiB,WAAW,QAAQ;AAClC,YAAI;AACF,eAAK,eAAe,OAAkC;AAAA,QACxD,QAAQ;AAAA,QAER;AACA,cAAM;AAAA,MACR;AAAA,IACF,UAAE;AACA,UAAI;AACF,aAAK,aAAa;AAClB,aAAK,iBAAiB;AACtB,aAAK,oBAAoB;AAAA,MAC3B,QAAQ;AAAA,MAER;AACA,WAAK,WAAW;AAAA,IAClB;AAAA,EACF;AAAA,EAEQ,eAAe,SAAwC;AAO7D,UAAM,WAAW,QAAQ;AAEzB,QAAI,aAAa,aAAa;AAC5B,WAAK,uBAAuB,OAAO;AAAA,IACrC,WAAW,aAAa,QAAQ;AAC9B,WAAK,kBAAkB,OAAO;AAAA,IAChC,WAAW,aAAa,UAAU;AAChC,WAAK,oBAAoB,OAAO;AAAA,IAClC;AAAA,EACF;AAAA,EAEQ,uBAAuB,SAAwC;AACrE,SAAK,YAAY;AAIjB,UAAM,QAAS,QAAQ,WAAmD,CAAC;AAE3E,UAAM,YACH,MAAM,MAA8B,QAAQ;AAE/C,QAAI,cAAc,KAAK,qBAAqB;AAC1C,WAAK,aAAa;AAGlB,WAAK,oBAAoB,KAAK,GAAG,KAAK,eAAe;AACrD,WAAK,kBAAkB,CAAC;AAExB,WAAK,mBAAmB,WAAW;AACnC,WAAK,sBAAsB,aAAa;AACxC,WAAK,oBAAoB,CAAC;AAC1B,WAAK,kBAAmB,MAAM,SAAoB;AAClD,WAAK,kBAAkB,CAAC;AACxB,WAAK,sBAAsB,OAAO;AAClC,WAAK,4BAA4B,CAAC,GAAG,KAAK,mBAAmB;AAAA,IAC/D;AAEA,UAAM,UAAU,MAAM;AACtB,QAAI,MAAM,QAAQ,OAAO,GAAG;AAC1B,WAAK,kBAAkB,KAAK,GAAG,qBAAqB,OAAO,CAAC;AAAA,IAC9D;AAEA,UAAM,QAAQ,aAAa,KAAK;AAChC,QAAI,OAAO,KAAK,KAAK,EAAE,SAAS,GAAG;AACjC,aAAO,OAAO,KAAK,iBAAiB,KAAK;AAAA,IAC3C;AAEA,UAAM,QAAQ,MAAM;AACpB,QAAI,OAAO;AACT,WAAK,kBAAkB;AAAA,IACzB;AAAA,EACF;AAAA,EAEQ,kBAAkB,SAAwC;AAGhE,UAAM,QAAS,QAAQ,WAAmD,CAAC;AAC3E,UAAM,UAAU,MAAM;AACtB,UAAM,gBAAgB,QAAQ;AAE9B,QAAI,kBAAkB,QAAW;AAC/B,WAAK,gBAAgB,KAAK;AAAA,QACxB,MAAM;AAAA,QACN,SAAS,cAAc,OAAO;AAAA,QAC9B,aAAa,cAAc,aAAa;AAAA,MAC1C,CAAC;AAAA,IACH,OAAO;AACL,WAAK,gBAAgB,KAAK;AAAA,QACxB,MAAM;AAAA,QACN,SAAS,cAAc,OAAO;AAAA,MAChC,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEQ,oBAAoB,SAAwC;AAClE,SAAK,aAAa;AAGlB,QAAI,QAAQ,WAAW,QAAW;AAChC,WAAK,aAAa,QAAQ;AAAA,IAC5B;AACA,SAAK,iBAAiB;AAEtB,UAAM,WAAoC,CAAC;AAC3C,eAAW,QAAQ;AAAA,MACjB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,GAAG;AACD,YAAM,MAAM,QAAQ,IAAI;AACxB,UAAI,QAAQ,UAAa,QAAQ,MAAM;AACrC,iBAAS,IAAI,IAAI;AAAA,MACnB;AAAA,IACF;AAEA,UAAM,QAAQ,QAAQ;AACtB,QAAI,SAAS,OAAO,UAAU,UAAU;AACtC,eAAS,QAAQ,cAAc,KAAK;AAAA,IACtC;AAEA,SAAK;AAAA,MACH;AAAA,MACA,OAAO,KAAK,QAAQ,EAAE,SAAS,IAAI,WAAW;AAAA,IAChD;AAAA,EACF;AAAA,EAEQ,eAAqB;AAC3B,QAAI,KAAK,qBAAqB,MAAM;AAClC;AAAA,IACF;AAEA,UAAM,SAAS,KAAK;AACpB,UAAM,UAAU,KAAK,YAAY;AACjC,UAAM,WAAW,KAAK,YAAY;AAElC,UAAM,aAAsC,CAAC;AAC7C,QAAI,KAAK,iBAAiB;AACxB,iBAAW,QAAQ,KAAK;AAAA,IAC1B;AACA,WAAO,OAAO,YAAY,KAAK,eAAe;AAE9C,UAAM,WAAqB;AAAA,MACzB;AAAA,MACA;AAAA,MACA;AAAA,MACA,WAAW,KAAK,uBAAuB,OAAO;AAAA,MAC9C,SAAS,OAAO;AAAA,MAChB,MAAM,KAAK,mBAAmB;AAAA,MAC9B,MAAM;AAAA,MACN,OAAO,KAAK;AAAA,MACZ,QAAQ,KAAK;AAAA,MACb,UAAU,OAAO,KAAK,UAAU,EAAE,SAAS,IAAI,CAAC,UAAU,IAAI,CAAC;AAAA,IACjE;AAEA,SAAK,SAAS,QAAQ;AAEtB,SAAK,oBAAoB,KAAK;AAAA,MAC5B,MAAM;AAAA,MACN,SAAS,KAAK;AAAA,IAChB,CAAC;AAED,SAAK,mBAAmB;AACxB,SAAK,sBAAsB;AAC3B,SAAK,oBAAoB,CAAC;AAC1B,SAAK,kBAAkB;AACvB,SAAK,kBAAkB,CAAC;AACxB,SAAK,sBAAsB;AAC3B,SAAK,4BAA4B,CAAC;AAAA,EACpC;AAAA,EAEQ,aAAmB;AACzB,SAAK,UAAU,MAAM;AACrB,SAAK,UAAU;AACf,SAAK,aAAa;AAClB,SAAK,eAAe;AACpB,SAAK,YAAY;AACjB,SAAK,aAAa;AAClB,SAAK,gBAAgB;AACrB,SAAK,iBAAiB;AACtB,SAAK,sBAAsB,CAAC;AAC5B,SAAK,kBAAkB,CAAC;AACxB,SAAK,mBAAmB;AACxB,SAAK,sBAAsB;AAC3B,SAAK,oBAAoB,CAAC;AAC1B,SAAK,kBAAkB;AACvB,SAAK,kBAAkB,CAAC;AACxB,SAAK,sBAAsB;AAC3B,SAAK,4BAA4B,CAAC;AAClC,SAAK,oBAAoB,MAAM;AAAA,EACjC;AACF;;;ACzwBA;;;AC8BO,SAAS,mBACd,gBACY;AAEZ,QAAM,YAAY,eAAe,KAAK,GAAG;AACzC,SAAO;AAAA;AAAA;AAAA,IACwC;AAAA;AAEjD;;;ACjCA,IAAI,aAAgC;AAEpC,eAAe,WAAgC;AAC7C,MAAI,YAAY;AACd,WAAO;AAAA,EACT;AACA,MAAI;AAIF,iBAAa,MAAM,mBAA+B,CAAC,eAAe,MAAM,CAAC;AACzE,WAAO;AAAA,EACT,QAAQ;AACN,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACF;AA2BA,SAAS,WAAW,KAAqB;AACvC,SAAO,IAAI,OAAO,CAAC,EAAE,YAAY,IAAI,IAAI,MAAM,CAAC;AAClD;AAMA,SAAS,eAAe,UAA0B;AAChD,QAAM,cAAsC;AAAA,IAC1C,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,QAAQ;AAAA,EACV;AACA,SAAO,YAAY,QAAQ,KAAK,WAAW,QAAQ;AACrD;AAMA,SAAS,YAAY,OAAuB;AAC1C,SAAO,MACJ,QAAQ,SAAS,KAAK,EACtB,QAAQ,OAAO,GAAG,EAClB,QAAQ,MAAM,GAAG;AACtB;AAMO,SAAS,cAAc,UAAkB,OAAuB;AACrE,SAAO,GAAG,eAAe,QAAQ,CAAC,IAAI,YAAY,KAAK,CAAC;AAC1D;AAMA,SAAS,0BAA0B,WAAyC;AAC1E,QAAM,cAAwB,CAAC;AAE/B,aAAW,eAAe,WAAW;AACnC,eAAW,SAAS,YAAY,QAAQ;AACtC,YAAM,aAAa,cAAc,YAAY,UAAU,MAAM,KAAK;AAClE,kBAAY,KAAK,eAAe,UAAU;AAAA,aACnC,YAAY,QAAQ;AAAA;AAAA,aAEpB,MAAM,KAAK;AAAA,kBACN,YAAY,SAAS;AAAA;AAAA,EAErC;AAAA,IACE;AAAA,EACF;AAEA,SAAO,YAAY,KAAK,MAAM;AAChC;AAKA,SAAS,mBACP,YACA,WACQ;AACR,QAAM,mBAAmB,WAAW,SAAS,qBAAqB;AAClE,MAAI,kBAAkB;AACpB,WAAO;AAAA,EACT;AACA,QAAM,iBAAiB,0BAA0B,SAAS;AAC1D,SAAO,GAAG,cAAc;AAAA;AAAA,EAAO,UAAU;AAC3C;AAKA,SAAS,oBAAoB,YAAmC;AAC9D,QAAM,QAAQ,WAAW,MAAM,uBAAuB;AACtD,SAAO,QAAQ,CAAC,KAAK;AACvB;AAeO,SAAS,0BACd,YACqB;AACrB,QAAM,gBAAgB,WAAW,MAAM,mCAAmC;AAC1E,MAAI,CAAC,eAAe;AAClB,WAAO,CAAC;AAAA,EACV;AAEA,QAAM,eAAe,cAAc,CAAC,EAAE,KAAK;AAC3C,MAAI,CAAC,cAAc;AACjB,WAAO,CAAC;AAAA,EACV;AAEA,QAAM,SAA8B,CAAC;AACrC,QAAM,aAAa,gBAAgB,YAAY;AAE/C,aAAW,QAAQ,YAAY;AAC7B,UAAM,UAAU,KAAK,KAAK;AAC1B,QAAI,CAAC,SAAS;AACZ;AAAA,IACF;AAEA,UAAM,aAAa,QAAQ,MAAM,oBAAoB;AACrD,QAAI,YAAY;AACd,YAAM,OAAO,WAAW,CAAC;AACzB,UAAI,OAAO,WAAW,CAAC,EAAE,KAAK;AAC9B,YAAM,aAAa,KAAK,SAAS,GAAG;AACpC,UAAI,YAAY;AACd,eAAO,KAAK,MAAM,GAAG,EAAE;AAAA,MACzB;AACA,aAAO,KAAK,EAAE,MAAM,MAAM,WAAW,CAAC;AAAA,IACxC;AAAA,EACF;AAEA,SAAO;AACT;AAKA,SAAS,gBAAgB,cAAgC;AACvD,QAAM,QAAkB,CAAC;AACzB,MAAI,UAAU;AACd,MAAI,QAAQ;AAEZ,aAAW,QAAQ,cAAc;AAC/B,QAAI,SAAS,KAAK;AAChB;AACA,iBAAW;AAAA,IACb,WAAW,SAAS,KAAK;AACvB;AACA,iBAAW;AAAA,IACb,WAAW,SAAS,OAAO,UAAU,GAAG;AACtC,YAAM,KAAK,OAAO;AAClB,gBAAU;AAAA,IACZ,OAAO;AACL,iBAAW;AAAA,IACb;AAAA,EACF;AAEA,MAAI,QAAQ,KAAK,GAAG;AAClB,UAAM,KAAK,OAAO;AAAA,EACpB;AAEA,SAAO;AACT;AAMA,SAAS,aAAa,OAAe,cAA+B;AAElE,MAAI,iBAAiB,UAAU;AAC7B,WAAO;AAAA,EACT;AAGA,MAAI,iBAAiB,OAAO;AAC1B,UAAM,SAAS,OAAO,SAAS,OAAO,EAAE;AACxC,QAAI,CAAC,OAAO,MAAM,MAAM,GAAG;AACzB,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AAGA,MAAI,iBAAiB,SAAS;AAC5B,UAAM,SAAS,OAAO,WAAW,KAAK;AACtC,QAAI,CAAC,OAAO,MAAM,MAAM,GAAG;AACzB,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AAGA,MAAI,iBAAiB,QAAQ;AAC3B,UAAM,QAAQ,MAAM,YAAY;AAChC,QAAI,UAAU,QAAQ;AACpB,aAAO;AAAA,IACT;AACA,QAAI,UAAU,SAAS;AACrB,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AAGA,MAAI,aAAa,SAAS,IAAI,GAAG;AAC/B,QAAI;AACF,YAAM,SAAS,KAAK,MAAM,KAAK;AAC/B,UAAI,MAAM,QAAQ,MAAM,GAAG;AACzB,eAAO;AAAA,MACT;AAAA,IACF,QAAQ;AAAA,IAER;AACA,WAAO;AAAA,EACT;AAGA,MAAI;AACF,WAAO,KAAK,MAAM,KAAK;AAAA,EACzB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAOA,SAAS,aACP,QACA,eACyB;AACzB,QAAM,UAAmC,CAAC;AAE1C,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AACjD,QAAI,OAAO,UAAU,UAAU;AAC7B,YAAM,eAAe,cAAc,IAAI,GAAG;AAE1C,UAAI,cAAc;AAChB,gBAAQ,GAAG,IAAI,aAAa,OAAO,YAAY;AAAA,MACjD,OAAO;AAEL,gBAAQ,GAAG,IAAI;AAAA,MACjB;AAAA,IACF,OAAO;AACL,cAAQ,GAAG,IAAI;AAAA,IACjB;AAAA,EACF;AAEA,SAAO;AACT;AAMA,SAAS,UAAU,KAAc,QAAQ,GAAG,WAAW,GAAY;AACjE,MAAI,QAAQ,UAAU;AACpB,WAAO,uBAAuB,OAAO,GAAG;AAAA,EAC1C;AAGA,MACE,QAAQ,QACR,QAAQ,UACR,OAAO,QAAQ,YACf,OAAO,QAAQ,YACf,OAAO,QAAQ,WACf;AACA,WAAO;AAAA,EACT;AAGA,MAAI,MAAM,QAAQ,GAAG,GAAG;AACtB,WAAO,IAAI,IAAI,CAAC,SAAS,UAAU,MAAM,QAAQ,GAAG,QAAQ,CAAC;AAAA,EAC/D;AAGA,MAAI,OAAO,QAAQ,UAAU;AAC3B,UAAM,SAAkC,CAAC;AAGzC,QAAI,IAAI,eAAe,IAAI,YAAY,SAAS,UAAU;AACxD,aAAO,WAAW,IAAI,YAAY;AAAA,IACpC;AAGA,eAAW,OAAO,OAAO,KAAK,GAAG,GAAG;AAClC,UAAI,IAAI,WAAW,GAAG,GAAG;AACvB;AAAA,MACF;AAEA,UAAI;AACF,cAAM,QAAS,IAAgC,GAAG;AAGlD,YAAI,OAAO,UAAU,YAAY;AAC/B;AAAA,QACF;AAEA,eAAO,GAAG,IAAI,UAAU,OAAO,QAAQ,GAAG,QAAQ;AAAA,MACpD,SAAS,OAAO;AACd,eAAO,GAAG,IACR,WAAW,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,MACrE;AAAA,IACF;AAIA,QAAI;AACF,YAAM,QAAQ,OAAO,eAAe,GAAG;AACvC,UAAI,SAAS,UAAU,OAAO,WAAW;AACvC,cAAM,cAAc,OAAO,0BAA0B,KAAK;AAC1D,mBAAW,CAAC,KAAK,UAAU,KAAK,OAAO,QAAQ,WAAW,GAAG;AAC3D,cAAI,IAAI,WAAW,GAAG,KAAK,QAAQ,iBAAiB,OAAO,QAAQ;AACjE;AAAA,UACF;AAGA,cAAI,WAAW,KAAK;AAClB,gBAAI;AACF,oBAAM,QAAS,IAAgC,GAAG;AAClD,kBAAI,OAAO,UAAU,YAAY;AAC/B,uBAAO,GAAG,IAAI,UAAU,OAAO,QAAQ,GAAG,QAAQ;AAAA,cACpD;AAAA,YACF,QAAQ;AAAA,YAER;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF,QAAQ;AAAA,IAER;AAEA,WAAO;AAAA,EACT;AAGA,SAAO,OAAO,GAAG;AACnB;AAMA,SAAS,mBACP,WACgC;AAChC,MAAI;AACF,WAAO,UAAU,WAAW,GAAG,CAAC;AAAA,EAClC,SAAS,QAAQ;AAEf,WAAO;AAAA,EACT;AACF;AAMA,IAAM,mBAAmB,CAAC,gBAAgB;AAc1C,SAAS,cAAc,SAAiD;AACtE,QAAM,WAAmC,CAAC;AAC1C,aAAW,OAAO,kBAAkB;AAClC,UAAM,QAAQ,QAAQ,GAAG;AACzB,QAAI,OAAO;AACT,eAAS,GAAG,IAAI;AAAA,IAClB;AAAA,EACF;AACA,SAAO;AACT;AAYA,eAAsB,oBACpB,YACA,QACA,WACA,SAC8B;AAC9B,QAAM,EAAE,aAAa,UAAU,IAAI,MAAM,SAAS;AAGlD,QAAM,eAAe,oBAAoB,UAAU;AACnD,MAAI,CAAC,cAAc;AACjB,UAAM,IAAI,MAAM,kCAAkC;AAAA,EACpD;AAGA,QAAM,aAAa,mBAAmB,YAAY,SAAS;AAG3D,QAAM,kBAAkB,cAAc,OAAO;AAG7C,QAAM,UAAU,YAAY;AAAA,IAC1B;AAAA,IACA,EAAE,eAAe,WAAW;AAAA,IAC5B;AAAA,EACF;AAGA,QAAM,MAAM,QAAQ,qBAAqB;AAGzC,QAAM,YAAY,IAAI,UAAU,kBAAkB;AAGlD,QAAM,SAAS,0BAA0B,UAAU;AACnD,QAAM,gBAAgB,IAAI,IAAI,OAAO,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;AAGjE,QAAM,OAAO,aAAa,QAAQ,aAAa;AAG/C,QAAM,iBAAiB,MAAM,QAAQ;AAAA,IACnC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAAA,IACA;AAAA;AAAA,IACA,CAAC,SAAS;AAAA;AAAA,IACV,CAAC;AAAA;AAAA,IACD;AAAA,EACF;AAEA,MAAI,CAAC,eAAe,KAAK,GAAG;AAC1B,UAAM,IAAI,MAAM,gCAAgC;AAAA,EAClD;AAGA,QAAM,eAAe,mBAAmB,SAAS;AAEjD,SAAO;AAAA,IACL,QAAQ,eAAe,OAAO,KAAK;AAAA,IACnC;AAAA,EACF;AACF;;;ACpfA;AAGO,IAAM,sBAAsB,CAAC,MAAM;AAyBnC,SAAS,yBAAyB,QAAgC;AACvE,MAAI,CAAC,oBAAoB,SAAS,OAAO,QAAQ,GAAG;AAClD,UAAM,IAAI;AAAA,MACR,wBAAwB,OAAO,QAAQ,4CAA4C,oBAAoB,KAAK,IAAI,CAAC;AAAA,IACnH;AAAA,EACF;AACF;AASO,SAAS,iBACd,QACA,sBACe;AACf,SAAO;AAAA,IACL;AAAA,IACA,GAAI,UAAU,EAAE,UAAU,OAAO,SAAS;AAAA,EAC5C;AACF;;;AClDA;AACA;AA8BA,IAAM,uBAAuB;AAE7B,IAAM,0BAA0B;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,SAASC,UAAiB;AACxB,UAAO,oBAAI,KAAK,GAAE,YAAY;AAChC;AAIA,IAAMC,iBAAgB;AAEtB,SAAS,eAAe,SAA2C;AACjE,MAAI,OAAO,YAAY,YAAY,YAAY,MAAM;AACnD,WAAO,EAAE,MAAM,WAAW,SAAS,OAAO,OAAO,EAAE;AAAA,EACrD;AAEA,QAAM,MAAM;AAEZ,MAAI,OAAO,IAAI,WAAW,YAAY;AACpC,WAAQ,IAA8C,OAAO;AAAA,EAC/D;AAEA,QAAM,aAAqC;AAAA,IACzC,OAAO;AAAA,IACP,IAAI;AAAA,IACJ,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,UAAU;AAAA,EACZ;AAEA,QAAM,SAAkC,CAAC;AAEzC,QAAM,UAAU,IAAI,WAChB,OAAQ,IAA+B,SAAS,CAAC,IAChD,IAAI;AAET,SAAO,QACJ,UAAU,WAAW,OAAO,IAAI,WAAc,IAAI,QAAQ;AAC7D,SAAO,UAAU,IAAI,WAAW;AAEhC,MAAI,IAAI,YAAY;AAClB,WAAO,aAAa,IAAI;AAAA,EAC1B;AACA,MAAI,IAAI,cAAc;AACpB,WAAO,eAAe,IAAI;AAAA,EAC5B;AACA,MAAI,IAAI,MAAM;AACZ,WAAO,OAAO,IAAI;AAAA,EACpB;AAEA,SAAO;AACT;AAEA,SAAS,iBACP,YACA,UACoB;AACpB,MAAI,YAAY;AACd,UAAM,SAAS,WAAW;AAC1B,QAAI,QAAQ;AACV,YAAM,QAAQ,OAAO,cAAc,OAAO,SAAS,OAAO;AAC1D,UAAI,OAAO;AACT,eAAO,OAAO,KAAK;AAAA,MACrB;AAAA,IACF;AAAA,EACF;AACA,MAAI,UAAU;AACZ,UAAM,UAAU,SAAS;AACzB,QAAI,SAAS;AACX,aAAO,OAAO,OAAO;AAAA,IACvB;AAAA,EACF;AACA,SAAO;AACT;AASA,SAASC,cAAa,OAA+B;AACnD,SAAO,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,IAAI,QAAQ;AACvE;AAgBA,SAAS,oBAAoB,KAAsC;AACjE,MAAI,OAAO,QAAQ,YAAY,QAAQ,QAAQ,MAAM,QAAQ,GAAG,GAAG;AACjE,WAAO;AAAA,EACT;AACA,QAAM,IAAI;AAGV,MAAI,6BAA6B,KAAK,iCAAiC,GAAG;AACxE,UAAM,YAAYA,cAAa,EAAE,uBAAuB;AACxD,UAAM,gBAAgBA,cAAa,EAAE,2BAA2B;AAChE,UAAM,YAAYA,cAAa,EAAE,YAAY;AAC7C,UAAM,eAAeA,cAAa,EAAE,aAAa;AACjD,QACE,cAAc,QACd,kBAAkB,QAClB,cAAc,QACd,iBAAiB,MACjB;AACA,aAAO;AAAA,IACT;AACA,UAAM,eACH,aAAa,MAAM,aAAa,MAAM,iBAAiB;AAC1D,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,aAAa,eAAe,gBAAgB;AAAA,MAC5C,mBAAmB;AAAA,IACrB;AAAA,EACF;AAGA,MACE,mBAAmB,KACnB,uBAAuB,KACvB,kBAAkB,KAClB,sBAAsB,GACtB;AACA,UAAM,gBAAiB,EAAE,yBAAyB,CAAC;AAInD,WAAO,kBAAkB;AAAA,MACvB,aACEA,cAAa,EAAE,aAAa,KAAKA,cAAa,EAAE,YAAY;AAAA,MAC9D,cACEA,cAAa,EAAE,iBAAiB,KAAKA,cAAa,EAAE,gBAAgB;AAAA,MACtE,aAAaA,cAAa,EAAE,YAAY,KAAKA,cAAa,EAAE,WAAW;AAAA,MACvE,mBAAmBA,cAAa,cAAc,aAAa;AAAA,IAC7D,CAAC;AAAA,EACH;AAGA,MAAI,wBAAwB,KAAK,4BAA4B,GAAG;AAC9D,WAAO,kBAAkB;AAAA,MACvB,aAAaA,cAAa,EAAE,kBAAkB;AAAA,MAC9C,cAAcA,cAAa,EAAE,sBAAsB;AAAA,MACnD,aAAaA,cAAa,EAAE,iBAAiB;AAAA,MAC7C,mBAAmBA,cAAa,EAAE,0BAA0B;AAAA,IAC9D,CAAC;AAAA,EACH;AAGA,MAAI,kBAAkB,KAAK,mBAAmB,GAAG;AAC/C,UAAM,eAAgB,EAAE,uBAAuB,CAAC;AAIhD,UAAM,cAAcA,cAAa,EAAE,YAAY;AAC/C,UAAM,eAAeA,cAAa,EAAE,aAAa;AACjD,QAAI,cAAcA,cAAa,EAAE,YAAY;AAC7C,QAAI,gBAAgB,QAAQ,gBAAgB,QAAQ,iBAAiB,MAAM;AACzE,oBAAc,cAAc;AAAA,IAC9B;AACA,WAAO,kBAAkB;AAAA,MACvB;AAAA,MACA;AAAA,MACA;AAAA,MACA,mBAAmBA,cAAa,aAAa,UAAU;AAAA,IACzD,CAAC;AAAA,EACH;AAEA,SAAO;AACT;AAOA,SAAS,kBAAkB,OAAgD;AACzE,QAAM,WACJ,MAAM,gBAAgB,QACtB,MAAM,iBAAiB,QACvB,MAAM,gBAAgB,QACtB,MAAM,sBAAsB;AAC9B,SAAO,WAAW,QAAQ;AAC5B;AAEA,SAAS,SAAS,QAAyB,OAA8B;AACvE,aAAW,OAAO;AAAA,IAChB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAAY;AACV,UAAM,QAAQ,MAAM,GAAG;AACvB,QAAI,UAAU,MAAM;AAClB,aAAO,GAAG,KAAK,OAAO,GAAG,KAAK,KAAK;AAAA,IACrC;AAAA,EACF;AACF;AAQA,SAAS,qBACP,aACwB;AACxB,MAAI,CAAC,aAAa,QAAQ;AACxB,WAAO;AAAA,EACT;AACA,QAAM,SAA0B;AAAA,IAC9B,aAAa;AAAA,IACb,cAAc;AAAA,IACd,aAAa;AAAA,IACb,mBAAmB;AAAA,EACrB;AACA,MAAI,QAAQ;AACZ,aAAW,SAAS,aAAa;AAC/B,QAAI,CAAC,MAAM,QAAQ,KAAK,GAAG;AACzB;AAAA,IACF;AACA,eAAW,OAAO,OAAO;AACvB,YAAM,MAAO,KAAwC;AAGrD,UAAI,CAAC,OAAO,OAAO,QAAQ,UAAU;AACnC;AAAA,MACF;AACA,YAAM,mBAAmB,IAAI;AAG7B,YAAM,QACJ,oBAAoB,IAAI,cAAc,KACtC,oBAAoB,kBAAkB,WAAW,KACjD,oBAAoB,kBAAkB,KAAK,KAC3C,oBAAoB,kBAAkB,UAAU;AAClD,UAAI,CAAC,OAAO;AACV;AAAA,MACF;AACA,cAAQ;AACR,eAAS,QAAQ,KAAK;AAAA,IACxB;AAAA,EACF;AACA,SAAO,QAAQ,SAAS;AAC1B;AAUA,SAASC,cACP,QACyB;AACzB,QAAM,cAAc,OAAO;AAC3B,QAAM,YAAa,OAAO,aAAa,OAAO;AAI9C,QAAM,aACJ,qBAAqB,WAAW,KAChC,oBAAoB,WAAW,UAAU,KACzC,oBAAoB,WAAW,WAAW,KAC1C,oBAAoB,WAAW,KAAK;AAEtC,QAAM,QAAiC,CAAC;AACxC,MAAI,CAAC,YAAY;AACf,WAAO;AAAA,EACT;AACA,MAAI,WAAW,gBAAgB,MAAM;AACnC,UAAM,cAAc,WAAW;AAAA,EACjC;AACA,MAAI,WAAW,iBAAiB,MAAM;AACpC,UAAM,eAAe,WAAW;AAAA,EAClC;AACA,MAAI,WAAW,gBAAgB,MAAM;AACnC,UAAM,cAAc,WAAW;AAAA,EACjC;AACA,MAAI,WAAW,sBAAsB,MAAM;AACzC,UAAM,oBAAoB,WAAW;AAAA,EACvC;AAEA,SAAO;AACT;AAEA,SAAS,yBACP,UACyB;AACzB,MAAI,CAAC,UAAU;AACb,WAAO,CAAC;AAAA,EACV;AACA,QAAM,SAAkC,CAAC;AACzC,aAAW,OAAO,yBAAyB;AACzC,QAAI,OAAO,UAAU;AACnB,aAAO,GAAG,IAAI,SAAS,GAAG;AAAA,IAC5B;AAAA,EACF;AACA,SAAO;AACT;AAgBO,IAAM,iCAAN,MAAqC;AAAA,EAe1C,YAAY,QAMT;AApBH,gBAAO;AAEP,uBAAc;AAEd;AAAA,2BAAkB;AAClB,6BAAoB;AAMpB,SAAQ,YAAmC,oBAAI,IAAI;AACnD,SAAQ,cAA4C,oBAAI,IAAI;AAS1D,SAAK,aAAa,IAAI,WAAW;AAAA,MAC/B,QAAQ,OAAO;AAAA,MACf,YAAY,OAAO,cAAc;AAAA,MACjC,SAAS,OAAO,WAAW;AAAA,IAC7B,CAAC;AACD,SAAK,mBAAmB,OAAO;AAC/B,SAAK,uBAAuB,OAAO,wBAAwB;AAAA,EAC7D;AAAA;AAAA,EAIQ,UACN,OACA,aACA,MACA,UACA,WACA,UACA,MACU;AAIV,UAAM,aAAa,cAAc,KAAK,UAAU,IAAI,WAAW,IAAI;AACnE,UAAM,WAAW,MAAM,SAAS,oBAAoB,MAAM;AAE1D,QAAI;AACJ,QAAI;AACJ,QAAI,YAAY;AACd,YAAM,WAAW,KAAK,YAAY,IAAI,WAAW,SAAS;AAC1D,UAAI,UAAU;AACZ,qBAAa;AAAA,MACf,OAAO;AACL,qBAAa;AAAA,UACX,SAAS,WAAW;AAAA,UACpB,eAAe;AAAA,UACf,WAAW,WAAW;AAAA,QACxB;AACA,aAAK,YAAY,IAAI,WAAW,WAAW,UAAU;AAAA,MACvD;AAIA,UAAI,CAAC,UAAU;AACb,YAAI,WAAiC;AACrC,eAAO,UAAU,WAAW,MAAM;AAChC,qBAAW,SAAS,WAChB,KAAK,UAAU,IAAI,SAAS,QAAQ,IACpC;AAAA,QACN;AACA,4BAAoB,WAChB,SAAS,SACR,WAAW,eAAe,UAAU;AAAA,MAC3C,OAAO;AACL,4BAAoB,eAAe;AAAA,MACrC;AAAA,IACF,OAAO;AACL,YAAM,gBAAgB,KAAK,uBAAuB,KAAK;AACvD,mBAAa;AAAA,QACX,SAAS,gBAAgB,cAAc,UAAU,WAAW;AAAA,QAC5D;AAAA,QACA,WAAW;AAAA,MACb;AACA,WAAK,YAAY,IAAI,OAAO,UAAU;AACtC,0BAAoB,eAAe,UAAU;AAAA,IAC/C;AAEA,UAAM,aAAa,yBAAyB,QAAQ;AACpD,UAAM,WACJ,OAAO,KAAK,UAAU,EAAE,SAAS,IAAI,CAAC,UAAU,IAAI,CAAC;AAEvD,UAAM,WAAqB;AAAA,MACzB,QAAQ;AAAA,MACR,SAAS,WAAW;AAAA,MACpB,WAAW,WAAW;AAAA,MACtB,UAAU;AAAA,MACV,WAAWH,QAAO;AAAA,MAClB;AAAA,MACA,MAAM;AAAA,MACN,OAAOC,eAAc,SAAS;AAAA,MAC9B;AAAA,IACF;AACA,QAAI,UAAU;AACZ,eAAS,SAAS;AAAA,IACpB;AACA,SAAK,UAAU,IAAI,OAAO,QAAQ;AAClC,WAAO;AAAA,EACT;AAAA,EAEQ,aACN,OACA,QACA,OACA,eACM;AACN,UAAM,WAAW,KAAK,UAAU,IAAI,KAAK;AACzC,QAAI,CAAC,UAAU;AACb;AAAA,IACF;AACA,SAAK,UAAU,OAAO,KAAK;AAE3B,aAAS,UAAUD,QAAO;AAC1B,aAAS,SAASC,eAAc,MAAM;AACtC,QAAI,UAAU,QAAW;AACvB,eAAS,QAAQ;AAAA,IACnB;AAEA,QAAI,iBAAiB,OAAO,KAAK,aAAa,EAAE,SAAS,GAAG;AAC1D,eAAS,SAAS,KAAK,aAAa;AAAA,IACtC;AAEA,SAAK,SAAS,QAAQ;AAEtB,QAAI,UAAU,SAAS,WAAW;AAChC,YAAM,aAAa,KAAK,YAAY,IAAI,KAAK;AAC7C,WAAK,oBAAoB,UAAU,YAAY,iBAAiB,IAAI;AACpE,WAAK,YAAY,OAAO,KAAK;AAAA,IAC/B;AAAA,EACF;AAAA,EAEQ,SAAS,UAA0B;AACzC,UAAM,WAAoC;AAAA,MACxC,MAAM,SAAS;AAAA,MACf,MAAM,SAAS;AAAA,IACjB;AACA,QAAI,SAAS,UAAU,QAAW;AAChC,eAAS,QAAQ,SAAS;AAAA,IAC5B;AACA,QAAI,SAAS,WAAW,QAAW;AACjC,eAAS,SAAS,SAAS;AAAA,IAC7B;AACA,QAAI,SAAS,UAAU,QAAW;AAChC,eAAS,QAAQ,SAAS;AAAA,IAC5B;AACA,QAAI,SAAS,SAAS,SAAS,GAAG;AAChC,eAAS,WAAW,SAAS;AAAA,IAC/B;AACA,QAAI,SAAS,QAAQ;AACnB,eAAS,SAAS;AAAA,IACpB;AAEA,UAAM,UAAmC;AAAA,MACvC,IAAI,SAAS;AAAA,MACb,UAAU,SAAS;AAAA,MACnB,YAAY,SAAS;AAAA,MACrB,UAAU,SAAS,WAAWD,QAAO;AAAA,MACrC,WAAW;AAAA,IACb;AACA,QAAI,SAAS,aAAa,MAAM;AAC9B,cAAQ,YAAY,SAAS;AAAA,IAC/B;AAEA,UAAM,UAAmC;AAAA,MACvC,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,kBAAkB,KAAK;AAAA,MACvB,eAAe,SAAS;AAAA,MACxB;AAAA,IACF;AAEA,QAAI;AACF,WAAK,WAAW,iBAAiB,OAAO;AAAA,IAC1C,QAAQ;AAAA,IAER;AAAA,EACF;AAAA,EAEQ,oBACN,UACA,eACM;AACN,UAAM,YAAY,kBAAkB;AAEpC,UAAM,YAAqC;AAAA,MACzC,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,kBAAkB,KAAK;AAAA,MACvB,eAAe;AAAA,QACb,IAAI,SAAS;AAAA,QACb,YAAY,SAAS;AAAA,QACrB,UAAU,SAAS,WAAWA,QAAO;AAAA,QACrC,eAAe,KAAK;AAAA,MACtB;AAAA,MACA;AAAA,IACF;AAEA,QAAI;AACF,WAAK,WAAW,kBAAkB,SAAS;AAAA,IAC7C,QAAQ;AAAA,IAER;AAAA,EACF;AAAA;AAAA,EAIA,MAAM,iBACJ,OACA,QACA,OACA,aACA,MACA,UACe;AACf,QAAI;AACF,YAAM,QAAQ,MAAM;AACpB,YAAM,OACH,MAAM,QAAmB,QAAQ,MAAM,SAAS,CAAC,KAAK;AACzD,WAAK;AAAA,QACH;AAAA,QACA;AAAA,QACA,OAAO,IAAI;AAAA,QACX;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF;AAAA,EAEA,MAAM,eACJ,SACA,OACe;AACf,QAAI;AACF,WAAK,aAAa,OAAO,OAAO;AAAA,IAClC,QAAQ;AAAA,IAER;AAAA,EACF;AAAA,EAEA,MAAM,iBAAiB,OAAgB,OAA8B;AACnE,QAAI;AACF,YAAM,WAAW;AACjB,UAAI,UAAU,aAAa,SAAS,iBAAiB;AACnD,aAAK,aAAa,OAAO,QAAW,MAAS;AAC7C;AAAA,MACF;AACA,WAAK;AAAA,QACH;AAAA,QACA;AAAA,QACA,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,MACvD;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF;AAAA;AAAA,EAIA,MAAM,qBACJ,KACA,UACA,OACA,aACA,cACA,MACA,UACe;AACf,QAAI;AACF,YAAM,QAAQ,iBAAiB,KAAK,QAAQ;AAC5C,YAAM,QAAQ,IAAI;AAClB,YAAM,OAAO,SAAS,QAAQ,MAAM,SAAS,CAAC,KAAK;AACnD,YAAM,YAAY,SAAS,IAAI,CAAC,UAAU,MAAM,IAAI,cAAc,CAAC;AAEnE,YAAM,WAAW,KAAK;AAAA,QACpB;AAAA,QACA;AAAA,QACA,OAAO,IAAI;AAAA,QACX;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA,eAAS,QAAQ;AAAA,IACnB,QAAQ;AAAA,IAER;AAAA,EACF;AAAA,EAEA,MAAM,eACJ,KACA,SACA,OACA,aACA,cACA,MACA,UACe;AACf,QAAI;AACF,YAAM,QAAQ,iBAAiB,KAAK,QAAQ;AAC5C,YAAM,QAAQ,IAAI;AAClB,YAAM,OAAO,SAAS,QAAQ,MAAM,SAAS,CAAC,KAAK;AAEnD,YAAM,WAAW,KAAK;AAAA,QACpB;AAAA,QACA;AAAA,QACA,OAAO,IAAI;AAAA,QACX;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA,eAAS,QAAQ;AAAA,IACnB,QAAQ;AAAA,IAER;AAAA,EACF;AAAA,EAEA,MAAM,aACJ,QACA,OACe;AACf,QAAI;AACF,UAAI;AACJ,YAAM,cAAc,OAAO;AAC3B,UAAI,aAAa,UAAU,YAAY,YAAY,SAAS,CAAC,GAAG,QAAQ;AACtE,cAAM,MAAM,YAAY,YAAY,SAAS,CAAC,EAC5C,YAAY,YAAY,SAAS,CAAC,EAAE,SAAS,CAC/C;AACA,cAAM,MAAM,IAAI;AAChB,oBAAY,MAAM,eAAe,GAAG,IAAK,IAAI,QAAQ,OAAO,GAAG;AAAA,MACjE;AAEA,YAAM,QAAQG,cAAa,MAAM;AACjC,YAAM,WAAW,KAAK,UAAU,IAAI,KAAK;AACzC,YAAM,QAAQ,UAAU;AAExB,YAAM,aAAsC,CAAC;AAC7C,UAAI,OAAO;AACT,mBAAW,QAAQ;AAAA,MACrB;AACA,aAAO,OAAO,YAAY,KAAK;AAE/B,WAAK;AAAA,QACH;AAAA,QACA;AAAA,QACA;AAAA,QACA,OAAO,KAAK,UAAU,EAAE,SAAS,IAAI,aAAa;AAAA,MACpD;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF;AAAA,EAEA,MAAM,eAAe,OAAgB,OAA8B;AACjE,QAAI;AACF,WAAK;AAAA,QACH;AAAA,QACA;AAAA,QACA,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,MACvD;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF;AAAA,EAEA,MAAM,oBAAmC;AAAA,EAIzC;AAAA;AAAA,EAIA,MAAM,gBACJ,MACA,OACA,OACA,aACA,MACA,UACe;AACf,QAAI;AACF,YAAM,OAAQ,KAAK,QAAmB;AACtC,WAAK;AAAA,QACH;AAAA,QACA;AAAA,QACA,OAAO,IAAI;AAAA,QACX;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF;AAAA,EAEA,MAAM,cAAc,QAAiB,OAA8B;AACjE,QAAI;AACF,WAAK,aAAa,OAAO,MAAM;AAAA,IACjC,QAAQ;AAAA,IAER;AAAA,EACF;AAAA,EAEA,MAAM,gBAAgB,OAAgB,OAA8B;AAClE,QAAI;AACF,WAAK;AAAA,QACH;AAAA,QACA;AAAA,QACA,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,MACvD;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF;AAAA;AAAA,EAIA,MAAM,qBACJ,WACA,OACA,OACA,aACA,MACA,UACe;AACf,QAAI;AACF,YAAM,OAAQ,UAAU,QAAmB;AAC3C,WAAK;AAAA,QACH;AAAA,QACA;AAAA,QACA,OAAO,IAAI;AAAA,QACX;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF;AAAA,EAEA,MAAM,mBAAmB,WAAoB,OAA8B;AACzE,QAAI;AACF,WAAK,aAAa,OAAO,SAAS;AAAA,IACpC,QAAQ;AAAA,IAER;AAAA,EACF;AAAA,EAEA,MAAM,qBAAqB,OAAgB,OAA8B;AACvE,QAAI;AACF,WAAK;AAAA,QACH;AAAA,QACA;AAAA,QACA,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,MACvD;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF;AACF;;;ACrvBO,IAAM,2BAAN,MAA+B;AAAA,EAKpC,YAAY,QAIT;AACD,SAAK,mBAAmB,OAAO;AAC/B,SAAK,aAAa,OAAO;AACzB,SAAK,uBAAuB,OAAO;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBA,MAAM,QACJ,OACA,OACA,SACwB;AAOxB,UAAM,EAAE,IAAI,IAAI,MAAM,mBAAoD;AAAA,MACxE;AAAA,MACA;AAAA,IACF,CAAC;AAaD,QAAI,KAAK,uBAAuB,KAAK,MAAM;AACzC,aAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,UAAM,cAAc,SAAS,WAAW;AAMxC,UAAM,WAAW,OAAO,WAAsC;AAC5D,YAAM,MAAM;AACZ,UAAI,eAAe,KAAK,WAAW;AACjC,YAAI;AACF,gBAAM,IAAI;AAAA,QACZ,QAAQ;AAAA,QAGR;AAAA,MACF;AACA,aAAO,KAAK;AAAA,IACd;AAEA,UAAM,WAA4B,EAAE,MAAM,SAAS,SAAS;AAM5D,UAAM,SAAS,KAAK;AAAA,MAClB,KAAK;AAAA,MACL;AAAA,MACA,CAAC,eACC;AAAA,QACE;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACJ;AAEA,WAAO,OAAO,KAAK;AAAA,EACrB;AACF;;;ALrLA;AAEA;;;AMJA;AAUO,IAAM,oBAAN,MAAwB;AAAA;AAAA;AAAA;AAAA;AAAA,EAK7B,IAAI,cAAsB;AACxB,UAAM,WAAW,KAAK,QAAQ;AAC9B,SAAK,aAAa;AAClB,WAAO,SAAS;AAAA,EAClB;AAAA;AAAA,EAGA,IAAI,YAAoB;AACtB,WAAO,KAAK,QAAQ,EAAE;AAAA,EACxB;AAAA;AAAA,EAGA,IAAI,qBAAyC;AAC3C,WAAO,KAAK,QAAQ,EAAE;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,IAAI,WAAgC;AAClC,WAAO,KAAK,QAAQ,EAAE;AAAA,EACxB;AAAA;AAAA,EAGA,IAAI,UAAkB;AACpB,WAAO,KAAK,QAAQ,EAAE;AAAA,EACxB;AAAA;AAAA,EAGA,IAAI,SAAkB;AACpB,WAAO,KAAK,KAAK,MAAM;AAAA,EACzB;AAAA;AAAA,EAGA,WAA6C;AAC3C,UAAM,WAAW,KAAK,KAAK;AAC3B,QAAI,UAAU;AACZ,WAAK,aAAa;AAAA,IACpB;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASQ,eAAqB;AAC3B,UAAM,MAAM,iBAAiB;AAC7B,QAAI,KAAK,eAAe;AACtB,UAAI,qBAAqB;AAAA,IAC3B;AAAA,EACF;AAAA,EAEQ,OAAyC;AAC/C,UAAM,MAAM,iBAAiB;AAC7B,QAAI,CAAC,KAAK,eAAe;AACvB,aAAO;AAAA,IACT;AAKA,UAAM,UAAU,IAAI,uBAAuB,IAAI;AAC/C,QAAI,CAAC,SAAS;AACZ,aAAO;AAAA,IACT;AACA,UAAM,QAAQ,IAAI;AAClB,WAAO;AAAA,MACL,aAAa,MAAM;AAAA,MACnB,WAAW,MAAM;AAAA,MACjB,oBAAoB,MAAM;AAAA,MAC1B,UAAU,MAAM;AAAA,MAChB;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,UAAqC;AAC3C,UAAM,WAAW,KAAK,KAAK;AAC3B,QAAI,CAAC,UAAU;AACb,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AACF;;;ANnGA;;;AO6CO,IAAM,+BAAN,MAA+D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWpE,YAAY,QAKT;AAdH,SAAQ,eAAsC,CAAC;AAE/C,SAAQ,qBAAwD,CAAC;AAa/D,SAAK,aAAa,IAAI,WAAW;AAAA,MAC/B,QAAQ,OAAO;AAAA,MACf,YAAY,OAAO,cAAc;AAAA,MACjC,SAAS,OAAO,WAAW;AAAA,IAC7B,CAAC;AACD,SAAK,uBAAuB,OAAO,wBAAwB;AAAA,EAC7D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,aAAa,OAA6B;AAC9C,SAAK,aAAa,MAAM,OAAO,IAAI;AAEnC,UAAM,gBAAgB,KAAK,uBAAuB;AAClD,QAAI,eAAe;AACjB,WAAK,mBAAmB,MAAM,OAAO,IAAI;AAAA,IAC3C;AAEA,SAAK,UAAU,OAAO,gBAAgB,EAAE,IAAI,cAAc,QAAQ,IAAI,CAAC,CAAC;AAAA,EAC1E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,WAAW,OAA6B;AAC5C,UAAM,UAAU,KAAK,mBAAmB,MAAM,OAAO;AAErD,SAAK;AAAA,MACH;AAAA,MACA,UAAU,EAAE,IAAI,QAAQ,QAAQ,IAAI,EAAE,WAAW,KAAK;AAAA,IACxD;AAEA,WAAO,KAAK,mBAAmB,MAAM,OAAO;AAC5C,WAAO,KAAK,aAAa,MAAM,OAAO;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,YAAY,MAAgC;AAEhD,SAAK,SAAS,IAAI;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,UAAU,MAAgC;AAE9C,SAAK,SAAS,IAAI;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,aAA4B;AAAA,EAElC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,SAAS,UAAkC;AAC/C,SAAK,eAAe,CAAC;AACrB,SAAK,qBAAqB,CAAC;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,UACN,OACA,YAAkD,CAAC,GAC7C;AACN,QAAI;AACF,YAAM,EAAE,WAAW,GAAG,eAAe,IAAI;AACzC,YAAM,YAAY,MAAM,OAAO;AAC/B,aAAO,OAAO,WAAW,cAAc;AAEvC,WAAK,WAAW,kBAAkB;AAAA,QAChC,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,eAAe;AAAA,QACf,WAAW,aAAa;AAAA,MAC1B,CAAC;AAAA,IACH,QAAQ;AAAA,IAER;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,WAEN,MAIA;AACA,UAAM,SAAiE,CAAC;AACxE,QAAI;AAEJ,QAAI;AACF,YAAM,aAAa,KAAK,OAAO;AAC/B,UAAI,OAAO,eAAe,YAAY,eAAe,MAAM;AACzD,eAAO,KAAK;AAAA,UACV,QAAQ;AAAA,UACR,MAAM;AAAA,UACN,OAAO,6BAA6B,OAAO,UAAU;AAAA,QACvD,CAAC;AACD,yBAAiB,CAAC;AAAA,MACpB,OAAO;AACL,yBAAiB;AAAA,MACnB;AAAA,IACF,SAAS,OAAO;AACd,aAAO,KAAK;AAAA,QACV,QAAQ;AAAA,QACR,MAAM;AAAA,QACN,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,MAC9D,CAAC;AACD,uBAAiB,CAAC;AAAA,IACpB;AAEA,QAAI,CAAC,eAAe,WAAW;AAC7B,qBAAe,YAAY,CAAC;AAAA,IAC9B;AAEA,WAAO,CAAC,gBAAgB,MAAM;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA,EAKQ,yBAEN,MACA,gBACA,QACM;AAON,QAAI,KAAK,UAAU,SAAS,YAAY;AACtC;AAAA,IACF;AAEA,UAAM,WAAW,eAAe;AAEhC,QAAI;AACF,YAAM,QAAQ,KAAK,UAAU;AAC7B,UAAI,UAAU,QAAW;AACvB,iBAAS,QAAQ;AAAA,MACnB;AAAA,IACF,SAAS,OAAO;AACd,aAAO,KAAK;AAAA,QACV,QAAQ;AAAA,QACR,MAAM;AAAA,QACN,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,MAC9D,CAAC;AAAA,IACH;AAEA,QAAI;AACF,YAAM,WAAW,KAAK,UAAU;AAChC,UAAI,aAAa,QAAW;AAC1B,iBAAS,WAAW;AAAA,MACtB;AAAA,IACF,SAAS,OAAO;AACd,aAAO,KAAK;AAAA,QACV,QAAQ;AAAA,QACR,MAAM;AAAA,QACN,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,MAC9D,CAAC;AAAA,IACH;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,mBACN,gBACA,SACM;AACN,UAAM,UAAU,KAAK,mBAAmB,OAAO;AAC/C,QAAI,SAAS;AACX,qBAAe,WAAW,QAAQ;AAClC,UAAI,CAAC,eAAe,WAAW;AAC7B,uBAAe,YAAY,QAAQ;AAAA,MACrC;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,iBACN,gBACA,QACyB;AACzB,UAAM,UAAmC;AAAA,MACvC,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,eAAe,eAAe,YAAY;AAAA,MAC1C,SAAS;AAAA,IACX;AAEA,QAAI,OAAO,SAAS,GAAG;AACrB,cAAQ,SAAS;AAAA,IACnB;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,SAEN,MACM;AACN,UAAM,SAAiE,CAAC;AACxE,UAAM,CAAC,gBAAgB,YAAY,IAAI,KAAK,WAAW,IAAI;AAC3D,WAAO,KAAK,GAAG,YAAY;AAE3B,SAAK,yBAAyB,MAAM,gBAAgB,MAAM;AAE1D,SAAK,mBAAmB,gBAAgB,KAAK,WAAW,EAAE;AAE1D,UAAM,UAAU,KAAK,iBAAiB,gBAAgB,MAAM;AAE5D,SAAK,WAAW,iBAAiB,OAAO;AAAA,EAC1C;AACF;;;AC1LA,SAAS,WAAW,OAAwC;AAC1D,MAAI,CAAC,SAAS,OAAO,UAAU,UAAU;AACvC,WAAO;AAAA,EACT;AACA,QAAM,IAAI;AACV,QAAM,WAAW,OAAO,EAAE,aAAa,WAAW,EAAE,WAAW;AAC/D,QAAM,UAAU,OAAO,EAAE,YAAY,WAAW,EAAE,UAAU;AAC5D,MAAI,YAAY,QAAQ,WAAW,MAAM;AACvC,WAAO;AAAA,EACT;AACA,SAAO,EAAE,UAAU,QAAQ;AAC7B;AAGA,SAAS,kBACP,QACA,OACa;AACb,QAAM,UAAU,MAAM,QAAQ,OAAO,OAAO,IAAI,OAAO,UAAU,CAAC;AAClE,QAAM,OACJ,OAAO,OAAO,SAAS,WACnB,OAAO,OACP,QACG,OAAO,CAAC,MAAM,EAAE,SAAS,UAAU,OAAO,EAAE,SAAS,QAAQ,EAC7D,IAAI,CAAC,MAAM,EAAE,IAAI,EACjB,KAAK,EAAE;AAChB,QAAM,YAAY,QACf,OAAO,CAAC,MAAM,EAAE,SAAS,WAAW,EACpC,IAAI,CAAC,OAAO;AAAA,IACX,YAAY,EAAE;AAAA,IACd,UAAU,EAAE;AAAA,IACZ,OAAO,EAAE,SAAS,EAAE;AAAA,EACtB,EAAE;AACJ,QAAM,UAAuB;AAAA,IAC3B;AAAA,IACA,WAAW,UAAU,SAAS,IAAI,YAAY;AAAA,IAC9C,OAAO,OAAO;AAAA,IACd,cAAc,OAAO;AAAA,EACvB;AACA,MAAI,OAAO;AACT,YAAQ,QAAQ;AAAA,EAClB;AACA,SAAO;AACT;AAQA,SAAS,iBACP,YACA,OACqD;AACrD,MAAI,OAAO;AACX,QAAM,YAAuB,CAAC;AAC9B,MAAI;AACJ,MAAI;AACJ,MAAI,YAAY;AAChB,QAAM,WAAW,MAAY;AAC3B,QAAI,WAAW;AACb;AAAA,IACF;AACA,gBAAY;AACZ,UAAM,UAAuB;AAAA,MAC3B;AAAA,MACA,WAAW,UAAU,SAAS,IAAI,YAAY;AAAA,MAC9C;AAAA,MACA;AAAA,IACF;AACA,QAAI,OAAO;AACT,cAAQ,QAAQ;AAAA,IAClB;AACA,eAAW,OAAO;AAAA,EACpB;AACA,SAAO,IAAI,gBAAoD;AAAA,IAC7D,UAAU,MAAM,YAAY;AAC1B,UAAI;AACF,YAAI,MAAM,SAAS,cAAc;AAC/B,kBAAQ,KAAK,SAAS,KAAK,aAAa;AAAA,QAC1C,WAAW,MAAM,SAAS,aAAa;AACrC,oBAAU,KAAK;AAAA,YACb,YAAY,KAAK;AAAA,YACjB,UAAU,KAAK;AAAA,YACf,OAAO,KAAK,SAAS,KAAK;AAAA,UAC5B,CAAC;AAAA,QACH,WAAW,MAAM,SAAS,UAAU;AAClC,kBAAQ,KAAK;AACb,yBAAe,KAAK;AAIpB,mBAAS;AAAA,QACX;AAAA,MACF,QAAQ;AAAA,MAER;AACA,iBAAW,QAAQ,IAAI;AAAA,IACzB;AAAA,IACA,QAAQ;AAEN,eAAS;AAAA,IACX;AAAA,EACF,CAAC;AACH;AAOO,IAAM,wBAAN,MAA4B;AAAA,EAIjC,YAAY,QAA4D;AACtE,SAAK,mBAAmB,OAAO;AAC/B,SAAK,aAAa,OAAO;AAAA,EAC3B;AAAA;AAAA,EAGA,IAAI,aAA4C;AAC9C,UAAM,MAAM,KAAK;AACjB,UAAM,WAAW,KAAK;AACtB,WAAO;AAAA,MACL,sBAAsB;AAAA,MACtB,cAAc,OAAO,EAAE,YAAY,QAAQ,MAAM,MAAM;AACrD,cAAM,QAAQ,WAAW,KAAK;AAK9B,cAAM,SAAS;AAAA,UAIb;AAAA,UACA;AAAA,YACE,MAAM;AAAA,YACN,UAAU,CAAC,WACT,kBAAmB,UAAU,CAAC,GAA4B,KAAK;AAAA,UACnE;AAAA,UACA,MAAM,WAAW;AAAA,QACnB;AACA,eAAO,OAAO,MAAM;AAAA,MACtB;AAAA,MACA,YAAY,OAAO,EAAE,UAAU,QAAQ,MAAM,MAAM;AACjD,cAAM,QAAQ,WAAW,KAAK;AAC9B,YAAI,iBAAiD,MAAM;AAAA,QAAC;AAC5D,cAAM,UAAU,IAAI,QAAqB,CAAC,YAAY;AACpD,2BAAiB;AAAA,QACnB,CAAC;AACD,cAAM,SAAS;AAAA,UAIb;AAAA;AAAA;AAAA;AAAA,UAIA,EAAE,MAAM,OAAO,UAAU,MAAM,QAAQ;AAAA,UACvC,YAAY;AACV,kBAAM,SAAS,MAAM,SAAS;AAC9B,kBAAM,SAAS,OAAO,OAAO;AAAA,cAC3B,iBAAiB,gBAAgB,KAAK;AAAA,YACxC;AACA,mBAAO,EAAE,GAAG,QAAQ,OAAO;AAAA,UAC7B;AAAA,QACF;AACA,eAAO,OAAO,MAAM;AAAA,MACtB;AAAA,IACF;AAAA,EACF;AACF;;;ARtSA;AA0BA,IAAM,oBAAoB,oBAAI,IAAwB;AACtD,IAAM,sBAAsB,oBAAI,IAAgC;AAEhE,IAAI,oBAAiE;AAErE,IAAM,yBAAwC,kBAAkB,KAAK,MAAM;AACzE,sBAAoB,wBAAuC;AAC7D,CAAC;AAmBD,IAAI,mBAAkC,CAAC;AAEvC,SAAS,eAA8B;AACrC,MAAI,mBAAmB;AACrB,WAAO,kBAAkB,SAAS,KAAK,CAAC;AAAA,EAC1C;AACA,SAAO;AACT;AAEA,SAAS,iBAAoB,OAAsB,IAAgB;AACjE,MAAI,mBAAmB;AACrB,WAAO,kBAAkB,IAAI,OAAO,EAAE;AAAA,EACxC;AAIA,QAAM,gBAAgB;AACtB,qBAAmB;AACnB,MAAI;AACF,UAAM,SAAS,GAAG;AAClB,QAAI,kBAAkB,SAAS;AAC7B,aAAO,OAAO,QAAQ,MAAM;AAC1B,2BAAmB;AAAA,MACrB,CAAC;AAAA,IACH;AACA,uBAAmB;AACnB,WAAO;AAAA,EACT,SAAS,OAAO;AACd,uBAAmB;AACnB,UAAM;AAAA,EACR;AACF;AAEA,SAAS,iBACP,OACoD;AACpD,MAAI,UAAU,QAAQ,OAAO,UAAU,UAAU;AAC/C,WAAO;AAAA,EACT;AACA,QAAM,YAAY;AAClB,SACE,OAAO,UAAU,SAAS,cAC1B,OAAO,UAAU,WAAW,cAC5B,OAAO,UAAU,UAAU,cAC3B,OAAO,UAAU,OAAO,aAAa,MAAM;AAE/C;AAWA,SAAS,mBACP,QACA,WACA,UAC0C;AAC1C,QAAM,UAAoB,CAAC;AAC3B,MAAI;AACJ,MAAI,YAAY;AAEhB,QAAM,WAAW,CAAC,aAAsB;AACtC,QAAI,WAAW;AACb;AAAA,IACF;AACA,gBAAY;AACZ,SAAK,SAAS;AAAA,MACZ,QAAQ,EAAE,SAAS,QAAQ,YAAY;AAAA,MACvC,GAAI,YAAY,EAAE,OAAO,SAAS;AAAA,IACpC,CAAC;AAAA,EACH;AAEA,QAAM,OAAO,CACX,QACA,QAEA,iBAAiB,WAAW,MAAM;AAChC,UAAM,KAAK,OAAO,MAAM;AAGxB,WAAO,GAAG,KAAK,QAAQ,GAAG;AAAA,EAC5B,CAAC;AAEH,QAAM,SAAS,OACb,QACA,QAC6C;AAC7C,QAAI;AACF,YAAM,SAAS,MAAM,KAAK,QAAQ,GAAG;AACrC,UAAI,OAAO,MAAM;AACf,sBAAc,OAAO;AACrB,iBAAS;AAAA,MACX,OAAO;AACL,gBAAQ,KAAK,OAAO,KAAK;AAAA,MAC3B;AACA,aAAO;AAAA,IACT,SAAS,OAAO;AACd,eAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAC/D,YAAM;AAAA,IACR;AAAA,EACF;AAEA,QAAM,UAAU;AAAA,IACd,KAAK,KAAe;AAClB,aAAO,OAAO,QAAQ,GAAG;AAAA,IAC3B;AAAA,IACA,OAAO,OAAuC;AAC5C,aAAO,OAAO,UAAU,KAAK;AAAA,IAC/B;AAAA,IACA,MAAM,KAAc;AAClB,aAAO,OAAO,SAAS,GAAG;AAAA,IAC5B;AAAA,IACA,CAAC,OAAO,aAAa,IAAI;AACvB,aAAO;AAAA,IACT;AAAA,IACA,CAAC,OAAO,YAAY,IAAI;AACtB,aAAO,OAAO,UAAU,MAAS,EAAE,KAAK,MAAM,MAAS;AAAA,IACzD;AAAA,EACF;AAEA,SAAO;AACT;AAMA,IAAI;AAiBJ,eAAe,qBAA2D;AACxE,MAAI,yBAAyB,QAAW;AACtC,WAAO;AAAA,EACT;AACA,MAAI;AAIF,UAAM,OAAO,MAAM,mBAAsD;AAAA,MACvE;AAAA,MACA;AAAA,IACF,CAAC;AACD,2BAAuB,KAAK;AAC5B,WAAO;AAAA,EACT,QAAQ;AACN,2BAAuB;AACvB,WAAO;AAAA,EACT;AACF;AAkCA,SAAS,2BAA2B,WAAmC;AACrE,MAAI;AACF,UAAM,IAAI;AACV,UAAM,QAAQ,GAAG,MAAM,SAAS,CAAC;AACjC,UAAM,eAAe,MAAM,KAAK,CAAC,SAAS,KAAK,QAAQ,KAAK,MAAM,CAAC;AACnE,QAAI,CAAC,cAAc,aAAa,MAAM;AACpC,aAAO;AAAA,IACT;AACA,UAAM,OAAO,aAAa,YAAY,KAAK,KAAK;AAChD,QAAI,CAAC,QAAQ,OAAO,SAAS,UAAU;AACrC,aAAO;AAAA,IACT;AACA,UAAM,WAAW,KAAK;AACtB,QAAI,CAAC,MAAM,QAAQ,QAAQ,KAAK,SAAS,WAAW,GAAG;AACrD,aAAO;AAAA,IACT;AACA,UAAM,WAAY,SACf;AAAA,MACC,CAAC,QACC,OAAO,QAAQ,YACf,QAAQ,QACR,UAAU,OACV,OAAQ,IAA0B,SAAS;AAAA,IAC/C,EACC,IAAI,CAAC,SAAS;AAAA,MACb,MAAM,IAAI;AAAA,MACV,SACE,OAAO,IAAI,YAAY,WACnB,IAAI,UACJ,KAAK,UAAU,IAAI,OAAO;AAAA,IAClC,EAAE;AACJ,QAAI,SAAS,SAAS,GAAG;AACvB,aAAO,KAAK,UAAU,QAAQ;AAAA,IAChC;AACA,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,4BACP,WACgC;AAChC,MAAI;AACF,UAAM,IAAI;AACV,UAAM,QAAQ,GAAG,MAAM,SAAS,CAAC;AACjC,UAAM,eAAe,MAAM,KAAK,CAAC,SAAS,KAAK,QAAQ,KAAK,MAAM,CAAC;AACnE,UAAM,QAAQ,GAAG;AAEjB,UAAM,UAAmC,CAAC;AAC1C,QAAI,cAAc,UAAU;AAC1B,cAAQ,WAAW,aAAa;AAAA,IAClC;AAGA,UAAM,OAAO,cAAc,aAAa,MAAM,KAAK;AACnD,QAAI,QAAQ,OAAO,SAAS,YAAY,OAAO,KAAK,UAAU,UAAU;AACtE,cAAQ,QAAQ,KAAK;AAAA,IACvB,OAAO;AACL,YAAM,MAAM,cAAc,aAAa;AACvC,UAAI,KAAK;AACP,cAAM,QAAQ,IAAI,MAAM,oBAAoB;AAC5C,YAAI,QAAQ,CAAC,GAAG;AACd,kBAAQ,QAAQ,MAAM,CAAC;AAAA,QACzB;AAAA,MACF;AAAA,IACF;AAEA,UAAM,cACJ,OAAO,eAAe,cAAc,OAAO,eAAe;AAC5D,UAAM,eACJ,OAAO,gBAAgB,cAAc,OAAO,gBAAgB;AAC9D,QAAI,gBAAgB,MAAM;AACxB,cAAQ,cAAc;AAAA,IACxB;AACA,QAAI,iBAAiB,MAAM;AACzB,cAAQ,eAAe;AAAA,IACzB;AAEA,UAAM,aAAa,GAAG,MAAM,QAAQ,cAAc;AAClD,QAAI,eAAe,MAAM;AACvB,cAAQ,aAAa;AAAA,IACvB;AAEA,WAAO,OAAO,KAAK,OAAO,EAAE,SAAS,IAAI,UAAU;AAAA,EACrD,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAsEA,IAAM,mBAAmB;AACzB,IAAM,sBAAsB;AAE5B,SAAS,gBAAgB,SAAuB;AAC9C,MAAI,OAAO,YAAY,YAAY,QAAQ,WAAW,GAAG;AACvD,UAAM,IAAI,YAAY,oDAAoD;AAAA,EAC5E;AACA,MAAI,QAAQ,SAAS,qBAAqB;AACxC,UAAM,IAAI;AAAA,MACR,mBAAmB,mBAAmB;AAAA,IACxC;AAAA,EACF;AACA,MAAI,CAAC,iBAAiB,KAAK,OAAO,GAAG;AACnC,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACF;AAuBA,IAAM,WAAwB;AAAA,EAC5B,SAAS;AAAA,EACT,aAAmB;AAAA,EAEnB;AAAA,EACA,YAAkB;AAAA,EAElB;AACF;AAEA,IAAM,YAA0B;AAAA,EAC9B,eAAqB;AAAA,EAErB;AAAA,EACA,cAAoB;AAAA,EAEpB;AAAA,EACA,aAAmB;AAAA,EAEnB;AACF;AAUO,SAAS,iBAA8B;AAC5C,QAAM,QAAQ,aAAa;AAC3B,QAAM,UAAU,MAAM,MAAM,SAAS,CAAC;AACtC,MAAI,CAAC,SAAS;AACZ,WAAO;AAAA,EACT;AACA,SAAO;AAAA,IACL,SAAS,QAAQ;AAAA,IACjB,WAAW,SAAwC;AACjD,UAAI;AACF,YAAI,OAAO,YAAY,YAAY,YAAY,MAAM;AACnD;AAAA,QACF;AAEA,gBAAQ,SAAS,KAAK,OAAO;AAAA,MAC/B,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,IACA,UAAU,QAAsB;AAC9B,UAAI;AACF,YAAI,OAAO,WAAW,UAAU;AAC9B;AAAA,QACF;AACA,gBAAQ,SAAS;AAAA,MACnB,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AACF;AAUO,SAAS,kBAAgC;AAC9C,QAAM,QAAQ,aAAa;AAC3B,QAAM,UAAU,MAAM,MAAM,SAAS,CAAC;AACtC,MAAI,CAAC,SAAS;AACZ,WAAO;AAAA,EACT;AAEA,QAAM,UAAU,QAAQ;AAExB,QAAM,wBAAwB,MAAkB;AAC9C,QAAI,aAAa,kBAAkB,IAAI,OAAO;AAC9C,QAAI,CAAC,YAAY;AACf,mBAAa;AAAA,QACX;AAAA,QACA,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,QAClC,UAAU,CAAC;AAAA,MACb;AACA,wBAAkB,IAAI,SAAS,UAAU;AAAA,IAC3C;AACA,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL,aAAa,WAAyB;AACpC,UAAI;AACF,cAAM,aAAa,sBAAsB;AACzC,mBAAW,YAAY;AAAA,MACzB,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,IACA,YAAY,UAAyC;AACnD,UAAI;AACF,YAAI,OAAO,aAAa,YAAY,aAAa,MAAM;AACrD;AAAA,QACF;AACA,cAAM,aAAa,sBAAsB;AACzC,mBAAW,WAAW,EAAE,GAAG,WAAW,UAAU,GAAG,SAAS;AAAA,MAC9D,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,IACA,WAAW,SAAwC;AACjD,UAAI;AACF,YAAI,OAAO,YAAY,YAAY,YAAY,MAAM;AACnD;AAAA,QACF;AACA,cAAM,aAAa,sBAAsB;AAEzC,mBAAW,SAAS,KAAK,OAAO;AAAA,MAClC,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AACF;AAqGO,IAAM,SAAN,MAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAsBlB,YAAY,QAAsB;AAChC,SAAK,SAAS,OAAO;AACrB,SAAK,aAAa,OAAO,cAAc;AACvC,SAAK,UAAU,OAAO,WAAW;AACjC,SAAK,UAAU,OAAO,WAAW,CAAC;AAClC,UAAM,UAAU,OAAO,WAAW;AAClC,QAAI,YAAY,CAAC,OAAO,UAAU,OAAO,OAAO,KAAK,MAAM,KAAK;AAC9D,cAAQ;AAAA,QACN;AAAA,MACF;AACA,WAAK,UAAU;AAAA,IACjB,OAAO;AACL,WAAK,UAAU;AAAA,IACjB;AACA,SAAK,aAAa,OAAO,cAAc;AACvC,QAAI,OAAO,YAAY;AACrB,+BAAyB,OAAO,UAAU;AAAA,IAC5C;AACA,SAAK,aAAa,OAAO;AACzB,SAAK,aAAa,IAAI,WAAW;AAAA,MAC/B,QAAQ,KAAK;AAAA,MACb,YAAY,KAAK;AAAA,MACjB,SAAS,KAAK;AAAA,IAChB,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAc,qBACZ,YACkC;AAClC,UAAM,SACJ,MAAM,KAAK,WAAW,eAAwC,UAAU;AAG1E,QAAI,OAAO,OAAO,MAAM;AACtB,YAAM,IAAI;AAAA,QACR,aAAa,UAAU,8BAA8B,KAAK,UAAU;AAAA,QACpE;AAAA,MACF;AAAA,IACF;AAGA,QAAI,CAAC,OAAO,QAAQ;AAClB,YAAM,IAAI;AAAA,QACR,aAAa,UAAU,2CAA2C,KAAK,UAAU,cAAc,OAAO,EAAE;AAAA,QACxG,cAAc,OAAO,EAAE;AAAA,MACzB;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,KACJ,YACA,SAAkC,CAAC,GACvB;AACZ,QAAI;AACF,YAAM,kBAAkB,MAAM,KAAK,qBAAqB,UAAU;AAClE,YAAM,kBAAkB,MAAM;AAAA,QAC5B,gBAAgB;AAAA,QAChB;AAAA,QACA,gBAAgB;AAAA,QAChB,KAAK;AAAA,MACP;AAKA,UAAI;AACJ,UAAI,OAAO,gBAAgB,WAAW,UAAU;AAC9C,oBAAY,gBAAgB;AAAA,MAC9B,OAAO;AACL,YAAI;AACF,sBACE,KAAK,UAAU,gBAAgB,MAAM,KACrC,OAAO,gBAAgB,MAAM;AAAA,QACjC,QAAQ;AACN;AAAA,YACE;AAAA,YACA;AAAA,UACF;AACA,sBAAY,OAAO,gBAAgB,MAAM;AAAA,QAC3C;AAAA,MACF;AAGA,WAAK,WAAW,kBAAkB,gBAAgB,IAAI;AAAA,QACpD,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,GAAI,OAAO,KAAK,MAAM,EAAE,SAAS,KAAK,EAAE,OAAO;AAAA,QAC/C,GAAI,gBAAgB,gBAAgB,QAAQ;AAAA,UAC1C,cAAc,gBAAgB;AAAA,QAChC;AAAA,MACF,CAAC;AAED,aAAO,gBAAgB;AAAA,IACzB,SAAS,OAAO;AACd,UAAI,iBAAiB,aAAa;AAChC,cAAM;AAAA,MACR;AACA,UAAI,iBAAiB,OAAO;AAC1B,cAAM,IAAI,YAAY,MAAM,OAAO;AAAA,MACrC;AACA,YAAM,IAAI,YAAY,+CAA+C;AAAA,IACvE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmBA,4BAA4B;AAC1B,WAAO,IAAI,6BAA6B;AAAA,MACtC,QAAQ,KAAK;AAAA,MACb,YAAY,KAAK;AAAA,MACjB,sBAAsB,MAAM;AAC1B,cAAM,QAAQ,aAAa;AAC3B,eAAO,MAAM,MAAM,SAAS,CAAC,KAAK;AAAA,MACpC;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAwBA,sBAAsB,kBAA0B;AAC9C,WAAO,IAAI,yBAAyB;AAAA,MAClC;AAAA,MACA,UAAU,KAAK,SAAS,KAAK,IAAI;AAAA,MACjC,sBAAsB,MAAM;AAC1B,cAAM,QAAQ,aAAa;AAC3B,eAAO,MAAM,MAAM,SAAS,CAAC,KAAK;AAAA,MACpC;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmBA,4BAA4B,kBAA0B;AACpD,WAAO,IAAI,+BAA+B;AAAA,MACxC,QAAQ,KAAK;AAAA,MACb;AAAA,MACA,YAAY,KAAK;AAAA,MACjB,sBAAsB,MAAM;AAC1B,cAAM,QAAQ,aAAa;AAC3B,eAAO,MAAM,MAAM,SAAS,CAAC,KAAK;AAAA,MACpC;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBA,4BAA4B,kBAA0B;AACpD,WAAO,KAAK,4BAA4B,gBAAgB;AAAA,EAC1D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAyBA,sBAAsB,kBAA0B;AAC9C,WAAO,IAAI,yBAAyB;AAAA,MAClC,QAAQ,KAAK;AAAA,MACb;AAAA,MACA,YAAY,KAAK;AAAA,MACjB,sBAAsB,MAAM;AAC1B,cAAM,QAAQ,aAAa;AAC3B,eAAO,MAAM,MAAM,SAAS,CAAC,KAAK;AAAA,MACpC;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA0BA,sBAAsB,kBAA0B;AAC9C,WAAO,IAAI,sBAAsB;AAAA,MAC/B;AAAA,MACA,UAAU,KAAK,SAAS,KAAK,IAAI;AAAA,IACnC,CAAC,EAAE;AAAA,EACL;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA8BA,SACE,gBACA,sBAGA,cAC+B;AAC/B,QAAI;AACJ,QAAI;AACJ,QAAI;AAEJ,QAAI,OAAO,yBAAyB,YAAY;AAC9C,mBAAa;AACb,eAAS;AACT,gBAAU;AAAA,IACZ,OAAO;AACL,mBAAa,KAAK;AAClB,eAAS;AACT,gBAAU;AACV,UAAI,CAAC,YAAY;AACf,cAAM,IAAI;AAAA,UACR;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,UAAM,aAAa,OAAO;AAC1B,QAAI,CAAC,YAAY;AACf,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAGA,uBAAmB;AAEnB,UAAM,YAAY,UAAU,SAAkC;AAC5D,YAAM,iBAAiB,MAAM,mBAAmB;AAChD,UAAI,CAAC,gBAAgB;AAEnB,kBAAU,YAAY;AACtB,eAAO,MACL,WACA,UAAU,EAAE,GAAG,IAAI;AAAA,MACvB;AAEA,YAAM,YAAY,IAAI,eAAe,qBAAqB;AAM1D,UAAI;AACJ,UAAI;AACJ,UAAI;AACF,wBACE,WACA,YAAY,EAAE,UAAU,CAAC;AAC3B,cAAMC,UACJ,cACA,UAAU;AACZ,YAAI,OAAOA,YAAW,YAAY;AAChC,gBAAM,IAAI;AAAA,YACR;AAAA,UACF;AAAA,QACF;AACA,wBAAgBA;AAAA,MAClB,QAAQ;AACN;AAAA,UACE,kBAAkB,UAAU;AAAA,UAC5B,kCAAkC,UAAU;AAAA,QAC9C;AACA,kBAAU,YAAY;AACtB,eAAO,MACL,WACA,UAAU,EAAE,GAAG,IAAI;AAAA,MACvB;AAEA,YAAM,SAAS,MAAM,cAAc,KAAK,aAAa,EAAE,GAAG,IAAI;AAE9D,gBAAU,YAAY;AAEtB,UAAI;AACF,cAAM,SAAS,2BAA2B,SAAS;AACnD,YAAI,QAAQ;AACV,yBAAe,EAAE,UAAU,MAAM;AAAA,QACnC;AACA,cAAM,WAAW,4BAA4B,SAAS;AACtD,YAAI,UAAU;AACZ,yBAAe,EAAE,WAAW,QAAQ;AAAA,QACtC;AAAA,MACF,QAAQ;AAAA,MAER;AAEA,UAAI;AACF,iBAAS,cAAc,SAAS;AAAA,MAClC,QAAQ;AAAA,MAER;AAEA,aAAO;AAAA,IACT;AAEA,cAAU,YAAY;AAEtB,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiCA,SACE,kBACA,aACA,SAC6B;AAC7B,QAAI,CAAC,KAAK,SAAS;AACjB,YAAMC,MAAK,OAAO,gBAAgB,aAAa,cAAc;AAC7D,aAAOA;AAAA,IACT;AAGA,UAAM,UACJ,OAAO,gBAAgB,aAAa,CAAC,IAAI;AAC3C,UAAM,KACJ,OAAO,gBAAgB,aAAa,cAAc;AACpD,UAAM,OAAO;AAQb,UAAM,oBAAoB,GAAG,YAAY,SAAS;AAClD,UAAM,mBACJ,sBACC,MAAM;AACL,UAAI;AACF,cAAM,MAAM,GAAG,SAAS;AACxB,eAAO,wBAAwB,KAAK,GAAG;AAAA,MACzC,QAAQ;AACN,eAAO;AAAA,MACT;AAAA,IACF,GAAG;AAEL,UAAM,YAAY,YAA4B,MAAsB;AAMlE,UAAI,CAAC,qBAAqB,CAAC,uBAAuB,GAAG;AACnD,eAAO,uBAAuB;AAAA,UAAK,MACjC,UAAU,MAAM,MAAM,IAAI;AAAA,QAC5B;AAAA,MACF;AAQA,UAAI;AACJ,UAAI;AAGJ,UAAI;AACJ,UAAI;AAEF,cAAM,eAAe,aAAa;AAClC,cAAM,gBAAgB,aAAa,aAAa,SAAS,CAAC;AAG1D,cAAM,sBAAsB,gBAAgB,OAAO,iBAAiB;AACpE,cAAM,UACJ,eAAe,WAAW,qBAAqB,WAAW,WAAW;AACvE,cAAM,SAAS,WAAW;AAC1B,cAAM,eAAe,eAAe,UAAU;AAC9C,cAAM,aAAa,iBAAiB;AAGpC,cAAM,aAA0B,EAAE,SAAS,QAAQ,UAAU,CAAC,EAAE;AAChE,mBAAW,CAAC,GAAG,cAAc,UAAU;AAGvC,cAAM,SAAS;AACf,cAAM,aAAY,oBAAI,KAAK,GAAE,YAAY;AAGzC,YAAI,cAAc,CAAC,kBAAkB,IAAI,OAAO,GAAG;AACjD,gBAAM,kBAAkB,iBAAiB;AAOzC,gBAAM,gBAAgB,iBAAiB,KAAK,YAAY,SAAS;AACjE,4BAAkB,IAAI,SAAS;AAAA,YAC7B;AAAA,YACA;AAAA,YACA,UAAU,CAAC;AAAA,YACX,GAAI,iBAAiB,aAAa;AAAA,cAChC,WAAW,gBAAgB;AAAA,YAC7B;AAAA,YACA,GAAI,iBAAiB,sBAAsB;AAAA,cACzC,oBAAoB,gBAAgB;AAAA,YACtC;AAAA,YACA;AAAA,UACF,CAAC;AACD,8BAAoB,IAAI,SAAS,CAAC,CAAC;AACnC,8BAAoB;AAAA,QACtB;AAGA,cAAM,eAAe,GAAG,SAAS,KAAK,GAAG,OAAO;AAChD,cAAM,iBAAiB;AAAA,UACrB;AAAA,UACA;AAAA,UACA,UAAU,QAAQ,QAAQ,gBAAgB;AAAA,UAC1C;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA,UAAU,QAAQ,QAAQ;AAAA,QAC5B;AAKA,cAAM,WAAW,OACf,QACA,aACG;AAcH,gBAAM,YAAY,iBAAiB;AACnC,gBAAM,uBAAuB,aACzB,WAAW,qBACX;AACJ,cAAI;AACJ,cAAI,wBAAwB,CAAC,UAAU,6BAA6B;AAClE,iCAAqB;AAAA,cACnB,IAAI,QAAc,CAAC,YAAY;AAC7B,qCAAqB;AAAA,cACvB,CAAC;AAAA,YACH;AAAA,UACF;AACA,cAAI;AACF,kBAAM,WAAU,oBAAI,KAAK,GAAE,YAAY;AAMvC,kBAAM,cAAc,KAAK,gBAAgB;AAAA,cACvC,GAAG;AAAA,cACH,GAAG;AAAA,cACH,UAAU,WAAW;AAAA,cACrB,QAAQ,WAAW;AAAA,cACnB;AAAA,cACA,GAAI,WAAW,aAAa,EAAE,WAAW,UAAU,UAAU;AAAA,cAC7D,GAAI,WAAW,qBAAqB;AAAA,gBAClC,mBAAmB,UAAU;AAAA,cAC/B;AAAA,YACF,CAAC;AAGD,gBAAI,YAAY;AACd,oBAAM,UAAU,oBAAoB,IAAI,OAAO,KAAK,CAAC;AACrD,sBAAQ,KAAK,WAAW;AACxB,kBAAI,sBAAsB;AAGxB,sBAAM,QAAQ,WAAW,OAAO;AAAA,cAClC,OAAO;AAML,oBAAI;AACJ,oBAAI;AACF,wBAAM,QAAQ,KAAK;AAAA,oBACjB,QAAQ,WAAW,OAAO;AAAA,oBAC1B,IAAI,QAAQ,CAAC,YAAY;AACvB,kCAAY,WAAW,SAAS,GAAI;AACpC,iCAAW,SAAS;AAAA,oBACtB,CAAC;AAAA,kBACH,CAAC;AAAA,gBACH,UAAE;AACA,sBAAI,WAAW;AACb,iCAAa,SAAS;AAAA,kBACxB;AAAA,gBACF;AAAA,cACF;AACA,kCAAoB,OAAO,OAAO;AAElC,oBAAM,aAAa,kBAAkB,IAAI,OAAO;AAChD,oBAAM,oBAAoB,KAAK,oBAAoB;AAAA,gBACjD;AAAA,gBACA;AAAA,gBACA,WAAW,YAAY,aAAa;AAAA,gBACpC;AAAA,gBACA,WAAW,YAAY;AAAA,gBACvB,UAAU,YAAY;AAAA,gBACtB,UAAU,YAAY,YAAY,CAAC;AAAA,gBACnC,WAAW,YAAY;AAAA,gBACvB,oBAAoB,YAAY;AAAA,gBAChC,eAAe,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA,gBAK3B,GAAI,WAAW,iBAAiB;AAAA,kBAC9B,iBAAiB;AAAA,oBACf,cAAc,UAAU,cAAc;AAAA,oBACtC,mBACE,UAAU,cAAc;AAAA,oBAC1B,eAAe,UAAU;AAAA,oBACzB,UAAU,UAAU,uBAAuB;AAAA,kBAC7C;AAAA,gBACF;AAAA,cACF,CAAC;AACD,gCAAkB,OAAO,OAAO;AAChC,kBAAI,sBAAsB;AACxB,sBAAM;AAAA,cACR;AAAA,YACF,OAAO;AAEL,oBAAM,UAAU,oBAAoB,IAAI,OAAO;AAC/C,kBAAI,SAAS;AACX,wBAAQ,KAAK,WAAW;AAAA,cAC1B,OAAO;AACL,oCAAoB,IAAI,SAAS,CAAC,WAAW,CAAC;AAAA,cAChD;AAAA,YACF;AAAA,UACF,QAAQ;AAAA,UAER,UAAE;AACA,iCAAqB;AAAA,UACvB;AAAA,QACF;AAOA,cAAM,mBAAmB,iBAAiB;AAC1C,YAAI,kBAAkB,YAAY,CAAC,YAAY;AAC7C,gBAAM,WAAW,iBAAiB;AAClC,gBAAM,aAAa,GAAG,gBAAgB,IAAI,eAAe,QAAQ;AACjE,gBAAM,YAAY,SAAS,IAAI,UAAU,KAAK;AAC9C,mBAAS,IAAI,YAAY,YAAY,CAAC;AAEtC,gBAAM,aACJ,iBAAiB,iBAAiB,SACjC,iBAAiB,iBAAiB,YACjC,QAAQ,iBAAiB;AAE7B,cAAI,YAAY;AACd,kBAAM,UAAU,GAAG,UAAU,IAAI,SAAS;AAC1C,kBAAM,WAAW,iBAAiB,SAAS,MAAM,IAAI,OAAO;AAC5D,gBAAI,UAAU;AACZ,kBAAI,SAAS,SAAS;AACtB,kBACE,SAAS,eAAe,UACxB,SAAS,eAAe,MACxB;AACA,yBAAS,iBAAiB;AAAA,kBACxB,MAAM,SAAS;AAAA,kBACf,MAAM,SAAS;AAAA,gBACjB,CAAC;AAAA,cACH;AASA,mBAAK,SAAS,EAAE,QAAQ,OAAO,CAAC;AAChC,kBAAI,kBAAkB;AACpB,uBAAO,QAAQ,QAAQ,MAAM;AAAA,cAC/B;AACA,qBAAO;AAAA,YACT;AAAA,UACF;AAAA,QACF;AAOA,cAAM,aAAa,CAAC,WAA0B;AAC5C,cAAI,QAAQ,UAAU;AAUpB,kBAAM,YAAY,iBAAiB;AACnC,kBAAM,uBAAuB,aACzB,WAAW,qBACX;AACJ,gBAAI;AACJ,gBAAI,sBAAsB;AACxB,mCAAqB;AAAA,gBACnB,IAAI,QAAc,CAAC,YAAY;AAC7B,uCAAqB;AAAA,gBACvB,CAAC;AAAA,cACH;AAAA,YACF;AACA,iBAAK,QAAQ,QAAQ,EAClB,KAAK,MAAM,QAAQ,SAAU,MAAM,CAAC,EACpC;AAAA,cAAK,CAAC,WACL;AAAA,gBACE,EAAE,QAAQ,OAAO;AAAA,gBACjB,EAAE,6BAA6B,KAAK;AAAA,cACtC;AAAA,YACF,EACC;AAAA,cAAM,CAAC,UACN;AAAA,gBACE;AAAA,kBACE,QAAQ;AAAA,kBACR,OACE,iBAAiB,QACb,oBAAoB,MAAM,OAAO,KACjC,oBAAoB,OAAO,KAAK,CAAC;AAAA,gBACzC;AAAA,gBACA,EAAE,6BAA6B,KAAK;AAAA,cACtC;AAAA,YACF,EACC,QAAQ,MAAM,qBAAqB,CAAC;AAAA,UACzC,OAAO;AACL,iBAAK,SAAS,EAAE,OAAO,CAAC;AAAA,UAC1B;AAAA,QACF;AAGA,6BAAqB,MAAe;AAClC,gBAAM,SAAS,GAAG,GAAG,IAAI;AAGzB,cAAI,kBAAkB,SAAS;AAC7B,mBAAO,OACJ,KAAK,CAAC,mBAAmB;AACxB,yBAAW,cAAc;AACzB,qBAAO;AAAA,YACT,CAAC,EACA,MAAM,CAAC,UAAmB;AACzB,mBAAK,SAAS;AAAA,gBACZ,QAAQ;AAAA,gBACR,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,cAC9D,CAAC;AACD,oBAAM;AAAA,YACR,CAAC;AAAA,UACL;AAKA,cAAI,iBAAiB,MAAM,GAAG;AAC5B,mBAAO,mBAAmB,QAAQ,UAAU,QAAQ;AAAA,UACtD;AAKA,qBAAW,MAAM;AACjB,iBAAO;AAAA,QACT;AAAA,MACF,SAAS,YAAY;AAInB,YAAI,mBAAmB;AACrB,4BAAkB,OAAO,iBAAiB;AAC1C,8BAAoB,OAAO,iBAAiB;AAAA,QAC9C;AAQA,YAAI,iBAAiB,GAAG;AACtB,gBAAM;AAAA,QACR;AAIA;AAAA,UACE,kBAAkB,gBAAgB;AAAA,UAClC,6BAA6B,gBAAgB;AAAA,QAC/C;AACA,eAAO,GAAG,GAAG,IAAI;AAAA,MACnB;AAKA,aAAO,iBAAiB,UAAU,kBAAkB;AAAA,IACtD;AAGA,WAAO,eAAe,WAAW,2BAA2B;AAAA,MAC1D,OAAO;AAAA,IACT,CAAC;AACD,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAsBA,SAAS,SAAgC;AACvC,oBAAgB,OAAO;AAEvB,WAAO;AAAA,MACL;AAAA,MACA,YAAY,CAAC,YAAuD;AAClE,YAAI,CAAC,KAAK,SAAS;AACjB,iBAAO,QAAQ,QAAQ;AAAA,QACzB;AACA,YAAI,OAAO,YAAY,YAAY,YAAY,MAAM;AACnD,iBAAO,QAAQ,QAAQ;AAAA,QACzB;AACA,eAAO,KAAK,WAAW,WAAW,SAAS;AAAA,UACzC,gBAAgB,CAAC,OAAO;AAAA,QAC1B,CAAC;AAAA,MACH;AAAA,MACA,aAAa,CAAC,aAAwD;AACpE,YAAI,CAAC,KAAK,SAAS;AACjB,iBAAO,QAAQ,QAAQ;AAAA,QACzB;AACA,YAAI,OAAO,aAAa,YAAY,aAAa,MAAM;AACrD,iBAAO,QAAQ,QAAQ;AAAA,QACzB;AACA,eAAO,KAAK,WAAW,WAAW,SAAS,EAAE,eAAe,SAAS,CAAC;AAAA,MACxE;AAAA,MACA,cAAc,CAAC,cAAwC;AACrD,YAAI,CAAC,KAAK,SAAS;AACjB,iBAAO,QAAQ,QAAQ;AAAA,QACzB;AACA,YAAI,OAAO,cAAc,YAAY,UAAU,WAAW,GAAG;AAC3D,iBAAO,QAAQ,QAAQ;AAAA,QACzB;AACA,eAAO,KAAK,WAAW,WAAW,SAAS,EAAE,cAAc,UAAU,CAAC;AAAA,MACxE;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAoBA,YAAY,kBAA0C;AACpD,WAAO,IAAI,eAAe,MAAM,gBAAgB;AAAA,EAClD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,oBAAoB,QAsBP;AAEnB,UAAM,WAAoC;AAAA,MACxC,IAAI,OAAO;AAAA,MACX,YAAY,OAAO;AAAA,MACnB,UAAU,OAAO;AAAA,MACjB,eAAe,OAAO;AAAA,IACxB;AAGA,QAAI,OAAO,YAAY,OAAO,KAAK,OAAO,QAAQ,EAAE,SAAS,GAAG;AAC9D,eAAS,WAAW,OAAO;AAAA,IAC7B;AACA,QAAI,OAAO,YAAY,OAAO,SAAS,SAAS,GAAG;AACjD,eAAS,WAAW,OAAO;AAAA,IAC7B;AACA,QAAI,OAAO,oBAAoB;AAC7B,eAAS,wBAAwB,OAAO;AAAA,IAC1C;AACA,QAAI,OAAO,eAAe;AACxB,eAAS,kBAAkB,OAAO;AAAA,IACpC;AACA,QAAI,OAAO,iBAAiB;AAC1B,eAAS,oBAAoB;AAAA,QAC3B,gBAAgB,OAAO,gBAAgB;AAAA,QACvC,GAAI,OAAO,gBAAgB,qBAAqB;AAAA,UAC9C,oBAAoB,OAAO,gBAAgB;AAAA,QAC7C;AAAA,QACA,GAAI,OAAO,gBAAgB,iBAAiB;AAAA,UAC1C,iBAAiB,OAAO,gBAAgB;AAAA,QAC1C;AAAA,QACA,UAAU,OAAO,gBAAgB;AAAA,MACnC;AAAA,IACF;AAEA,WAAO,KAAK,WAAW,kBAAkB;AAAA,MACvC,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,kBAAkB,OAAO;AAAA,MACzB,eAAe;AAAA,MACf,WAAW;AAAA,MACX,GAAI,OAAO,aAAa,EAAE,WAAW,OAAO,UAAU;AAAA,MACtD,GAAI,OAAO,aAAa,EAAE,WAAW,OAAO,UAAU;AAAA,IACxD,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,gBAAgB,QAiBH;AAEnB,UAAM,mBAAmB,eAAe,OAAO,MAAM;AACrD,UAAM,mBAAmB,eAAe,OAAO,MAAM;AAGrD,UAAM,eAAwC;AAAA,MAC5C,IAAI,OAAO;AAAA,MACX,UAAU,OAAO;AAAA,MACjB,YAAY,OAAO;AAAA,MACnB,UAAU,OAAO;AAAA,MACjB,WAAW;AAAA,QACT,MAAM,OAAO;AAAA,QACb,MAAM,OAAO;AAAA,QACb,OAAO,iBAAiB;AAAA,QACxB,QAAQ,iBAAiB;AAAA;AAAA,QAEzB,GAAI,iBAAiB,SAAS,UAAa;AAAA,UACzC,YAAY,iBAAiB;AAAA,QAC/B;AAAA,QACA,GAAI,iBAAiB,SAAS,UAAa;AAAA,UACzC,aAAa,iBAAiB;AAAA,QAChC;AAAA,QACA,GAAI,OAAO,iBAAiB,UAAa;AAAA,UACvC,eAAe,OAAO;AAAA,QACxB;AAAA,QACA,GAAI,OAAO,UAAU,UAAa;AAAA,UAChC,OAAO,OAAO;AAAA,UACd,cAAc;AAAA,QAChB;AAAA,QACA,GAAI,OAAO,YACT,OAAO,SAAS,SAAS,KAAK;AAAA,UAC5B,UAAU,OAAO;AAAA,QACnB;AAAA,QACF,GAAI,OAAO,WAAW,UAAa,EAAE,QAAQ,OAAO,OAAO;AAAA,MAC7D;AAAA,IACF;AAGA,QAAI,OAAO,cAAc;AACvB,mBAAa,YAAY,OAAO;AAAA,IAClC;AACA,QAAI,OAAO,mBAAmB;AAC5B,mBAAa,uBAAuB,OAAO;AAAA,IAC7C;AAEA,WAAO,KAAK,WAAW,iBAAiB;AAAA,MACtC,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,eAAe,OAAO;AAAA,MACtB,kBAAkB,OAAO;AAAA,MACzB,SAAS;AAAA,MACT,GAAI,OAAO,aAAa,EAAE,WAAW,OAAO,UAAU;AAAA,IACxD,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAsBA,MAAM,OACJ,kBAEA,IACA,SACgC;AAChC,UAAM,aAAc,GACjB;AACH,QAAI,WAAW;AACf,QAAI,eAAe,QAAW;AAM5B,iBAAW,KAAK;AAAA,QACd;AAAA,QACA,EAAE,MAAM,kBAAkB,MAAM,QAAQ;AAAA,QACxC;AAAA,MACF;AAAA,IACF,WAAW,eAAe,kBAAkB;AAC1C,YAAM,IAAI;AAAA,QACR,gDAAgD,UAAU,iCAC7B,gBAAgB;AAAA,MAE/C;AAAA,IACF;AACA,UAAM,EAAE,QAAQ,SAAS,IAAI,MAAM;AACnC,WAAO;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAAA;AAAA;AAAA;AAAA;AAAA;AA3qCa,OAMK,oBAAoB;AAsrC/B,IAAM,iBAAN,MAAqB;AAAA,EAC1B,YACmB,QACA,kBACjB;AAFiB;AACA;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAuBH,SACE,aACA,SAC6B;AAE7B,UAAM,UACJ,OAAO,gBAAgB,aAAa,CAAC,IAAI;AAC3C,UAAM,KACJ,OAAO,gBAAgB,aAAa,cAAc;AAEpD,WAAO,KAAK,OAAO,SAAS,KAAK,kBAAkB,SAAS,EAAE;AAAA,EAChE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA4BA,wBAAwB;AACtB,WAAO,KAAK,OAAO,sBAAsB,KAAK,gBAAgB;AAAA,EAChE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAyBA,wBAAwB;AACtB,WAAO,KAAK,OAAO,sBAAsB,KAAK,gBAAgB;AAAA,EAChE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAwBA,8BAA8B;AAC5B,WAAO,KAAK,OAAO,4BAA4B,KAAK,gBAAgB;AAAA,EACtE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,8BAA8B;AAC5B,WAAO,KAAK,OAAO,4BAA4B,KAAK,gBAAgB;AAAA,EACtE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBA,SACE,gBACA,sBAGA,cAC+B;AAC/B,WAAO,KAAK,OAAO;AAAA,MACjB;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;;;AStgEA,eAAe,OACb,OACwB;AACxB,MAAI;AACF,WAAO,MAAM;AAAA,EACf,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAuBA,eAAe,MAAM,QAAmD;AACtE,QAAM,IAAK,UAAU,CAAC;AACtB,QAAM,CAAC,MAAM,OAAO,YAAY,cAAc,WAAW,WAAW,IAClE,MAAM,QAAQ,IAAI;AAAA,IAChB,OAAO,EAAE,IAAI;AAAA,IACb,OAAO,EAAE,KAAK;AAAA,IACd,OAAO,EAAE,UAAU;AAAA,IACnB,OAAO,EAAE,YAAY;AAAA,IACrB,OAAO,EAAE,SAAS;AAAA,IAClB,OAAO,EAAE,WAAW;AAAA,EACtB,CAAC;AACH,SAAO;AAAA,IACL;AAAA,IACA,OAAO,cAAc;AAAA,IACrB;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAsBA,eAAe,eACb,QACA,QACgC;AAChC,QAAM,CAAC,MAAM,IAAI,IAAI,OAAO,IAAI;AAChC,SAAO,IAAI;AACX,QAAM,SAAoB,CAAC;AAC3B,QAAM,SAAS,KAAK,UAAU;AAC9B,MAAI;AACF,eAAS;AACP,YAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK;AAC1C,UAAI,MAAM;AACR;AAAA,MACF;AACA,aAAO,KAAK,KAAK;AAAA,IACnB;AAAA,EACF,QAAQ;AAAA,EAER;AACA,SAAO,EAAE,OAAO;AAClB;AAEO,IAAM,aAAa;AAAA,EACxB;AAAA,EACA;AACF;","names":["superjson","nowIso","safeSerialize","asTokenCount","extractUsage","method","fn"]}
|