bitfab 0.58.5 → 0.59.1

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.
Files changed (42) hide show
  1. package/dist/autoTrace.cjs.map +1 -1
  2. package/dist/autoTrace.d.cts +2 -0
  3. package/dist/autoTrace.d.ts +2 -0
  4. package/dist/autoTrace.js +1 -1
  5. package/dist/{chunk-TAEWAXPA.js → chunk-3D5EEY47.js} +54 -38
  6. package/dist/chunk-3D5EEY47.js.map +1 -0
  7. package/dist/{chunk-OTQA6MCF.js → chunk-4F46OBRG.js} +18 -10
  8. package/dist/chunk-4F46OBRG.js.map +1 -0
  9. package/dist/{chunk-ETZUSSF6.js → chunk-5DNB7EN7.js} +1 -1
  10. package/dist/chunk-5DNB7EN7.js.map +1 -0
  11. package/dist/{chunk-QIBFNIIF.js → chunk-5MN6WIMW.js} +29 -14
  12. package/dist/chunk-5MN6WIMW.js.map +1 -0
  13. package/dist/{chunk-7SPNHC33.js → chunk-GJCZABUC.js} +29 -14
  14. package/dist/chunk-GJCZABUC.js.map +1 -0
  15. package/dist/{chunk-UYAQRSCB.js → chunk-NVOQ7YMI.js} +149 -41
  16. package/dist/chunk-NVOQ7YMI.js.map +1 -0
  17. package/dist/{http-F6QV3YLY.js → http-2QEMP27E.js} +4 -2
  18. package/dist/{http-XDKEIZNV.js → http-OXKVRA3E.js} +4 -2
  19. package/dist/index.cjs +225 -82
  20. package/dist/index.cjs.map +1 -1
  21. package/dist/index.d.cts +98 -43
  22. package/dist/index.d.ts +98 -43
  23. package/dist/index.js +12 -4
  24. package/dist/node.cjs +225 -82
  25. package/dist/node.cjs.map +1 -1
  26. package/dist/node.d.cts +1 -1
  27. package/dist/node.d.ts +1 -1
  28. package/dist/node.js +12 -4
  29. package/dist/node.js.map +1 -1
  30. package/dist/{replay-WLJFWS6T.js → replay-WYPFFXSU.js} +3 -3
  31. package/dist/replayCli.js +2 -2
  32. package/dist/seedCli.js +2 -2
  33. package/package.json +1 -1
  34. package/dist/chunk-7SPNHC33.js.map +0 -1
  35. package/dist/chunk-ETZUSSF6.js.map +0 -1
  36. package/dist/chunk-OTQA6MCF.js.map +0 -1
  37. package/dist/chunk-QIBFNIIF.js.map +0 -1
  38. package/dist/chunk-TAEWAXPA.js.map +0 -1
  39. package/dist/chunk-UYAQRSCB.js.map +0 -1
  40. /package/dist/{http-F6QV3YLY.js.map → http-2QEMP27E.js.map} +0 -0
  41. /package/dist/{http-XDKEIZNV.js.map → http-OXKVRA3E.js.map} +0 -0
  42. /package/dist/{replay-WLJFWS6T.js.map → replay-WYPFFXSU.js.map} +0 -0
@@ -6,7 +6,7 @@ import {
6
6
  runWithAutoTraceEntry,
7
7
  runWithAutoTraceNodeConfiguration,
8
8
  runWithAutoTraceRootContext
9
- } from "./chunk-ETZUSSF6.js";
9
+ } from "./chunk-5DNB7EN7.js";
10
10
  import {
11
11
  NO_MOCK_OVERRIDE,
12
12
  createIntegrationFixtureContext,
@@ -17,7 +17,7 @@ import {
17
17
  serializeValue,
18
18
  toJsonSafe,
19
19
  toJsonSafeReport
20
- } from "./chunk-TAEWAXPA.js";
20
+ } from "./chunk-3D5EEY47.js";
21
21
  import {
22
22
  BitfabError,
23
23
  CONTENT_OFF_KEY,
@@ -28,6 +28,7 @@ import {
28
28
  ROOT_TRACE_FUNCTION_KEY_FIELD,
29
29
  SimulationPlan,
30
30
  callerTraceMetadata,
31
+ experimentIdWireFields,
31
32
  getReplayContext,
32
33
  gitRunner,
33
34
  isFrameworkInstrumentation,
@@ -35,7 +36,7 @@ import {
35
36
  readEnv,
36
37
  recordCallerTraceMetadata,
37
38
  retireTraceMetadata
38
- } from "./chunk-7SPNHC33.js";
39
+ } from "./chunk-GJCZABUC.js";
39
40
  import {
40
41
  __privateAdd,
41
42
  __privateGet,
@@ -1262,11 +1263,39 @@ function currentCommitRef() {
1262
1263
 
1263
1264
  // src/datasets.ts
1264
1265
  var DEFAULT_RERUN_TIMEOUT_MS = 9e4;
1265
- var DEFAULT_RERUN_POLL_INTERVAL_MS = 1e3;
1266
+ var RERUN_POLL_INTERVAL_MS = 1e3;
1266
1267
  var TERMINAL_RERUN_STATUSES = /* @__PURE__ */ new Set([
1267
1268
  "completed",
1268
1269
  "errored"
1269
1270
  ]);
1271
+ var GraderRerunError = class extends Error {
1272
+ constructor(message, run) {
1273
+ super(message);
1274
+ this.run = run;
1275
+ this.name = "GraderRerunError";
1276
+ }
1277
+ };
1278
+ var GraderRerunTimeoutError = class extends GraderRerunError {
1279
+ constructor(datasetId, run, timeoutMs) {
1280
+ super(
1281
+ `Grader re-run ${run.id} on dataset ${datasetId} was still ${run.status} after ${timeoutMs}ms. It keeps running on Bitfab; read it later with getGraderRerun.`,
1282
+ run
1283
+ );
1284
+ this.name = "GraderRerunTimeoutError";
1285
+ }
1286
+ };
1287
+ function finishedRerun(datasetId, run, joinedExisting) {
1288
+ if (!TERMINAL_RERUN_STATUSES.has(run.status)) {
1289
+ return null;
1290
+ }
1291
+ if (run.status === "errored") {
1292
+ throw new GraderRerunError(
1293
+ `Grader re-run ${run.id} on dataset ${datasetId} errored: ${run.error ?? "no reason recorded"}`,
1294
+ run
1295
+ );
1296
+ }
1297
+ return { run, joinedExisting };
1298
+ }
1270
1299
  function sleep(ms) {
1271
1300
  return new Promise((resolve) => setTimeout(resolve, ms));
1272
1301
  }
@@ -1366,28 +1395,25 @@ var DatasetsClient = class {
1366
1395
  { graderIds }
1367
1396
  );
1368
1397
  }
1369
- /**
1370
- * Re-run graders over every trace in the dataset. Defaults to every assigned
1371
- * grader; an unassigned id is rejected. Waits for the run to finish (up to
1372
- * `timeoutMs`, default 90s) unless `wait` is `false`, and returns the last
1373
- * run state seen either way. A request matching an in-flight run joins it.
1374
- */
1375
1398
  async rerunGraders(datasetId, options = {}) {
1376
1399
  const started = await this.httpClient.request(
1377
1400
  datasetPath(datasetId, "/rerunGraders"),
1378
1401
  options.graderIds === void 0 ? {} : { graderIds: options.graderIds }
1379
1402
  );
1380
- if (options.wait === false) {
1381
- return started;
1382
- }
1383
- const deadline = Date.now() + (options.timeoutMs ?? DEFAULT_RERUN_TIMEOUT_MS);
1384
- const interval = options.pollIntervalMs ?? DEFAULT_RERUN_POLL_INTERVAL_MS;
1403
+ const timeoutMs = options.timeoutMs ?? DEFAULT_RERUN_TIMEOUT_MS;
1404
+ const deadline = Date.now() + timeoutMs;
1385
1405
  let run = started.run;
1386
- while (!TERMINAL_RERUN_STATUSES.has(run.status) && Date.now() < deadline) {
1387
- await sleep(interval);
1406
+ while (true) {
1407
+ const finished = finishedRerun(datasetId, run, started.joinedExisting);
1408
+ if (finished !== null) {
1409
+ return finished;
1410
+ }
1411
+ if (Date.now() >= deadline) {
1412
+ throw new GraderRerunTimeoutError(datasetId, run, timeoutMs);
1413
+ }
1414
+ await sleep(RERUN_POLL_INTERVAL_MS);
1388
1415
  run = await this.getGraderRerun(datasetId, run.id) ?? run;
1389
1416
  }
1390
- return { run, joinedExisting: started.joinedExisting };
1391
1417
  }
1392
1418
  /**
1393
1419
  * The dataset's active grader re-run, or the run named by `runId`. Returns
@@ -1459,27 +1485,27 @@ var LabelsClient = class {
1459
1485
  constructor(httpClient) {
1460
1486
  this.httpClient = httpClient;
1461
1487
  }
1462
- async save(update, testRunId) {
1463
- const [outcome] = await this.saveAll([update], testRunId);
1488
+ async save(update, experimentId) {
1489
+ const [outcome] = await this.saveAll([update], experimentId);
1464
1490
  return outcome;
1465
1491
  }
1466
- async saveAll(updates, testRunId) {
1492
+ async saveAll(updates, experimentId) {
1467
1493
  const response = await this.httpClient.request(
1468
1494
  LABELS_PATH,
1469
1495
  {
1470
1496
  labels: updates,
1471
- ...testRunId === void 0 ? {} : { testRunId }
1497
+ ...experimentId === void 0 ? {} : experimentIdWireFields(experimentId)
1472
1498
  }
1473
1499
  );
1474
1500
  return response.labels;
1475
1501
  }
1476
1502
  /** Withhold a verdict for a trace or replay attempt whose check did not run. */
1477
- async skip(target, testRunId) {
1478
- return this.save({ ...target, skip: true }, testRunId);
1503
+ async skip(target, experimentId) {
1504
+ return this.save({ ...target, skip: true }, experimentId);
1479
1505
  }
1480
1506
  /** Clear a previous verdict for a trace, replay attempt, or assertion. */
1481
- async archive(target, testRunId) {
1482
- return this.save({ ...target, archive: true }, testRunId);
1507
+ async archive(target, experimentId) {
1508
+ return this.save({ ...target, archive: true }, experimentId);
1483
1509
  }
1484
1510
  async saveHuman(update) {
1485
1511
  const [outcome] = await this.saveHumanAll([update]);
@@ -3205,6 +3231,46 @@ function runWithSeedContext(ctx, fn) {
3205
3231
  // src/traces.ts
3206
3232
  var ASSERTIONS_PATH = "/api/sdk/traces/assertions";
3207
3233
  var SEARCH_PATH = "/api/sdk/traces/search";
3234
+ var DEFAULT_GENERATION_TIMEOUT_MS = 6e5;
3235
+ var GENERATION_POLL_INTERVAL_MS = 2e3;
3236
+ var AssertionGenerationError = class extends Error {
3237
+ constructor(message, traceId) {
3238
+ super(message);
3239
+ this.traceId = traceId;
3240
+ this.name = "AssertionGenerationError";
3241
+ }
3242
+ };
3243
+ var AssertionGenerationTimeoutError = class extends AssertionGenerationError {
3244
+ constructor(traceId, timeoutMs) {
3245
+ super(
3246
+ `Assertion generation for trace ${traceId} did not finish within ${timeoutMs}ms. Generation keeps running on Bitfab. Call getAssertions and read its generation field to check its status.`,
3247
+ traceId
3248
+ );
3249
+ this.name = "AssertionGenerationTimeoutError";
3250
+ }
3251
+ };
3252
+ function sleep2(ms) {
3253
+ return new Promise((resolve) => setTimeout(resolve, ms));
3254
+ }
3255
+ function isGenerationFinished(traceId, generation) {
3256
+ if (generation === null || generation.status === "running") {
3257
+ return false;
3258
+ }
3259
+ if (generation.status === "failed") {
3260
+ throw new AssertionGenerationError(
3261
+ `Assertion generation for trace ${traceId} failed: ${generation.error ?? "no reason recorded"}. Pass regenerate: true to try again.`,
3262
+ traceId
3263
+ );
3264
+ }
3265
+ return true;
3266
+ }
3267
+ function draftsInGenerationOrder(assertions, assertionIds) {
3268
+ const byId = new Map(assertions.map((assertion) => [assertion.id, assertion]));
3269
+ return assertionIds.flatMap((id) => {
3270
+ const assertion = byId.get(id);
3271
+ return assertion === void 0 ? [] : [assertion];
3272
+ });
3273
+ }
3208
3274
  function traceAssertionsPath(traceId, suffix = "") {
3209
3275
  return `/api/sdk/traces/${encodeURIComponent(traceId)}/assertions${suffix}`;
3210
3276
  }
@@ -3236,6 +3302,34 @@ var TracesClient = class {
3236
3302
  });
3237
3303
  return response.assertions;
3238
3304
  }
3305
+ async generateAssertions(traceId, options = {}) {
3306
+ const started = await this.httpClient.request(
3307
+ traceAssertionsPath(traceId, "/generate"),
3308
+ {
3309
+ ...options.guidance === void 0 ? {} : { guidance: options.guidance },
3310
+ ...options.categoryIds === void 0 ? {} : { categoryIds: options.categoryIds },
3311
+ ...options.regenerate === void 0 ? {} : { regenerate: options.regenerate }
3312
+ }
3313
+ );
3314
+ if (isGenerationFinished(traceId, started.generation)) {
3315
+ return started.assertions;
3316
+ }
3317
+ const timeoutMs = options.timeoutMs ?? DEFAULT_GENERATION_TIMEOUT_MS;
3318
+ const deadline = Date.now() + timeoutMs;
3319
+ while (true) {
3320
+ if (Date.now() >= deadline) {
3321
+ throw new AssertionGenerationTimeoutError(traceId, timeoutMs);
3322
+ }
3323
+ await sleep2(GENERATION_POLL_INTERVAL_MS);
3324
+ const read2 = await this.getAssertions(traceId);
3325
+ if (isGenerationFinished(traceId, read2.generation)) {
3326
+ return draftsInGenerationOrder(
3327
+ read2.assertions,
3328
+ read2.generation.assertionIds
3329
+ );
3330
+ }
3331
+ }
3332
+ }
3239
3333
  async archiveAssertions(params) {
3240
3334
  const response = await this.httpClient.request(
3241
3335
  traceAssertionsPath(params.traceId, "/archive"),
@@ -3734,6 +3828,15 @@ var BitfabVercelAiHandler = class {
3734
3828
  };
3735
3829
 
3736
3830
  // src/client.ts
3831
+ function resolveSpanExperimentId(options) {
3832
+ const { experimentId, testRunId } = options;
3833
+ if (experimentId !== void 0 && testRunId !== void 0 && experimentId !== testRunId) {
3834
+ throw new BitfabError(
3835
+ `experimentId ("${experimentId}") and its deprecated alias testRunId ("${testRunId}") were both passed with different values. Pass only experimentId.`
3836
+ );
3837
+ }
3838
+ return experimentId ?? testRunId;
3839
+ }
3737
3840
  var TRUNCATION_LIMIT_ORDER = [
3738
3841
  "max_depth",
3739
3842
  "max_captured_subtree_spans"
@@ -4323,13 +4426,12 @@ var Bitfab = class {
4323
4426
  "bitfab.node({ capture: false }) cannot use mockOnReplay: true because an uncaptured node has no recorded output."
4324
4427
  );
4325
4428
  }
4429
+ const experimentId = resolveSpanExperimentId(options);
4326
4430
  return {
4327
4431
  capture,
4328
4432
  type: options.type ?? "custom",
4329
4433
  ...options.name !== void 0 && { name: options.name },
4330
- ...options.testRunId !== void 0 && {
4331
- testRunId: options.testRunId
4332
- },
4434
+ ...experimentId !== void 0 && { experimentId },
4333
4435
  ...options.mockOnReplay !== void 0 && {
4334
4436
  mockOnReplay: options.mockOnReplay
4335
4437
  },
@@ -4464,6 +4566,7 @@ var Bitfab = class {
4464
4566
  return invokeWithoutNode();
4465
4567
  }
4466
4568
  const mockOnReplay = nodeConfiguration?.mockOnReplay ?? options.mockOnReplayDefault;
4569
+ const nodeExperimentId = nodeConfiguration === void 0 ? void 0 : resolveSpanExperimentId(nodeConfiguration);
4467
4570
  const childOptions = {
4468
4571
  name: spanName,
4469
4572
  type: nodeConfiguration?.type ?? "function",
@@ -4474,8 +4577,8 @@ var Bitfab = class {
4474
4577
  captureContent: true,
4475
4578
  autoTraceDefinition: definition,
4476
4579
  ...declaredNode && { declaredNode },
4477
- ...nodeConfiguration?.testRunId !== void 0 && {
4478
- testRunId: nodeConfiguration.testRunId
4580
+ ...nodeExperimentId !== void 0 && {
4581
+ experimentId: nodeExperimentId
4479
4582
  },
4480
4583
  ...mockOnReplay !== void 0 && {
4481
4584
  mockOnReplay
@@ -5136,6 +5239,7 @@ var Bitfab = class {
5136
5239
  const options = typeof optionsOrFn === "function" ? {} : optionsOrFn;
5137
5240
  const fn = typeof optionsOrFn === "function" ? optionsOrFn : maybeFn;
5138
5241
  const self = this;
5242
+ const optionExperimentId = resolveSpanExperimentId(options);
5139
5243
  const fnIsAsyncFunction = fn.constructor.name === "AsyncFunction";
5140
5244
  const fnReturnsPromise = fnIsAsyncFunction || (() => {
5141
5245
  try {
@@ -5238,7 +5342,7 @@ var Bitfab = class {
5238
5342
  const inputs = args;
5239
5343
  const startedAt = nowIsoTimestamp();
5240
5344
  const replayCtxAtStart = getReplayContext();
5241
- const testRunId = replayCtxAtStart?.testRunId ?? options.testRunId;
5345
+ const experimentId = replayCtxAtStart?.experimentId ?? optionExperimentId;
5242
5346
  if (isRootSpan && !activeTraceStates.has(traceId)) {
5243
5347
  const dbSnapshotRef = buildSnapshotRef(self.dbSnapshot, startedAt);
5244
5348
  self.simulationPlan.refresh();
@@ -5247,7 +5351,7 @@ var Bitfab = class {
5247
5351
  traceFunctionKey,
5248
5352
  startedAt,
5249
5353
  contexts: [],
5250
- ...testRunId !== void 0 && { testRunId },
5354
+ ...experimentId !== void 0 && { experimentId },
5251
5355
  ...replayCtxAtStart?.inputSourceTraceId && {
5252
5356
  inputSourceTraceId: replayCtxAtStart.inputSourceTraceId
5253
5357
  },
@@ -5293,7 +5397,7 @@ var Bitfab = class {
5293
5397
  contexts: newContext.contexts,
5294
5398
  prompt: newContext.prompt,
5295
5399
  endedAt,
5296
- ...testRunId !== void 0 && { testRunId },
5400
+ ...experimentId !== void 0 && { experimentId },
5297
5401
  ...replayCtx?.inputSourceSpanId && {
5298
5402
  inputSourceSpanId: replayCtx.inputSourceSpanId
5299
5403
  }
@@ -5314,7 +5418,7 @@ var Bitfab = class {
5314
5418
  name: traceState?.name,
5315
5419
  metadata: callerTraceMetadata(traceId),
5316
5420
  contexts: traceState?.contexts ?? [],
5317
- testRunId: traceState?.testRunId,
5421
+ experimentId: traceState?.experimentId,
5318
5422
  inputSourceTraceId: traceState?.inputSourceTraceId,
5319
5423
  replayAttempt: traceState?.replayAttempt,
5320
5424
  dbSnapshotRef: traceState?.dbSnapshotRef,
@@ -5785,7 +5889,7 @@ var Bitfab = class {
5785
5889
  completed: true,
5786
5890
  ...params.dropped && { dropped: true },
5787
5891
  ...params.sessionId && { sessionId: params.sessionId },
5788
- ...params.testRunId && { testRunId: params.testRunId }
5892
+ ...params.experimentId !== void 0 && experimentIdWireFields(params.experimentId)
5789
5893
  });
5790
5894
  }
5791
5895
  sendsSpanOnCompletion(context) {
@@ -5897,7 +6001,7 @@ var Bitfab = class {
5897
6001
  },
5898
6002
  ...params.declaredNode === true && { [DECLARED_NODE_FIELD]: true },
5899
6003
  rawSpan: externalSpan,
5900
- ...params.testRunId && { testRunId: params.testRunId },
6004
+ ...params.experimentId !== void 0 && experimentIdWireFields(params.experimentId),
5901
6005
  ...params.mocked && { mocked: true },
5902
6006
  ...params.mockTarget && { mockTarget: params.mockTarget },
5903
6007
  ...params.mockSource && { mockSource: params.mockSource }
@@ -6043,7 +6147,7 @@ var Bitfab = class {
6043
6147
  await runWithSeedContext({ traceId }, async () => target(...args));
6044
6148
  } finally {
6045
6149
  try {
6046
- const { flushTraces: flushTraces2 } = await import("./http-F6QV3YLY.js");
6150
+ const { flushTraces: flushTraces2 } = await import("./http-2QEMP27E.js");
6047
6151
  await flushTraces2(3e4);
6048
6152
  } finally {
6049
6153
  unrecorded = activeTraceStates.delete(traceId);
@@ -6102,7 +6206,7 @@ var Bitfab = class {
6102
6206
  `Function is wrapped with trace function key '${wrappedKey}' but replay was called with '${traceFunctionKey}'. Pass matching keys, or pass the unwrapped function to replay it under the explicit key.`
6103
6207
  );
6104
6208
  }
6105
- const { replay: doReplay } = await import("./replay-WLJFWS6T.js");
6209
+ const { replay: doReplay } = await import("./replay-WYPFFXSU.js");
6106
6210
  return doReplay(
6107
6211
  this.httpClient,
6108
6212
  this.serviceUrl,
@@ -6422,7 +6526,7 @@ async function seedFromRegistry(registry, pipeline, cases, options = {}) {
6422
6526
  sessionId: seedCase.sessionId
6423
6527
  })
6424
6528
  );
6425
- const { flushTraces: flushTraces2 } = await import("./http-F6QV3YLY.js");
6529
+ const { flushTraces: flushTraces2 } = await import("./http-2QEMP27E.js");
6426
6530
  await flushTraces2(3e4);
6427
6531
  return { pipeline, traceFunctionKey, traceIds };
6428
6532
  }
@@ -6440,6 +6544,8 @@ function resolveTraceFunctionKey(registration) {
6440
6544
  export {
6441
6545
  AssertionCategoriesClient,
6442
6546
  BitfabClaudeAgentHandler,
6547
+ GraderRerunError,
6548
+ GraderRerunTimeoutError,
6443
6549
  DatasetsClient,
6444
6550
  SUPPORTED_PROVIDERS,
6445
6551
  GradersClient,
@@ -6449,6 +6555,8 @@ export {
6449
6555
  BitfabOpenAIAgentHandler,
6450
6556
  OrganizationMembersClient,
6451
6557
  BitfabRivetIntegration,
6558
+ AssertionGenerationError,
6559
+ AssertionGenerationTimeoutError,
6452
6560
  TracesClient,
6453
6561
  BitfabOpenAITracingProcessor,
6454
6562
  BitfabVercelAiHandler,
@@ -6462,4 +6570,4 @@ export {
6462
6570
  reseedFromRegistry,
6463
6571
  seedFromRegistry
6464
6572
  };
6465
- //# sourceMappingURL=chunk-UYAQRSCB.js.map
6573
+ //# sourceMappingURL=chunk-NVOQ7YMI.js.map