bitfab 0.24.1 → 0.26.0

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
@@ -651,6 +651,30 @@ interface ReplayOptions {
651
651
  * Omit it to spread the recorded inputs unchanged.
652
652
  */
653
653
  adaptInputs?: (inputs: unknown[], ctx: AdaptContext) => unknown[];
654
+ /**
655
+ * Called once per item as it finishes, in completion order (not input
656
+ * order), with running totals for the whole run. Use it to render replay
657
+ * progress, for example a terminal progress bar. Replay does not know
658
+ * pass/fail at this point (verdicts are assigned later), so the totals only
659
+ * distinguish items whose function ran (`succeeded`) from items that threw
660
+ * (`errored`).
661
+ *
662
+ * Invoked synchronously right after each item settles, so keep it cheap. A
663
+ * throwing callback never crashes the run: the error is swallowed so progress
664
+ * UI can't break replay.
665
+ */
666
+ onProgress?: (progress: ReplayProgress) => void;
667
+ }
668
+ /** Running totals reported to {@link ReplayOptions.onProgress} as replay proceeds. */
669
+ interface ReplayProgress {
670
+ /** Items that have finished so far, whether they succeeded or errored. */
671
+ completed: number;
672
+ /** Total number of items in this replay run. */
673
+ total: number;
674
+ /** Of the completed items, how many ran the function without throwing. */
675
+ succeeded: number;
676
+ /** Of the completed items, how many threw (their `item.error` is set). */
677
+ errored: number;
654
678
  }
655
679
  /** Per-trace context passed to {@link ReplayOptions.adaptInputs}. */
656
680
  interface AdaptContext {
@@ -1360,10 +1384,97 @@ declare class BitfabFunction {
1360
1384
  * @returns A wrapped function with the same signature that creates spans
1361
1385
  */
1362
1386
  withSpan<TArgs extends unknown[], TReturn>(optionsOrFn: SpanOptions | ((...args: TArgs) => TReturn), maybeFn?: (...args: TArgs) => TReturn): (...args: TArgs) => TReturn;
1387
+ /**
1388
+ * Get a Vercel AI SDK language-model middleware bound to this function's key.
1389
+ *
1390
+ * Equivalent to `client.getVercelAiMiddleware(key)` but reuses the key bound
1391
+ * on this handle, so an outer `withSpan` root and the middleware-traced model
1392
+ * calls share one key without repeating the string. With a matching key, the
1393
+ * outer span is the replayable root and the model-call spans nest beneath it.
1394
+ *
1395
+ * Nesting is captured when the model is called, so keep the
1396
+ * `generateText` / `streamText` call inside this handle's `withSpan`; the
1397
+ * middleware object itself can be created anywhere.
1398
+ *
1399
+ * ```typescript
1400
+ * const chatTurn = client.getFunction("chat-turn");
1401
+ * const runChatTurn = chatTurn.withSpan(
1402
+ * { type: "agent", finalize: finalizers.aiSdk },
1403
+ * (messages) => streamText({ model, messages }),
1404
+ * );
1405
+ * const model = wrapLanguageModel({
1406
+ * model: openai("gpt-4o"),
1407
+ * middleware: chatTurn.getVercelAiMiddleware(),
1408
+ * });
1409
+ * ```
1410
+ *
1411
+ * @returns A Vercel AI SDK middleware configured for this client and key
1412
+ */
1413
+ getVercelAiMiddleware(): BitfabLanguageModelMiddleware;
1414
+ /**
1415
+ * Get a Claude Agent SDK handler bound to this function's key.
1416
+ *
1417
+ * Equivalent to `client.getClaudeAgentHandler(key)` but reuses the key bound
1418
+ * on this handle, so an outer `withSpan` root and the handler share one key
1419
+ * without repeating the string. With a matching key, the outer span is the
1420
+ * replayable root and every handler span nests beneath it.
1421
+ *
1422
+ * Use the handler inside this handle's `withSpan` body so its spans capture
1423
+ * the enclosing root; framework calls made with no active span record their
1424
+ * own root instead.
1425
+ *
1426
+ * ```typescript
1427
+ * const pipeline = client.getFunction("my-agent");
1428
+ * const tracedRun = pipeline.withSpan({ type: "agent" }, async (prompt) => {
1429
+ * const handler = pipeline.getClaudeAgentHandler();
1430
+ * const options = handler.instrumentOptions({ model: "claude-sonnet-4-6" });
1431
+ * for await (const msg of handler.wrapQuery(query({ prompt, options }))) { ... }
1432
+ * });
1433
+ * ```
1434
+ *
1435
+ * @returns A Claude Agent SDK handler configured for this client and key
1436
+ */
1437
+ getClaudeAgentHandler(): BitfabClaudeAgentHandler;
1438
+ /**
1439
+ * Get a LangGraph/LangChain callback handler bound to this function's key.
1440
+ *
1441
+ * Equivalent to `client.getLangGraphCallbackHandler(key)` but reuses the key
1442
+ * bound on this handle, so an outer `withSpan` root and the handler share one
1443
+ * key without repeating the string. With a matching key, the outer span is
1444
+ * the replayable root and the LangGraph spans nest beneath it.
1445
+ *
1446
+ * Use the handler inside this handle's `withSpan` body so its spans capture
1447
+ * the enclosing root; framework calls made with no active span record their
1448
+ * own root instead.
1449
+ *
1450
+ * ```typescript
1451
+ * const pipeline = client.getFunction("my-pipeline");
1452
+ * const tracedRun = pipeline.withSpan({ type: "agent" }, async (query) => {
1453
+ * const handler = pipeline.getLangGraphCallbackHandler();
1454
+ * return agent.invoke({ messages: [...] }, { callbacks: [handler] });
1455
+ * });
1456
+ * ```
1457
+ *
1458
+ * @returns A LangGraph/LangChain callback handler for this client and key
1459
+ */
1460
+ getLangGraphCallbackHandler(): BitfabLangGraphCallbackHandler;
1461
+ /**
1462
+ * Alias of {@link getLangGraphCallbackHandler} — LangChain and LangGraph
1463
+ * share one callback system, so the same bound handler serves both.
1464
+ *
1465
+ * @returns A LangChain callback handler for this client and key
1466
+ */
1467
+ getLangChainCallbackHandler(): BitfabLangGraphCallbackHandler;
1363
1468
  /**
1364
1469
  * Wrap a BAML client method to automatically capture prompt and LLM metadata.
1365
1470
  * Delegates to the parent client's wrapBAML method.
1366
1471
  *
1472
+ * Unlike the other methods on this handle, `wrapBAML` does NOT use the bound
1473
+ * key: it opens no span of its own. It enriches the *current* span (via
1474
+ * `getCurrentSpan().setPrompt()` / `addContext()`), so call it inside a
1475
+ * function wrapped by this handle's `withSpan` — the bound key keys that
1476
+ * wrapper, and the BAML prompt/metadata attach to it.
1477
+ *
1367
1478
  * @param methodOrClient - Either a BAML method (uses constructor bamlClient) or the BAML client instance
1368
1479
  * @param maybeMethodOrOptions - The BAML method when the first argument is a client, or WrapBAMLOptions when the first argument is the method
1369
1480
  * @param maybeOptions - WrapBAMLOptions when using the two-argument (client, method) form
@@ -1380,7 +1491,7 @@ declare class BitfabFunction {
1380
1491
  /**
1381
1492
  * SDK version from package.json (injected at build time)
1382
1493
  */
1383
- declare const __version__ = "0.24.1";
1494
+ declare const __version__ = "0.26.0";
1384
1495
 
1385
1496
  /**
1386
1497
  * Constants for the Bitfab SDK.
@@ -1448,4 +1559,4 @@ declare const finalizers: {
1448
1559
  readableStream: typeof readableStream;
1449
1560
  };
1450
1561
 
1451
- 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 };
1562
+ 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 ReplayProgress, 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
@@ -651,6 +651,30 @@ interface ReplayOptions {
651
651
  * Omit it to spread the recorded inputs unchanged.
652
652
  */
653
653
  adaptInputs?: (inputs: unknown[], ctx: AdaptContext) => unknown[];
654
+ /**
655
+ * Called once per item as it finishes, in completion order (not input
656
+ * order), with running totals for the whole run. Use it to render replay
657
+ * progress, for example a terminal progress bar. Replay does not know
658
+ * pass/fail at this point (verdicts are assigned later), so the totals only
659
+ * distinguish items whose function ran (`succeeded`) from items that threw
660
+ * (`errored`).
661
+ *
662
+ * Invoked synchronously right after each item settles, so keep it cheap. A
663
+ * throwing callback never crashes the run: the error is swallowed so progress
664
+ * UI can't break replay.
665
+ */
666
+ onProgress?: (progress: ReplayProgress) => void;
667
+ }
668
+ /** Running totals reported to {@link ReplayOptions.onProgress} as replay proceeds. */
669
+ interface ReplayProgress {
670
+ /** Items that have finished so far, whether they succeeded or errored. */
671
+ completed: number;
672
+ /** Total number of items in this replay run. */
673
+ total: number;
674
+ /** Of the completed items, how many ran the function without throwing. */
675
+ succeeded: number;
676
+ /** Of the completed items, how many threw (their `item.error` is set). */
677
+ errored: number;
654
678
  }
655
679
  /** Per-trace context passed to {@link ReplayOptions.adaptInputs}. */
656
680
  interface AdaptContext {
@@ -1360,10 +1384,97 @@ declare class BitfabFunction {
1360
1384
  * @returns A wrapped function with the same signature that creates spans
1361
1385
  */
1362
1386
  withSpan<TArgs extends unknown[], TReturn>(optionsOrFn: SpanOptions | ((...args: TArgs) => TReturn), maybeFn?: (...args: TArgs) => TReturn): (...args: TArgs) => TReturn;
1387
+ /**
1388
+ * Get a Vercel AI SDK language-model middleware bound to this function's key.
1389
+ *
1390
+ * Equivalent to `client.getVercelAiMiddleware(key)` but reuses the key bound
1391
+ * on this handle, so an outer `withSpan` root and the middleware-traced model
1392
+ * calls share one key without repeating the string. With a matching key, the
1393
+ * outer span is the replayable root and the model-call spans nest beneath it.
1394
+ *
1395
+ * Nesting is captured when the model is called, so keep the
1396
+ * `generateText` / `streamText` call inside this handle's `withSpan`; the
1397
+ * middleware object itself can be created anywhere.
1398
+ *
1399
+ * ```typescript
1400
+ * const chatTurn = client.getFunction("chat-turn");
1401
+ * const runChatTurn = chatTurn.withSpan(
1402
+ * { type: "agent", finalize: finalizers.aiSdk },
1403
+ * (messages) => streamText({ model, messages }),
1404
+ * );
1405
+ * const model = wrapLanguageModel({
1406
+ * model: openai("gpt-4o"),
1407
+ * middleware: chatTurn.getVercelAiMiddleware(),
1408
+ * });
1409
+ * ```
1410
+ *
1411
+ * @returns A Vercel AI SDK middleware configured for this client and key
1412
+ */
1413
+ getVercelAiMiddleware(): BitfabLanguageModelMiddleware;
1414
+ /**
1415
+ * Get a Claude Agent SDK handler bound to this function's key.
1416
+ *
1417
+ * Equivalent to `client.getClaudeAgentHandler(key)` but reuses the key bound
1418
+ * on this handle, so an outer `withSpan` root and the handler share one key
1419
+ * without repeating the string. With a matching key, the outer span is the
1420
+ * replayable root and every handler span nests beneath it.
1421
+ *
1422
+ * Use the handler inside this handle's `withSpan` body so its spans capture
1423
+ * the enclosing root; framework calls made with no active span record their
1424
+ * own root instead.
1425
+ *
1426
+ * ```typescript
1427
+ * const pipeline = client.getFunction("my-agent");
1428
+ * const tracedRun = pipeline.withSpan({ type: "agent" }, async (prompt) => {
1429
+ * const handler = pipeline.getClaudeAgentHandler();
1430
+ * const options = handler.instrumentOptions({ model: "claude-sonnet-4-6" });
1431
+ * for await (const msg of handler.wrapQuery(query({ prompt, options }))) { ... }
1432
+ * });
1433
+ * ```
1434
+ *
1435
+ * @returns A Claude Agent SDK handler configured for this client and key
1436
+ */
1437
+ getClaudeAgentHandler(): BitfabClaudeAgentHandler;
1438
+ /**
1439
+ * Get a LangGraph/LangChain callback handler bound to this function's key.
1440
+ *
1441
+ * Equivalent to `client.getLangGraphCallbackHandler(key)` but reuses the key
1442
+ * bound on this handle, so an outer `withSpan` root and the handler share one
1443
+ * key without repeating the string. With a matching key, the outer span is
1444
+ * the replayable root and the LangGraph spans nest beneath it.
1445
+ *
1446
+ * Use the handler inside this handle's `withSpan` body so its spans capture
1447
+ * the enclosing root; framework calls made with no active span record their
1448
+ * own root instead.
1449
+ *
1450
+ * ```typescript
1451
+ * const pipeline = client.getFunction("my-pipeline");
1452
+ * const tracedRun = pipeline.withSpan({ type: "agent" }, async (query) => {
1453
+ * const handler = pipeline.getLangGraphCallbackHandler();
1454
+ * return agent.invoke({ messages: [...] }, { callbacks: [handler] });
1455
+ * });
1456
+ * ```
1457
+ *
1458
+ * @returns A LangGraph/LangChain callback handler for this client and key
1459
+ */
1460
+ getLangGraphCallbackHandler(): BitfabLangGraphCallbackHandler;
1461
+ /**
1462
+ * Alias of {@link getLangGraphCallbackHandler} — LangChain and LangGraph
1463
+ * share one callback system, so the same bound handler serves both.
1464
+ *
1465
+ * @returns A LangChain callback handler for this client and key
1466
+ */
1467
+ getLangChainCallbackHandler(): BitfabLangGraphCallbackHandler;
1363
1468
  /**
1364
1469
  * Wrap a BAML client method to automatically capture prompt and LLM metadata.
1365
1470
  * Delegates to the parent client's wrapBAML method.
1366
1471
  *
1472
+ * Unlike the other methods on this handle, `wrapBAML` does NOT use the bound
1473
+ * key: it opens no span of its own. It enriches the *current* span (via
1474
+ * `getCurrentSpan().setPrompt()` / `addContext()`), so call it inside a
1475
+ * function wrapped by this handle's `withSpan` — the bound key keys that
1476
+ * wrapper, and the BAML prompt/metadata attach to it.
1477
+ *
1367
1478
  * @param methodOrClient - Either a BAML method (uses constructor bamlClient) or the BAML client instance
1368
1479
  * @param maybeMethodOrOptions - The BAML method when the first argument is a client, or WrapBAMLOptions when the first argument is the method
1369
1480
  * @param maybeOptions - WrapBAMLOptions when using the two-argument (client, method) form
@@ -1380,7 +1491,7 @@ declare class BitfabFunction {
1380
1491
  /**
1381
1492
  * SDK version from package.json (injected at build time)
1382
1493
  */
1383
- declare const __version__ = "0.24.1";
1494
+ declare const __version__ = "0.26.0";
1384
1495
 
1385
1496
  /**
1386
1497
  * Constants for the Bitfab SDK.
@@ -1448,4 +1559,4 @@ declare const finalizers: {
1448
1559
  readableStream: typeof readableStream;
1449
1560
  };
1450
1561
 
1451
- 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 };
1562
+ 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 ReplayProgress, 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
@@ -23,7 +23,7 @@ import {
23
23
  flushTraces,
24
24
  getCurrentSpan,
25
25
  getCurrentTrace
26
- } from "./chunk-J4D6PRM4.js";
26
+ } from "./chunk-GCAJN5I7.js";
27
27
  import {
28
28
  BitfabError
29
29
  } from "./chunk-26MUT4IP.js";
package/dist/node.cjs CHANGED
@@ -429,13 +429,15 @@ async function processItem(httpClient, serverItem, fn, testRunId, mockStrategy,
429
429
  dbSnapshotRef: serverItem.dbSnapshotRef ?? null
430
430
  };
431
431
  }
432
- async function mapWithConcurrency(tasks, maxConcurrency) {
432
+ async function mapWithConcurrency(tasks, maxConcurrency, onSettled) {
433
433
  const results = new Array(tasks.length);
434
434
  let nextIndex = 0;
435
435
  async function worker() {
436
436
  while (nextIndex < tasks.length) {
437
437
  const index = nextIndex++;
438
- results[index] = await tasks[index]();
438
+ const result = await tasks[index]();
439
+ results[index] = result;
440
+ onSettled?.(result, index);
439
441
  }
440
442
  }
441
443
  const workers = Array.from(
@@ -495,7 +497,26 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options) {
495
497
  options?.adaptInputs
496
498
  )
497
499
  );
498
- const resultItems = await mapWithConcurrency(tasks, maxConcurrency);
500
+ const total = tasks.length;
501
+ let completed = 0;
502
+ let succeeded = 0;
503
+ let errored = 0;
504
+ const resultItems = await mapWithConcurrency(
505
+ tasks,
506
+ maxConcurrency,
507
+ options?.onProgress ? (item) => {
508
+ completed += 1;
509
+ if (item.error === null) {
510
+ succeeded += 1;
511
+ } else {
512
+ errored += 1;
513
+ }
514
+ try {
515
+ options?.onProgress?.({ completed, total, succeeded, errored });
516
+ } catch {
517
+ }
518
+ } : void 0
519
+ );
499
520
  const completeResult = await httpClient.completeReplay(testRunId);
500
521
  const serverTraceIds = completeResult.traceIds;
501
522
  const replayTokens = completeResult.tokens;
@@ -589,7 +610,7 @@ registerAsyncLocalStorageClass(
589
610
  );
590
611
 
591
612
  // src/version.generated.ts
592
- var __version__ = "0.24.1";
613
+ var __version__ = "0.26.0";
593
614
 
594
615
  // src/constants.ts
595
616
  var DEFAULT_SERVICE_URL = "https://bitfab.ai";
@@ -4095,10 +4116,105 @@ var BitfabFunction = class {
4095
4116
  const fn = typeof optionsOrFn === "function" ? optionsOrFn : maybeFn;
4096
4117
  return this.client.withSpan(this.traceFunctionKey, options, fn);
4097
4118
  }
4119
+ /**
4120
+ * Get a Vercel AI SDK language-model middleware bound to this function's key.
4121
+ *
4122
+ * Equivalent to `client.getVercelAiMiddleware(key)` but reuses the key bound
4123
+ * on this handle, so an outer `withSpan` root and the middleware-traced model
4124
+ * calls share one key without repeating the string. With a matching key, the
4125
+ * outer span is the replayable root and the model-call spans nest beneath it.
4126
+ *
4127
+ * Nesting is captured when the model is called, so keep the
4128
+ * `generateText` / `streamText` call inside this handle's `withSpan`; the
4129
+ * middleware object itself can be created anywhere.
4130
+ *
4131
+ * ```typescript
4132
+ * const chatTurn = client.getFunction("chat-turn");
4133
+ * const runChatTurn = chatTurn.withSpan(
4134
+ * { type: "agent", finalize: finalizers.aiSdk },
4135
+ * (messages) => streamText({ model, messages }),
4136
+ * );
4137
+ * const model = wrapLanguageModel({
4138
+ * model: openai("gpt-4o"),
4139
+ * middleware: chatTurn.getVercelAiMiddleware(),
4140
+ * });
4141
+ * ```
4142
+ *
4143
+ * @returns A Vercel AI SDK middleware configured for this client and key
4144
+ */
4145
+ getVercelAiMiddleware() {
4146
+ return this.client.getVercelAiMiddleware(this.traceFunctionKey);
4147
+ }
4148
+ /**
4149
+ * Get a Claude Agent SDK handler bound to this function's key.
4150
+ *
4151
+ * Equivalent to `client.getClaudeAgentHandler(key)` but reuses the key bound
4152
+ * on this handle, so an outer `withSpan` root and the handler share one key
4153
+ * without repeating the string. With a matching key, the outer span is the
4154
+ * replayable root and every handler span nests beneath it.
4155
+ *
4156
+ * Use the handler inside this handle's `withSpan` body so its spans capture
4157
+ * the enclosing root; framework calls made with no active span record their
4158
+ * own root instead.
4159
+ *
4160
+ * ```typescript
4161
+ * const pipeline = client.getFunction("my-agent");
4162
+ * const tracedRun = pipeline.withSpan({ type: "agent" }, async (prompt) => {
4163
+ * const handler = pipeline.getClaudeAgentHandler();
4164
+ * const options = handler.instrumentOptions({ model: "claude-sonnet-4-6" });
4165
+ * for await (const msg of handler.wrapQuery(query({ prompt, options }))) { ... }
4166
+ * });
4167
+ * ```
4168
+ *
4169
+ * @returns A Claude Agent SDK handler configured for this client and key
4170
+ */
4171
+ getClaudeAgentHandler() {
4172
+ return this.client.getClaudeAgentHandler(this.traceFunctionKey);
4173
+ }
4174
+ /**
4175
+ * Get a LangGraph/LangChain callback handler bound to this function's key.
4176
+ *
4177
+ * Equivalent to `client.getLangGraphCallbackHandler(key)` but reuses the key
4178
+ * bound on this handle, so an outer `withSpan` root and the handler share one
4179
+ * key without repeating the string. With a matching key, the outer span is
4180
+ * the replayable root and the LangGraph spans nest beneath it.
4181
+ *
4182
+ * Use the handler inside this handle's `withSpan` body so its spans capture
4183
+ * the enclosing root; framework calls made with no active span record their
4184
+ * own root instead.
4185
+ *
4186
+ * ```typescript
4187
+ * const pipeline = client.getFunction("my-pipeline");
4188
+ * const tracedRun = pipeline.withSpan({ type: "agent" }, async (query) => {
4189
+ * const handler = pipeline.getLangGraphCallbackHandler();
4190
+ * return agent.invoke({ messages: [...] }, { callbacks: [handler] });
4191
+ * });
4192
+ * ```
4193
+ *
4194
+ * @returns A LangGraph/LangChain callback handler for this client and key
4195
+ */
4196
+ getLangGraphCallbackHandler() {
4197
+ return this.client.getLangGraphCallbackHandler(this.traceFunctionKey);
4198
+ }
4199
+ /**
4200
+ * Alias of {@link getLangGraphCallbackHandler} — LangChain and LangGraph
4201
+ * share one callback system, so the same bound handler serves both.
4202
+ *
4203
+ * @returns A LangChain callback handler for this client and key
4204
+ */
4205
+ getLangChainCallbackHandler() {
4206
+ return this.client.getLangChainCallbackHandler(this.traceFunctionKey);
4207
+ }
4098
4208
  /**
4099
4209
  * Wrap a BAML client method to automatically capture prompt and LLM metadata.
4100
4210
  * Delegates to the parent client's wrapBAML method.
4101
4211
  *
4212
+ * Unlike the other methods on this handle, `wrapBAML` does NOT use the bound
4213
+ * key: it opens no span of its own. It enriches the *current* span (via
4214
+ * `getCurrentSpan().setPrompt()` / `addContext()`), so call it inside a
4215
+ * function wrapped by this handle's `withSpan` — the bound key keys that
4216
+ * wrapper, and the BAML prompt/metadata attach to it.
4217
+ *
4102
4218
  * @param methodOrClient - Either a BAML method (uses constructor bamlClient) or the BAML client instance
4103
4219
  * @param maybeMethodOrOptions - The BAML method when the first argument is a client, or WrapBAMLOptions when the first argument is the method
4104
4220
  * @param maybeOptions - WrapBAMLOptions when using the two-argument (client, method) form