@bitfab/sdk 0.36.4 → 0.36.6

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.cjs CHANGED
@@ -42,7 +42,7 @@ var __version__;
42
42
  var init_version_generated = __esm({
43
43
  "src/version.generated.ts"() {
44
44
  "use strict";
45
- __version__ = "0.36.4";
45
+ __version__ = "0.36.6";
46
46
  }
47
47
  });
48
48
 
@@ -2384,12 +2384,13 @@ function sleep(ms) {
2384
2384
  unrefTimer(timer);
2385
2385
  });
2386
2386
  }
2387
- async function mapWithConcurrency2(tasks, maxConcurrency, onSettled) {
2387
+ async function mapWithConcurrency2(tasks, maxConcurrency, onSettled, onStarted) {
2388
2388
  const results = new Array(tasks.length);
2389
2389
  let nextIndex = 0;
2390
2390
  async function worker() {
2391
2391
  while (nextIndex < tasks.length) {
2392
2392
  const index = nextIndex++;
2393
+ onStarted?.(index);
2393
2394
  const result = await tasks[index]();
2394
2395
  results[index] = result;
2395
2396
  onSettled?.(result, index);
@@ -2476,13 +2477,15 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
2476
2477
  )
2477
2478
  );
2478
2479
  const total = tasks.length;
2480
+ const onItemFinish = options?.onItemFinish ?? options?.onProgress;
2479
2481
  let completed = 0;
2482
+ let started = 0;
2480
2483
  let succeeded = 0;
2481
2484
  let errored = 0;
2482
2485
  const resultItems = await mapWithConcurrency2(
2483
2486
  tasks,
2484
2487
  maxConcurrency,
2485
- options?.onProgress ? (item) => {
2488
+ (item) => {
2486
2489
  completed += 1;
2487
2490
  if (item.error === null) {
2488
2491
  succeeded += 1;
@@ -2490,18 +2493,17 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
2490
2493
  errored += 1;
2491
2494
  }
2492
2495
  try {
2493
- options?.onProgress?.({
2496
+ onItemFinish?.({
2494
2497
  testRunId,
2495
2498
  completed,
2496
2499
  total,
2497
2500
  succeeded,
2498
2501
  errored,
2499
2502
  item: {
2500
- // The server replay trace id isn't known until completeReplay
2501
- // runs (below), so it can't be reported mid-run and we never
2502
- // emit the client-side placeholder. originalTraceId (the
2503
- // historical trace) is known now and is what a UI keys on to
2504
- // identify what just settled.
2503
+ // The server replay trace id isn't known until completeReplay runs
2504
+ // (below), so it can't be reported mid-run and we never emit the
2505
+ // client-side placeholder. originalTraceId (the historical trace)
2506
+ // is known now and is what a UI keys on to identify what settled.
2505
2507
  traceId: null,
2506
2508
  originalTraceId: item.originalTraceId ?? null,
2507
2509
  originalSpanId: item.originalSpanId ?? null,
@@ -2522,6 +2524,30 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
2522
2524
  });
2523
2525
  } catch {
2524
2526
  }
2527
+ },
2528
+ options?.onItemStart ? (index) => {
2529
+ started += 1;
2530
+ const serverItem = serverItems[index];
2531
+ const originalTraceId = serverItem.originalTraceId ?? serverItem.sourceTraceId;
2532
+ const originalSpanId = serverItem.originalSpanId ?? serverItem.sourceSpanId;
2533
+ try {
2534
+ options.onItemStart?.({
2535
+ type: "started",
2536
+ testRunId,
2537
+ started,
2538
+ completed,
2539
+ total,
2540
+ succeeded,
2541
+ errored,
2542
+ item: {
2543
+ originalTraceId,
2544
+ originalSpanId,
2545
+ sourceTraceId: originalTraceId,
2546
+ sourceSpanId: originalSpanId
2547
+ }
2548
+ });
2549
+ } catch {
2550
+ }
2525
2551
  } : void 0
2526
2552
  );
2527
2553
  await preserveReplayFailure(
@@ -2584,17 +2610,19 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
2584
2610
  testRunUrl: fullTestRunUrl
2585
2611
  };
2586
2612
  await writeReplayResultFile(result);
2587
- try {
2588
- options?.onProgress?.({
2589
- type: "complete",
2590
- testRunId,
2591
- completed: total,
2592
- total,
2593
- succeeded,
2594
- errored,
2595
- result
2596
- });
2597
- } catch {
2613
+ if (!options?.onItemFinish) {
2614
+ try {
2615
+ options?.onProgress?.({
2616
+ type: "complete",
2617
+ testRunId,
2618
+ completed: total,
2619
+ total,
2620
+ succeeded,
2621
+ errored,
2622
+ result
2623
+ });
2624
+ } catch {
2625
+ }
2598
2626
  }
2599
2627
  return result;
2600
2628
  }
@@ -5768,7 +5796,7 @@ var Bitfab = class {
5768
5796
  }
5769
5797
  };
5770
5798
  executeWithContext = () => {
5771
- const result = fn(...args);
5799
+ const result = fn.apply(this, args);
5772
5800
  if (result instanceof Promise) {
5773
5801
  return result.then((resolvedResult) => {
5774
5802
  recordSpan(resolvedResult);
@@ -5798,7 +5826,7 @@ var Bitfab = class {
5798
5826
  `withSpan-setup:${traceFunctionKey}`,
5799
5827
  `tracing setup failed for "${traceFunctionKey}"; running it untraced. The function still runs and returns normally; no span is recorded.`
5800
5828
  );
5801
- return fn(...args);
5829
+ return fn.apply(this, args);
5802
5830
  }
5803
5831
  return runWithSpanStack(newStack, executeWithContext);
5804
5832
  };
@@ -5807,6 +5835,40 @@ var Bitfab = class {
5807
5835
  });
5808
5836
  return wrappedFn;
5809
5837
  }
5838
+ /**
5839
+ * Create a standard ECMAScript method decorator that records each invocation
5840
+ * as a span.
5841
+ *
5842
+ * It supports instance, static, and private methods; use
5843
+ * {@link Bitfab.withSpan} for standalone functions, class fields, and
5844
+ * accessors.
5845
+ *
5846
+ * @example
5847
+ * ```typescript
5848
+ * const bitfab = new Bitfab({ apiKey: process.env.BITFAB_API_KEY });
5849
+ *
5850
+ * class OrderService {
5851
+ * @bitfab.span("order-processing", { type: "agent" })
5852
+ * async process(orderId: string) {
5853
+ * return { orderId };
5854
+ * }
5855
+ * }
5856
+ * ```
5857
+ *
5858
+ * @param traceFunctionKey - A string identifier for grouping spans
5859
+ * @param options - Span configuration applied to the decorated method
5860
+ * @returns A standard ECMAScript method decorator
5861
+ */
5862
+ span(traceFunctionKey, options = {}) {
5863
+ return (originalMethod, context) => {
5864
+ if (context.kind !== "method") {
5865
+ throw new BitfabError(
5866
+ `Bitfab span decorators can only decorate methods; ${String(context.name)} is a ${context.kind}`
5867
+ );
5868
+ }
5869
+ return this.withSpan(traceFunctionKey, options, originalMethod);
5870
+ };
5871
+ }
5810
5872
  /**
5811
5873
  * Get a detached handle to a previously-created trace, looked up by the
5812
5874
  * canonical Bitfab trace ID.
@@ -6083,6 +6145,27 @@ var BitfabFunction = class {
6083
6145
  const fn = typeof optionsOrFn === "function" ? optionsOrFn : maybeFn;
6084
6146
  return this.client.withSpan(this.traceFunctionKey, options, fn);
6085
6147
  }
6148
+ /**
6149
+ * Create a standard ECMAScript method decorator bound to this function key.
6150
+ *
6151
+ * @example
6152
+ * ```typescript
6153
+ * const orders = client.getFunction("order-processing");
6154
+ *
6155
+ * class OrderService {
6156
+ * @orders.span({ type: "agent" })
6157
+ * async process(orderId: string) {
6158
+ * return { orderId };
6159
+ * }
6160
+ * }
6161
+ * ```
6162
+ *
6163
+ * @param options - Span configuration applied to the decorated method
6164
+ * @returns A standard ECMAScript method decorator
6165
+ */
6166
+ span(options = {}) {
6167
+ return this.client.span(this.traceFunctionKey, options);
6168
+ }
6086
6169
  /**
6087
6170
  * Get a Vercel AI SDK language-model middleware bound to this function's key.
6088
6171
  *