@bitfab/sdk 0.13.6 → 0.13.8

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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/version.generated.ts","../src/constants.ts","../src/errors.ts","../src/http.ts","../src/asyncStorage.ts","../src/replayContext.ts","../src/serialize.ts"],"sourcesContent":["/**\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.13.8\"\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 * 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 * 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\"\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// 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 await Promise.race([\n Promise.allSettled(Array.from(pendingTracePromises)),\n new Promise<void>((resolve) => setTimeout(resolve, timeoutMs)),\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 payload, handling circular references\n let body: string\n let serializationError: string | undefined\n try {\n body = JSON.stringify(payload)\n } catch (error) {\n serializationError =\n error instanceof Error ? error.message : String(error)\n // Create fallback payload with error info\n body = JSON.stringify({\n ...Object.fromEntries(\n Object.entries(payload).filter(\n ([, v]) => typeof v === \"string\" || typeof v === \"number\",\n ),\n ),\n rawSpan: {},\n errors: [\n { source: \"sdk\", step: \"json_serialize\", error: serializationError },\n ],\n })\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 */\n sendExternalTrace(payload: Record<string, unknown>): void {\n void 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,\n traceIds?: string[],\n codeChangeDescription?: string,\n codeChangeFiles?: CodeChangeFile[],\n includeDbBranchLease?: boolean,\n experimentGroupId?: string,\n ): Promise<StartReplayResponse> {\n const payload: Record<string, unknown> = { traceFunctionKey, limit }\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 // 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\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 * 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 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\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 * 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\"\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\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 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"],"mappings":"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","names":[]}
package/dist/index.cjs CHANGED
@@ -35,7 +35,7 @@ var __version__;
35
35
  var init_version_generated = __esm({
36
36
  "src/version.generated.ts"() {
37
37
  "use strict";
38
- __version__ = "0.13.6";
38
+ __version__ = "0.13.8";
39
39
  }
40
40
  });
41
41
 
@@ -142,7 +142,9 @@ var init_http = __esm({
142
142
  )
143
143
  ),
144
144
  rawSpan: {},
145
- errors: [{ step: "json_serialize", error: serializationError }]
145
+ errors: [
146
+ { source: "sdk", step: "json_serialize", error: serializationError }
147
+ ]
146
148
  });
147
149
  }
148
150
  try {
@@ -384,11 +386,11 @@ var init_http = __esm({
384
386
  { timeout: 9e4 }
385
387
  );
386
388
  }
387
- /** Release a previously-resolved DB branch lease. Idempotent server-side. */
388
- async releaseDbBranchLease(leaseId) {
389
+ /** Release a previously-resolved DB branch by deleting its Neon branch. Idempotent server-side. */
390
+ async releaseDbBranchLease(neonBranchId) {
389
391
  await this.request(
390
392
  "/api/sdk/replay/releaseDbBranchLease",
391
- { leaseId },
393
+ { neonBranchId },
392
394
  { timeout: 3e4 }
393
395
  );
394
396
  }
@@ -608,11 +610,11 @@ async function processItem(httpClient, serverItem, fn, testRunId, mockStrategy,
608
610
  } finally {
609
611
  if (lease) {
610
612
  try {
611
- await httpClient.releaseDbBranchLease(lease.leaseId);
613
+ await httpClient.releaseDbBranchLease(lease.neonBranchId);
612
614
  } catch (e) {
613
615
  try {
614
616
  console.warn(
615
- `Bitfab: failed to release DB branch lease ${lease.leaseId} (TTL janitor will catch it): ${e instanceof Error ? e.message : String(e)}`
617
+ `Bitfab: failed to release DB branch ${lease.neonBranchId} (TTL janitor will catch it): ${e instanceof Error ? e.message : String(e)}`
616
618
  );
617
619
  } catch {
618
620
  }
@@ -1498,16 +1500,7 @@ init_constants();
1498
1500
 
1499
1501
  // src/dbSnapshot.ts
1500
1502
  init_errors();
1501
- var SUPPORTED_PROVIDERS = [
1502
- "neon",
1503
- "ardent",
1504
- "dolt",
1505
- "gfs",
1506
- "mongodb-atlas",
1507
- "dynamodb",
1508
- "snowflake",
1509
- "bigquery"
1510
- ];
1503
+ var SUPPORTED_PROVIDERS = ["neon"];
1511
1504
  function validateDbSnapshotConfig(config) {
1512
1505
  if (!SUPPORTED_PROVIDERS.includes(config.provider)) {
1513
1506
  throw new BitfabError(
@@ -2034,14 +2027,6 @@ var ReplayEnvironment = class {
2034
2027
  get traceId() {
2035
2028
  return this.require().traceId;
2036
2029
  }
2037
- /**
2038
- * How the resolver pinned this branch.
2039
- * - "timestamp": snapshot at SDK wall clock; bounded by replication lag.
2040
- * - "lsn": customer LSN mapped to a replica snapshot (future).
2041
- */
2042
- get precision() {
2043
- return this.require().precision;
2044
- }
2045
2030
  /** True when read inside a replay item that has a resolved branch. */
2046
2031
  get active() {
2047
2032
  return this.read() !== null;
@@ -2065,8 +2050,7 @@ var ReplayEnvironment = class {
2065
2050
  expiresAt: lease.expiresAt,
2066
2051
  providerConsoleUrl: lease.providerConsoleUrl,
2067
2052
  readOnly: lease.readOnly,
2068
- traceId,
2069
- precision: lease.precision
2053
+ traceId
2070
2054
  };
2071
2055
  }
2072
2056
  require() {
@@ -2186,6 +2170,7 @@ var BitfabOpenAITracingProcessor = class {
2186
2170
  const jsonResult = span.toJSON();
2187
2171
  if (typeof jsonResult !== "object" || jsonResult === null) {
2188
2172
  errors.push({
2173
+ source: "sdk",
2189
2174
  step: "span.toJSON()",
2190
2175
  error: `Returned unexpected type: ${typeof jsonResult}`
2191
2176
  });
@@ -2195,6 +2180,7 @@ var BitfabOpenAITracingProcessor = class {
2195
2180
  }
2196
2181
  } catch (error) {
2197
2182
  errors.push({
2183
+ source: "sdk",
2198
2184
  step: "span.toJSON()",
2199
2185
  error: error instanceof Error ? error.message : String(error)
2200
2186
  });
@@ -2214,6 +2200,7 @@ var BitfabOpenAITracingProcessor = class {
2214
2200
  spanData.input = span.spanData?._input || [];
2215
2201
  } catch (error) {
2216
2202
  errors.push({
2203
+ source: "sdk",
2217
2204
  step: "access_input",
2218
2205
  error: error instanceof Error ? error.message : String(error)
2219
2206
  });
@@ -2222,6 +2209,7 @@ var BitfabOpenAITracingProcessor = class {
2222
2209
  spanData.response = span.spanData?._response || null;
2223
2210
  } catch (error) {
2224
2211
  errors.push({
2212
+ source: "sdk",
2225
2213
  step: "access_response",
2226
2214
  error: error instanceof Error ? error.message : String(error)
2227
2215
  });
@@ -2918,7 +2906,6 @@ var Bitfab = class {
2918
2906
  try {
2919
2907
  const endedAt = (/* @__PURE__ */ new Date()).toISOString();
2920
2908
  const replayCtx = getReplayContext();
2921
- const dbSnapshotRefForSpan = isRootSpan ? activeTraceStates.get(traceId)?.dbSnapshotRef : void 0;
2922
2909
  const spanPromise = self.sendWrapperSpan({
2923
2910
  ...baseSpanParams,
2924
2911
  ...params,
@@ -2928,9 +2915,6 @@ var Bitfab = class {
2928
2915
  ...replayCtx?.testRunId && { testRunId: replayCtx.testRunId },
2929
2916
  ...replayCtx?.inputSourceSpanId && {
2930
2917
  inputSourceSpanId: replayCtx.inputSourceSpanId
2931
- },
2932
- ...dbSnapshotRefForSpan && {
2933
- dbSnapshotRef: dbSnapshotRefForSpan
2934
2918
  }
2935
2919
  });
2936
2920
  if (isRootSpan) {
@@ -3154,14 +3138,14 @@ var Bitfab = class {
3154
3138
  ...params.functionName !== void 0 && {
3155
3139
  function_name: params.functionName
3156
3140
  },
3157
- ...params.error !== void 0 && { error: params.error },
3141
+ ...params.error !== void 0 && {
3142
+ error: params.error,
3143
+ error_source: "code"
3144
+ },
3158
3145
  ...params.contexts && params.contexts.length > 0 && {
3159
3146
  contexts: params.contexts
3160
3147
  },
3161
- ...params.prompt !== void 0 && { prompt: params.prompt },
3162
- ...params.dbSnapshotRef && {
3163
- db_snapshot_ref: params.dbSnapshotRef
3164
- }
3148
+ ...params.prompt !== void 0 && { prompt: params.prompt }
3165
3149
  }
3166
3150
  };
3167
3151
  if (params.parentSpanId) {