@bitfab/sdk 0.61.0 → 0.61.2

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.
Files changed (141) hide show
  1. package/README.md +8 -5
  2. package/dist/autoTrace.cjs +1 -1
  3. package/dist/autoTrace.cjs.map +1 -1
  4. package/dist/autoTrace.js +1 -1
  5. package/dist/chunk-6R33XLNY.js +28 -0
  6. package/dist/chunk-6R33XLNY.js.map +1 -0
  7. package/dist/{chunk-5DNB7EN7.js → chunk-BMJNDIVA.js} +2 -2
  8. package/dist/chunk-BMJNDIVA.js.map +1 -0
  9. package/dist/{chunk-5IQRMYJP.js → chunk-DSVQPSAL.js} +122 -52
  10. package/dist/chunk-DSVQPSAL.js.map +1 -0
  11. package/dist/{chunk-PURSV2TW.js → chunk-HNEKBDI7.js} +7 -7
  12. package/dist/{chunk-PURSV2TW.js.map → chunk-HNEKBDI7.js.map} +1 -1
  13. package/dist/{chunk-5BM2IXP6.js → chunk-IR5KCKHF.js} +42 -2
  14. package/dist/{chunk-5BM2IXP6.js.map → chunk-IR5KCKHF.js.map} +1 -1
  15. package/dist/chunk-OXFZJP4E.js +30 -0
  16. package/dist/chunk-OXFZJP4E.js.map +1 -0
  17. package/dist/chunk-PACLPKDH.js +513 -0
  18. package/dist/chunk-PACLPKDH.js.map +1 -0
  19. package/dist/{chunk-YELSIC3R.js → chunk-SJPMWVJ3.js} +42 -2
  20. package/dist/{chunk-YELSIC3R.js.map → chunk-SJPMWVJ3.js.map} +1 -1
  21. package/dist/{chunk-UFGNWMWI.js → chunk-X5DRPZJJ.js} +171 -48
  22. package/dist/chunk-X5DRPZJJ.js.map +1 -0
  23. package/dist/{http-34JZXPJP.js → http-OEABHRHY.js} +2 -2
  24. package/dist/{http-TMPQJHDB.js → http-RNI6PKQ3.js} +2 -2
  25. package/dist/index.cjs +212 -49
  26. package/dist/index.cjs.map +1 -1
  27. package/dist/index.d.cts +27 -1
  28. package/dist/index.d.ts +27 -1
  29. package/dist/index.js +4 -4
  30. package/dist/node.cjs +212 -49
  31. package/dist/node.cjs.map +1 -1
  32. package/dist/node.js +4 -4
  33. package/dist/{replay-HTRWQTOY.js → replay-3ERB6W6N.js} +3 -3
  34. package/dist/replayCli.js +4 -3
  35. package/dist/replayCli.js.map +1 -1
  36. package/dist/seedCli.js +2 -2
  37. package/dist/transform/babel.cjs +418 -0
  38. package/dist/transform/babel.cjs.map +1 -0
  39. package/dist/transform/babel.d.cts +27 -0
  40. package/dist/transform/babel.d.ts +27 -0
  41. package/dist/transform/babel.js +379 -0
  42. package/dist/transform/babel.js.map +1 -0
  43. package/dist/transform/bun.cjs +586 -0
  44. package/dist/transform/bun.cjs.map +1 -0
  45. package/dist/transform/bun.d.cts +12 -0
  46. package/dist/transform/bun.d.ts +12 -0
  47. package/dist/transform/bun.js +14 -0
  48. package/dist/transform/bun.js.map +1 -0
  49. package/dist/transform/esbuild.cjs +586 -0
  50. package/dist/transform/esbuild.cjs.map +1 -0
  51. package/dist/transform/esbuild.d.cts +12 -0
  52. package/dist/transform/esbuild.d.ts +12 -0
  53. package/dist/transform/esbuild.js +14 -0
  54. package/dist/transform/esbuild.js.map +1 -0
  55. package/dist/transform/loaderRuntime.cjs +627 -0
  56. package/dist/transform/loaderRuntime.cjs.map +1 -0
  57. package/dist/transform/loaderRuntime.d.cts +12 -0
  58. package/dist/transform/loaderRuntime.d.ts +12 -0
  59. package/dist/transform/loaderRuntime.js +93 -0
  60. package/dist/transform/loaderRuntime.js.map +1 -0
  61. package/dist/transform/nest.cjs +589 -0
  62. package/dist/transform/nest.cjs.map +1 -0
  63. package/dist/transform/nest.d.cts +16 -0
  64. package/dist/transform/nest.d.ts +16 -0
  65. package/dist/transform/nest.js +17 -0
  66. package/dist/transform/nest.js.map +1 -0
  67. package/dist/transform/next.cjs +641 -0
  68. package/dist/transform/next.cjs.map +1 -0
  69. package/dist/transform/next.d.cts +40 -0
  70. package/dist/transform/next.d.ts +40 -0
  71. package/dist/transform/next.js +69 -0
  72. package/dist/transform/next.js.map +1 -0
  73. package/dist/transform/nodeLoader.js +640 -0
  74. package/dist/transform/nodeLoader.js.map +1 -0
  75. package/dist/transform/register.js +5 -0
  76. package/dist/transform/register.js.map +1 -0
  77. package/dist/transform/rolldown.cjs +586 -0
  78. package/dist/transform/rolldown.cjs.map +1 -0
  79. package/dist/transform/rolldown.d.cts +12 -0
  80. package/dist/transform/rolldown.d.ts +12 -0
  81. package/dist/transform/rolldown.js +14 -0
  82. package/dist/transform/rolldown.js.map +1 -0
  83. package/dist/transform/rollup.cjs +586 -0
  84. package/dist/transform/rollup.cjs.map +1 -0
  85. package/dist/transform/rollup.d.cts +12 -0
  86. package/dist/transform/rollup.d.ts +12 -0
  87. package/dist/transform/rollup.js +14 -0
  88. package/dist/transform/rollup.js.map +1 -0
  89. package/dist/transform/rsbuild.cjs +586 -0
  90. package/dist/transform/rsbuild.cjs.map +1 -0
  91. package/dist/transform/rsbuild.d.cts +12 -0
  92. package/dist/transform/rsbuild.d.ts +12 -0
  93. package/dist/transform/rsbuild.js +14 -0
  94. package/dist/transform/rsbuild.js.map +1 -0
  95. package/dist/transform/rspack.cjs +586 -0
  96. package/dist/transform/rspack.cjs.map +1 -0
  97. package/dist/transform/rspack.d.cts +12 -0
  98. package/dist/transform/rspack.d.ts +12 -0
  99. package/dist/transform/rspack.js +14 -0
  100. package/dist/transform/rspack.js.map +1 -0
  101. package/dist/transform/swc.cjs +592 -0
  102. package/dist/transform/swc.cjs.map +1 -0
  103. package/dist/transform/swc.d.cts +32 -0
  104. package/dist/transform/swc.d.ts +32 -0
  105. package/dist/transform/swc.js +33 -0
  106. package/dist/transform/swc.js.map +1 -0
  107. package/dist/transform/typescript.cjs +566 -0
  108. package/dist/transform/typescript.cjs.map +1 -0
  109. package/dist/transform/typescript.d.cts +22 -0
  110. package/dist/transform/typescript.d.ts +22 -0
  111. package/dist/transform/typescript.js +10 -0
  112. package/dist/transform/typescript.js.map +1 -0
  113. package/dist/transform/unplugin.cjs +583 -0
  114. package/dist/transform/unplugin.cjs.map +1 -0
  115. package/dist/transform/unplugin.d.cts +6 -0
  116. package/dist/transform/unplugin.d.ts +6 -0
  117. package/dist/transform/unplugin.js +9 -0
  118. package/dist/transform/unplugin.js.map +1 -0
  119. package/dist/transform/vite.cjs +586 -0
  120. package/dist/transform/vite.cjs.map +1 -0
  121. package/dist/transform/vite.d.cts +15 -0
  122. package/dist/transform/vite.d.ts +15 -0
  123. package/dist/transform/vite.js +14 -0
  124. package/dist/transform/vite.js.map +1 -0
  125. package/dist/transform/webpack.cjs +586 -0
  126. package/dist/transform/webpack.cjs.map +1 -0
  127. package/dist/transform/webpack.d.cts +12 -0
  128. package/dist/transform/webpack.d.ts +12 -0
  129. package/dist/transform/webpack.js +14 -0
  130. package/dist/transform/webpack.js.map +1 -0
  131. package/dist/transformOptions-Df2_Chtc.d.cts +10 -0
  132. package/dist/transformOptions-Df2_Chtc.d.ts +10 -0
  133. package/package.json +167 -7
  134. package/transform-loader.cjs +19 -0
  135. package/transform-loader.d.cts +19 -0
  136. package/dist/chunk-5DNB7EN7.js.map +0 -1
  137. package/dist/chunk-5IQRMYJP.js.map +0 -1
  138. package/dist/chunk-UFGNWMWI.js.map +0 -1
  139. /package/dist/{http-34JZXPJP.js.map → http-OEABHRHY.js.map} +0 -0
  140. /package/dist/{http-TMPQJHDB.js.map → http-RNI6PKQ3.js.map} +0 -0
  141. /package/dist/{replay-HTRWQTOY.js.map → replay-3ERB6W6N.js.map} +0 -0
package/README.md CHANGED
@@ -85,21 +85,24 @@ pnpm validate
85
85
  ### Basic Installation
86
86
 
87
87
  ```bash
88
- npm install bitfab
88
+ npm install @bitfab/sdk
89
89
  # or
90
- pnpm add bitfab
90
+ pnpm add @bitfab/sdk
91
91
  # or
92
- yarn add bitfab
92
+ yarn add @bitfab/sdk
93
93
  ```
94
94
 
95
+ Automatic subtree transform adapters are included under
96
+ `@bitfab/sdk/transform/*`; no second package is required.
97
+
95
98
  ### With OpenAI Agents SDK Tracing
96
99
 
97
100
  If you want to use the OpenAI Agents SDK tracing integration:
98
101
 
99
102
  ```bash
100
- npm install bitfab @openai/agents
103
+ npm install @bitfab/sdk @openai/agents
101
104
  # or
102
- pnpm add bitfab @openai/agents
105
+ pnpm add @bitfab/sdk @openai/agents
103
106
  ```
104
107
 
105
108
  The `@openai/agents` package is an optional peer dependency - the SDK works fine without it unless you need tracing functionality.
@@ -175,7 +175,7 @@ function settleAutoTraceRoot(context) {
175
175
  }
176
176
  warnOnce(
177
177
  "auto-trace-transform-missing",
178
- `trace root "${context.traceFunctionKey}" recorded only its own span. No module in this build was compiled by @bitfab/transform, so calls beneath the root were not discovered. Install @bitfab/transform and add its adapter to the server build: ${SUBTREE_TRACING_DOCS_URL}`
178
+ `trace root "${context.traceFunctionKey}" recorded only its own span. No module in this build was compiled by @bitfab/sdk/transform, so calls beneath the root were not discovered. Add the SDK's transform adapter to the server build: ${SUBTREE_TRACING_DOCS_URL}`
179
179
  );
180
180
  }
181
181
  function runWithAutoTraceRootContext(context, spanStack, fn) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/autoTrace.ts","../src/asyncStorage.ts","../src/captureSuppression.ts","../src/warnOnce.ts"],"sourcesContent":["import {\n type AsyncLocalStorageLike,\n createAsyncLocalStorage,\n} from \"./asyncStorage.js\"\nimport { isCaptureSuppressed } from \"./captureSuppression.js\"\nimport { warnOnce } from \"./warnOnce.js\"\n\nexport interface AutoTraceFunctionDefinition {\n id: string\n name: string\n file: string\n line: number\n column: number\n async?: boolean\n wrapper?: boolean\n}\n\nexport interface AutoTraceNodeConfiguration {\n functionName: string\n name?: string\n type?: \"llm\" | \"agent\" | \"function\" | \"guardrail\" | \"handoff\" | \"custom\"\n capture: boolean\n experimentId?: string\n /** @deprecated Use experimentId. */\n testRunId?: string\n mockOnReplay?: boolean\n // biome-ignore lint/suspicious/noExplicitAny: node finalizers receive the configured function's result, whose type is owned by the caller\n finalize?: (result: any) => unknown | Promise<unknown>\n}\n\nexport interface NestedTraceLink {\n traceFunctionKey: string\n traceId?: string\n rootSpanId?: string\n}\n\nexport interface AutoTraceEntry {\n context: AutoTraceContext\n depth: number\n spanStack: unknown\n}\n\nexport interface AutoTraceContext {\n readonly traceFunctionKey: string\n invoke<T>(\n definition: AutoTraceFunctionDefinition,\n inputs: unknown[],\n fn: () => T,\n entry: AutoTraceEntry,\n nodeConfiguration?: AutoTraceNodeConfiguration,\n ): T\n invokeNestedRoot<T>(\n name: string,\n functionName: string,\n inputs: unknown[],\n fn: () => T,\n entry: AutoTraceEntry,\n link: NestedTraceLink | undefined,\n ): T\n}\n\ninterface AutoTraceScope {\n entries: readonly AutoTraceEntry[]\n nodeConfiguration?: AutoTraceNodeConfiguration\n}\n\ninterface AutoTraceState {\n storage: AsyncLocalStorageLike<AutoTraceScope> | null\n browserScope: AutoTraceScope | undefined\n // Older SDK copies read this field when sharing the process-wide V4 state.\n capturePolicies: WeakMap<object, Map<string, ReadonlySet<string>>>\n activeRoots: number\n}\n\ninterface AutoTraceGlobal {\n __bitfabAutoTraceStateV4?: AutoTraceState\n __bitfab_auto_trace_transformed_v1__?: boolean\n}\n\ninterface AutoTraceAsyncGenerator {\n next(value?: unknown): Promise<IteratorResult<unknown, unknown>>\n return(value?: unknown): Promise<IteratorResult<unknown, unknown>>\n throw(error?: unknown): Promise<IteratorResult<unknown, unknown>>\n [Symbol.asyncIterator](): AutoTraceAsyncGenerator\n}\n\nconst autoTraceGlobal = globalThis as unknown as AutoTraceGlobal\nconst autoTraceState: AutoTraceState =\n autoTraceGlobal.__bitfabAutoTraceStateV4 ?? {\n storage: null,\n browserScope: undefined,\n capturePolicies: new WeakMap(),\n activeRoots: 0,\n }\nautoTraceGlobal.__bitfabAutoTraceStateV4 = autoTraceState\n\nfunction initializeAutoTraceStorage(): void {\n autoTraceState.storage ??= createAsyncLocalStorage<AutoTraceScope>()\n}\n\nfunction runWithAutoTraceScope<T>(scope: AutoTraceScope, fn: () => T): T {\n initializeAutoTraceStorage()\n if (autoTraceState.storage) {\n return autoTraceState.storage.run(scope, fn)\n }\n\n const previous = autoTraceState.browserScope\n autoTraceState.browserScope = scope\n try {\n return fn()\n } finally {\n autoTraceState.browserScope = previous\n }\n}\n\nexport function currentAutoTraceEntries(): readonly AutoTraceEntry[] {\n return currentAutoTraceScope()?.entries ?? []\n}\n\nfunction replaceEntry(\n entries: readonly AutoTraceEntry[],\n previous: AutoTraceEntry,\n updated: AutoTraceEntry,\n): readonly AutoTraceEntry[] {\n return entries.map((entry) => (entry === previous ? updated : entry))\n}\n\nexport function runWithAutoTraceEntry<T>(\n previous: AutoTraceEntry,\n updated: AutoTraceEntry,\n fn: () => T,\n): T {\n const result = runWithAutoTraceScope(\n { entries: replaceEntry(currentAutoTraceEntries(), previous, updated) },\n fn,\n )\n if (isAutoTraceAsyncGenerator(result)) {\n return wrapAutoTraceEntryAsyncGenerator(previous, updated, result) as T\n }\n return result\n}\n\nfunction wrapAutoTraceEntryAsyncGenerator(\n previous: AutoTraceEntry,\n updated: AutoTraceEntry,\n source: AutoTraceAsyncGenerator,\n): AutoTraceAsyncGenerator {\n const step = (\n method: \"next\" | \"return\" | \"throw\",\n value?: unknown,\n ): Promise<IteratorResult<unknown, unknown>> =>\n runWithAutoTraceScope(\n { entries: replaceEntry(currentAutoTraceEntries(), previous, updated) },\n () => source[method](value),\n )\n const wrapped: AutoTraceAsyncGenerator = {\n next: (value) => step(\"next\", value),\n return: (value) => step(\"return\", value),\n throw: (error) => step(\"throw\", error),\n [Symbol.asyncIterator]: () => wrapped,\n }\n return wrapped\n}\n\nexport function clearAutoTraceNodeConfiguration<T>(fn: () => T): T {\n return runWithAutoTraceScope({ entries: currentAutoTraceEntries() }, fn)\n}\n\nexport function runWithAutoTraceNodeConfiguration<T>(\n nodeConfiguration: AutoTraceNodeConfiguration,\n fn: () => T,\n): T {\n const scope = currentAutoTraceScope()\n if (!scope || scope.entries.length === 0) {\n return fn()\n }\n\n const result = runWithAutoTraceScope({ ...scope, nodeConfiguration }, fn)\n if (isAutoTraceAsyncGenerator(result)) {\n return wrapAutoTraceNodeAsyncGenerator(nodeConfiguration, result) as T\n }\n return result\n}\n\nconst SUBTREE_TRACING_DOCS_URL =\n \"https://docs.bitfab.ai/typescript-sdk#experimental-subtree-tracing\"\n\nfunction noteTransformedModule(): void {\n autoTraceGlobal.__bitfab_auto_trace_transformed_v1__ = true\n}\n\nfunction transformInstalled(): boolean {\n return autoTraceGlobal.__bitfab_auto_trace_transformed_v1__ === true\n}\n\nfunction runsOnNode(): boolean {\n return typeof process !== \"undefined\" && Boolean(process.versions?.node)\n}\n\nfunction closeAutoTraceRoot(): void {\n autoTraceState.activeRoots -= 1\n}\n\nfunction settleAutoTraceRoot(context: AutoTraceContext): void {\n closeAutoTraceRoot()\n if (transformInstalled() || !runsOnNode()) {\n return\n }\n warnOnce(\n \"auto-trace-transform-missing\",\n `trace root \"${context.traceFunctionKey}\" recorded only its own span. ` +\n \"No module in this build was compiled by @bitfab/transform, so calls \" +\n \"beneath the root were not discovered. Install @bitfab/transform and \" +\n `add its adapter to the server build: ${SUBTREE_TRACING_DOCS_URL}`,\n )\n}\n\nexport function runWithAutoTraceRootContext<T>(\n context: AutoTraceContext,\n spanStack: unknown,\n fn: () => T,\n): T {\n autoTraceState.activeRoots += 1\n const entries = [\n ...currentAutoTraceEntries(),\n { context, depth: 0, spanStack },\n ]\n let result: T\n try {\n result = runWithAutoTraceScope({ entries }, fn)\n } catch (error) {\n settleAutoTraceRoot(context)\n throw error\n }\n\n if (isAutoTraceAsyncGenerator(result)) {\n closeAutoTraceRoot()\n return wrapAutoTraceAsyncGenerator(context, spanStack, result) as T\n }\n\n if (result instanceof Promise) {\n return result.finally(() => {\n settleAutoTraceRoot(context)\n }) as T\n }\n\n settleAutoTraceRoot(context)\n return result\n}\n\nexport function invokeThroughAutoTraceEntries<T>(\n entries: readonly AutoTraceEntry[],\n step: (entry: AutoTraceEntry, next: () => T) => T,\n fn: () => T,\n): T {\n let run = fn\n for (let index = entries.length - 1; index >= 0; index -= 1) {\n const entry = entries[index] as AutoTraceEntry\n const next = run\n run = () => step(entry, next)\n }\n return run()\n}\n\nfunction isAutoTraceAsyncGenerator(\n value: unknown,\n): value is AutoTraceAsyncGenerator {\n if (value === null || typeof value !== \"object\") {\n return false\n }\n const candidate = value as Record<PropertyKey, unknown>\n return (\n typeof candidate.next === \"function\" &&\n typeof candidate.return === \"function\" &&\n typeof candidate.throw === \"function\" &&\n typeof candidate[Symbol.asyncIterator] === \"function\"\n )\n}\n\nfunction wrapAutoTraceAsyncGenerator(\n context: AutoTraceContext,\n spanStack: unknown,\n source: AutoTraceAsyncGenerator,\n): AutoTraceAsyncGenerator {\n const step = (\n method: \"next\" | \"return\" | \"throw\",\n value?: unknown,\n ): Promise<IteratorResult<unknown, unknown>> =>\n runWithAutoTraceRootContext(context, spanStack, () => source[method](value))\n const wrapped: AutoTraceAsyncGenerator = {\n next: (value) => step(\"next\", value),\n return: (value) => step(\"return\", value),\n throw: (error) => step(\"throw\", error),\n [Symbol.asyncIterator]: () => wrapped,\n }\n return wrapped\n}\n\nfunction wrapAutoTraceNodeAsyncGenerator(\n nodeConfiguration: AutoTraceNodeConfiguration,\n source: AutoTraceAsyncGenerator,\n): AutoTraceAsyncGenerator {\n const step = (\n method: \"next\" | \"return\" | \"throw\",\n value?: unknown,\n ): Promise<IteratorResult<unknown, unknown>> =>\n runWithAutoTraceNodeConfiguration(nodeConfiguration, () =>\n source[method](value),\n )\n const wrapped: AutoTraceAsyncGenerator = {\n next: (value) => step(\"next\", value),\n return: (value) => step(\"return\", value),\n throw: (error) => step(\"throw\", error),\n [Symbol.asyncIterator]: () => wrapped,\n }\n return wrapped\n}\n\nfunction shareFinalize(\n configuration: AutoTraceNodeConfiguration,\n): AutoTraceNodeConfiguration {\n const finalize = configuration.finalize\n if (finalize === undefined) {\n return configuration\n }\n let settled: Promise<unknown> | undefined\n return {\n ...configuration,\n finalize: (result: unknown) => {\n settled ??= Promise.resolve().then(() => finalize(result))\n return settled\n },\n }\n}\n\nexport function __bitfabAutoSpan<T>(\n definition: AutoTraceFunctionDefinition,\n inputs: unknown[],\n fn: () => T,\n): T {\n noteTransformedModule()\n const scope = currentAutoTraceScope()\n if (!scope || scope.entries.length === 0 || isCaptureSuppressed()) {\n return fn()\n }\n const nameParts = definition.name.split(\".\")\n const simpleName = nameParts[nameParts.length - 1]\n const nodeConfiguration =\n simpleName === scope.nodeConfiguration?.functionName\n ? shareFinalize(scope.nodeConfiguration)\n : undefined\n return invokeThroughAutoTraceEntries(\n scope.entries,\n (entry, next) =>\n entry.context.invoke(definition, inputs, next, entry, nodeConfiguration),\n fn,\n )\n}\n\n/**\n * Preserve a function's original call arguments for transform cases where\n * parameter bindings discard them, such as destructured arrow parameters.\n *\n * This helper is internal transform/runtime protocol. The proxy preserves the\n * target's callability, arity, async identity, and non-constructibility while\n * only allocating a trace closure beneath an active automatic trace root.\n *\n * @experimental The automatic tracing protocol may change.\n */\nexport function __bitfabAutoWrap<T extends (...args: never[]) => unknown>(\n definition: AutoTraceFunctionDefinition,\n fn: T,\n): T {\n noteTransformedModule()\n if (fn.name === \"\") {\n const nameParts = definition.name.split(\".\")\n const inferredName = nameParts[nameParts.length - 1]\n if (inferredName !== undefined) {\n Object.defineProperty(fn, \"name\", {\n configurable: true,\n value: inferredName,\n })\n }\n }\n\n const target = fn as unknown as (...args: unknown[]) => unknown\n return new Proxy(target, {\n apply(callTarget, thisArg, args) {\n if (!__bitfabAutoTraceActive()) {\n return Reflect.apply(callTarget, thisArg, args)\n }\n return __bitfabAutoSpan(definition, args, () =>\n Reflect.apply(callTarget, thisArg, args),\n )\n },\n }) as unknown as T\n}\n\n/**\n * Return whether the current call is inside an automatic trace root.\n *\n * Build transforms use this before allocating function metadata, captured\n * inputs, or an invocation closure. It is internal transform/runtime protocol,\n * not a supported application API.\n *\n * @experimental The automatic tracing protocol may change.\n */\nexport function __bitfabAutoTraceActive(): boolean {\n if (autoTraceState.activeRoots === 0 || isCaptureSuppressed()) {\n return false\n }\n return currentAutoTraceEntries().length > 0\n}\n\nfunction currentAutoTraceScope(): AutoTraceScope | undefined {\n initializeAutoTraceStorage()\n return autoTraceState.storage?.getStore() ?? autoTraceState.browserScope\n}\n\nexport function _resetAutoTraceTransformDetection(): void {\n autoTraceGlobal.__bitfab_auto_trace_transformed_v1__ = undefined\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","interface CaptureSuppressionState {\n depth: number\n}\n\ninterface CaptureSuppressionGlobal {\n __bitfabCaptureSuppressionV1?: CaptureSuppressionState\n}\n\nconst suppressionGlobal = globalThis as unknown as CaptureSuppressionGlobal\nconst suppressionState: CaptureSuppressionState =\n suppressionGlobal.__bitfabCaptureSuppressionV1 ?? { depth: 0 }\nsuppressionGlobal.__bitfabCaptureSuppressionV1 = suppressionState\n\nexport function isCaptureSuppressed(): boolean {\n return suppressionState.depth > 0\n}\n\nexport function runWithCaptureSuppressed<T>(fn: () => T): T {\n suppressionState.depth += 1\n try {\n return fn()\n } finally {\n suppressionState.depth -= 1\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 warn(message: string): void {\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\nexport function warnOnce(key: string, message: string): void {\n if (warned.has(key)) {\n return\n }\n warned.add(key)\n warn(message)\n}\n\n/** Test-only: clear the dedup set so a warning can fire again. */\nexport function _resetWarnOnce(): void {\n warned.clear()\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/autoTrace.ts","../src/asyncStorage.ts","../src/captureSuppression.ts","../src/warnOnce.ts"],"sourcesContent":["import {\n type AsyncLocalStorageLike,\n createAsyncLocalStorage,\n} from \"./asyncStorage.js\"\nimport { isCaptureSuppressed } from \"./captureSuppression.js\"\nimport { warnOnce } from \"./warnOnce.js\"\n\nexport interface AutoTraceFunctionDefinition {\n id: string\n name: string\n file: string\n line: number\n column: number\n async?: boolean\n wrapper?: boolean\n}\n\nexport interface AutoTraceNodeConfiguration {\n functionName: string\n name?: string\n type?: \"llm\" | \"agent\" | \"function\" | \"guardrail\" | \"handoff\" | \"custom\"\n capture: boolean\n experimentId?: string\n /** @deprecated Use experimentId. */\n testRunId?: string\n mockOnReplay?: boolean\n // biome-ignore lint/suspicious/noExplicitAny: node finalizers receive the configured function's result, whose type is owned by the caller\n finalize?: (result: any) => unknown | Promise<unknown>\n}\n\nexport interface NestedTraceLink {\n traceFunctionKey: string\n traceId?: string\n rootSpanId?: string\n}\n\nexport interface AutoTraceEntry {\n context: AutoTraceContext\n depth: number\n spanStack: unknown\n}\n\nexport interface AutoTraceContext {\n readonly traceFunctionKey: string\n invoke<T>(\n definition: AutoTraceFunctionDefinition,\n inputs: unknown[],\n fn: () => T,\n entry: AutoTraceEntry,\n nodeConfiguration?: AutoTraceNodeConfiguration,\n ): T\n invokeNestedRoot<T>(\n name: string,\n functionName: string,\n inputs: unknown[],\n fn: () => T,\n entry: AutoTraceEntry,\n link: NestedTraceLink | undefined,\n ): T\n}\n\ninterface AutoTraceScope {\n entries: readonly AutoTraceEntry[]\n nodeConfiguration?: AutoTraceNodeConfiguration\n}\n\ninterface AutoTraceState {\n storage: AsyncLocalStorageLike<AutoTraceScope> | null\n browserScope: AutoTraceScope | undefined\n // Older SDK copies read this field when sharing the process-wide V4 state.\n capturePolicies: WeakMap<object, Map<string, ReadonlySet<string>>>\n activeRoots: number\n}\n\ninterface AutoTraceGlobal {\n __bitfabAutoTraceStateV4?: AutoTraceState\n __bitfab_auto_trace_transformed_v1__?: boolean\n}\n\ninterface AutoTraceAsyncGenerator {\n next(value?: unknown): Promise<IteratorResult<unknown, unknown>>\n return(value?: unknown): Promise<IteratorResult<unknown, unknown>>\n throw(error?: unknown): Promise<IteratorResult<unknown, unknown>>\n [Symbol.asyncIterator](): AutoTraceAsyncGenerator\n}\n\nconst autoTraceGlobal = globalThis as unknown as AutoTraceGlobal\nconst autoTraceState: AutoTraceState =\n autoTraceGlobal.__bitfabAutoTraceStateV4 ?? {\n storage: null,\n browserScope: undefined,\n capturePolicies: new WeakMap(),\n activeRoots: 0,\n }\nautoTraceGlobal.__bitfabAutoTraceStateV4 = autoTraceState\n\nfunction initializeAutoTraceStorage(): void {\n autoTraceState.storage ??= createAsyncLocalStorage<AutoTraceScope>()\n}\n\nfunction runWithAutoTraceScope<T>(scope: AutoTraceScope, fn: () => T): T {\n initializeAutoTraceStorage()\n if (autoTraceState.storage) {\n return autoTraceState.storage.run(scope, fn)\n }\n\n const previous = autoTraceState.browserScope\n autoTraceState.browserScope = scope\n try {\n return fn()\n } finally {\n autoTraceState.browserScope = previous\n }\n}\n\nexport function currentAutoTraceEntries(): readonly AutoTraceEntry[] {\n return currentAutoTraceScope()?.entries ?? []\n}\n\nfunction replaceEntry(\n entries: readonly AutoTraceEntry[],\n previous: AutoTraceEntry,\n updated: AutoTraceEntry,\n): readonly AutoTraceEntry[] {\n return entries.map((entry) => (entry === previous ? updated : entry))\n}\n\nexport function runWithAutoTraceEntry<T>(\n previous: AutoTraceEntry,\n updated: AutoTraceEntry,\n fn: () => T,\n): T {\n const result = runWithAutoTraceScope(\n { entries: replaceEntry(currentAutoTraceEntries(), previous, updated) },\n fn,\n )\n if (isAutoTraceAsyncGenerator(result)) {\n return wrapAutoTraceEntryAsyncGenerator(previous, updated, result) as T\n }\n return result\n}\n\nfunction wrapAutoTraceEntryAsyncGenerator(\n previous: AutoTraceEntry,\n updated: AutoTraceEntry,\n source: AutoTraceAsyncGenerator,\n): AutoTraceAsyncGenerator {\n const step = (\n method: \"next\" | \"return\" | \"throw\",\n value?: unknown,\n ): Promise<IteratorResult<unknown, unknown>> =>\n runWithAutoTraceScope(\n { entries: replaceEntry(currentAutoTraceEntries(), previous, updated) },\n () => source[method](value),\n )\n const wrapped: AutoTraceAsyncGenerator = {\n next: (value) => step(\"next\", value),\n return: (value) => step(\"return\", value),\n throw: (error) => step(\"throw\", error),\n [Symbol.asyncIterator]: () => wrapped,\n }\n return wrapped\n}\n\nexport function clearAutoTraceNodeConfiguration<T>(fn: () => T): T {\n return runWithAutoTraceScope({ entries: currentAutoTraceEntries() }, fn)\n}\n\nexport function runWithAutoTraceNodeConfiguration<T>(\n nodeConfiguration: AutoTraceNodeConfiguration,\n fn: () => T,\n): T {\n const scope = currentAutoTraceScope()\n if (!scope || scope.entries.length === 0) {\n return fn()\n }\n\n const result = runWithAutoTraceScope({ ...scope, nodeConfiguration }, fn)\n if (isAutoTraceAsyncGenerator(result)) {\n return wrapAutoTraceNodeAsyncGenerator(nodeConfiguration, result) as T\n }\n return result\n}\n\nconst SUBTREE_TRACING_DOCS_URL =\n \"https://docs.bitfab.ai/typescript-sdk#experimental-subtree-tracing\"\n\nfunction noteTransformedModule(): void {\n autoTraceGlobal.__bitfab_auto_trace_transformed_v1__ = true\n}\n\nfunction transformInstalled(): boolean {\n return autoTraceGlobal.__bitfab_auto_trace_transformed_v1__ === true\n}\n\nfunction runsOnNode(): boolean {\n return typeof process !== \"undefined\" && Boolean(process.versions?.node)\n}\n\nfunction closeAutoTraceRoot(): void {\n autoTraceState.activeRoots -= 1\n}\n\nfunction settleAutoTraceRoot(context: AutoTraceContext): void {\n closeAutoTraceRoot()\n if (transformInstalled() || !runsOnNode()) {\n return\n }\n warnOnce(\n \"auto-trace-transform-missing\",\n `trace root \"${context.traceFunctionKey}\" recorded only its own span. ` +\n \"No module in this build was compiled by @bitfab/sdk/transform, so calls \" +\n \"beneath the root were not discovered. Add the SDK's transform adapter \" +\n `to the server build: ${SUBTREE_TRACING_DOCS_URL}`,\n )\n}\n\nexport function runWithAutoTraceRootContext<T>(\n context: AutoTraceContext,\n spanStack: unknown,\n fn: () => T,\n): T {\n autoTraceState.activeRoots += 1\n const entries = [\n ...currentAutoTraceEntries(),\n { context, depth: 0, spanStack },\n ]\n let result: T\n try {\n result = runWithAutoTraceScope({ entries }, fn)\n } catch (error) {\n settleAutoTraceRoot(context)\n throw error\n }\n\n if (isAutoTraceAsyncGenerator(result)) {\n closeAutoTraceRoot()\n return wrapAutoTraceAsyncGenerator(context, spanStack, result) as T\n }\n\n if (result instanceof Promise) {\n return result.finally(() => {\n settleAutoTraceRoot(context)\n }) as T\n }\n\n settleAutoTraceRoot(context)\n return result\n}\n\nexport function invokeThroughAutoTraceEntries<T>(\n entries: readonly AutoTraceEntry[],\n step: (entry: AutoTraceEntry, next: () => T) => T,\n fn: () => T,\n): T {\n let run = fn\n for (let index = entries.length - 1; index >= 0; index -= 1) {\n const entry = entries[index] as AutoTraceEntry\n const next = run\n run = () => step(entry, next)\n }\n return run()\n}\n\nfunction isAutoTraceAsyncGenerator(\n value: unknown,\n): value is AutoTraceAsyncGenerator {\n if (value === null || typeof value !== \"object\") {\n return false\n }\n const candidate = value as Record<PropertyKey, unknown>\n return (\n typeof candidate.next === \"function\" &&\n typeof candidate.return === \"function\" &&\n typeof candidate.throw === \"function\" &&\n typeof candidate[Symbol.asyncIterator] === \"function\"\n )\n}\n\nfunction wrapAutoTraceAsyncGenerator(\n context: AutoTraceContext,\n spanStack: unknown,\n source: AutoTraceAsyncGenerator,\n): AutoTraceAsyncGenerator {\n const step = (\n method: \"next\" | \"return\" | \"throw\",\n value?: unknown,\n ): Promise<IteratorResult<unknown, unknown>> =>\n runWithAutoTraceRootContext(context, spanStack, () => source[method](value))\n const wrapped: AutoTraceAsyncGenerator = {\n next: (value) => step(\"next\", value),\n return: (value) => step(\"return\", value),\n throw: (error) => step(\"throw\", error),\n [Symbol.asyncIterator]: () => wrapped,\n }\n return wrapped\n}\n\nfunction wrapAutoTraceNodeAsyncGenerator(\n nodeConfiguration: AutoTraceNodeConfiguration,\n source: AutoTraceAsyncGenerator,\n): AutoTraceAsyncGenerator {\n const step = (\n method: \"next\" | \"return\" | \"throw\",\n value?: unknown,\n ): Promise<IteratorResult<unknown, unknown>> =>\n runWithAutoTraceNodeConfiguration(nodeConfiguration, () =>\n source[method](value),\n )\n const wrapped: AutoTraceAsyncGenerator = {\n next: (value) => step(\"next\", value),\n return: (value) => step(\"return\", value),\n throw: (error) => step(\"throw\", error),\n [Symbol.asyncIterator]: () => wrapped,\n }\n return wrapped\n}\n\nfunction shareFinalize(\n configuration: AutoTraceNodeConfiguration,\n): AutoTraceNodeConfiguration {\n const finalize = configuration.finalize\n if (finalize === undefined) {\n return configuration\n }\n let settled: Promise<unknown> | undefined\n return {\n ...configuration,\n finalize: (result: unknown) => {\n settled ??= Promise.resolve().then(() => finalize(result))\n return settled\n },\n }\n}\n\nexport function __bitfabAutoSpan<T>(\n definition: AutoTraceFunctionDefinition,\n inputs: unknown[],\n fn: () => T,\n): T {\n noteTransformedModule()\n const scope = currentAutoTraceScope()\n if (!scope || scope.entries.length === 0 || isCaptureSuppressed()) {\n return fn()\n }\n const nameParts = definition.name.split(\".\")\n const simpleName = nameParts[nameParts.length - 1]\n const nodeConfiguration =\n simpleName === scope.nodeConfiguration?.functionName\n ? shareFinalize(scope.nodeConfiguration)\n : undefined\n return invokeThroughAutoTraceEntries(\n scope.entries,\n (entry, next) =>\n entry.context.invoke(definition, inputs, next, entry, nodeConfiguration),\n fn,\n )\n}\n\n/**\n * Preserve a function's original call arguments for transform cases where\n * parameter bindings discard them, such as destructured arrow parameters.\n *\n * This helper is internal transform/runtime protocol. The proxy preserves the\n * target's callability, arity, async identity, and non-constructibility while\n * only allocating a trace closure beneath an active automatic trace root.\n *\n * @experimental The automatic tracing protocol may change.\n */\nexport function __bitfabAutoWrap<T extends (...args: never[]) => unknown>(\n definition: AutoTraceFunctionDefinition,\n fn: T,\n): T {\n noteTransformedModule()\n if (fn.name === \"\") {\n const nameParts = definition.name.split(\".\")\n const inferredName = nameParts[nameParts.length - 1]\n if (inferredName !== undefined) {\n Object.defineProperty(fn, \"name\", {\n configurable: true,\n value: inferredName,\n })\n }\n }\n\n const target = fn as unknown as (...args: unknown[]) => unknown\n return new Proxy(target, {\n apply(callTarget, thisArg, args) {\n if (!__bitfabAutoTraceActive()) {\n return Reflect.apply(callTarget, thisArg, args)\n }\n return __bitfabAutoSpan(definition, args, () =>\n Reflect.apply(callTarget, thisArg, args),\n )\n },\n }) as unknown as T\n}\n\n/**\n * Return whether the current call is inside an automatic trace root.\n *\n * Build transforms use this before allocating function metadata, captured\n * inputs, or an invocation closure. It is internal transform/runtime protocol,\n * not a supported application API.\n *\n * @experimental The automatic tracing protocol may change.\n */\nexport function __bitfabAutoTraceActive(): boolean {\n if (autoTraceState.activeRoots === 0 || isCaptureSuppressed()) {\n return false\n }\n return currentAutoTraceEntries().length > 0\n}\n\nfunction currentAutoTraceScope(): AutoTraceScope | undefined {\n initializeAutoTraceStorage()\n return autoTraceState.storage?.getStore() ?? autoTraceState.browserScope\n}\n\nexport function _resetAutoTraceTransformDetection(): void {\n autoTraceGlobal.__bitfab_auto_trace_transformed_v1__ = undefined\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","interface CaptureSuppressionState {\n depth: number\n}\n\ninterface CaptureSuppressionGlobal {\n __bitfabCaptureSuppressionV1?: CaptureSuppressionState\n}\n\nconst suppressionGlobal = globalThis as unknown as CaptureSuppressionGlobal\nconst suppressionState: CaptureSuppressionState =\n suppressionGlobal.__bitfabCaptureSuppressionV1 ?? { depth: 0 }\nsuppressionGlobal.__bitfabCaptureSuppressionV1 = suppressionState\n\nexport function isCaptureSuppressed(): boolean {\n return suppressionState.depth > 0\n}\n\nexport function runWithCaptureSuppressed<T>(fn: () => T): T {\n suppressionState.depth += 1\n try {\n return fn()\n } finally {\n suppressionState.depth -= 1\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 warn(message: string): void {\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\nexport function warnOnce(key: string, message: string): void {\n if (warned.has(key)) {\n return\n }\n warned.add(key)\n warn(message)\n}\n\n/** Test-only: clear the dedup set so a warning can fire again. */\nexport function _resetWarnOnce(): void {\n warned.clear()\n}\n"],"mappings":"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","names":[]}
package/dist/autoTrace.js CHANGED
@@ -9,7 +9,7 @@ import {
9
9
  runWithAutoTraceEntry,
10
10
  runWithAutoTraceNodeConfiguration,
11
11
  runWithAutoTraceRootContext
12
- } from "./chunk-5DNB7EN7.js";
12
+ } from "./chunk-BMJNDIVA.js";
13
13
  import "./chunk-BAOIRE5T.js";
14
14
  export {
15
15
  __bitfabAutoSpan,
@@ -0,0 +1,28 @@
1
+ // ../bitfab-typescript-transform/src/transformOptions.ts
2
+ var AUTO_TRACE_FUNCTION_ID_VERSION = "ts-auto-v1";
3
+ var AUTO_TRACE_TRANSFORM_MARKER = "__bitfab_auto_trace_transformed_v1__";
4
+ function autoTraceFunctionId(file, name) {
5
+ return `${AUTO_TRACE_FUNCTION_ID_VERSION}:${file}#${name}`;
6
+ }
7
+ function shouldTransformBitfabFile(filename, options) {
8
+ if (!filename) {
9
+ return false;
10
+ }
11
+ if (options.include && !options.include(filename)) {
12
+ return false;
13
+ }
14
+ const normalized = filename.replace(/\\/g, "/").split(/[?#]/, 1)[0] ?? "";
15
+ const normalizedCwd = options.cwd?.replace(/\\/g, "/").replace(/\/$/, "");
16
+ const isAbsolute = normalized.startsWith("/") || /^[A-Za-z]:\//.test(normalized);
17
+ if (normalizedCwd && isAbsolute && normalized !== normalizedCwd && !normalized.startsWith(`${normalizedCwd}/`)) {
18
+ return false;
19
+ }
20
+ return !normalized.includes("/node_modules/") && !normalized.endsWith(".d.ts") && /\.[cm]?[jt]sx?$/.test(normalized);
21
+ }
22
+
23
+ export {
24
+ AUTO_TRACE_TRANSFORM_MARKER,
25
+ autoTraceFunctionId,
26
+ shouldTransformBitfabFile
27
+ };
28
+ //# sourceMappingURL=chunk-6R33XLNY.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../bitfab-typescript-transform/src/transformOptions.ts"],"sourcesContent":["export interface BitfabTransformOptions {\n /** Module that exports the automatic span runtime. */\n runtimeModule?: string\n /** Working directory removed from generated function IDs. */\n cwd?: string\n /** Return false to leave a file unchanged. */\n include?: (filename: string) => boolean\n}\n\nconst AUTO_TRACE_FUNCTION_ID_VERSION = \"ts-auto-v1\"\nexport const AUTO_TRACE_TRANSFORM_MARKER =\n \"__bitfab_auto_trace_transformed_v1__\"\n\nexport function autoTraceFunctionId(file: string, name: string): string {\n return `${AUTO_TRACE_FUNCTION_ID_VERSION}:${file}#${name}`\n}\n\nexport function shouldTransformBitfabFile(\n filename: string,\n options: BitfabTransformOptions,\n): boolean {\n if (!filename) {\n return false\n }\n if (options.include && !options.include(filename)) {\n return false\n }\n\n const normalized = filename.replace(/\\\\/g, \"/\").split(/[?#]/, 1)[0] ?? \"\"\n const normalizedCwd = options.cwd?.replace(/\\\\/g, \"/\").replace(/\\/$/, \"\")\n const isAbsolute =\n normalized.startsWith(\"/\") || /^[A-Za-z]:\\//.test(normalized)\n if (\n normalizedCwd &&\n isAbsolute &&\n normalized !== normalizedCwd &&\n !normalized.startsWith(`${normalizedCwd}/`)\n ) {\n return false\n }\n return (\n !normalized.includes(\"/node_modules/\") &&\n !normalized.endsWith(\".d.ts\") &&\n /\\.[cm]?[jt]sx?$/.test(normalized)\n )\n}\n"],"mappings":";AASA,IAAM,iCAAiC;AAChC,IAAM,8BACX;AAEK,SAAS,oBAAoB,MAAc,MAAsB;AACtE,SAAO,GAAG,8BAA8B,IAAI,IAAI,IAAI,IAAI;AAC1D;AAEO,SAAS,0BACd,UACA,SACS;AACT,MAAI,CAAC,UAAU;AACb,WAAO;AAAA,EACT;AACA,MAAI,QAAQ,WAAW,CAAC,QAAQ,QAAQ,QAAQ,GAAG;AACjD,WAAO;AAAA,EACT;AAEA,QAAM,aAAa,SAAS,QAAQ,OAAO,GAAG,EAAE,MAAM,QAAQ,CAAC,EAAE,CAAC,KAAK;AACvE,QAAM,gBAAgB,QAAQ,KAAK,QAAQ,OAAO,GAAG,EAAE,QAAQ,OAAO,EAAE;AACxE,QAAM,aACJ,WAAW,WAAW,GAAG,KAAK,eAAe,KAAK,UAAU;AAC9D,MACE,iBACA,cACA,eAAe,iBACf,CAAC,WAAW,WAAW,GAAG,aAAa,GAAG,GAC1C;AACA,WAAO;AAAA,EACT;AACA,SACE,CAAC,WAAW,SAAS,gBAAgB,KACrC,CAAC,WAAW,SAAS,OAAO,KAC5B,kBAAkB,KAAK,UAAU;AAErC;","names":[]}
@@ -92,7 +92,7 @@ function settleAutoTraceRoot(context) {
92
92
  }
93
93
  warnOnce(
94
94
  "auto-trace-transform-missing",
95
- `trace root "${context.traceFunctionKey}" recorded only its own span. No module in this build was compiled by @bitfab/transform, so calls beneath the root were not discovered. Install @bitfab/transform and add its adapter to the server build: ${SUBTREE_TRACING_DOCS_URL}`
95
+ `trace root "${context.traceFunctionKey}" recorded only its own span. No module in this build was compiled by @bitfab/sdk/transform, so calls beneath the root were not discovered. Add the SDK's transform adapter to the server build: ${SUBTREE_TRACING_DOCS_URL}`
96
96
  );
97
97
  }
98
98
  function runWithAutoTraceRootContext(context, spanStack, fn) {
@@ -240,4 +240,4 @@ export {
240
240
  __bitfabAutoTraceActive,
241
241
  _resetAutoTraceTransformDetection
242
242
  };
243
- //# sourceMappingURL=chunk-5DNB7EN7.js.map
243
+ //# sourceMappingURL=chunk-BMJNDIVA.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/autoTrace.ts"],"sourcesContent":["import {\n type AsyncLocalStorageLike,\n createAsyncLocalStorage,\n} from \"./asyncStorage.js\"\nimport { isCaptureSuppressed } from \"./captureSuppression.js\"\nimport { warnOnce } from \"./warnOnce.js\"\n\nexport interface AutoTraceFunctionDefinition {\n id: string\n name: string\n file: string\n line: number\n column: number\n async?: boolean\n wrapper?: boolean\n}\n\nexport interface AutoTraceNodeConfiguration {\n functionName: string\n name?: string\n type?: \"llm\" | \"agent\" | \"function\" | \"guardrail\" | \"handoff\" | \"custom\"\n capture: boolean\n experimentId?: string\n /** @deprecated Use experimentId. */\n testRunId?: string\n mockOnReplay?: boolean\n // biome-ignore lint/suspicious/noExplicitAny: node finalizers receive the configured function's result, whose type is owned by the caller\n finalize?: (result: any) => unknown | Promise<unknown>\n}\n\nexport interface NestedTraceLink {\n traceFunctionKey: string\n traceId?: string\n rootSpanId?: string\n}\n\nexport interface AutoTraceEntry {\n context: AutoTraceContext\n depth: number\n spanStack: unknown\n}\n\nexport interface AutoTraceContext {\n readonly traceFunctionKey: string\n invoke<T>(\n definition: AutoTraceFunctionDefinition,\n inputs: unknown[],\n fn: () => T,\n entry: AutoTraceEntry,\n nodeConfiguration?: AutoTraceNodeConfiguration,\n ): T\n invokeNestedRoot<T>(\n name: string,\n functionName: string,\n inputs: unknown[],\n fn: () => T,\n entry: AutoTraceEntry,\n link: NestedTraceLink | undefined,\n ): T\n}\n\ninterface AutoTraceScope {\n entries: readonly AutoTraceEntry[]\n nodeConfiguration?: AutoTraceNodeConfiguration\n}\n\ninterface AutoTraceState {\n storage: AsyncLocalStorageLike<AutoTraceScope> | null\n browserScope: AutoTraceScope | undefined\n // Older SDK copies read this field when sharing the process-wide V4 state.\n capturePolicies: WeakMap<object, Map<string, ReadonlySet<string>>>\n activeRoots: number\n}\n\ninterface AutoTraceGlobal {\n __bitfabAutoTraceStateV4?: AutoTraceState\n __bitfab_auto_trace_transformed_v1__?: boolean\n}\n\ninterface AutoTraceAsyncGenerator {\n next(value?: unknown): Promise<IteratorResult<unknown, unknown>>\n return(value?: unknown): Promise<IteratorResult<unknown, unknown>>\n throw(error?: unknown): Promise<IteratorResult<unknown, unknown>>\n [Symbol.asyncIterator](): AutoTraceAsyncGenerator\n}\n\nconst autoTraceGlobal = globalThis as unknown as AutoTraceGlobal\nconst autoTraceState: AutoTraceState =\n autoTraceGlobal.__bitfabAutoTraceStateV4 ?? {\n storage: null,\n browserScope: undefined,\n capturePolicies: new WeakMap(),\n activeRoots: 0,\n }\nautoTraceGlobal.__bitfabAutoTraceStateV4 = autoTraceState\n\nfunction initializeAutoTraceStorage(): void {\n autoTraceState.storage ??= createAsyncLocalStorage<AutoTraceScope>()\n}\n\nfunction runWithAutoTraceScope<T>(scope: AutoTraceScope, fn: () => T): T {\n initializeAutoTraceStorage()\n if (autoTraceState.storage) {\n return autoTraceState.storage.run(scope, fn)\n }\n\n const previous = autoTraceState.browserScope\n autoTraceState.browserScope = scope\n try {\n return fn()\n } finally {\n autoTraceState.browserScope = previous\n }\n}\n\nexport function currentAutoTraceEntries(): readonly AutoTraceEntry[] {\n return currentAutoTraceScope()?.entries ?? []\n}\n\nfunction replaceEntry(\n entries: readonly AutoTraceEntry[],\n previous: AutoTraceEntry,\n updated: AutoTraceEntry,\n): readonly AutoTraceEntry[] {\n return entries.map((entry) => (entry === previous ? updated : entry))\n}\n\nexport function runWithAutoTraceEntry<T>(\n previous: AutoTraceEntry,\n updated: AutoTraceEntry,\n fn: () => T,\n): T {\n const result = runWithAutoTraceScope(\n { entries: replaceEntry(currentAutoTraceEntries(), previous, updated) },\n fn,\n )\n if (isAutoTraceAsyncGenerator(result)) {\n return wrapAutoTraceEntryAsyncGenerator(previous, updated, result) as T\n }\n return result\n}\n\nfunction wrapAutoTraceEntryAsyncGenerator(\n previous: AutoTraceEntry,\n updated: AutoTraceEntry,\n source: AutoTraceAsyncGenerator,\n): AutoTraceAsyncGenerator {\n const step = (\n method: \"next\" | \"return\" | \"throw\",\n value?: unknown,\n ): Promise<IteratorResult<unknown, unknown>> =>\n runWithAutoTraceScope(\n { entries: replaceEntry(currentAutoTraceEntries(), previous, updated) },\n () => source[method](value),\n )\n const wrapped: AutoTraceAsyncGenerator = {\n next: (value) => step(\"next\", value),\n return: (value) => step(\"return\", value),\n throw: (error) => step(\"throw\", error),\n [Symbol.asyncIterator]: () => wrapped,\n }\n return wrapped\n}\n\nexport function clearAutoTraceNodeConfiguration<T>(fn: () => T): T {\n return runWithAutoTraceScope({ entries: currentAutoTraceEntries() }, fn)\n}\n\nexport function runWithAutoTraceNodeConfiguration<T>(\n nodeConfiguration: AutoTraceNodeConfiguration,\n fn: () => T,\n): T {\n const scope = currentAutoTraceScope()\n if (!scope || scope.entries.length === 0) {\n return fn()\n }\n\n const result = runWithAutoTraceScope({ ...scope, nodeConfiguration }, fn)\n if (isAutoTraceAsyncGenerator(result)) {\n return wrapAutoTraceNodeAsyncGenerator(nodeConfiguration, result) as T\n }\n return result\n}\n\nconst SUBTREE_TRACING_DOCS_URL =\n \"https://docs.bitfab.ai/typescript-sdk#experimental-subtree-tracing\"\n\nfunction noteTransformedModule(): void {\n autoTraceGlobal.__bitfab_auto_trace_transformed_v1__ = true\n}\n\nfunction transformInstalled(): boolean {\n return autoTraceGlobal.__bitfab_auto_trace_transformed_v1__ === true\n}\n\nfunction runsOnNode(): boolean {\n return typeof process !== \"undefined\" && Boolean(process.versions?.node)\n}\n\nfunction closeAutoTraceRoot(): void {\n autoTraceState.activeRoots -= 1\n}\n\nfunction settleAutoTraceRoot(context: AutoTraceContext): void {\n closeAutoTraceRoot()\n if (transformInstalled() || !runsOnNode()) {\n return\n }\n warnOnce(\n \"auto-trace-transform-missing\",\n `trace root \"${context.traceFunctionKey}\" recorded only its own span. ` +\n \"No module in this build was compiled by @bitfab/sdk/transform, so calls \" +\n \"beneath the root were not discovered. Add the SDK's transform adapter \" +\n `to the server build: ${SUBTREE_TRACING_DOCS_URL}`,\n )\n}\n\nexport function runWithAutoTraceRootContext<T>(\n context: AutoTraceContext,\n spanStack: unknown,\n fn: () => T,\n): T {\n autoTraceState.activeRoots += 1\n const entries = [\n ...currentAutoTraceEntries(),\n { context, depth: 0, spanStack },\n ]\n let result: T\n try {\n result = runWithAutoTraceScope({ entries }, fn)\n } catch (error) {\n settleAutoTraceRoot(context)\n throw error\n }\n\n if (isAutoTraceAsyncGenerator(result)) {\n closeAutoTraceRoot()\n return wrapAutoTraceAsyncGenerator(context, spanStack, result) as T\n }\n\n if (result instanceof Promise) {\n return result.finally(() => {\n settleAutoTraceRoot(context)\n }) as T\n }\n\n settleAutoTraceRoot(context)\n return result\n}\n\nexport function invokeThroughAutoTraceEntries<T>(\n entries: readonly AutoTraceEntry[],\n step: (entry: AutoTraceEntry, next: () => T) => T,\n fn: () => T,\n): T {\n let run = fn\n for (let index = entries.length - 1; index >= 0; index -= 1) {\n const entry = entries[index] as AutoTraceEntry\n const next = run\n run = () => step(entry, next)\n }\n return run()\n}\n\nfunction isAutoTraceAsyncGenerator(\n value: unknown,\n): value is AutoTraceAsyncGenerator {\n if (value === null || typeof value !== \"object\") {\n return false\n }\n const candidate = value as Record<PropertyKey, unknown>\n return (\n typeof candidate.next === \"function\" &&\n typeof candidate.return === \"function\" &&\n typeof candidate.throw === \"function\" &&\n typeof candidate[Symbol.asyncIterator] === \"function\"\n )\n}\n\nfunction wrapAutoTraceAsyncGenerator(\n context: AutoTraceContext,\n spanStack: unknown,\n source: AutoTraceAsyncGenerator,\n): AutoTraceAsyncGenerator {\n const step = (\n method: \"next\" | \"return\" | \"throw\",\n value?: unknown,\n ): Promise<IteratorResult<unknown, unknown>> =>\n runWithAutoTraceRootContext(context, spanStack, () => source[method](value))\n const wrapped: AutoTraceAsyncGenerator = {\n next: (value) => step(\"next\", value),\n return: (value) => step(\"return\", value),\n throw: (error) => step(\"throw\", error),\n [Symbol.asyncIterator]: () => wrapped,\n }\n return wrapped\n}\n\nfunction wrapAutoTraceNodeAsyncGenerator(\n nodeConfiguration: AutoTraceNodeConfiguration,\n source: AutoTraceAsyncGenerator,\n): AutoTraceAsyncGenerator {\n const step = (\n method: \"next\" | \"return\" | \"throw\",\n value?: unknown,\n ): Promise<IteratorResult<unknown, unknown>> =>\n runWithAutoTraceNodeConfiguration(nodeConfiguration, () =>\n source[method](value),\n )\n const wrapped: AutoTraceAsyncGenerator = {\n next: (value) => step(\"next\", value),\n return: (value) => step(\"return\", value),\n throw: (error) => step(\"throw\", error),\n [Symbol.asyncIterator]: () => wrapped,\n }\n return wrapped\n}\n\nfunction shareFinalize(\n configuration: AutoTraceNodeConfiguration,\n): AutoTraceNodeConfiguration {\n const finalize = configuration.finalize\n if (finalize === undefined) {\n return configuration\n }\n let settled: Promise<unknown> | undefined\n return {\n ...configuration,\n finalize: (result: unknown) => {\n settled ??= Promise.resolve().then(() => finalize(result))\n return settled\n },\n }\n}\n\nexport function __bitfabAutoSpan<T>(\n definition: AutoTraceFunctionDefinition,\n inputs: unknown[],\n fn: () => T,\n): T {\n noteTransformedModule()\n const scope = currentAutoTraceScope()\n if (!scope || scope.entries.length === 0 || isCaptureSuppressed()) {\n return fn()\n }\n const nameParts = definition.name.split(\".\")\n const simpleName = nameParts[nameParts.length - 1]\n const nodeConfiguration =\n simpleName === scope.nodeConfiguration?.functionName\n ? shareFinalize(scope.nodeConfiguration)\n : undefined\n return invokeThroughAutoTraceEntries(\n scope.entries,\n (entry, next) =>\n entry.context.invoke(definition, inputs, next, entry, nodeConfiguration),\n fn,\n )\n}\n\n/**\n * Preserve a function's original call arguments for transform cases where\n * parameter bindings discard them, such as destructured arrow parameters.\n *\n * This helper is internal transform/runtime protocol. The proxy preserves the\n * target's callability, arity, async identity, and non-constructibility while\n * only allocating a trace closure beneath an active automatic trace root.\n *\n * @experimental The automatic tracing protocol may change.\n */\nexport function __bitfabAutoWrap<T extends (...args: never[]) => unknown>(\n definition: AutoTraceFunctionDefinition,\n fn: T,\n): T {\n noteTransformedModule()\n if (fn.name === \"\") {\n const nameParts = definition.name.split(\".\")\n const inferredName = nameParts[nameParts.length - 1]\n if (inferredName !== undefined) {\n Object.defineProperty(fn, \"name\", {\n configurable: true,\n value: inferredName,\n })\n }\n }\n\n const target = fn as unknown as (...args: unknown[]) => unknown\n return new Proxy(target, {\n apply(callTarget, thisArg, args) {\n if (!__bitfabAutoTraceActive()) {\n return Reflect.apply(callTarget, thisArg, args)\n }\n return __bitfabAutoSpan(definition, args, () =>\n Reflect.apply(callTarget, thisArg, args),\n )\n },\n }) as unknown as T\n}\n\n/**\n * Return whether the current call is inside an automatic trace root.\n *\n * Build transforms use this before allocating function metadata, captured\n * inputs, or an invocation closure. It is internal transform/runtime protocol,\n * not a supported application API.\n *\n * @experimental The automatic tracing protocol may change.\n */\nexport function __bitfabAutoTraceActive(): boolean {\n if (autoTraceState.activeRoots === 0 || isCaptureSuppressed()) {\n return false\n }\n return currentAutoTraceEntries().length > 0\n}\n\nfunction currentAutoTraceScope(): AutoTraceScope | undefined {\n initializeAutoTraceStorage()\n return autoTraceState.storage?.getStore() ?? autoTraceState.browserScope\n}\n\nexport function _resetAutoTraceTransformDetection(): void {\n autoTraceGlobal.__bitfab_auto_trace_transformed_v1__ = undefined\n}\n"],"mappings":"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","names":[]}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  BitfabError
3
- } from "./chunk-5BM2IXP6.js";
3
+ } from "./chunk-IR5KCKHF.js";
4
4
 
5
5
  // src/codeChange.ts
6
6
  var NUL = String.fromCharCode(0);
@@ -81,18 +81,39 @@ var VALUE_FLAGS = /* @__PURE__ */ new Set([
81
81
  "--grader-ids",
82
82
  "--mock",
83
83
  "--param",
84
- "--params"
84
+ "--params",
85
+ "--resume"
85
86
  ]);
86
87
  var BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
87
88
  "--only-with-assertions",
88
89
  "--db-branch",
89
90
  "--no-db-branch",
90
91
  "--no-code-change",
91
- "--dry-run"
92
+ "--dry-run",
93
+ "--force"
92
94
  ]);
93
95
  var HELP_FLAGS = /* @__PURE__ */ new Set(["--help", "-h"]);
94
96
  var MAX_ATTEMPTS = 100;
95
97
  var MAX_PINNED_TRACE_IDS = 100;
98
+ var RESUME_CONFLICTING_FLAGS = [
99
+ ["traceIds", "--trace-ids"],
100
+ ["datasetIds", "--dataset-ids"],
101
+ ["limit", "--limit"],
102
+ ["attempts", "--attempts"],
103
+ ["graderIds", "--grader-ids"],
104
+ ["onlyWithAssertions", "--only-with-assertions"],
105
+ ["dryRun", "--dry-run"]
106
+ ];
107
+ var RESUME_CLEARED_OPTIONS = {
108
+ traceIds: void 0,
109
+ limit: void 0,
110
+ datasetId: void 0,
111
+ datasetIds: void 0,
112
+ attempts: void 0,
113
+ graderIds: void 0,
114
+ onlyWithAssertions: void 0,
115
+ dryRun: void 0
116
+ };
96
117
  function hasApprovedAssertion(assertions) {
97
118
  return assertions.some((assertion) => assertion.approvalState === "approved");
98
119
  }
@@ -156,6 +177,8 @@ Options:
156
177
  --mock none|all|marked
157
178
  --db-branch, --no-db-branch
158
179
  --dry-run (resolve inputs, run nothing)
180
+ --resume EXPERIMENT_ID (finish an experiment that stopped partway, running only the items it did not finish, with the traces, attempts, and graders it started with)
181
+ --force (with --resume, resume even when the experiment may still be running or the code changed since it started)
159
182
  --params PATH
160
183
  --param name=value (repeatable)
161
184
  -h, --help`;
@@ -236,7 +259,7 @@ async function seedFromRegistry(registry, pipeline, cases, options = {}) {
236
259
  sessionId: seedCase.sessionId
237
260
  })
238
261
  );
239
- const { flushTraces: flushTraces2 } = await import("./http-34JZXPJP.js");
262
+ const { flushTraces: flushTraces2 } = await import("./http-OEABHRHY.js");
240
263
  await flushTraces2(3e4);
241
264
  return { pipeline, traceFunctionKey, traceIds };
242
265
  }
@@ -356,6 +379,9 @@ function parseReplayCliArgs(registry, argv) {
356
379
  case "--dry-run":
357
380
  parsed.dryRun = true;
358
381
  break;
382
+ case "--force":
383
+ parsed.force = true;
384
+ break;
359
385
  }
360
386
  continue;
361
387
  }
@@ -414,6 +440,22 @@ ${usage(registry)}`
414
440
  case "--param":
415
441
  parsed.params.push(raw);
416
442
  break;
443
+ case "--resume":
444
+ parsed.resume = raw;
445
+ break;
446
+ }
447
+ }
448
+ if (parsed.force === true && parsed.resume === void 0) {
449
+ throw new BitfabError("--force only applies with --resume <experimentId>.");
450
+ }
451
+ if (parsed.resume !== void 0) {
452
+ const conflicting = RESUME_CONFLICTING_FLAGS.filter(
453
+ ([key]) => parsed[key] !== void 0
454
+ ).map(([, flag]) => flag);
455
+ if (conflicting.length > 0) {
456
+ throw new BitfabError(
457
+ `--resume reuses the traces, attempts, and graders experiment ${parsed.resume} started with, so it cannot be combined with ${conflicting.join(", ")}.`
458
+ );
417
459
  }
418
460
  }
419
461
  if (parsed.traceIds !== void 0 && parsed.datasetIds !== void 0) {
@@ -525,7 +567,12 @@ function renderSummary(pipeline, result, stderr) {
525
567
  let matched = 0;
526
568
  let missed = 0;
527
569
  let errors = 0;
570
+ let carriedOver = 0;
528
571
  for (const item of result.items) {
572
+ if (item.carriedOver === true) {
573
+ carriedOver += 1;
574
+ continue;
575
+ }
529
576
  if (item.error !== null) {
530
577
  errors += 1;
531
578
  continue;
@@ -545,7 +592,10 @@ function renderSummary(pipeline, result, stderr) {
545
592
  }
546
593
  stderr("\n\u2500\u2500\u2500 Summary \u2500\u2500\u2500");
547
594
  stderr(` Pipeline: ${pipeline}`);
548
- stderr(` Replayed: ${result.items.length}`);
595
+ stderr(` Replayed: ${result.items.length - carriedOver}`);
596
+ if (carriedOver > 0) {
597
+ stderr(` Carried over from the earlier run: ${carriedOver}`);
598
+ }
549
599
  if (result.attempts > 1) {
550
600
  stderr(` Attempts: ${result.attempts}`);
551
601
  }
@@ -582,6 +632,9 @@ function safeJson(value) {
582
632
  return String(value);
583
633
  }
584
634
  }
635
+ function resumeCommand(registryPath, pipeline, experimentId) {
636
+ return `Resume with: bitfab-replay --registry ${registryPath ?? "<path>"} ${pipeline} --resume ${experimentId}`;
637
+ }
585
638
  function reportReplayError(error, stderr) {
586
639
  for (const item of error.items) {
587
640
  stderr(
@@ -589,7 +642,7 @@ function reportReplayError(error, stderr) {
589
642
  );
590
643
  }
591
644
  }
592
- async function runReplayCli(registry, argv = typeof process === "undefined" ? [] : process.argv.slice(2), io = {}) {
645
+ async function runReplayCli(registry, argv = typeof process === "undefined" ? [] : process.argv.slice(2), io = {}, registryPath) {
593
646
  const stdout = io.stdout ?? console.log;
594
647
  const stderr = io.stderr ?? console.error;
595
648
  const args = parseReplayCliArgs(registry, argv);
@@ -610,6 +663,7 @@ async function runReplayCli(registry, argv = typeof process === "undefined" ? []
610
663
  }
611
664
  const selectedDatasetIds = args.datasetIds ?? registrationDatasetIds;
612
665
  const codeChange = await loadCodeChange(args.codeChangePath, readFile);
666
+ let startedExperimentId;
613
667
  const options = {
614
668
  ...registrationOptions,
615
669
  ...args.name === void 0 ? {} : { name: args.name },
@@ -633,69 +687,85 @@ async function runReplayCli(registry, argv = typeof process === "undefined" ? []
633
687
  onItemStart: reportReplayProgress,
634
688
  onItemFinish: reportReplayProgress,
635
689
  onExperimentStart: ({ experimentId, experimentUrl }) => {
690
+ startedExperimentId = experimentId;
636
691
  stderr(`[replay] Experiment ${experimentId}: ${experimentUrl}`);
637
692
  }
638
693
  };
639
- if (args.traceIds !== void 0) {
640
- options.traceIds = args.traceIds;
641
- options.datasetIds = void 0;
642
- } else if (args.datasetIds !== void 0) {
643
- options.traceIds = void 0;
644
- }
645
- const bound = args.limit ?? registrationOptions.limit;
646
- options.limit = void 0;
647
- if (options.traceIds !== void 0) {
648
- if (bound !== void 0) {
649
- options.traceIds = await boundTraceIds(
650
- registration.client,
651
- options.traceIds,
652
- bound,
653
- options.onlyWithAssertions === true
654
- );
694
+ if (args.resume !== void 0) {
695
+ Object.assign(options, RESUME_CLEARED_OPTIONS, {
696
+ resume: args.resume,
697
+ ...args.force === true ? { force: true } : {}
698
+ });
699
+ stderr(
700
+ `[replay] Resuming experiment ${args.resume} of "${traceFunctionKey}"...`
701
+ );
702
+ } else {
703
+ if (args.traceIds !== void 0) {
704
+ options.traceIds = args.traceIds;
705
+ options.datasetIds = void 0;
706
+ } else if (args.datasetIds !== void 0) {
707
+ options.traceIds = void 0;
655
708
  }
656
- } else if (options.datasetIds !== void 0) {
657
- if (bound !== void 0) {
658
- const pinned = await pinnedDatasetMembers(
659
- registration.client,
660
- options.datasetIds,
661
- bound,
662
- options.onlyWithAssertions === true
663
- );
664
- if (pinned !== void 0) {
665
- options.traceIds = pinned;
709
+ const bound = args.limit ?? registrationOptions.limit;
710
+ options.limit = void 0;
711
+ if (options.traceIds !== void 0) {
712
+ if (bound !== void 0) {
713
+ options.traceIds = await boundTraceIds(
714
+ registration.client,
715
+ options.traceIds,
716
+ bound,
717
+ options.onlyWithAssertions === true
718
+ );
719
+ }
720
+ } else if (options.datasetIds !== void 0) {
721
+ if (bound !== void 0) {
722
+ const pinned = await pinnedDatasetMembers(
723
+ registration.client,
724
+ options.datasetIds,
725
+ bound,
726
+ options.onlyWithAssertions === true
727
+ );
728
+ if (pinned !== void 0) {
729
+ options.traceIds = pinned;
730
+ }
666
731
  }
732
+ } else {
733
+ options.limit = bound ?? 10;
667
734
  }
668
- } else {
669
- options.limit = bound ?? 10;
735
+ const attemptsSuffix = options.attempts !== void 0 && options.attempts > 1 ? ` (${options.attempts} attempts each)` : "";
736
+ stderr(
737
+ `[replay] ${args.dryRun === true ? "Resolving inputs for" : "Replaying"} ${describeSelection(options)} from "${traceFunctionKey}"${attemptsSuffix}...`
738
+ );
670
739
  }
671
- const attemptsSuffix = options.attempts !== void 0 && options.attempts > 1 ? ` (${options.attempts} attempts each)` : "";
672
- stderr(
673
- `[replay] ${args.dryRun === true ? "Resolving inputs for" : "Replaying"} ${describeSelection(options)} from "${traceFunctionKey}"${attemptsSuffix}...`
674
- );
740
+ let result;
675
741
  try {
676
- const result = await registration.client.replay(
742
+ result = await registration.client.replay(
677
743
  traceFunctionKey,
678
744
  registration.fn,
679
745
  options
680
746
  );
681
- if (args.dryRun === true) {
682
- renderDryRun(args.pipeline, result, stderr);
683
- } else {
684
- renderSummary(args.pipeline, result, stderr);
685
- }
686
- stdout(serializeReplayResult(result));
687
- if (result.items.length === 0) {
688
- throw new BitfabError(
689
- `No traces matched "${traceFunctionKey}", so nothing was replayed. Seed cases with --seed, or capture a trace first.`
690
- );
691
- }
692
- return result;
693
747
  } catch (error) {
694
748
  if (error instanceof ReplayError) {
695
749
  reportReplayError(error, stderr);
696
750
  }
751
+ const experimentId = error instanceof ReplayError ? error.experimentId : startedExperimentId;
752
+ if (experimentId !== void 0) {
753
+ stderr(resumeCommand(registryPath, args.pipeline, experimentId));
754
+ }
697
755
  throw error;
698
756
  }
757
+ if (args.dryRun === true) {
758
+ renderDryRun(args.pipeline, result, stderr);
759
+ } else {
760
+ renderSummary(args.pipeline, result, stderr);
761
+ }
762
+ stdout(serializeReplayResult(result));
763
+ if (result.items.length === 0) {
764
+ throw new BitfabError(
765
+ `No traces matched "${traceFunctionKey}", so nothing was replayed. Seed cases with --seed, or capture a trace first.`
766
+ );
767
+ }
768
+ return result;
699
769
  }
700
770
 
701
771
  // src/registryCommand.ts
@@ -790,4 +860,4 @@ export {
790
860
  runRegistryMain,
791
861
  runIfEntrypoint
792
862
  };
793
- //# sourceMappingURL=chunk-5IQRMYJP.js.map
863
+ //# sourceMappingURL=chunk-DSVQPSAL.js.map