@bitfab/sdk 0.74.2 → 0.74.4

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.
@@ -644,6 +644,7 @@ const VALUE_FLAGS = /* @__PURE__ */ new Set([
644
644
  "--dataset-id",
645
645
  "--dataset-ids",
646
646
  "--grader-ids",
647
+ "--category-ids",
647
648
  "--mock",
648
649
  "--param",
649
650
  "--params",
@@ -688,6 +689,7 @@ const RESUME_CONFLICTING_FLAGS = [
688
689
  ["attempts", "--attempts"],
689
690
  ["graderIds", "--grader-ids"],
690
691
  ["onlyWithAssertions", "--only-with-assertions"],
692
+ ["categoryIds", "--category-ids"],
691
693
  ["dryRun", "--dry-run"]
692
694
  ];
693
695
  const RESUME_CLEARED_OPTIONS = {
@@ -698,26 +700,30 @@ const RESUME_CLEARED_OPTIONS = {
698
700
  attempts: void 0,
699
701
  graderIds: void 0,
700
702
  onlyWithAssertions: void 0,
703
+ categoryIds: void 0,
701
704
  dryRun: void 0
702
705
  };
703
- function hasApprovedAssertion(assertions) {
704
- return assertions.some((assertion) => assertion.approvalState === "approved");
706
+ function narrowsToAssertions(narrowing) {
707
+ return narrowing.onlyWithAssertions || narrowing.categoryIds !== void 0;
705
708
  }
706
- async function boundTraceIds(client, traceIds, limit, onlyWithAssertions) {
709
+ function hasApprovedAssertion(assertions, categoryIds) {
710
+ return assertions.some((assertion) => assertion.approvalState === "approved" && (categoryIds === void 0 || assertion.category_id !== null && categoryIds.includes(assertion.category_id)));
711
+ }
712
+ async function boundTraceIds(client, traceIds, limit, narrowing) {
707
713
  if (!Number.isInteger(limit) || limit < 1) throw new BitfabError("Replay limit must be a positive integer.");
708
- if (!onlyWithAssertions || limit >= traceIds.length) return traceIds.slice(0, limit);
714
+ if (!narrowsToAssertions(narrowing) || limit >= traceIds.length) return traceIds.slice(0, limit);
709
715
  const selected = [];
710
716
  for (const traceId of traceIds) {
711
717
  const { assertions, inheritedFrom } = await client.traces.getAssertions(traceId);
712
- if (inheritedFrom === null && hasApprovedAssertion(assertions)) {
718
+ if (inheritedFrom === null && hasApprovedAssertion(assertions, narrowing.categoryIds)) {
713
719
  selected.push(traceId);
714
720
  if (selected.length === limit) break;
715
721
  }
716
722
  }
717
- if (selected.length === 0) throw new BitfabError("No traces with approved assertions matched this replay selection.");
723
+ if (selected.length === 0) throw new BitfabError(narrowing.categoryIds === void 0 ? "No traces with approved assertions matched this replay selection." : "No traces with an approved assertion in the given categories matched this replay selection.");
718
724
  return selected;
719
725
  }
720
- async function pinnedDatasetMembers(client, datasetIds, limit, onlyWithAssertions = false) {
726
+ async function pinnedDatasetMembers(client, datasetIds, limit, narrowing = { onlyWithAssertions: false }) {
721
727
  const members = /* @__PURE__ */ new Set();
722
728
  for (const datasetId of datasetIds) {
723
729
  const { traceIds } = await client.datasets.listTraces(datasetId);
@@ -726,10 +732,10 @@ async function pinnedDatasetMembers(client, datasetIds, limit, onlyWithAssertion
726
732
  const ordered = [...members].sort();
727
733
  if (limit >= ordered.length) return;
728
734
  if (limit > MAX_PINNED_TRACE_IDS) throw new BitfabError(`Bounding a dataset replay to ${limit} names one trace ID per replayed item, and a replay accepts at most ${MAX_PINNED_TRACE_IDS}. Drop the limit to replay every selected dataset in full.`);
729
- return boundTraceIds(client, ordered, limit, onlyWithAssertions);
735
+ return boundTraceIds(client, ordered, limit, narrowing);
730
736
  }
731
737
  function usage(registry) {
732
- return `Usage: bitfab-replay --registry <path> <${registry === void 0 ? "pipeline" : Object.keys(registry).join("|")}> [options]\n\nOptions:\n --limit N (bounds a trace ID or dataset selection instead of replacing it)\n --attempts N (replay each trace N times in this run, max ${MAX_ATTEMPTS})\n --trace-ids id1,id2\n --name NAME (what this run is testing, such as "baseline"; Bitfab already records the commit, branch, and datasets)\n --notes TEXT (run conditions Bitfab cannot see, such as a forced feature flag)\n --metadata key=value (repeatable; tags kept on the experiment, such as which schedule launched it, and filterable through client.experiments.list)\n --concurrency N, --max-concurrency N\n --code-change working-tree|last-branch|default-branch|ref|skip|manual (required: the code change this run tests; working-tree is the uncommitted changes vs HEAD, last-branch the diff against the branch this one was cut from, default-branch the diff against the default branch, ref the diff against --code-change-base, skip none, manual the edits in --code-change-file)\n --code-change-base BRANCH|COMMIT (with --code-change ref: the branch or commit to diff against)\n --code-change-file PATH (with --code-change manual: a JSON file of { description, files })\n --experiment-group-id UUID (join this experiment group; a new UUID creates the group)\n --experiment-group-name NAME (name the group when this run creates it or it has no name yet; requires --experiment-group-id)\n --dataset-ids uuid1,uuid2 (--dataset-id is the same flag)\n --grader-ids id1,id2\n --only-with-assertions (replay only traces carrying an approved assertion)\n --skip-assertion-judging (don't judge approved assertions on each replay; judging is on by default and costs model calls)\n --judge-assertions (deprecated: judging is on by default)\n --mock none|all|marked\n --db-branch, --no-db-branch\n --dry-run (resolve inputs, run nothing)\n --fail-on-error (exit 1 after printing the result when any replayed item errored; under --dry-run, items whose inputs failed to resolve count)\n --resume EXPERIMENT_ID (finish an experiment that stopped partway, running only the items it did not finish, with the traces, attempts, and graders it started with)\n --force (with --resume, resume even when the experiment may still be running or the code changed since it started)\n --params PATH\n --param name=value (repeatable)\n -h, --help`;
738
+ return `Usage: bitfab-replay --registry <path> <${registry === void 0 ? "pipeline" : Object.keys(registry).join("|")}> [options]\n\nOptions:\n --limit N (bounds a trace ID or dataset selection instead of replacing it)\n --attempts N (replay each trace N times in this run, max ${MAX_ATTEMPTS})\n --trace-ids id1,id2\n --name NAME (what this run is testing, such as "baseline"; Bitfab already records the commit, branch, and datasets)\n --notes TEXT (run conditions Bitfab cannot see, such as a forced feature flag)\n --metadata key=value (repeatable; tags kept on the experiment, such as which schedule launched it, and filterable through client.experiments.list)\n --concurrency N, --max-concurrency N\n --code-change working-tree|last-branch|default-branch|ref|skip|manual (required: the code change this run tests; working-tree is the uncommitted changes vs HEAD, last-branch the diff against the branch this one was cut from, default-branch the diff against the default branch, ref the diff against --code-change-base, skip none, manual the edits in --code-change-file)\n --code-change-base BRANCH|COMMIT (with --code-change ref: the branch or commit to diff against)\n --code-change-file PATH (with --code-change manual: a JSON file of { description, files })\n --experiment-group-id UUID (join this experiment group; a new UUID creates the group)\n --experiment-group-name NAME (name the group when this run creates it or it has no name yet; requires --experiment-group-id)\n --dataset-ids uuid1,uuid2 (--dataset-id is the same flag)\n --grader-ids id1,id2\n --only-with-assertions (replay only traces carrying an approved assertion)\n --category-ids id1,id2 (with --trace-ids or --dataset-ids: replay only the traces carrying an approved assertion in one of these categories; which assertions are judged stays the same)\n --skip-assertion-judging (don't judge approved assertions on each replay; judging is on by default and costs model calls)\n --judge-assertions (deprecated: judging is on by default)\n --mock none|all|marked\n --db-branch, --no-db-branch\n --dry-run (resolve inputs, run nothing)\n --fail-on-error (exit 1 after printing the result when any replayed item errored; under --dry-run, items whose inputs failed to resolve count)\n --resume EXPERIMENT_ID (finish an experiment that stopped partway, running only the items it did not finish, with the traces, attempts, and graders it started with)\n --force (with --resume, resume even when the experiment may still be running or the code changed since it started)\n --params PATH\n --param name=value (repeatable)\n -h, --help`;
733
739
  }
734
740
  var ReplayCliHelp = class extends Error {};
735
741
  async function reseedFromRegistry(registry, pipeline, traceIds) {
@@ -939,6 +945,9 @@ function parseReplayCliArgs(registry, argv) {
939
945
  case "--grader-ids":
940
946
  parsed.graderIds = commaSeparated(flag, raw);
941
947
  break;
948
+ case "--category-ids":
949
+ parsed.categoryIds = commaSeparated(flag, raw);
950
+ break;
942
951
  case "--mock":
943
952
  if (raw !== "none" && raw !== "all" && raw !== "marked") throw new BitfabError(`--mock must be one of: none, all, marked (received '${raw}').`);
944
953
  parsed.mock = raw;
@@ -1164,6 +1173,7 @@ async function runReplayCli(registry, argv = typeof process === "undefined" ? []
1164
1173
  datasetIds: selectedDatasetIds,
1165
1174
  ...args.graderIds === void 0 ? {} : { graderIds: args.graderIds },
1166
1175
  ...args.onlyWithAssertions === void 0 ? {} : { onlyWithAssertions: args.onlyWithAssertions },
1176
+ ...args.categoryIds === void 0 ? {} : { categoryIds: args.categoryIds },
1167
1177
  ...args.skipAssertionJudging === void 0 ? {} : { skipAssertionJudging: args.skipAssertionJudging },
1168
1178
  ...args.mock === void 0 ? {} : { mock: args.mock },
1169
1179
  ...args.dbBranch === void 0 ? {} : { dbBranch: args.dbBranch && registrationOptions.dbBranch !== void 0 && registrationOptions.dbBranch !== false ? registrationOptions.dbBranch : args.dbBranch },
@@ -1197,13 +1207,18 @@ async function runReplayCli(registry, argv = typeof process === "undefined" ? []
1197
1207
  options.traceIds = args.traceIds;
1198
1208
  options.datasetIds = void 0;
1199
1209
  } else if (args.datasetIds !== void 0) options.traceIds = void 0;
1210
+ if (options.categoryIds !== void 0 && options.traceIds === void 0 && options.datasetIds === void 0) throw new BitfabError("--category-ids narrows a trace ID or dataset selection. Pass it with --trace-ids or --dataset-ids.");
1200
1211
  const bound = args.limit ?? registrationOptions.limit;
1201
1212
  options.limit = void 0;
1213
+ const narrowing = {
1214
+ onlyWithAssertions: options.onlyWithAssertions === true,
1215
+ categoryIds: options.categoryIds
1216
+ };
1202
1217
  if (options.traceIds !== void 0) {
1203
- if (bound !== void 0) options.traceIds = await boundTraceIds(registration.client, options.traceIds, bound, options.onlyWithAssertions === true);
1218
+ if (bound !== void 0) options.traceIds = await boundTraceIds(registration.client, options.traceIds, bound, narrowing);
1204
1219
  } else if (options.datasetIds !== void 0) {
1205
1220
  if (bound !== void 0) {
1206
- const pinned = await pinnedDatasetMembers(registration.client, options.datasetIds, bound, options.onlyWithAssertions === true);
1221
+ const pinned = await pinnedDatasetMembers(registration.client, options.datasetIds, bound, narrowing);
1207
1222
  if (pinned !== void 0) options.traceIds = pinned;
1208
1223
  }
1209
1224
  } else options.limit = bound ?? 10;
@@ -1323,4 +1338,4 @@ function runIfEntrypoint(moduleUrl, main) {
1323
1338
  //#endregion
1324
1339
  export { runRegistryMain as a, runSeedCli as c, runIfEntrypoint as i, parseRegistryCommandArgs as n, checkReplayCliArgs as o, resolveRegistry as r, runReplayCli as s, importRegistry as t };
1325
1340
 
1326
- //# sourceMappingURL=registryCommand-BQcyBmhN.js.map
1341
+ //# sourceMappingURL=registryCommand-Bm2-Peq8.js.map