bitfab 0.23.0 → 0.23.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.
package/dist/index.d.cts CHANGED
@@ -171,6 +171,122 @@ declare class BitfabClaudeAgentHandler {
171
171
  private resetState;
172
172
  }
173
173
 
174
+ /**
175
+ * Vercel AI SDK integration for Bitfab tracing.
176
+ *
177
+ * The Vercel AI SDK (`ai`) routes every `generateText` / `streamText` /
178
+ * `generateObject` / `streamObject` call through a language model. Bitfab hooks
179
+ * that model with a *language-model middleware* (`wrapLanguageModel`), so each
180
+ * model call is captured as a keyed `llm` span with no hand-written `withSpan`:
181
+ *
182
+ * ```typescript
183
+ * import { Bitfab } from "@bitfab/sdk";
184
+ * import { wrapLanguageModel, streamText } from "ai";
185
+ * import { openai } from "@ai-sdk/openai";
186
+ *
187
+ * const bitfab = new Bitfab({ apiKey: "..." });
188
+ *
189
+ * const model = wrapLanguageModel({
190
+ * model: openai("gpt-4o"),
191
+ * middleware: bitfab.getVercelAiMiddleware("chat-turn"),
192
+ * });
193
+ *
194
+ * const result = streamText({ model, messages });
195
+ * return result.toUIMessageStreamResponse(); // live stream untouched
196
+ * ```
197
+ *
198
+ * The span records the call parameters (the prompt/messages) as its input and a
199
+ * serializable summary (`{ text, toolCalls, usage, finishReason }`) as its
200
+ * output. Streaming is handled by passing the model's stream through a
201
+ * transform that accumulates the assembled text/usage as the caller consumes
202
+ * it: the live stream is handed back unchanged (first-byte latency untouched)
203
+ * and the span is finalized once the stream completes.
204
+ *
205
+ * The middleware is fully duck-typed (no static or dynamic `ai` import), so it
206
+ * adds no dependency and is browser-safe. It works with `ai` v5 and v6.
207
+ */
208
+ type LlmSpanOptions = {
209
+ type: "llm";
210
+ finalize: (result: unknown) => unknown | Promise<unknown>;
211
+ };
212
+ type WithSpanFn$1 = <TArgs extends unknown[], TReturn>(traceFunctionKey: string, options: LlmSpanOptions, fn: (...args: TArgs) => TReturn) => (...args: TArgs) => TReturn;
213
+ /**
214
+ * Duck-typed subset of the Vercel AI SDK language-model call parameters. The
215
+ * only field we read for the span input is `prompt` (the messages), but the
216
+ * whole object is recorded so the call is reconstructable on replay.
217
+ */
218
+ interface VercelCallParams {
219
+ prompt?: unknown;
220
+ [key: string]: unknown;
221
+ }
222
+ /** A content part of a non-streaming `doGenerate` result. */
223
+ interface VercelContentPart {
224
+ type: string;
225
+ text?: string;
226
+ toolCallId?: string;
227
+ toolName?: string;
228
+ input?: unknown;
229
+ args?: unknown;
230
+ }
231
+ /** Duck-typed subset of a non-streaming `doGenerate` result. */
232
+ interface VercelGenerateResult {
233
+ content?: VercelContentPart[];
234
+ text?: string;
235
+ usage?: unknown;
236
+ finishReason?: unknown;
237
+ [key: string]: unknown;
238
+ }
239
+ /** Duck-typed subset of a single streaming part from `doStream`. */
240
+ interface VercelStreamPart {
241
+ type: string;
242
+ delta?: string;
243
+ textDelta?: string;
244
+ toolCallId?: string;
245
+ toolName?: string;
246
+ input?: unknown;
247
+ args?: unknown;
248
+ usage?: unknown;
249
+ finishReason?: unknown;
250
+ }
251
+ /** Duck-typed subset of a streaming `doStream` result. */
252
+ interface VercelStreamResult {
253
+ stream: ReadableStream<VercelStreamPart>;
254
+ [key: string]: unknown;
255
+ }
256
+ interface MiddlewareCall<TResult> {
257
+ doGenerate: () => PromiseLike<VercelGenerateResult>;
258
+ doStream: () => PromiseLike<VercelStreamResult>;
259
+ params: VercelCallParams;
260
+ model: unknown;
261
+ __result?: TResult;
262
+ }
263
+ /**
264
+ * The structural shape of a Vercel AI SDK language-model middleware. Matches
265
+ * `LanguageModelV3Middleware` from `@ai-sdk/provider` without importing it, so
266
+ * the SDK stays dependency-free. `wrapLanguageModel` only reads the method
267
+ * fields (it ignores `specificationVersion`), so this object drops straight in.
268
+ */
269
+ interface BitfabLanguageModelMiddleware {
270
+ specificationVersion: "v3";
271
+ wrapGenerate: (options: MiddlewareCall<VercelGenerateResult>) => Promise<any>;
272
+ wrapStream: (options: MiddlewareCall<VercelStreamResult>) => Promise<any>;
273
+ }
274
+ /**
275
+ * Vercel AI SDK middleware that records each language-model call as a keyed
276
+ * `llm` span. Obtain it from {@link BitfabClient.getVercelAiMiddleware} rather
277
+ * than constructing it directly.
278
+ */
279
+ declare class BitfabVercelAiHandler {
280
+ private readonly traceFunctionKey;
281
+ private readonly withSpanFn;
282
+ constructor(config: {
283
+ traceFunctionKey: string;
284
+ withSpan: WithSpanFn$1;
285
+ });
286
+ /** The `wrapLanguageModel` middleware object for this trace function key. */
287
+ get middleware(): BitfabLanguageModelMiddleware;
288
+ }
289
+
174
290
  /**
175
291
  * Per-trace database snapshot ref capture.
176
292
  *
@@ -330,6 +446,14 @@ declare class BitfabLangGraphCallbackHandler {
330
446
  * replayable with no hand-written `withSpan`. The processor's spans nest
331
447
  * underneath it automatically (it remaps onto the active span context).
332
448
  *
449
+ * When `wrapRun` runs inside an enclosing Bitfab span (the replay auto-wrap, or
450
+ * a caller's own `withSpan`), that span is already the replayable root: the
451
+ * handler skips opening a second one and lets the processor nest the run's spans
452
+ * under the existing root. This mirrors the Claude Agent SDK and LangGraph
453
+ * handlers, which no-op their root span under an enclosing span, and keeps a
454
+ * replayed run's span tree identical to the original (no doubled root agent
455
+ * span).
456
+ *
333
457
  * Use both together: register the processor once at startup, then call
334
458
  * `handler.wrapRun(agent, input)` instead of `run(agent, input)`.
335
459
  */
@@ -339,6 +463,7 @@ type RootSpanOptions = {
339
463
  finalize: (result: unknown) => unknown | Promise<unknown>;
340
464
  };
341
465
  type WithSpanFn = <TArgs extends unknown[], TReturn>(traceFunctionKey: string, options: RootSpanOptions, fn: (...args: TArgs) => TReturn) => (...args: TArgs) => TReturn;
466
+ type GetActiveSpanContextFn = () => unknown | null;
342
467
  type RunInput<TContext, TAgent extends Agent<any, any>> = string | AgentInputItem[] | RunState<TContext, TAgent>;
343
468
  /**
344
469
  * OpenAI Agents SDK handler that records a replayable root span around a run.
@@ -361,9 +486,11 @@ type RunInput<TContext, TAgent extends Agent<any, any>> = string | AgentInputIte
361
486
  declare class BitfabOpenAIAgentHandler {
362
487
  private readonly traceFunctionKey;
363
488
  private readonly withSpanFn;
489
+ private readonly getActiveSpanContext?;
364
490
  constructor(config: {
365
491
  traceFunctionKey: string;
366
492
  withSpan: WithSpanFn;
493
+ getActiveSpanContext?: GetActiveSpanContextFn;
367
494
  });
368
495
  /**
369
496
  * Drop-in replacement for the OpenAI Agents SDK's `run()` that records a
@@ -694,10 +821,6 @@ declare class BitfabOpenAITracingProcessor implements TracingProcessor {
694
821
  private sendSpan;
695
822
  }
696
823
 
697
- /**
698
- * Bitfab client for provider-based API calls.
699
- */
700
-
701
824
  /**
702
825
  * Options for wrapBAML.
703
826
  */
@@ -1014,6 +1137,31 @@ declare class Bitfab {
1014
1137
  * @returns A BitfabClaudeAgentHandler configured for this client
1015
1138
  */
1016
1139
  getClaudeAgentHandler(traceFunctionKey: string): BitfabClaudeAgentHandler;
1140
+ /**
1141
+ * Get a Vercel AI SDK language-model middleware for tracing.
1142
+ *
1143
+ * Pass it to the AI SDK's `wrapLanguageModel` and use the wrapped model with
1144
+ * `generateText` / `streamText` / `generateObject` / `streamObject`. Every
1145
+ * call through that model is captured as a keyed `llm` span carrying the call
1146
+ * parameters (the prompt) as input and a serializable summary
1147
+ * (`{ text, toolCalls, usage, finishReason }`) as output. Streaming is
1148
+ * captured without disturbing the caller's live stream.
1149
+ *
1150
+ * ```typescript
1151
+ * import { wrapLanguageModel, streamText } from "ai";
1152
+ * import { openai } from "@ai-sdk/openai";
1153
+ *
1154
+ * const model = wrapLanguageModel({
1155
+ * model: openai("gpt-4o"),
1156
+ * middleware: client.getVercelAiMiddleware("chat-turn"),
1157
+ * });
1158
+ * const result = streamText({ model, messages });
1159
+ * ```
1160
+ *
1161
+ * @param traceFunctionKey - Groups traces under this key in Bitfab
1162
+ * @returns A Vercel AI SDK middleware configured for this client
1163
+ */
1164
+ getVercelAiMiddleware(traceFunctionKey: string): BitfabLanguageModelMiddleware;
1017
1165
  /**
1018
1166
  * Wrap a BAML client method to automatically capture prompt and LLM metadata.
1019
1167
  *
@@ -1210,7 +1358,7 @@ declare class BitfabFunction {
1210
1358
  /**
1211
1359
  * SDK version from package.json (injected at build time)
1212
1360
  */
1213
- declare const __version__ = "0.23.0";
1361
+ declare const __version__ = "0.23.2";
1214
1362
 
1215
1363
  /**
1216
1364
  * Constants for the Bitfab SDK.
@@ -1278,4 +1426,4 @@ declare const finalizers: {
1278
1426
  readableStream: typeof readableStream;
1279
1427
  };
1280
1428
 
1281
- export { type ActiveSpanContext, type AdaptContext, type AdaptInputsFn, type AllowedEnvVars, type BamlExecutionResult, Bitfab, BitfabClaudeAgentHandler, type BitfabConfig, BitfabError, BitfabFunction, BitfabLangGraphCallbackHandler as BitfabLangChainCallbackHandler, BitfabLangGraphCallbackHandler, BitfabOpenAIAgentHandler, BitfabOpenAITracingProcessor, type CodeChangeFile, type CurrentSpan, type CurrentTrace, DEFAULT_SERVICE_URL, type DbSnapshotConfig, type DbSnapshotProvider, type DbSnapshotRef, type DetachedTrace, type MockStrategy, type ProviderDefinition, ReplayEnvironment, type ReplayEnvironmentSnapshot, type ReplayItem, type ReplayOptions, type ReplayResult, SUPPORTED_PROVIDERS, type SpanOptions, type SpanType, type TokenUsage, type TraceResponse, type TracingProcessor, type WrapBAMLOptions, type WrappedBamlFn, __version__, finalizers, flushTraces, getCurrentSpan, getCurrentTrace };
1429
+ export { type ActiveSpanContext, type AdaptContext, type AdaptInputsFn, type AllowedEnvVars, type BamlExecutionResult, Bitfab, BitfabClaudeAgentHandler, type BitfabConfig, BitfabError, BitfabFunction, BitfabLangGraphCallbackHandler as BitfabLangChainCallbackHandler, BitfabLangGraphCallbackHandler, type BitfabLanguageModelMiddleware, BitfabOpenAIAgentHandler, BitfabOpenAITracingProcessor, BitfabVercelAiHandler, type CodeChangeFile, type CurrentSpan, type CurrentTrace, DEFAULT_SERVICE_URL, type DbSnapshotConfig, type DbSnapshotProvider, type DbSnapshotRef, type DetachedTrace, type MockStrategy, type ProviderDefinition, ReplayEnvironment, type ReplayEnvironmentSnapshot, type ReplayItem, type ReplayOptions, type ReplayResult, SUPPORTED_PROVIDERS, type SpanOptions, type SpanType, type TokenUsage, type TraceResponse, type TracingProcessor, type VercelCallParams, type VercelGenerateResult, type VercelStreamResult, type WrapBAMLOptions, type WrappedBamlFn, __version__, finalizers, flushTraces, getCurrentSpan, getCurrentTrace };
package/dist/index.d.ts CHANGED
@@ -171,6 +171,122 @@ declare class BitfabClaudeAgentHandler {
171
171
  private resetState;
172
172
  }
173
173
 
174
+ /**
175
+ * Vercel AI SDK integration for Bitfab tracing.
176
+ *
177
+ * The Vercel AI SDK (`ai`) routes every `generateText` / `streamText` /
178
+ * `generateObject` / `streamObject` call through a language model. Bitfab hooks
179
+ * that model with a *language-model middleware* (`wrapLanguageModel`), so each
180
+ * model call is captured as a keyed `llm` span with no hand-written `withSpan`:
181
+ *
182
+ * ```typescript
183
+ * import { Bitfab } from "@bitfab/sdk";
184
+ * import { wrapLanguageModel, streamText } from "ai";
185
+ * import { openai } from "@ai-sdk/openai";
186
+ *
187
+ * const bitfab = new Bitfab({ apiKey: "..." });
188
+ *
189
+ * const model = wrapLanguageModel({
190
+ * model: openai("gpt-4o"),
191
+ * middleware: bitfab.getVercelAiMiddleware("chat-turn"),
192
+ * });
193
+ *
194
+ * const result = streamText({ model, messages });
195
+ * return result.toUIMessageStreamResponse(); // live stream untouched
196
+ * ```
197
+ *
198
+ * The span records the call parameters (the prompt/messages) as its input and a
199
+ * serializable summary (`{ text, toolCalls, usage, finishReason }`) as its
200
+ * output. Streaming is handled by passing the model's stream through a
201
+ * transform that accumulates the assembled text/usage as the caller consumes
202
+ * it: the live stream is handed back unchanged (first-byte latency untouched)
203
+ * and the span is finalized once the stream completes.
204
+ *
205
+ * The middleware is fully duck-typed (no static or dynamic `ai` import), so it
206
+ * adds no dependency and is browser-safe. It works with `ai` v5 and v6.
207
+ */
208
+ type LlmSpanOptions = {
209
+ type: "llm";
210
+ finalize: (result: unknown) => unknown | Promise<unknown>;
211
+ };
212
+ type WithSpanFn$1 = <TArgs extends unknown[], TReturn>(traceFunctionKey: string, options: LlmSpanOptions, fn: (...args: TArgs) => TReturn) => (...args: TArgs) => TReturn;
213
+ /**
214
+ * Duck-typed subset of the Vercel AI SDK language-model call parameters. The
215
+ * only field we read for the span input is `prompt` (the messages), but the
216
+ * whole object is recorded so the call is reconstructable on replay.
217
+ */
218
+ interface VercelCallParams {
219
+ prompt?: unknown;
220
+ [key: string]: unknown;
221
+ }
222
+ /** A content part of a non-streaming `doGenerate` result. */
223
+ interface VercelContentPart {
224
+ type: string;
225
+ text?: string;
226
+ toolCallId?: string;
227
+ toolName?: string;
228
+ input?: unknown;
229
+ args?: unknown;
230
+ }
231
+ /** Duck-typed subset of a non-streaming `doGenerate` result. */
232
+ interface VercelGenerateResult {
233
+ content?: VercelContentPart[];
234
+ text?: string;
235
+ usage?: unknown;
236
+ finishReason?: unknown;
237
+ [key: string]: unknown;
238
+ }
239
+ /** Duck-typed subset of a single streaming part from `doStream`. */
240
+ interface VercelStreamPart {
241
+ type: string;
242
+ delta?: string;
243
+ textDelta?: string;
244
+ toolCallId?: string;
245
+ toolName?: string;
246
+ input?: unknown;
247
+ args?: unknown;
248
+ usage?: unknown;
249
+ finishReason?: unknown;
250
+ }
251
+ /** Duck-typed subset of a streaming `doStream` result. */
252
+ interface VercelStreamResult {
253
+ stream: ReadableStream<VercelStreamPart>;
254
+ [key: string]: unknown;
255
+ }
256
+ interface MiddlewareCall<TResult> {
257
+ doGenerate: () => PromiseLike<VercelGenerateResult>;
258
+ doStream: () => PromiseLike<VercelStreamResult>;
259
+ params: VercelCallParams;
260
+ model: unknown;
261
+ __result?: TResult;
262
+ }
263
+ /**
264
+ * The structural shape of a Vercel AI SDK language-model middleware. Matches
265
+ * `LanguageModelV3Middleware` from `@ai-sdk/provider` without importing it, so
266
+ * the SDK stays dependency-free. `wrapLanguageModel` only reads the method
267
+ * fields (it ignores `specificationVersion`), so this object drops straight in.
268
+ */
269
+ interface BitfabLanguageModelMiddleware {
270
+ specificationVersion: "v3";
271
+ wrapGenerate: (options: MiddlewareCall<VercelGenerateResult>) => Promise<any>;
272
+ wrapStream: (options: MiddlewareCall<VercelStreamResult>) => Promise<any>;
273
+ }
274
+ /**
275
+ * Vercel AI SDK middleware that records each language-model call as a keyed
276
+ * `llm` span. Obtain it from {@link BitfabClient.getVercelAiMiddleware} rather
277
+ * than constructing it directly.
278
+ */
279
+ declare class BitfabVercelAiHandler {
280
+ private readonly traceFunctionKey;
281
+ private readonly withSpanFn;
282
+ constructor(config: {
283
+ traceFunctionKey: string;
284
+ withSpan: WithSpanFn$1;
285
+ });
286
+ /** The `wrapLanguageModel` middleware object for this trace function key. */
287
+ get middleware(): BitfabLanguageModelMiddleware;
288
+ }
289
+
174
290
  /**
175
291
  * Per-trace database snapshot ref capture.
176
292
  *
@@ -330,6 +446,14 @@ declare class BitfabLangGraphCallbackHandler {
330
446
  * replayable with no hand-written `withSpan`. The processor's spans nest
331
447
  * underneath it automatically (it remaps onto the active span context).
332
448
  *
449
+ * When `wrapRun` runs inside an enclosing Bitfab span (the replay auto-wrap, or
450
+ * a caller's own `withSpan`), that span is already the replayable root: the
451
+ * handler skips opening a second one and lets the processor nest the run's spans
452
+ * under the existing root. This mirrors the Claude Agent SDK and LangGraph
453
+ * handlers, which no-op their root span under an enclosing span, and keeps a
454
+ * replayed run's span tree identical to the original (no doubled root agent
455
+ * span).
456
+ *
333
457
  * Use both together: register the processor once at startup, then call
334
458
  * `handler.wrapRun(agent, input)` instead of `run(agent, input)`.
335
459
  */
@@ -339,6 +463,7 @@ type RootSpanOptions = {
339
463
  finalize: (result: unknown) => unknown | Promise<unknown>;
340
464
  };
341
465
  type WithSpanFn = <TArgs extends unknown[], TReturn>(traceFunctionKey: string, options: RootSpanOptions, fn: (...args: TArgs) => TReturn) => (...args: TArgs) => TReturn;
466
+ type GetActiveSpanContextFn = () => unknown | null;
342
467
  type RunInput<TContext, TAgent extends Agent<any, any>> = string | AgentInputItem[] | RunState<TContext, TAgent>;
343
468
  /**
344
469
  * OpenAI Agents SDK handler that records a replayable root span around a run.
@@ -361,9 +486,11 @@ type RunInput<TContext, TAgent extends Agent<any, any>> = string | AgentInputIte
361
486
  declare class BitfabOpenAIAgentHandler {
362
487
  private readonly traceFunctionKey;
363
488
  private readonly withSpanFn;
489
+ private readonly getActiveSpanContext?;
364
490
  constructor(config: {
365
491
  traceFunctionKey: string;
366
492
  withSpan: WithSpanFn;
493
+ getActiveSpanContext?: GetActiveSpanContextFn;
367
494
  });
368
495
  /**
369
496
  * Drop-in replacement for the OpenAI Agents SDK's `run()` that records a
@@ -694,10 +821,6 @@ declare class BitfabOpenAITracingProcessor implements TracingProcessor {
694
821
  private sendSpan;
695
822
  }
696
823
 
697
- /**
698
- * Bitfab client for provider-based API calls.
699
- */
700
-
701
824
  /**
702
825
  * Options for wrapBAML.
703
826
  */
@@ -1014,6 +1137,31 @@ declare class Bitfab {
1014
1137
  * @returns A BitfabClaudeAgentHandler configured for this client
1015
1138
  */
1016
1139
  getClaudeAgentHandler(traceFunctionKey: string): BitfabClaudeAgentHandler;
1140
+ /**
1141
+ * Get a Vercel AI SDK language-model middleware for tracing.
1142
+ *
1143
+ * Pass it to the AI SDK's `wrapLanguageModel` and use the wrapped model with
1144
+ * `generateText` / `streamText` / `generateObject` / `streamObject`. Every
1145
+ * call through that model is captured as a keyed `llm` span carrying the call
1146
+ * parameters (the prompt) as input and a serializable summary
1147
+ * (`{ text, toolCalls, usage, finishReason }`) as output. Streaming is
1148
+ * captured without disturbing the caller's live stream.
1149
+ *
1150
+ * ```typescript
1151
+ * import { wrapLanguageModel, streamText } from "ai";
1152
+ * import { openai } from "@ai-sdk/openai";
1153
+ *
1154
+ * const model = wrapLanguageModel({
1155
+ * model: openai("gpt-4o"),
1156
+ * middleware: client.getVercelAiMiddleware("chat-turn"),
1157
+ * });
1158
+ * const result = streamText({ model, messages });
1159
+ * ```
1160
+ *
1161
+ * @param traceFunctionKey - Groups traces under this key in Bitfab
1162
+ * @returns A Vercel AI SDK middleware configured for this client
1163
+ */
1164
+ getVercelAiMiddleware(traceFunctionKey: string): BitfabLanguageModelMiddleware;
1017
1165
  /**
1018
1166
  * Wrap a BAML client method to automatically capture prompt and LLM metadata.
1019
1167
  *
@@ -1210,7 +1358,7 @@ declare class BitfabFunction {
1210
1358
  /**
1211
1359
  * SDK version from package.json (injected at build time)
1212
1360
  */
1213
- declare const __version__ = "0.23.0";
1361
+ declare const __version__ = "0.23.2";
1214
1362
 
1215
1363
  /**
1216
1364
  * Constants for the Bitfab SDK.
@@ -1278,4 +1426,4 @@ declare const finalizers: {
1278
1426
  readableStream: typeof readableStream;
1279
1427
  };
1280
1428
 
1281
- export { type ActiveSpanContext, type AdaptContext, type AdaptInputsFn, type AllowedEnvVars, type BamlExecutionResult, Bitfab, BitfabClaudeAgentHandler, type BitfabConfig, BitfabError, BitfabFunction, BitfabLangGraphCallbackHandler as BitfabLangChainCallbackHandler, BitfabLangGraphCallbackHandler, BitfabOpenAIAgentHandler, BitfabOpenAITracingProcessor, type CodeChangeFile, type CurrentSpan, type CurrentTrace, DEFAULT_SERVICE_URL, type DbSnapshotConfig, type DbSnapshotProvider, type DbSnapshotRef, type DetachedTrace, type MockStrategy, type ProviderDefinition, ReplayEnvironment, type ReplayEnvironmentSnapshot, type ReplayItem, type ReplayOptions, type ReplayResult, SUPPORTED_PROVIDERS, type SpanOptions, type SpanType, type TokenUsage, type TraceResponse, type TracingProcessor, type WrapBAMLOptions, type WrappedBamlFn, __version__, finalizers, flushTraces, getCurrentSpan, getCurrentTrace };
1429
+ export { type ActiveSpanContext, type AdaptContext, type AdaptInputsFn, type AllowedEnvVars, type BamlExecutionResult, Bitfab, BitfabClaudeAgentHandler, type BitfabConfig, BitfabError, BitfabFunction, BitfabLangGraphCallbackHandler as BitfabLangChainCallbackHandler, BitfabLangGraphCallbackHandler, type BitfabLanguageModelMiddleware, BitfabOpenAIAgentHandler, BitfabOpenAITracingProcessor, BitfabVercelAiHandler, type CodeChangeFile, type CurrentSpan, type CurrentTrace, DEFAULT_SERVICE_URL, type DbSnapshotConfig, type DbSnapshotProvider, type DbSnapshotRef, type DetachedTrace, type MockStrategy, type ProviderDefinition, ReplayEnvironment, type ReplayEnvironmentSnapshot, type ReplayItem, type ReplayOptions, type ReplayResult, SUPPORTED_PROVIDERS, type SpanOptions, type SpanType, type TokenUsage, type TraceResponse, type TracingProcessor, type VercelCallParams, type VercelGenerateResult, type VercelStreamResult, type WrapBAMLOptions, type WrappedBamlFn, __version__, finalizers, flushTraces, getCurrentSpan, getCurrentTrace };
package/dist/index.js CHANGED
@@ -14,6 +14,7 @@ import {
14
14
  BitfabLangGraphCallbackHandler,
15
15
  BitfabOpenAIAgentHandler,
16
16
  BitfabOpenAITracingProcessor,
17
+ BitfabVercelAiHandler,
17
18
  DEFAULT_SERVICE_URL,
18
19
  ReplayEnvironment,
19
20
  SUPPORTED_PROVIDERS,
@@ -22,7 +23,7 @@ import {
22
23
  flushTraces,
23
24
  getCurrentSpan,
24
25
  getCurrentTrace
25
- } from "./chunk-QOPP5TSO.js";
26
+ } from "./chunk-PP5K6RIU.js";
26
27
  import {
27
28
  BitfabError
28
29
  } from "./chunk-EQI6ZJC3.js";
@@ -35,6 +36,7 @@ export {
35
36
  BitfabLangGraphCallbackHandler,
36
37
  BitfabOpenAIAgentHandler,
37
38
  BitfabOpenAITracingProcessor,
39
+ BitfabVercelAiHandler,
38
40
  DEFAULT_SERVICE_URL,
39
41
  ReplayEnvironment,
40
42
  SUPPORTED_PROVIDERS,
package/dist/node.cjs CHANGED
@@ -495,6 +495,7 @@ __export(node_exports, {
495
495
  BitfabLangGraphCallbackHandler: () => BitfabLangGraphCallbackHandler,
496
496
  BitfabOpenAIAgentHandler: () => BitfabOpenAIAgentHandler,
497
497
  BitfabOpenAITracingProcessor: () => BitfabOpenAITracingProcessor,
498
+ BitfabVercelAiHandler: () => BitfabVercelAiHandler,
498
499
  DEFAULT_SERVICE_URL: () => DEFAULT_SERVICE_URL,
499
500
  ReplayEnvironment: () => ReplayEnvironment,
500
501
  SUPPORTED_PROVIDERS: () => SUPPORTED_PROVIDERS,
@@ -514,7 +515,7 @@ registerAsyncLocalStorageClass(
514
515
  );
515
516
 
516
517
  // src/version.generated.ts
517
- var __version__ = "0.23.0";
518
+ var __version__ = "0.23.2";
518
519
 
519
520
  // src/constants.ts
520
521
  var DEFAULT_SERVICE_URL = "https://bitfab.ai";
@@ -2302,9 +2303,17 @@ var BitfabOpenAIAgentHandler = class {
2302
2303
  constructor(config) {
2303
2304
  this.traceFunctionKey = config.traceFunctionKey;
2304
2305
  this.withSpanFn = config.withSpan;
2306
+ this.getActiveSpanContext = config.getActiveSpanContext;
2305
2307
  }
2306
2308
  async wrapRun(agent, input, options) {
2307
2309
  const { run } = await import("@openai/agents");
2310
+ if (this.getActiveSpanContext?.() != null) {
2311
+ return run(
2312
+ agent,
2313
+ input,
2314
+ options
2315
+ );
2316
+ }
2308
2317
  const isStreaming = options?.stream === true;
2309
2318
  const finalize = async (result) => {
2310
2319
  const res = result;
@@ -2620,6 +2629,135 @@ var BitfabOpenAITracingProcessor = class {
2620
2629
  }
2621
2630
  };
2622
2631
 
2632
+ // src/vercelAiSdk.ts
2633
+ function modelLabel(model) {
2634
+ if (!model || typeof model !== "object") {
2635
+ return void 0;
2636
+ }
2637
+ const m = model;
2638
+ const provider = typeof m.provider === "string" ? m.provider : void 0;
2639
+ const modelId = typeof m.modelId === "string" ? m.modelId : void 0;
2640
+ if (provider == null && modelId == null) {
2641
+ return void 0;
2642
+ }
2643
+ return { provider, modelId };
2644
+ }
2645
+ function summarizeGenerate(result, model) {
2646
+ const content = Array.isArray(result.content) ? result.content : [];
2647
+ const text = typeof result.text === "string" ? result.text : content.filter((p) => p.type === "text" && typeof p.text === "string").map((p) => p.text).join("");
2648
+ const toolCalls = content.filter((p) => p.type === "tool-call").map((p) => ({
2649
+ toolCallId: p.toolCallId,
2650
+ toolName: p.toolName,
2651
+ input: p.input ?? p.args
2652
+ }));
2653
+ const summary = {
2654
+ text,
2655
+ toolCalls: toolCalls.length > 0 ? toolCalls : void 0,
2656
+ usage: result.usage,
2657
+ finishReason: result.finishReason
2658
+ };
2659
+ if (model) {
2660
+ summary.model = model;
2661
+ }
2662
+ return summary;
2663
+ }
2664
+ function accumulateStream(onComplete, model) {
2665
+ let text = "";
2666
+ const toolCalls = [];
2667
+ let usage;
2668
+ let finishReason;
2669
+ let completed = false;
2670
+ const complete = () => {
2671
+ if (completed) {
2672
+ return;
2673
+ }
2674
+ completed = true;
2675
+ const summary = {
2676
+ text,
2677
+ toolCalls: toolCalls.length > 0 ? toolCalls : void 0,
2678
+ usage,
2679
+ finishReason
2680
+ };
2681
+ if (model) {
2682
+ summary.model = model;
2683
+ }
2684
+ onComplete(summary);
2685
+ };
2686
+ return new TransformStream({
2687
+ transform(part, controller) {
2688
+ try {
2689
+ if (part?.type === "text-delta") {
2690
+ text += part.delta ?? part.textDelta ?? "";
2691
+ } else if (part?.type === "tool-call") {
2692
+ toolCalls.push({
2693
+ toolCallId: part.toolCallId,
2694
+ toolName: part.toolName,
2695
+ input: part.input ?? part.args
2696
+ });
2697
+ } else if (part?.type === "finish") {
2698
+ usage = part.usage;
2699
+ finishReason = part.finishReason;
2700
+ complete();
2701
+ }
2702
+ } catch {
2703
+ }
2704
+ controller.enqueue(part);
2705
+ },
2706
+ flush() {
2707
+ complete();
2708
+ }
2709
+ });
2710
+ }
2711
+ var BitfabVercelAiHandler = class {
2712
+ constructor(config) {
2713
+ this.traceFunctionKey = config.traceFunctionKey;
2714
+ this.withSpanFn = config.withSpan;
2715
+ }
2716
+ /** The `wrapLanguageModel` middleware object for this trace function key. */
2717
+ get middleware() {
2718
+ const key = this.traceFunctionKey;
2719
+ const withSpan = this.withSpanFn;
2720
+ return {
2721
+ specificationVersion: "v3",
2722
+ wrapGenerate: async ({ doGenerate, params, model }) => {
2723
+ const label = modelLabel(model);
2724
+ const traced = withSpan(
2725
+ key,
2726
+ {
2727
+ type: "llm",
2728
+ finalize: (result) => summarizeGenerate(result ?? {}, label)
2729
+ },
2730
+ () => doGenerate()
2731
+ );
2732
+ return traced(params);
2733
+ },
2734
+ wrapStream: async ({ doStream, params, model }) => {
2735
+ const label = modelLabel(model);
2736
+ let resolveSummary = () => {
2737
+ };
2738
+ const summary = new Promise((resolve) => {
2739
+ resolveSummary = resolve;
2740
+ });
2741
+ const traced = withSpan(
2742
+ key,
2743
+ // The wrapped fn returns immediately with the live stream, so the span
2744
+ // output cannot be read from the return value. `finalize` instead
2745
+ // awaits the summary the accumulator resolves once the stream drains.
2746
+ { type: "llm", finalize: () => summary },
2747
+ async () => {
2748
+ const result = await doStream();
2749
+ const stream = result.stream.pipeThrough(
2750
+ accumulateStream(resolveSummary, label)
2751
+ );
2752
+ return { ...result, stream };
2753
+ }
2754
+ );
2755
+ return traced(params);
2756
+ }
2757
+ };
2758
+ }
2759
+ };
2760
+
2623
2761
  // src/client.ts
2624
2762
  var activeTraceStates = /* @__PURE__ */ new Map();
2625
2763
  var pendingSpanPromises = /* @__PURE__ */ new Map();
@@ -3048,7 +3186,11 @@ var Bitfab = class {
3048
3186
  getOpenAiAgentHandler(traceFunctionKey) {
3049
3187
  return new BitfabOpenAIAgentHandler({
3050
3188
  traceFunctionKey,
3051
- withSpan: this.withSpan.bind(this)
3189
+ withSpan: this.withSpan.bind(this),
3190
+ getActiveSpanContext: () => {
3191
+ const stack = getSpanStack();
3192
+ return stack[stack.length - 1] ?? null;
3193
+ }
3052
3194
  });
3053
3195
  }
3054
3196
  /**
@@ -3131,6 +3273,36 @@ var Bitfab = class {
3131
3273
  }
3132
3274
  });
3133
3275
  }
3276
+ /**
3277
+ * Get a Vercel AI SDK language-model middleware for tracing.
3278
+ *
3279
+ * Pass it to the AI SDK's `wrapLanguageModel` and use the wrapped model with
3280
+ * `generateText` / `streamText` / `generateObject` / `streamObject`. Every
3281
+ * call through that model is captured as a keyed `llm` span carrying the call
3282
+ * parameters (the prompt) as input and a serializable summary
3283
+ * (`{ text, toolCalls, usage, finishReason }`) as output. Streaming is
3284
+ * captured without disturbing the caller's live stream.
3285
+ *
3286
+ * ```typescript
3287
+ * import { wrapLanguageModel, streamText } from "ai";
3288
+ * import { openai } from "@ai-sdk/openai";
3289
+ *
3290
+ * const model = wrapLanguageModel({
3291
+ * model: openai("gpt-4o"),
3292
+ * middleware: client.getVercelAiMiddleware("chat-turn"),
3293
+ * });
3294
+ * const result = streamText({ model, messages });
3295
+ * ```
3296
+ *
3297
+ * @param traceFunctionKey - Groups traces under this key in Bitfab
3298
+ * @returns A Vercel AI SDK middleware configured for this client
3299
+ */
3300
+ getVercelAiMiddleware(traceFunctionKey) {
3301
+ return new BitfabVercelAiHandler({
3302
+ traceFunctionKey,
3303
+ withSpan: this.withSpan.bind(this)
3304
+ }).middleware;
3305
+ }
3134
3306
  /**
3135
3307
  * Wrap a BAML client method to automatically capture prompt and LLM metadata.
3136
3308
  *
@@ -3673,7 +3845,7 @@ var Bitfab = class {
3673
3845
  if (wrappedKey === void 0) {
3674
3846
  replayFn = this.withSpan(
3675
3847
  traceFunctionKey,
3676
- { name: fn.name || "Replay", type: "agent" },
3848
+ { name: traceFunctionKey, type: "agent" },
3677
3849
  fn
3678
3850
  );
3679
3851
  } else if (wrappedKey !== traceFunctionKey) {
@@ -3807,6 +3979,7 @@ assertAsyncStorageRegistered();
3807
3979
  BitfabLangGraphCallbackHandler,
3808
3980
  BitfabOpenAIAgentHandler,
3809
3981
  BitfabOpenAITracingProcessor,
3982
+ BitfabVercelAiHandler,
3810
3983
  DEFAULT_SERVICE_URL,
3811
3984
  ReplayEnvironment,
3812
3985
  SUPPORTED_PROVIDERS,