bitfab 0.40.0 → 0.42.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.cjs CHANGED
@@ -51,7 +51,7 @@ var __version__, __packageName__;
51
51
  var init_version_generated = __esm({
52
52
  "src/version.generated.ts"() {
53
53
  "use strict";
54
- __version__ = "0.40.0";
54
+ __version__ = "0.42.0";
55
55
  __packageName__ = "bitfab";
56
56
  }
57
57
  });
@@ -1346,7 +1346,7 @@ function sourceTraceIdOf(payload) {
1346
1346
  const id = rawTrace?.id;
1347
1347
  return typeof id === "string" ? id : void 0;
1348
1348
  }
1349
- var REPLAY_DB_BRANCH_REQUEST_TIMEOUT_MS, OTLP_TRACES_ENDPOINT, RETRYABLE_STATUSES, EXIT_FLUSH_TIMEOUT_MS, DEFAULT_LIFECYCLE_TIMEOUT_MS2, pendingTracePromises, carrierSeq, HttpClient;
1349
+ var REPLAY_DB_BRANCH_REQUEST_TIMEOUT_MS, REPLAY_COMPLETE_REQUEST_TIMEOUT_MS, OTLP_TRACES_ENDPOINT, RETRYABLE_STATUSES, EXIT_FLUSH_TIMEOUT_MS, DEFAULT_LIFECYCLE_TIMEOUT_MS2, pendingTracePromises, carrierSeq, HttpClient;
1350
1350
  var init_http = __esm({
1351
1351
  "src/http.ts"() {
1352
1352
  "use strict";
@@ -1360,6 +1360,7 @@ var init_http = __esm({
1360
1360
  init_unrefTimer();
1361
1361
  init_warnOnce();
1362
1362
  REPLAY_DB_BRANCH_REQUEST_TIMEOUT_MS = 3e5;
1363
+ REPLAY_COMPLETE_REQUEST_TIMEOUT_MS = 12e4;
1363
1364
  OTLP_TRACES_ENDPOINT = "/api/sdk/otel/v1/traces";
1364
1365
  RETRYABLE_STATUSES = /* @__PURE__ */ new Set([429, 500, 502, 503, 504]);
1365
1366
  EXIT_FLUSH_TIMEOUT_MS = 5e3;
@@ -1849,7 +1850,7 @@ var init_http = __esm({
1849
1850
  * Start a replay session by fetching historical traces.
1850
1851
  * Blocking call - creates a test run and returns lightweight item references.
1851
1852
  */
1852
- async startReplay(traceFunctionKey, limit, traceIds, name, codeChangeDescription, codeChangeFiles, includeDbBranchLease, experimentGroupId, datasetId, graderIds, dbBranchSettings) {
1853
+ async startReplay(traceFunctionKey, limit, traceIds, name, codeChangeDescription, codeChangeFiles, includeDbBranchLease, experimentGroupId, datasetId, graderIds, dbBranchSettings, attempts) {
1853
1854
  const payload = { traceFunctionKey };
1854
1855
  if (limit !== void 0) {
1855
1856
  payload.limit = limit;
@@ -1882,6 +1883,9 @@ var init_http = __esm({
1882
1883
  if (dbBranchSettings !== void 0) {
1883
1884
  payload.dbBranchSettings = dbBranchSettings;
1884
1885
  }
1886
+ if (attempts !== void 0 && attempts > 1) {
1887
+ payload.attempts = attempts;
1888
+ }
1885
1889
  const timeout = includeDbBranchLease ? REPLAY_DB_BRANCH_REQUEST_TIMEOUT_MS : 3e4;
1886
1890
  return this.request("/api/sdk/replay/start", payload, {
1887
1891
  timeout
@@ -1997,7 +2001,7 @@ var init_http = __esm({
1997
2001
  return this.request(
1998
2002
  "/api/sdk/replay/complete",
1999
2003
  { testRunId },
2000
- { timeout: 3e4 }
2004
+ { timeout: REPLAY_COMPLETE_REQUEST_TIMEOUT_MS }
2001
2005
  );
2002
2006
  }
2003
2007
  /**
@@ -2006,10 +2010,15 @@ var init_http = __esm({
2006
2010
  * snapshot + preview branch and polls operations to readiness, which
2007
2011
  * can take seconds.
2008
2012
  */
2009
- async resolveDbBranchLease(testRunId, traceId, dbBranchSettings) {
2013
+ async resolveDbBranchLease(testRunId, traceId, dbBranchSettings, attempt) {
2010
2014
  return this.request(
2011
2015
  "/api/sdk/replay/resolveDbBranchLease",
2012
- { testRunId, traceId, dbBranchSettings },
2016
+ {
2017
+ testRunId,
2018
+ traceId,
2019
+ dbBranchSettings,
2020
+ ...attempt !== void 0 && attempt > 0 ? { attempt } : {}
2021
+ },
2013
2022
  { timeout: REPLAY_DB_BRANCH_REQUEST_TIMEOUT_MS }
2014
2023
  );
2015
2024
  }
@@ -2445,6 +2454,23 @@ __export(replay_exports, {
2445
2454
  sleepForReplayPersistence: () => sleepForReplayPersistence,
2446
2455
  waitForReplayPersistence: () => waitForReplayPersistence
2447
2456
  });
2457
+ function expandReplayWork(serverItems, attempts) {
2458
+ return Array.from(
2459
+ { length: attempts },
2460
+ (_, attempt) => serverItems.map((serverItem) => ({ serverItem, attempt }))
2461
+ ).flat();
2462
+ }
2463
+ function resolveAttempts(attempts) {
2464
+ if (attempts === void 0) {
2465
+ return 1;
2466
+ }
2467
+ if (!Number.isInteger(attempts) || attempts < 1 || attempts > MAX_REPLAY_ATTEMPTS) {
2468
+ throw new BitfabError(
2469
+ `attempts must be an integer from 1 to ${MAX_REPLAY_ATTEMPTS} (got ${attempts}).`
2470
+ );
2471
+ }
2472
+ return attempts;
2473
+ }
2448
2474
  function dbBranchEnabled(dbBranch) {
2449
2475
  return dbBranch !== void 0 && dbBranch !== false;
2450
2476
  }
@@ -2568,7 +2594,7 @@ function buildMockTree(rootNode) {
2568
2594
  }
2569
2595
  return { spans };
2570
2596
  }
2571
- async function processItem(httpClient, serverItem, fn, testRunId, mockStrategy, resolvedOverrides, replayedTraceId, includeDbBranchLease, dbBranchSettings, adaptInputs, dryRun) {
2597
+ async function processItem(httpClient, serverItem, fn, testRunId, mockStrategy, resolvedOverrides, replayedTraceId, attempt, includeDbBranchLease, dbBranchSettings, adaptInputs, dryRun) {
2572
2598
  let lease = includeDbBranchLease ? serverItem.dbBranchLease : void 0;
2573
2599
  let leaseError = includeDbBranchLease ? serverItem.dbBranchLeaseError : void 0;
2574
2600
  let dbSnapshotRef = serverItem.dbSnapshotRef;
@@ -2590,7 +2616,8 @@ async function processItem(httpClient, serverItem, fn, testRunId, mockStrategy,
2590
2616
  resolved = await httpClient.resolveDbBranchLease(
2591
2617
  testRunId,
2592
2618
  originalTraceId,
2593
- dbBranchSettings
2619
+ dbBranchSettings,
2620
+ attempt
2594
2621
  );
2595
2622
  } catch (cause) {
2596
2623
  throw new DbBranchReplayError(
@@ -2670,6 +2697,7 @@ async function processItem(httpClient, serverItem, fn, testRunId, mockStrategy,
2670
2697
  originalSpanId,
2671
2698
  sourceTraceId: originalTraceId,
2672
2699
  sourceSpanId: originalSpanId,
2700
+ attempt,
2673
2701
  input: inputs,
2674
2702
  result: void 0,
2675
2703
  originalOutput,
@@ -2698,6 +2726,7 @@ async function processItem(httpClient, serverItem, fn, testRunId, mockStrategy,
2698
2726
  inputSourceSpanId: span.id,
2699
2727
  inputSourceTraceId: span.externalTraceId,
2700
2728
  sourceBitfabTraceId: originalTraceId,
2729
+ replayAttempt: attempt,
2701
2730
  mockTree,
2702
2731
  callCounters: mockTree ? /* @__PURE__ */ new Map() : void 0,
2703
2732
  mockStrategy,
@@ -2749,6 +2778,7 @@ async function processItem(httpClient, serverItem, fn, testRunId, mockStrategy,
2749
2778
  // Deprecated aliases for originalTraceId/originalSpanId.
2750
2779
  sourceTraceId: originalTraceId,
2751
2780
  sourceSpanId: originalSpanId,
2781
+ attempt,
2752
2782
  input: inputs,
2753
2783
  result,
2754
2784
  originalOutput,
@@ -2877,6 +2907,7 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
2877
2907
  } catch {
2878
2908
  }
2879
2909
  }
2910
+ const attempts = resolveAttempts(options?.attempts);
2880
2911
  await replayContextReady;
2881
2912
  let codeChangeDescription = options?.codeChangeDescription;
2882
2913
  let codeChangeFiles = options?.codeChangeFiles;
@@ -2909,7 +2940,8 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
2909
2940
  options?.experimentGroupId,
2910
2941
  options?.datasetId,
2911
2942
  options?.graderIds,
2912
- resolveDbBranchSettings(options?.dbBranch)
2943
+ resolveDbBranchSettings(options?.dbBranch),
2944
+ attempts
2913
2945
  );
2914
2946
  if (serverItems.length === 0) {
2915
2947
  try {
@@ -2926,10 +2958,11 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
2926
2958
  ...normalizeMockOverrides(options?.mockOverride),
2927
2959
  ...registeredOverrides
2928
2960
  ];
2929
- const replayedTraceIds = serverItems.map(() => randomUuid());
2961
+ const workItems = expandReplayWork(serverItems, attempts);
2962
+ const replayedTraceIds = workItems.map(() => randomUuid());
2930
2963
  httpClient.trackTraceDeliveries(replayedTraceIds);
2931
- const tasks = serverItems.map(
2932
- (serverItem, index) => () => processItem(
2964
+ const tasks = workItems.map(
2965
+ ({ serverItem, attempt }, index) => () => processItem(
2933
2966
  httpClient,
2934
2967
  serverItem,
2935
2968
  fn,
@@ -2937,6 +2970,7 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
2937
2970
  mockStrategy,
2938
2971
  resolvedOverrides,
2939
2972
  replayedTraceIds[index],
2973
+ attempt,
2940
2974
  dbBranchEnabled(options?.dbBranch) && options?.dryRun !== true,
2941
2975
  resolveDbBranchSettings(options?.dbBranch),
2942
2976
  options?.adaptInputs,
@@ -3004,6 +3038,7 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
3004
3038
  // Deprecated aliases for originalTraceId/originalSpanId.
3005
3039
  sourceTraceId: item.originalTraceId ?? null,
3006
3040
  sourceSpanId: item.originalSpanId ?? null,
3041
+ attempt: item.attempt,
3007
3042
  input: item.input,
3008
3043
  result: item.result,
3009
3044
  originalOutput: item.originalOutput,
@@ -3025,7 +3060,7 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
3025
3060
  },
3026
3061
  options?.onItemStart ? (index) => {
3027
3062
  started += 1;
3028
- const serverItem = serverItems[index];
3063
+ const { serverItem, attempt } = workItems[index];
3029
3064
  const originalTraceId = serverItem.originalTraceId ?? serverItem.sourceTraceId;
3030
3065
  const originalSpanId = serverItem.originalSpanId ?? serverItem.sourceSpanId;
3031
3066
  try {
@@ -3041,7 +3076,8 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
3041
3076
  originalTraceId,
3042
3077
  originalSpanId,
3043
3078
  sourceTraceId: originalTraceId,
3044
- sourceSpanId: originalSpanId
3079
+ sourceSpanId: originalSpanId,
3080
+ attempt
3045
3081
  }
3046
3082
  });
3047
3083
  } catch {
@@ -3053,7 +3089,8 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
3053
3089
  const dryResult = {
3054
3090
  items: resultItems,
3055
3091
  testRunId,
3056
- testRunUrl: fullTestRunUrl
3092
+ testRunUrl: fullTestRunUrl,
3093
+ attempts
3057
3094
  };
3058
3095
  await writeReplayResultFile(dryResult);
3059
3096
  return dryResult;
@@ -3122,7 +3159,8 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
3122
3159
  const result = {
3123
3160
  items: resultItems,
3124
3161
  testRunId,
3125
- testRunUrl: fullTestRunUrl
3162
+ testRunUrl: fullTestRunUrl,
3163
+ attempts
3126
3164
  };
3127
3165
  await writeReplayResultFile(result);
3128
3166
  if (!options?.onItemFinish) {
@@ -3163,7 +3201,7 @@ async function writeReplayResultFile(result) {
3163
3201
  }
3164
3202
  }
3165
3203
  }
3166
- var REPLAY_PERSISTENCE_TIMEOUT_MS, BITFAB_PROGRESS_PREFIX, ReplayError, DbBranchReplayError;
3204
+ var REPLAY_PERSISTENCE_TIMEOUT_MS, MAX_REPLAY_ATTEMPTS, BITFAB_PROGRESS_PREFIX, ReplayError, DbBranchReplayError;
3167
3205
  var init_replay = __esm({
3168
3206
  "src/replay.ts"() {
3169
3207
  "use strict";
@@ -3175,6 +3213,7 @@ var init_replay = __esm({
3175
3213
  init_replayContext();
3176
3214
  init_serialize();
3177
3215
  REPLAY_PERSISTENCE_TIMEOUT_MS = 3e4;
3216
+ MAX_REPLAY_ATTEMPTS = 100;
3178
3217
  BITFAB_PROGRESS_PREFIX = "@@bitfab:progress ";
3179
3218
  ReplayError = class extends BitfabError {
3180
3219
  constructor(message, items, testRunId, testRunUrl, cause) {
@@ -3532,8 +3571,7 @@ var BitfabClaudeAgentHandler = class {
3532
3571
  const externalTrace = {
3533
3572
  id: traceId,
3534
3573
  started_at: this.traceStartedAt ?? nowIso(),
3535
- ended_at: endedAt ?? nowIso(),
3536
- workflow_name: this.traceFunctionKey
3574
+ ended_at: endedAt ?? nowIso()
3537
3575
  };
3538
3576
  if (metadata) {
3539
3577
  externalTrace.metadata = metadata;
@@ -4827,8 +4865,7 @@ var BitfabLangGraphCallbackHandler = class {
4827
4865
  externalTrace: {
4828
4866
  id: rootSpan.traceId,
4829
4867
  started_at: rootSpan.startedAt,
4830
- ended_at: rootSpan.endedAt ?? nowIso2(),
4831
- workflow_name: this.traceFunctionKey
4868
+ ended_at: rootSpan.endedAt ?? nowIso2()
4832
4869
  },
4833
4870
  completed
4834
4871
  };
@@ -4846,8 +4883,7 @@ var BitfabLangGraphCallbackHandler = class {
4846
4883
  traceFunctionKey: this.traceFunctionKey,
4847
4884
  externalTrace: {
4848
4885
  id: rootSpan.traceId,
4849
- started_at: rootSpan.startedAt,
4850
- workflow_name: this.traceFunctionKey
4886
+ started_at: rootSpan.startedAt
4851
4887
  },
4852
4888
  completed: false
4853
4889
  };
@@ -6005,6 +6041,8 @@ var noOpSpan = {
6005
6041
  var noOpTrace = {
6006
6042
  setSessionId() {
6007
6043
  },
6044
+ setName() {
6045
+ },
6008
6046
  setMetadata() {
6009
6047
  },
6010
6048
  addContext() {
@@ -6079,6 +6117,15 @@ function getCurrentTrace() {
6079
6117
  } catch {
6080
6118
  }
6081
6119
  },
6120
+ setName(name) {
6121
+ if (typeof name !== "string" || name.length === 0) {
6122
+ return;
6123
+ }
6124
+ try {
6125
+ getOrCreateTraceState().name = name;
6126
+ } catch {
6127
+ }
6128
+ },
6082
6129
  setMetadata(metadata) {
6083
6130
  try {
6084
6131
  if (typeof metadata !== "object" || metadata === null) {
@@ -7013,6 +7060,9 @@ var Bitfab = class {
7013
7060
  ...replayCtxAtStart?.inputSourceTraceId && {
7014
7061
  inputSourceTraceId: replayCtxAtStart.inputSourceTraceId
7015
7062
  },
7063
+ ...replayCtxAtStart?.replayAttempt !== void 0 && {
7064
+ replayAttempt: replayCtxAtStart.replayAttempt
7065
+ },
7016
7066
  dbSnapshotRef
7017
7067
  });
7018
7068
  registeredTraceId = traceId;
@@ -7058,10 +7108,12 @@ var Bitfab = class {
7058
7108
  startedAt: traceState?.startedAt ?? startedAt,
7059
7109
  endedAt,
7060
7110
  sessionId: traceState?.sessionId,
7111
+ name: traceState?.name,
7061
7112
  metadata: traceState?.metadata,
7062
7113
  contexts: traceState?.contexts ?? [],
7063
7114
  testRunId: traceState?.testRunId,
7064
7115
  inputSourceTraceId: traceState?.inputSourceTraceId,
7116
+ replayAttempt: traceState?.replayAttempt,
7065
7117
  dbSnapshotRef: traceState?.dbSnapshotRef,
7066
7118
  dropped: traceState?.dropped,
7067
7119
  ingestionType: traceState?.ingestionType,
@@ -7376,6 +7428,15 @@ var Bitfab = class {
7376
7428
  return Promise.resolve();
7377
7429
  }
7378
7430
  return this.httpClient.patchTrace(traceId, { setSessionId: sessionId });
7431
+ },
7432
+ setName: (name) => {
7433
+ if (!this.isTracingEnabled()) {
7434
+ return Promise.resolve();
7435
+ }
7436
+ if (typeof name !== "string" || name.length === 0) {
7437
+ return Promise.resolve();
7438
+ }
7439
+ return this.httpClient.patchTrace(traceId, { setName: name });
7379
7440
  }
7380
7441
  };
7381
7442
  }
@@ -7436,9 +7497,11 @@ var Bitfab = class {
7436
7497
  const rawTrace = {
7437
7498
  id: params.traceId,
7438
7499
  started_at: params.startedAt,
7439
- ended_at: params.endedAt,
7440
- workflow_name: params.traceFunctionKey
7500
+ ended_at: params.endedAt
7441
7501
  };
7502
+ if (params.name) {
7503
+ rawTrace.name = params.name;
7504
+ }
7442
7505
  if (params.metadata && Object.keys(params.metadata).length > 0) {
7443
7506
  rawTrace.metadata = params.metadata;
7444
7507
  }
@@ -7448,6 +7511,9 @@ var Bitfab = class {
7448
7511
  if (params.inputSourceTraceId) {
7449
7512
  rawTrace.input_source_trace_id = params.inputSourceTraceId;
7450
7513
  }
7514
+ if (params.replayAttempt !== void 0) {
7515
+ rawTrace.replay_attempt = params.replayAttempt;
7516
+ }
7451
7517
  if (params.dbSnapshotRef) {
7452
7518
  rawTrace.db_snapshot_ref = params.dbSnapshotRef;
7453
7519
  }
@@ -7631,6 +7697,7 @@ var Bitfab = class {
7631
7697
  contexts: [],
7632
7698
  ingestionType: "seeded",
7633
7699
  ...options.sessionId !== void 0 && { sessionId: options.sessionId },
7700
+ ...options.name !== void 0 && { name: options.name },
7634
7701
  ...options.metadata !== void 0 && { metadata: options.metadata }
7635
7702
  });
7636
7703
  try {
@@ -7653,6 +7720,7 @@ var Bitfab = class {
7653
7720
  startedAt,
7654
7721
  endedAt: startedAt,
7655
7722
  sessionId: options.sessionId,
7723
+ name: options.name,
7656
7724
  metadata: options.metadata,
7657
7725
  contexts: [],
7658
7726
  ingestionType: "seeded"