bitfab 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
@@ -51,7 +51,7 @@ var __version__;
51
51
  var init_version_generated = __esm({
52
52
  "src/version.generated.ts"() {
53
53
  "use strict";
54
- __version__ = "0.36.4";
54
+ __version__ = "0.36.6";
55
55
  }
56
56
  });
57
57
 
@@ -2393,12 +2393,13 @@ function sleep(ms) {
2393
2393
  unrefTimer(timer);
2394
2394
  });
2395
2395
  }
2396
- async function mapWithConcurrency2(tasks, maxConcurrency, onSettled) {
2396
+ async function mapWithConcurrency2(tasks, maxConcurrency, onSettled, onStarted) {
2397
2397
  const results = new Array(tasks.length);
2398
2398
  let nextIndex = 0;
2399
2399
  async function worker() {
2400
2400
  while (nextIndex < tasks.length) {
2401
2401
  const index = nextIndex++;
2402
+ onStarted?.(index);
2402
2403
  const result = await tasks[index]();
2403
2404
  results[index] = result;
2404
2405
  onSettled?.(result, index);
@@ -2485,13 +2486,15 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
2485
2486
  )
2486
2487
  );
2487
2488
  const total = tasks.length;
2489
+ const onItemFinish = options?.onItemFinish ?? options?.onProgress;
2488
2490
  let completed = 0;
2491
+ let started = 0;
2489
2492
  let succeeded = 0;
2490
2493
  let errored = 0;
2491
2494
  const resultItems = await mapWithConcurrency2(
2492
2495
  tasks,
2493
2496
  maxConcurrency,
2494
- options?.onProgress ? (item) => {
2497
+ (item) => {
2495
2498
  completed += 1;
2496
2499
  if (item.error === null) {
2497
2500
  succeeded += 1;
@@ -2499,18 +2502,17 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
2499
2502
  errored += 1;
2500
2503
  }
2501
2504
  try {
2502
- options?.onProgress?.({
2505
+ onItemFinish?.({
2503
2506
  testRunId,
2504
2507
  completed,
2505
2508
  total,
2506
2509
  succeeded,
2507
2510
  errored,
2508
2511
  item: {
2509
- // The server replay trace id isn't known until completeReplay
2510
- // runs (below), so it can't be reported mid-run and we never
2511
- // emit the client-side placeholder. originalTraceId (the
2512
- // historical trace) is known now and is what a UI keys on to
2513
- // identify what just settled.
2512
+ // The server replay trace id isn't known until completeReplay runs
2513
+ // (below), so it can't be reported mid-run and we never emit the
2514
+ // client-side placeholder. originalTraceId (the historical trace)
2515
+ // is known now and is what a UI keys on to identify what settled.
2514
2516
  traceId: null,
2515
2517
  originalTraceId: item.originalTraceId ?? null,
2516
2518
  originalSpanId: item.originalSpanId ?? null,
@@ -2531,6 +2533,30 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
2531
2533
  });
2532
2534
  } catch {
2533
2535
  }
2536
+ },
2537
+ options?.onItemStart ? (index) => {
2538
+ started += 1;
2539
+ const serverItem = serverItems[index];
2540
+ const originalTraceId = serverItem.originalTraceId ?? serverItem.sourceTraceId;
2541
+ const originalSpanId = serverItem.originalSpanId ?? serverItem.sourceSpanId;
2542
+ try {
2543
+ options.onItemStart?.({
2544
+ type: "started",
2545
+ testRunId,
2546
+ started,
2547
+ completed,
2548
+ total,
2549
+ succeeded,
2550
+ errored,
2551
+ item: {
2552
+ originalTraceId,
2553
+ originalSpanId,
2554
+ sourceTraceId: originalTraceId,
2555
+ sourceSpanId: originalSpanId
2556
+ }
2557
+ });
2558
+ } catch {
2559
+ }
2534
2560
  } : void 0
2535
2561
  );
2536
2562
  await preserveReplayFailure(
@@ -2593,17 +2619,19 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
2593
2619
  testRunUrl: fullTestRunUrl
2594
2620
  };
2595
2621
  await writeReplayResultFile(result);
2596
- try {
2597
- options?.onProgress?.({
2598
- type: "complete",
2599
- testRunId,
2600
- completed: total,
2601
- total,
2602
- succeeded,
2603
- errored,
2604
- result
2605
- });
2606
- } catch {
2622
+ if (!options?.onItemFinish) {
2623
+ try {
2624
+ options?.onProgress?.({
2625
+ type: "complete",
2626
+ testRunId,
2627
+ completed: total,
2628
+ total,
2629
+ succeeded,
2630
+ errored,
2631
+ result
2632
+ });
2633
+ } catch {
2634
+ }
2607
2635
  }
2608
2636
  return result;
2609
2637
  }
@@ -5777,7 +5805,7 @@ var Bitfab = class {
5777
5805
  }
5778
5806
  };
5779
5807
  executeWithContext = () => {
5780
- const result = fn(...args);
5808
+ const result = fn.apply(this, args);
5781
5809
  if (result instanceof Promise) {
5782
5810
  return result.then((resolvedResult) => {
5783
5811
  recordSpan(resolvedResult);
@@ -5807,7 +5835,7 @@ var Bitfab = class {
5807
5835
  `withSpan-setup:${traceFunctionKey}`,
5808
5836
  `tracing setup failed for "${traceFunctionKey}"; running it untraced. The function still runs and returns normally; no span is recorded.`
5809
5837
  );
5810
- return fn(...args);
5838
+ return fn.apply(this, args);
5811
5839
  }
5812
5840
  return runWithSpanStack(newStack, executeWithContext);
5813
5841
  };
@@ -5816,6 +5844,40 @@ var Bitfab = class {
5816
5844
  });
5817
5845
  return wrappedFn;
5818
5846
  }
5847
+ /**
5848
+ * Create a standard ECMAScript method decorator that records each invocation
5849
+ * as a span.
5850
+ *
5851
+ * It supports instance, static, and private methods; use
5852
+ * {@link Bitfab.withSpan} for standalone functions, class fields, and
5853
+ * accessors.
5854
+ *
5855
+ * @example
5856
+ * ```typescript
5857
+ * const bitfab = new Bitfab({ apiKey: process.env.BITFAB_API_KEY });
5858
+ *
5859
+ * class OrderService {
5860
+ * @bitfab.span("order-processing", { type: "agent" })
5861
+ * async process(orderId: string) {
5862
+ * return { orderId };
5863
+ * }
5864
+ * }
5865
+ * ```
5866
+ *
5867
+ * @param traceFunctionKey - A string identifier for grouping spans
5868
+ * @param options - Span configuration applied to the decorated method
5869
+ * @returns A standard ECMAScript method decorator
5870
+ */
5871
+ span(traceFunctionKey, options = {}) {
5872
+ return (originalMethod, context) => {
5873
+ if (context.kind !== "method") {
5874
+ throw new BitfabError(
5875
+ `Bitfab span decorators can only decorate methods; ${String(context.name)} is a ${context.kind}`
5876
+ );
5877
+ }
5878
+ return this.withSpan(traceFunctionKey, options, originalMethod);
5879
+ };
5880
+ }
5819
5881
  /**
5820
5882
  * Get a detached handle to a previously-created trace, looked up by the
5821
5883
  * canonical Bitfab trace ID.
@@ -6092,6 +6154,27 @@ var BitfabFunction = class {
6092
6154
  const fn = typeof optionsOrFn === "function" ? optionsOrFn : maybeFn;
6093
6155
  return this.client.withSpan(this.traceFunctionKey, options, fn);
6094
6156
  }
6157
+ /**
6158
+ * Create a standard ECMAScript method decorator bound to this function key.
6159
+ *
6160
+ * @example
6161
+ * ```typescript
6162
+ * const orders = client.getFunction("order-processing");
6163
+ *
6164
+ * class OrderService {
6165
+ * @orders.span({ type: "agent" })
6166
+ * async process(orderId: string) {
6167
+ * return { orderId };
6168
+ * }
6169
+ * }
6170
+ * ```
6171
+ *
6172
+ * @param options - Span configuration applied to the decorated method
6173
+ * @returns A standard ECMAScript method decorator
6174
+ */
6175
+ span(options = {}) {
6176
+ return this.client.span(this.traceFunctionKey, options);
6177
+ }
6095
6178
  /**
6096
6179
  * Get a Vercel AI SDK language-model middleware bound to this function's key.
6097
6180
  *