@bitfab/sdk 0.38.10 → 0.40.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.
@@ -7,19 +7,21 @@ import {
7
7
  runWithAutoTraceRootContext
8
8
  } from "./chunk-ZUD7OFYB.js";
9
9
  import {
10
- BitfabError,
11
- DEFAULT_SERVICE_URL,
12
- HttpClient,
13
10
  NO_MOCK_OVERRIDE,
14
11
  deserializeValue,
15
- getReplayContext,
16
12
  randomUuid,
17
13
  resolveMockValue,
18
14
  serializeValue,
19
15
  toJsonSafe,
20
- toJsonSafeReport,
16
+ toJsonSafeReport
17
+ } from "./chunk-EXT5FK54.js";
18
+ import {
19
+ BitfabError,
20
+ DEFAULT_SERVICE_URL,
21
+ HttpClient,
22
+ getReplayContext,
21
23
  warnOnce
22
- } from "./chunk-BNOVHUQB.js";
24
+ } from "./chunk-A22EYRSY.js";
23
25
  import {
24
26
  __privateAdd,
25
27
  __privateGet,
@@ -947,6 +949,131 @@ async function runFunctionWithBaml(bamlSource, inputs, providers, envVars) {
947
949
  };
948
950
  }
949
951
 
952
+ // src/datasets.ts
953
+ var DEFAULT_RERUN_TIMEOUT_MS = 9e4;
954
+ var DEFAULT_RERUN_POLL_INTERVAL_MS = 1e3;
955
+ var TERMINAL_RERUN_STATUSES = /* @__PURE__ */ new Set([
956
+ "completed",
957
+ "errored"
958
+ ]);
959
+ function sleep(ms) {
960
+ return new Promise((resolve) => setTimeout(resolve, ms));
961
+ }
962
+ function datasetPath(datasetId, suffix = "") {
963
+ return `/api/sdk/datasets/${encodeURIComponent(datasetId)}${suffix}`;
964
+ }
965
+ var DatasetsClient = class {
966
+ constructor(httpClient) {
967
+ this.httpClient = httpClient;
968
+ }
969
+ /**
970
+ * Create a dataset, or update the one already named this way under the same
971
+ * trace function. `created` reports which happened. An omitted description
972
+ * leaves an existing one untouched.
973
+ */
974
+ async save(params) {
975
+ return this.httpClient.request("/api/sdk/datasets", {
976
+ traceFunctionKey: params.traceFunctionKey,
977
+ name: params.name,
978
+ ...params.description === void 0 ? {} : { description: params.description }
979
+ });
980
+ }
981
+ /**
982
+ * List datasets, scoped to one trace function when `traceFunctionKey` is
983
+ * given and organization-wide otherwise.
984
+ */
985
+ async list(params = {}) {
986
+ const query = params.traceFunctionKey === void 0 ? "" : `?traceFunctionKey=${encodeURIComponent(params.traceFunctionKey)}`;
987
+ const response = await this.httpClient.get(
988
+ `/api/sdk/datasets${query}`
989
+ );
990
+ return response.datasets;
991
+ }
992
+ /** Fetch one dataset by id. Rejects with a 404 `BitfabError` when it is not in this organization. */
993
+ async get(datasetId) {
994
+ const response = await this.httpClient.get(
995
+ datasetPath(datasetId)
996
+ );
997
+ return response.dataset;
998
+ }
999
+ /** The ids of every trace in the dataset, the same membership a replay with `datasetId` selects. */
1000
+ async listTraces(datasetId) {
1001
+ return this.httpClient.get(
1002
+ datasetPath(datasetId, "/traces")
1003
+ );
1004
+ }
1005
+ /**
1006
+ * Add traces to the dataset (1 to 100 ids per call). Traces outside the
1007
+ * organization or under another trace function are reported in
1008
+ * `skippedTraceIds` rather than failing the call.
1009
+ */
1010
+ async addTraces(datasetId, traceIds) {
1011
+ return this.httpClient.request(
1012
+ datasetPath(datasetId, "/traces"),
1013
+ { traceIds }
1014
+ );
1015
+ }
1016
+ /** Remove traces from the dataset. The traces themselves are never deleted. */
1017
+ async removeTraces(datasetId, traceIds) {
1018
+ return this.httpClient.request(
1019
+ datasetPath(datasetId, "/removeTraces"),
1020
+ { traceIds }
1021
+ );
1022
+ }
1023
+ /**
1024
+ * Assign graders to the dataset (1 to 100 ids per call). Graders outside the
1025
+ * organization or under another trace function are reported in
1026
+ * `skippedGraderIds` rather than failing the call.
1027
+ */
1028
+ async addGraders(datasetId, graderIds) {
1029
+ return this.httpClient.request(
1030
+ datasetPath(datasetId, "/graders"),
1031
+ { graderIds }
1032
+ );
1033
+ }
1034
+ /** Unassign graders from the dataset. */
1035
+ async removeGraders(datasetId, graderIds) {
1036
+ return this.httpClient.request(
1037
+ datasetPath(datasetId, "/removeGraders"),
1038
+ { graderIds }
1039
+ );
1040
+ }
1041
+ /**
1042
+ * Re-run graders over every trace in the dataset. Defaults to every assigned
1043
+ * grader; an unassigned id is rejected. Waits for the run to finish (up to
1044
+ * `timeoutMs`, default 90s) unless `wait` is `false`, and returns the last
1045
+ * run state seen either way. A request matching an in-flight run joins it.
1046
+ */
1047
+ async rerunGraders(datasetId, options = {}) {
1048
+ const started = await this.httpClient.request(
1049
+ datasetPath(datasetId, "/rerunGraders"),
1050
+ options.graderIds === void 0 ? {} : { graderIds: options.graderIds }
1051
+ );
1052
+ if (options.wait === false) {
1053
+ return started;
1054
+ }
1055
+ const deadline = Date.now() + (options.timeoutMs ?? DEFAULT_RERUN_TIMEOUT_MS);
1056
+ const interval = options.pollIntervalMs ?? DEFAULT_RERUN_POLL_INTERVAL_MS;
1057
+ let run = started.run;
1058
+ while (!TERMINAL_RERUN_STATUSES.has(run.status) && Date.now() < deadline) {
1059
+ await sleep(interval);
1060
+ run = await this.getGraderRerun(datasetId, run.id) ?? run;
1061
+ }
1062
+ return { run, joinedExisting: started.joinedExisting };
1063
+ }
1064
+ /**
1065
+ * The dataset's active grader re-run, or the run named by `runId`. Returns
1066
+ * `null` when nothing is active or the run does not belong to this dataset.
1067
+ */
1068
+ async getGraderRerun(datasetId, runId) {
1069
+ const query = runId === void 0 ? "" : `?runId=${encodeURIComponent(runId)}`;
1070
+ const response = await this.httpClient.get(
1071
+ datasetPath(datasetId, `/rerunGraders${query}`)
1072
+ );
1073
+ return response.run;
1074
+ }
1075
+ };
1076
+
950
1077
  // src/dbSnapshot.ts
951
1078
  var SUPPORTED_PROVIDERS = ["neon"];
952
1079
  function validateDbSnapshotConfig(config) {
@@ -2658,6 +2785,7 @@ var Bitfab = class {
2658
2785
  serviceUrl: this.serviceUrl,
2659
2786
  timeout: this.timeout
2660
2787
  });
2788
+ this.datasets = new DatasetsClient(this.httpClient);
2661
2789
  }
2662
2790
  /**
2663
2791
  * Decorate a class method as an automatically expanded trace root.
@@ -3568,6 +3696,7 @@ var Bitfab = class {
3568
3696
  inputSourceTraceId: traceState?.inputSourceTraceId,
3569
3697
  dbSnapshotRef: traceState?.dbSnapshotRef,
3570
3698
  dropped: traceState?.dropped,
3699
+ ingestionType: traceState?.ingestionType,
3571
3700
  // Built AFTER the wrapped fn finished, so `accessed` reflects
3572
3701
  // whether customer code obtained the branch URL during this
3573
3702
  // item. Omitted entirely when no lease was attached, so the
@@ -3791,6 +3920,7 @@ var Bitfab = class {
3791
3920
  Object.defineProperty(wrappedFn, "_bitfabTraceFunctionKey", {
3792
3921
  value: traceFunctionKey
3793
3922
  });
3923
+ Object.defineProperty(wrappedFn, "_bitfabWrappedFn", { value: fn });
3794
3924
  return wrappedFn;
3795
3925
  }
3796
3926
  /**
@@ -3953,6 +4083,9 @@ var Bitfab = class {
3953
4083
  if (params.dbSnapshotRef) {
3954
4084
  rawTrace.db_snapshot_ref = params.dbSnapshotRef;
3955
4085
  }
4086
+ if (params.ingestionType) {
4087
+ rawTrace.ingestion_type = params.ingestionType;
4088
+ }
3956
4089
  if (params.dbSnapshotUsage) {
3957
4090
  rawTrace.db_snapshot_usage = {
3958
4091
  neon_branch_id: params.dbSnapshotUsage.neonBranchId,
@@ -4099,6 +4232,68 @@ var Bitfab = class {
4099
4232
  clearMockOverrides() {
4100
4233
  this.mockOverrides.length = 0;
4101
4234
  }
4235
+ /**
4236
+ * Write a replayable trace from a case, without running anything.
4237
+ *
4238
+ * Use this to turn a corpus you already hold (a Braintrust dataset, a
4239
+ * spreadsheet, hand-written cases) into traces that {@link replay} can
4240
+ * select. The recorded root span carries `input` as its input and `expected`
4241
+ * as its output, so replay reports each item against the value you expected
4242
+ * rather than against a previous run.
4243
+ *
4244
+ * A seeded trace has no child spans and no database pin, so replay mocking
4245
+ * has nothing recorded to substitute and `dbBranch` refuses it. Pass
4246
+ * `mockOverride` at replay time for calls that must not run.
4247
+ *
4248
+ * @returns The trace ID, usable with `replay({ traceIds: [...] })`.
4249
+ */
4250
+ seedTrace(traceFunctionKey, options) {
4251
+ const { input } = options;
4252
+ const fn = options.fn?._bitfabWrappedFn ?? options.fn;
4253
+ if (fn && input.length < fn.length) {
4254
+ throw new BitfabError(
4255
+ `Seeded case supplies ${input.length} argument(s) but ${fn.name === "" ? "the function" : fn.name} requires ${fn.length}. Fix the case, or omit fn to seed it anyway.`
4256
+ );
4257
+ }
4258
+ const traceId = randomUuid();
4259
+ const startedAt = nowIsoTimestamp();
4260
+ activeTraceStates.set(traceId, {
4261
+ traceId,
4262
+ startedAt,
4263
+ contexts: [],
4264
+ ingestionType: "seeded",
4265
+ ...options.sessionId !== void 0 && { sessionId: options.sessionId },
4266
+ ...options.metadata !== void 0 && { metadata: options.metadata }
4267
+ });
4268
+ try {
4269
+ this.sendWrapperSpan({
4270
+ traceFunctionKey,
4271
+ spanName: options.spanName ?? traceFunctionKey,
4272
+ traceId,
4273
+ spanId: randomUuid(),
4274
+ parentSpanId: null,
4275
+ inputs: input,
4276
+ result: options.expected,
4277
+ startedAt,
4278
+ endedAt: startedAt,
4279
+ spanType: options.spanType ?? "agent",
4280
+ captureContent: true
4281
+ });
4282
+ this.sendTraceCompletion({
4283
+ traceFunctionKey,
4284
+ traceId,
4285
+ startedAt,
4286
+ endedAt: startedAt,
4287
+ sessionId: options.sessionId,
4288
+ metadata: options.metadata,
4289
+ contexts: [],
4290
+ ingestionType: "seeded"
4291
+ });
4292
+ } finally {
4293
+ activeTraceStates.delete(traceId);
4294
+ }
4295
+ return traceId;
4296
+ }
4102
4297
  async replay(traceFunctionKey, fn, options) {
4103
4298
  const wrappedKey = fn._bitfabTraceFunctionKey;
4104
4299
  let replayFn = fn;
@@ -4113,7 +4308,7 @@ var Bitfab = class {
4113
4308
  `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.`
4114
4309
  );
4115
4310
  }
4116
- const { replay: doReplay } = await import("./replay-SMUBBMNK.js");
4311
+ const { replay: doReplay } = await import("./replay-352POXG3.js");
4117
4312
  return doReplay(
4118
4313
  this.httpClient,
4119
4314
  this.serviceUrl,
@@ -4349,9 +4544,41 @@ var finalizers = {
4349
4544
  function defineReplayRegistry(registry) {
4350
4545
  return registry;
4351
4546
  }
4547
+ async function seedFromRegistry(registry, pipeline, cases) {
4548
+ const registration = registry[pipeline];
4549
+ if (registration === void 0) {
4550
+ throw new BitfabError(
4551
+ `Unknown pipeline '${pipeline}'. Registered: ${Object.keys(registry).join(", ")}`
4552
+ );
4553
+ }
4554
+ const traceFunctionKey = resolveTraceFunctionKey(registration);
4555
+ const traceIds = cases.map(
4556
+ (seedCase) => registration.client.seedTrace(traceFunctionKey, {
4557
+ input: seedCase.input,
4558
+ expected: seedCase.expected,
4559
+ fn: registration.fn,
4560
+ metadata: seedCase.metadata,
4561
+ sessionId: seedCase.sessionId
4562
+ })
4563
+ );
4564
+ const { flushTraces: flushTraces2 } = await import("./http-2OFIGQOK.js");
4565
+ await flushTraces2(3e4);
4566
+ return { pipeline, traceFunctionKey, traceIds };
4567
+ }
4568
+ function resolveTraceFunctionKey(registration) {
4569
+ const wrappedKey = registration.fn._bitfabTraceFunctionKey;
4570
+ const key = registration.traceFunctionKey ?? wrappedKey;
4571
+ if (key === void 0) {
4572
+ throw new BitfabError(
4573
+ "Replay registry entry uses a plain function. Set traceFunctionKey to the key its production handler records."
4574
+ );
4575
+ }
4576
+ return key;
4577
+ }
4352
4578
 
4353
4579
  export {
4354
4580
  BitfabClaudeAgentHandler,
4581
+ DatasetsClient,
4355
4582
  SUPPORTED_PROVIDERS,
4356
4583
  BitfabLangGraphCallbackHandler,
4357
4584
  BitfabLangGraphIntegration,
@@ -4364,6 +4591,7 @@ export {
4364
4591
  Bitfab,
4365
4592
  BitfabFunction,
4366
4593
  finalizers,
4367
- defineReplayRegistry
4594
+ defineReplayRegistry,
4595
+ seedFromRegistry
4368
4596
  };
4369
- //# sourceMappingURL=chunk-UE4GGPM6.js.map
4597
+ //# sourceMappingURL=chunk-5NT4YDCQ.js.map