@warmhub/cli 0.76.0 → 0.77.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.
Files changed (2) hide show
  1. package/dist/wh.js +174 -67
  2. package/package.json +1 -1
package/dist/wh.js CHANGED
@@ -27287,6 +27287,7 @@ var RE2JS = class RE2JS2 {
27287
27287
  // ../../packages/rules/src/shape-validation-types.ts
27288
27288
  var MAX_CONTENT_FIELD_BYTES = 64 * 1024;
27289
27289
  var MAX_INDEXABLE_SCALAR_FIELDS_PER_SHAPE = 256;
27290
+ var MAX_INDEXABLE_FIELD_PATH_BYTES = 256;
27290
27291
  var UNSUPPORTED_REGEX_SYNTAX_REASON = "uses unsupported regex syntax";
27291
27292
  var CONTENT_FIELD_LIMIT_ERROR = `WarmHub content fields are limited to ${MAX_CONTENT_FIELD_BYTES} bytes. ` + "WarmHub is not a document store; store large documents in S3, Box, Drive, or another document system and reference them from WarmHub instead.";
27292
27293
  var textEncoder = new TextEncoder;
@@ -27771,6 +27772,10 @@ function validateShapeDefinition(data, options = {}) {
27771
27772
  const seenIndexableFieldPaths = new Set;
27772
27773
  const duplicateIndexableFieldPaths = new Set;
27773
27774
  for (const fieldPath of indexableFieldPaths) {
27775
+ const pathBytes = utf8ByteLength(fieldPath);
27776
+ if (pathBytes > MAX_INDEXABLE_FIELD_PATH_BYTES) {
27777
+ errors.push(`Indexable field path "${escapeFieldNameForDisplay(fieldPath)}" is ${pathBytes} bytes; maximum is ${MAX_INDEXABLE_FIELD_PATH_BYTES}`);
27778
+ }
27774
27779
  const foldedPath = foldFieldPath(fieldPath);
27775
27780
  if (seenIndexableFieldPaths.has(foldedPath)) {
27776
27781
  duplicateIndexableFieldPaths.add(foldedPath);
@@ -27855,7 +27860,7 @@ function findSystemComponent(componentId) {
27855
27860
  // ../../packages/sdk-ts/package.json
27856
27861
  var package_default = {
27857
27862
  name: "@warmhub/sdk-ts",
27858
- version: "0.74.0",
27863
+ version: "0.75.0",
27859
27864
  private: false,
27860
27865
  type: "module",
27861
27866
  description: "The TypeScript SDK for WarmHub — create repos, commit and query data, and compound knowledge with your AI agents.",
@@ -28158,12 +28163,14 @@ var MAX_STREAM_APPEND_OPERATION_COUNT2 = MAX_STREAM_APPEND_OPERATION_COUNT;
28158
28163
  class PartialStreamSubmissionError extends Error {
28159
28164
  code = "PARTIAL_STREAM_SUBMISSION";
28160
28165
  completedOperations;
28166
+ acknowledgedOperationCount;
28161
28167
  cause;
28162
28168
  constructor(input) {
28163
28169
  super("Stream submission failed. A timed-out append may already have landed, so inspect repository state before sending any further operations.");
28164
28170
  this.name = "WarmHubError";
28165
28171
  this.cause = input.cause;
28166
28172
  this.completedOperations = input.completedOperations;
28173
+ this.acknowledgedOperationCount = input.acknowledgedOperationCount ?? input.completedOperations.length;
28167
28174
  }
28168
28175
  }
28169
28176
 
@@ -28355,6 +28362,7 @@ async function submitOperationsViaStream(client, args) {
28355
28362
  let createdByEmail;
28356
28363
  let repoSeq;
28357
28364
  const chunkResults = [];
28365
+ let acknowledgedOperationCount = 0;
28358
28366
  let sawAmbiguousAttempt = false;
28359
28367
  for (const { operations: chunk, start: chunkStart } of chunkOperations(operations, chunkSize)) {
28360
28368
  let attempt = 1;
@@ -28381,12 +28389,13 @@ async function submitOperationsViaStream(client, args) {
28381
28389
  repoSeq = appendResult.repoSeq;
28382
28390
  }
28383
28391
  chunkResults.push(...offsetChunkResultIndexes(appendResult.results, chunkStart));
28392
+ acknowledgedOperationCount += chunk.length;
28384
28393
  break;
28385
28394
  } catch (cause) {
28386
- if (chunkResults.length === 0 && !priorAttemptAmbiguous && isDefiniteClientError(cause)) {
28395
+ if (acknowledgedOperationCount === 0 && !priorAttemptAmbiguous && isDefiniteClientError(cause)) {
28387
28396
  throw cause;
28388
28397
  }
28389
- if (chunkResults.length === 0 && chunkIsAtomic && policy !== false && attempt < policy.maxAttempts && isTransientStreamFailure(cause)) {
28398
+ if (acknowledgedOperationCount === 0 && chunkIsAtomic && policy !== false && attempt < policy.maxAttempts && isTransientStreamFailure(cause)) {
28390
28399
  await sleep2(computeBackoffDelayMs(attempt, policy));
28391
28400
  attempt += 1;
28392
28401
  priorAttemptAmbiguous = true;
@@ -28400,7 +28409,8 @@ async function submitOperationsViaStream(client, args) {
28400
28409
  }, args.committer, createdByEmail, repoSeq, args.message, chunkResults, operations));
28401
28410
  throw new PartialStreamSubmissionError({
28402
28411
  cause,
28403
- completedOperations
28412
+ completedOperations,
28413
+ acknowledgedOperationCount
28404
28414
  });
28405
28415
  }
28406
28416
  }
@@ -28413,7 +28423,8 @@ async function submitOperationsViaStream(client, args) {
28413
28423
  if (sawAmbiguousAttempt) {
28414
28424
  throw new PartialStreamSubmissionError({
28415
28425
  cause: failure,
28416
- completedOperations: completedOperationsFrom(result)
28426
+ completedOperations: completedOperationsFrom(result),
28427
+ acknowledgedOperationCount
28417
28428
  });
28418
28429
  }
28419
28430
  throw failure;
@@ -39149,7 +39160,7 @@ var createFlags3 = {
39149
39160
  description: "Only apply if the --revise target is still at this version (optimistic concurrency). Requires --revise."
39150
39161
  }),
39151
39162
  "lease-id": flag.string({
39152
- description: "Read-lease token from `wh thing lease`, bound to --revise/--retract (auto-released on success)"
39163
+ description: "read-lease token from `wh thing lease`, bound to --revise or one --retract target (auto-released on success)"
39153
39164
  })
39154
39165
  };
39155
39166
 
@@ -39410,6 +39421,9 @@ function buildAddOperations(input) {
39410
39421
  }
39411
39422
  function buildRetractOperations(input) {
39412
39423
  const { retractNames, kinds, reasons, leaseId } = input;
39424
+ if (leaseId !== undefined && retractNames.length !== 1) {
39425
+ throw new CliError(2 /* UserInput */, "USER_INPUT", `--lease-id requires exactly one --retract target; received ${retractNames.length}.`, undefined, "wh commit submit --retract Player/alice --lease-id lease-xyz --repo acme/world");
39426
+ }
39413
39427
  const assertCardinality = (flagName, values) => {
39414
39428
  if (values.length === 0)
39415
39429
  return;
@@ -39474,11 +39488,78 @@ function synthesizeCommitMessage(operations) {
39474
39488
  return name ? `add ${name}` : "add";
39475
39489
  }
39476
39490
 
39491
+ // ../../packages/warmhub-cli/src/domains/commit-submit-source.ts
39492
+ var SOURCE_FLAGS = [
39493
+ ["--stream", "stream"],
39494
+ ["--ops", "ops"],
39495
+ ["--file", "file"],
39496
+ ["--add", "add"],
39497
+ ["--revise", "revise"],
39498
+ ["--retract", "retract"],
39499
+ ["--type", "collection"]
39500
+ ];
39501
+ var ALLOWED_FLAGS = {
39502
+ "--stream": new Set,
39503
+ "--ops": new Set,
39504
+ "--file": new Set,
39505
+ "--add": new Set(["data", "shape", "about", "kind"]),
39506
+ "--revise": new Set(["data", "kind"]),
39507
+ "--retract": new Set(["reason", "kind"]),
39508
+ "--type": new Set(["name", "members"])
39509
+ };
39510
+ var SOURCE_COMMAND_EXAMPLES = {
39511
+ "--stream": "wh commit submit --stream --stream-id import-1 --skip-existing -m 'Import operations' --repo acme/world",
39512
+ "--ops": `wh commit submit --ops '[{"operation":"add","kind":"thing","name":"Proof/example","data":{}}]' -m 'Add Proof/example' --repo acme/world`,
39513
+ "--file": "wh commit submit --file ops.json -m 'Apply operations' --repo acme/world",
39514
+ "--add": "wh commit submit --add Proof/example --data '{}' -m 'Add Proof/example' --repo acme/world",
39515
+ "--revise": "wh commit submit --revise Proof/example --data '{}' -m 'Revise Proof/example' --repo acme/world",
39516
+ "--retract": "wh commit submit --retract Proof/example -m 'Retract Proof/example' --repo acme/world",
39517
+ "--type": "wh commit submit --type arc --name route --members Location/a,Location/b -m 'Add route' --repo acme/world"
39518
+ };
39519
+ function resolveCommitOperationSource(input) {
39520
+ const selected = SOURCE_FLAGS.filter(([, key]) => input[key]).map(([flag2]) => flag2);
39521
+ if (selected.length === 0) {
39522
+ usageError("Usage: wh commit submit --ops '<json>' or --add <name> [--data <json>]", `wh commit submit --add player --shape location --data '{"x":0,"y":0}'`);
39523
+ }
39524
+ if (selected.length > 1) {
39525
+ throw new CliError(2 /* UserInput */, "USER_INPUT", `Commit operation sources cannot be combined: ${selected.join(", ")}.`, undefined, `Choose one source, for example: ${SOURCE_COMMAND_EXAMPLES[selected[0]]}`);
39526
+ }
39527
+ return selected[0];
39528
+ }
39529
+ function assertFlagsApplyToCommitSource(source, input) {
39530
+ const allowed = ALLOWED_FLAGS[source];
39531
+ const invalid = Object.entries(input).filter(([flag2, present]) => present && !allowed.has(flag2)).map(([flag2]) => `--${flag2}`);
39532
+ if (invalid.length === 0)
39533
+ return;
39534
+ const verb = invalid.length === 1 ? "does" : "do";
39535
+ throw new CliError(2 /* UserInput */, "USER_INPUT", `${invalid.join(", ")} ${verb} not apply to the ${source} operation source.`, undefined, `Remove ${invalid.join(", ")} and retry: ${SOURCE_COMMAND_EXAMPLES[source]}`);
39536
+ }
39537
+ function requireCommitSourceValue(source, value) {
39538
+ if (value !== undefined)
39539
+ return value;
39540
+ throw new Error(`Missing value for selected commit operation source ${source}`);
39541
+ }
39542
+
39477
39543
  // ../../packages/warmhub-cli/src/domains/commit-submit-stream.ts
39478
39544
  import { createReadStream as createReadStream2 } from "node:fs";
39479
39545
  import { writeFile as writeFile2 } from "node:fs/promises";
39480
39546
  import { createInterface as createInterface2 } from "node:readline";
39481
39547
 
39548
+ // ../../packages/warmhub-cli/src/domains/commit-submit-partial-receipt.ts
39549
+ class JsonlPartialSubmissionError extends CliError {
39550
+ }
39551
+ function jsonlPartialSubmissionError(args) {
39552
+ const { acknowledgedOperationCount, cause } = args;
39553
+ if (args.failedAppendMayHaveLanded === true) {
39554
+ const backendCode = toWarmHubError(cause).backendCode;
39555
+ const suffix = backendCode ? ` (backend: ${backendCode})` : "";
39556
+ return new JsonlPartialSubmissionError(4 /* Backend */, "BACKEND", `Stream append failed after ${acknowledgedOperationCount} acknowledged operation(s).${suffix}`, cause, "The failed append may also have landed; inspect repository state before submitting any remaining JSONL operations.", undefined, backendCode);
39557
+ }
39558
+ const message = cause instanceof Error ? cause.message : String(cause);
39559
+ const causeHint = cause instanceof CliError && cause.hint ? `${cause.hint} ` : "";
39560
+ return new JsonlPartialSubmissionError(4 /* Backend */, "BACKEND", `${message} (${acknowledgedOperationCount} earlier operation(s) already acknowledged by the server before this input failure).`, cause, `${causeHint}Earlier chunks have landed; inspect repository state before submitting any remaining JSONL operations.`);
39561
+ }
39562
+
39482
39563
  // ../../packages/warmhub-cli/src/domains/commit-submit-utils.ts
39483
39564
  var DEFAULT_JSONL_STREAM_CHUNK_SIZE = Math.max(1, Math.min(MAX_STREAM_APPEND_OPERATION_COUNT, Number(process.env.WH_STREAM_CHUNK_SIZE) || DEFAULT_STREAM_APPEND_CHUNK_SIZE));
39484
39565
  function resolveJsonlStreamChunkSize(chunkSize) {
@@ -39788,13 +39869,13 @@ async function applyJsonlCommit(ctx, args) {
39788
39869
  const streamId = args.streamId;
39789
39870
  const tAppendStart = performance.now();
39790
39871
  progress.start(t0);
39872
+ let opCount = 0;
39791
39873
  try {
39792
39874
  const operations = [];
39793
39875
  const submittedOperations = [];
39794
39876
  let allocatedTokenRanges = [];
39795
39877
  let createdByEmail;
39796
39878
  let repoSeq;
39797
- let opCount = 0;
39798
39879
  let parsedOpCount = 0;
39799
39880
  let chunk = [];
39800
39881
  let lineNumber = 0;
@@ -39818,9 +39899,11 @@ async function applyJsonlCommit(ctx, args) {
39818
39899
  } catch (cause) {
39819
39900
  const completed = opCount;
39820
39901
  if (opCount > 0 || firstJsonlAppendErrorMayHaveCommitted(cause)) {
39821
- const backendCode = toWarmHubError(cause).backendCode;
39822
- const suffix = backendCode ? ` (backend: ${backendCode})` : "";
39823
- throw new CliError(4 /* Backend */, "BACKEND", `Stream append failed after ${completed} acknowledged operation(s).${suffix}`, cause, "The failed append may also have landed; inspect repository state before submitting any remaining JSONL operations.", undefined, backendCode);
39902
+ throw jsonlPartialSubmissionError({
39903
+ acknowledgedOperationCount: completed,
39904
+ cause,
39905
+ failedAppendMayHaveLanded: true
39906
+ });
39824
39907
  }
39825
39908
  throw cause;
39826
39909
  }
@@ -39881,18 +39964,9 @@ async function applyJsonlCommit(ctx, args) {
39881
39964
  continue;
39882
39965
  assertWithinStreamOpLimit(parsedOpCount + 1);
39883
39966
  const operation = safeParseJson(trimmed, `${args.lineLabel} JSONL line ${lineNumber}`);
39967
+ rejectLegacyLifecycleOperations([operation]);
39884
39968
  if (args.allowNulBytes !== true) {
39885
- try {
39886
- assertNoNulBytes("data" in operation ? operation.data : undefined, `${args.lineLabel} JSONL line ${lineNumber}`);
39887
- } catch (cause) {
39888
- if (cause instanceof CliError) {
39889
- if (opCount > 0) {
39890
- const baseHint = cause.hint && cause.hint.length > 0 ? `${cause.hint} ` : "";
39891
- throw new CliError(4 /* Backend */, "BACKEND", `${cause.message} (${opCount} earlier operation(s) already acknowledged by the server before this NUL-byte rejection).`, undefined, `${baseHint}The earlier chunks have landed; inspect repository state before submitting any remaining JSONL operations.`);
39892
- }
39893
- }
39894
- throw cause;
39895
- }
39969
+ assertNoNulBytes("data" in operation ? operation.data : undefined, `${args.lineLabel} JSONL line ${lineNumber}`);
39896
39970
  }
39897
39971
  parsedOpCount += 1;
39898
39972
  chunk.push(withSkipExisting(operation, args.skipExisting === true));
@@ -40018,7 +40092,13 @@ async function applyJsonlCommit(ctx, args) {
40018
40092
  });
40019
40093
  } catch (error) {
40020
40094
  progress.onError();
40021
- throw error;
40095
+ if (error instanceof JsonlPartialSubmissionError || opCount === 0) {
40096
+ throw error;
40097
+ }
40098
+ throw jsonlPartialSubmissionError({
40099
+ acknowledgedOperationCount: opCount,
40100
+ cause: error
40101
+ });
40022
40102
  }
40023
40103
  }
40024
40104
  async function applyJsonlFileCommit(ctx, args) {
@@ -40113,9 +40193,27 @@ var handleSubmit = async (ctx, { flags, args }) => {
40113
40193
  }
40114
40194
  const collectionType = flags.type;
40115
40195
  const jsonlFile = opsFile?.endsWith(".jsonl") === true;
40116
- if (streamInput && (opsJson !== undefined || opsFile !== undefined || addNames.length > 0 || reviseName !== undefined || retractNames.length > 0 || collectionType !== undefined)) {
40117
- throw new CliError(2 /* UserInput */, "USER_INPUT", "--stream cannot be combined with --ops, --file, --add, --revise, --retract, or --type.");
40118
- }
40196
+ const operationSource = resolveCommitOperationSource({
40197
+ stream: streamInput,
40198
+ ops: opsJson !== undefined,
40199
+ file: opsFile !== undefined,
40200
+ add: addNames.length > 0,
40201
+ revise: reviseName !== undefined,
40202
+ retract: retractNames.length > 0,
40203
+ collection: collectionType !== undefined
40204
+ });
40205
+ if (operationSource === "--retract" && (dataJsons.length > 0 || shapes.length > 0 || abouts.length > 0)) {
40206
+ throw new CliError(2 /* UserInput */, "USER_INPUT", "--retract cannot be combined with --data, --shape, or --about.", undefined, "Use --file <path.json> for mixed operation writes.");
40207
+ }
40208
+ assertFlagsApplyToCommitSource(operationSource, {
40209
+ data: dataJsons.length > 0,
40210
+ shape: shapes.length > 0,
40211
+ about: abouts.length > 0,
40212
+ reason: reasons.length > 0,
40213
+ kind: kinds.length > 0,
40214
+ name: flags.name !== undefined,
40215
+ members: flags.members !== undefined
40216
+ });
40119
40217
  if (chunkSize !== undefined && !streamInput && !jsonlFile) {
40120
40218
  throw new CliError(2 /* UserInput */, "USER_INPUT", "--chunk-size requires --stream or a .jsonl --file.");
40121
40219
  }
@@ -40125,20 +40223,20 @@ var handleSubmit = async (ctx, { flags, args }) => {
40125
40223
  if (streamId !== undefined && !streamInput && !jsonlFile) {
40126
40224
  throw new CliError(2 /* UserInput */, "USER_INPUT", "--stream-id requires --stream or a .jsonl --file.");
40127
40225
  }
40226
+ if (timingOut !== undefined && !jsonlFile) {
40227
+ throw new CliError(2 /* UserInput */, "USER_INPUT", "--timing-out requires a .jsonl --file.", undefined, "wh commit submit --file ops.jsonl --timing-out timing.json --stream-id import-1 --skip-existing -m 'Import operations' --repo acme/world");
40228
+ }
40128
40229
  if ((streamInput || jsonlFile) && streamId === undefined) {
40129
40230
  throw new CliError(2 /* UserInput */, "USER_INPUT", "JSONL streaming requires --stream-id.", undefined, "Choose a stable id up front so add streams can rebuild token state on full rerun: --stream-id bulk-2026-06-04.");
40130
40231
  }
40131
40232
  if ((streamInput || jsonlFile) && !skipExisting) {
40132
40233
  throw new CliError(2 /* UserInput */, "USER_INPUT", "JSONL streaming requires --skip-existing.", undefined, "Full-input rerun recovery depends on idempotent add operations; pass --skip-existing with --stream-id.");
40133
40234
  }
40134
- const shorthandModeCount = (addNames.length > 0 ? 1 : 0) + (reviseName !== undefined ? 1 : 0) + (retractNames.length > 0 ? 1 : 0) + (collectionType !== undefined ? 1 : 0);
40135
- if (!streamInput && !opsJson && !opsFile && shorthandModeCount > 1) {
40136
- throw new CliError(2 /* UserInput */, "USER_INPUT", "Short-form write flags cannot mix --add, --revise, --retract, or --type.", undefined, "Use --file <path.json> for mixed operation writes.");
40137
- }
40138
40235
  let operations;
40139
- if (streamInput) {
40236
+ if (operationSource === "--stream") {
40140
40237
  operations = [];
40141
- } else if (collectionType) {
40238
+ } else if (operationSource === "--type") {
40239
+ const selectedCollectionType = requireCommitSourceValue(operationSource, collectionType);
40142
40240
  if (!flags.name) {
40143
40241
  usageError("Usage: wh commit submit --type <arc|bond|set|list> --name <collection-name> --members <wref1,wref2,...>", "wh commit submit --type arc --name route --members Location/a,Location/b");
40144
40242
  }
@@ -40147,40 +40245,42 @@ var handleSubmit = async (ctx, { flags, args }) => {
40147
40245
  }
40148
40246
  const members = flags.members.split(",").map((m) => m.trim()).filter(Boolean);
40149
40247
  const arityMap = { arc: 2, bond: 2, pair: 2 };
40150
- const expected = arityMap[collectionType];
40151
- const collectionExample = `wh commit submit --type ${collectionType} --name ${flags.name} --members Location/a,Location/b`;
40248
+ const expected = arityMap[selectedCollectionType];
40249
+ const collectionExample = `wh commit submit --type ${selectedCollectionType} --name ${flags.name} --members Location/a,Location/b`;
40152
40250
  if (expected && members.length !== expected) {
40153
- throw new CliError(2 /* UserInput */, "USER_INPUT", `${collectionType} requires exactly ${expected} members, got ${members.length}`, undefined, collectionExample);
40251
+ throw new CliError(2 /* UserInput */, "USER_INPUT", `${selectedCollectionType} requires exactly ${expected} members, got ${members.length}`, undefined, collectionExample);
40154
40252
  }
40155
40253
  if (members.length === 0) {
40156
- throw new CliError(2 /* UserInput */, "USER_INPUT", `${collectionType} requires at least 1 member`, undefined, collectionExample);
40254
+ throw new CliError(2 /* UserInput */, "USER_INPUT", `${selectedCollectionType} requires at least 1 member`, undefined, collectionExample);
40157
40255
  }
40158
40256
  operations = [
40159
40257
  {
40160
40258
  operation: "add",
40161
40259
  kind: "collection",
40162
- type: collectionType,
40260
+ type: selectedCollectionType,
40163
40261
  name: flags.name,
40164
40262
  members
40165
40263
  }
40166
40264
  ];
40167
- } else if (opsJson) {
40168
- operations = parseJsonArray(opsJson, "--ops", {
40265
+ } else if (operationSource === "--ops") {
40266
+ const selectedOpsJson = requireCommitSourceValue(operationSource, opsJson);
40267
+ operations = parseJsonArray(selectedOpsJson, "--ops", {
40169
40268
  fileFlagSibling: "-f/--file"
40170
40269
  });
40171
- } else if (opsFile) {
40172
- if (opsFile.endsWith(".jsonl")) {
40270
+ } else if (operationSource === "--file") {
40271
+ const selectedOpsFile = requireCommitSourceValue(operationSource, opsFile);
40272
+ if (selectedOpsFile.endsWith(".jsonl")) {
40173
40273
  operations = [];
40174
40274
  } else {
40175
40275
  let file;
40176
40276
  try {
40177
- file = await readFile2(opsFile, "utf-8");
40277
+ file = await readFile2(selectedOpsFile, "utf-8");
40178
40278
  } catch (e) {
40179
- throw new CliError(2 /* UserInput */, "USER_INPUT", `Cannot read file '${opsFile}': ${e instanceof Error ? e.message : String(e)}`, undefined, "Check that the file path is correct and the file exists.");
40279
+ throw new CliError(2 /* UserInput */, "USER_INPUT", `Cannot read file '${selectedOpsFile}': ${e instanceof Error ? e.message : String(e)}`, undefined, "Check that the file path is correct and the file exists.");
40180
40280
  }
40181
40281
  operations = parseJsonArray(file, "--file contents");
40182
40282
  }
40183
- } else if (addNames.length > 0) {
40283
+ } else if (operationSource === "--add") {
40184
40284
  operations = buildAddOperations({
40185
40285
  addNames,
40186
40286
  dataJsons,
@@ -40188,17 +40288,14 @@ var handleSubmit = async (ctx, { flags, args }) => {
40188
40288
  abouts,
40189
40289
  kinds
40190
40290
  });
40191
- } else if (retractNames.length > 0) {
40192
- if (dataJsons.length > 0 || shapes.length > 0 || abouts.length > 0) {
40193
- throw new CliError(2 /* UserInput */, "USER_INPUT", "--retract cannot be combined with --data, --shape, or --about.", undefined, "Use --file <path.json> for mixed operation writes.");
40194
- }
40291
+ } else if (operationSource === "--retract") {
40195
40292
  operations = buildRetractOperations({
40196
40293
  retractNames,
40197
40294
  kinds,
40198
40295
  reasons,
40199
40296
  leaseId: leaseIdFlag
40200
40297
  });
40201
- } else if (reviseName) {
40298
+ } else if (operationSource === "--revise") {
40202
40299
  if (dataJsons.length > 1) {
40203
40300
  throw new CliError(2 /* UserInput */, "USER_INPUT", `--revise supports a single operation, but --data was repeated ${dataJsons.length} times.`, undefined, "Use --file <path.json> for multi-revision writes.");
40204
40301
  }
@@ -40220,13 +40317,13 @@ var handleSubmit = async (ctx, { flags, args }) => {
40220
40317
  }
40221
40318
  ];
40222
40319
  } else {
40223
- usageError("Usage: wh commit submit --ops '<json>' or --add <name> [--data <json>]", `wh commit submit --add player --shape location --data '{"x":0,"y":0}'`);
40320
+ operations = [];
40224
40321
  }
40225
40322
  if (!streamInput && operations.length > 0) {
40226
40323
  rejectLegacyLifecycleOperations(operations);
40227
40324
  assertWithinStreamOpLimit(operations.length);
40228
40325
  if (!allowNulBytes) {
40229
- const source = opsJson ? "--ops" : opsFile ? opsFile : addNames.length > 0 ? "--add" : reviseName !== undefined ? "--revise" : collectionType ? "--type" : "op";
40326
+ const source = operationSource === "--file" ? opsFile : operationSource;
40230
40327
  for (let i = 0;i < operations.length; i++) {
40231
40328
  const op = operations[i];
40232
40329
  const namePart = op.name ? ` (${op.name})` : "";
@@ -45671,21 +45768,27 @@ function buildSubscriptionMutationArgs(flags, usage, example) {
45671
45768
  }
45672
45769
  return mutationArgs;
45673
45770
  }
45674
- function rejectCommitOnlyFlags(flags, eventType) {
45771
+ function rejectCommitOnlyFlags(flags, eventType, correctiveExample) {
45675
45772
  for (const f of ["on", "filter", "source"]) {
45676
45773
  const v = flags[f];
45677
45774
  if (typeof v === "string" && v.length > 0) {
45678
- usageError(`--${f} is not valid for ${eventType} subscriptions — metadata events have no shape, filter, or source`, `wh sub create metadata-hook ${isOrgScopedEventType(eventType) ? "--org myorg" : "--repo myorg/myrepo"} --event ${eventType} --webhook-url https://example.com/hook`);
45775
+ usageError(`--${f} is not valid for ${eventType} subscriptions — metadata events have no shape, filter, or source`, correctiveExample ?? `wh sub create metadata-hook ${isOrgScopedEventType(eventType) ? "--org myorg" : "--repo myorg/myrepo"} --event ${eventType} --webhook-url https://example.com/hook`);
45679
45776
  }
45680
45777
  }
45681
45778
  }
45682
- function resolveSubScope(ctx, flags) {
45779
+ function resolveSubScope(ctx, flags, correctiveExample) {
45780
+ rejectConflictingSubScope(ctx, flags, correctiveExample);
45683
45781
  if (typeof flags.org === "string" && flags.org) {
45684
45782
  return { orgName: flags.org };
45685
45783
  }
45686
45784
  const { org, repo } = resolveRepoContext(ctx);
45687
45785
  return { orgName: org, repoName: repo };
45688
45786
  }
45787
+ function rejectConflictingSubScope(ctx, flags, correctiveExample) {
45788
+ if (flags.org !== undefined && ctx.invocation.flags.repo !== undefined) {
45789
+ usageError("Flags --org and --repo cannot be used together", correctiveExample);
45790
+ }
45791
+ }
45689
45792
  function scopeLabel(scope) {
45690
45793
  return scope.repoName ? `${scope.orgName}/${scope.repoName}` : scope.orgName;
45691
45794
  }
@@ -45711,14 +45814,12 @@ var handleCreate7 = async (ctx, { flags, args }) => {
45711
45814
  ...fallbackWebhookUrl ? { fallbackWebhookUrl } : {},
45712
45815
  ...allowTraceReentry ? { allowTraceReentry: true } : {}
45713
45816
  };
45817
+ rejectConflictingSubScope(ctx, flags, example);
45714
45818
  if (isOrgScopedEventType(eventType)) {
45715
45819
  const orgName = typeof flags.org === "string" ? flags.org : undefined;
45716
45820
  if (!orgName) {
45717
45821
  usageError(`${eventType} subscriptions are org-scoped — pass --org <org> (not --repo)`, `wh sub create org-hook --org myorg --event ${eventType} --webhook-url https://example.com/hook`);
45718
45822
  }
45719
- if (ctx.invocation.flags.repo !== undefined) {
45720
- usageError(`--repo is not valid for ${eventType} subscriptions — use --org <org>`, `wh sub create org-hook --org ${orgName} --event ${eventType} --webhook-url https://example.com/hook`);
45721
- }
45722
45823
  rejectCommitOnlyFlags(flags, eventType);
45723
45824
  const result2 = await ctx.client.subscription.create({
45724
45825
  orgName,
@@ -45734,6 +45835,9 @@ var handleCreate7 = async (ctx, { flags, args }) => {
45734
45835
  });
45735
45836
  return;
45736
45837
  }
45838
+ if (flags.org !== undefined) {
45839
+ usageError(`Flag --org cannot be used with repo-scoped ${eventType} subscriptions`, `wh sub create repo-hook --repo myorg/myrepo --event ${eventType} --webhook-url https://example.com/hook`);
45840
+ }
45737
45841
  const { org, repo } = resolveRepoContext(ctx);
45738
45842
  if (eventType !== "commit") {
45739
45843
  rejectCommitOnlyFlags(flags, eventType);
@@ -45779,7 +45883,7 @@ var handleUpdate4 = async (ctx, { flags, args }) => {
45779
45883
  usageError(usage, example);
45780
45884
  }
45781
45885
  rejectRemovedCronFlags(flags);
45782
- const scope = resolveSubScope(ctx, flags);
45886
+ const scope = resolveSubScope(ctx, flags, example);
45783
45887
  const scopeArg = scope.repoName ? `--repo ${scopeLabel(scope)}` : `--org ${scope.orgName}`;
45784
45888
  const existing = await ctx.client.subscription.get({ ...scope, name });
45785
45889
  if (existing.kind !== "webhook") {
@@ -45788,6 +45892,9 @@ var handleUpdate4 = async (ctx, { flags, args }) => {
45788
45892
  if (flags.kind && flags.kind !== existing.kind) {
45789
45893
  usageError(usage, example);
45790
45894
  }
45895
+ if (existing.eventType !== "commit") {
45896
+ rejectCommitOnlyFlags(flags, existing.eventType, `wh sub update ${name} ${scopeArg}`);
45897
+ }
45791
45898
  const patchArgs = buildSubscriptionPatchArgs(flags, usage, example);
45792
45899
  const result = await ctx.client.subscription.update({
45793
45900
  ...scope,
@@ -45808,7 +45915,7 @@ var handleView8 = async (ctx, { args, flags }) => {
45808
45915
  if (!name) {
45809
45916
  usageError("Usage: wh sub view <name> [--show-secrets] (--repo org/repo | --org org)", "wh sub view signal-hook --repo myorg/myrepo");
45810
45917
  }
45811
- const scope = resolveSubScope(ctx, flags);
45918
+ const scope = resolveSubScope(ctx, flags, "wh sub view signal-hook --repo myorg/myrepo");
45812
45919
  const sub = await ctx.client.subscription.get({ ...scope, name });
45813
45920
  const revealed = flags["show-secrets"] ? await ctx.client.subscription.reveal({ ...scope, name }) : undefined;
45814
45921
  writeOutput(ctx, revealed ? { ...sub, ...revealed } : sub, () => {
@@ -45923,7 +46030,7 @@ function renderSubscriptionLog(out, statusOut, c, subscriptionName, result) {
45923
46030
 
45924
46031
  // ../../packages/warmhub-cli/src/domains/sub/handlers-management.ts
45925
46032
  var handleList7 = async (ctx, { flags }) => {
45926
- const scope = resolveSubScope(ctx, flags);
46033
+ const scope = resolveSubScope(ctx, flags, "wh sub list --repo myorg/myrepo");
45927
46034
  const label = scopeLabel(scope);
45928
46035
  const all = await ctx.client.subscription.list(scope);
45929
46036
  const items = all.slice(0, flags.limit ?? all.length);
@@ -45949,7 +46056,7 @@ var handlePause = async (ctx, { args, flags }) => {
45949
46056
  if (!name) {
45950
46057
  usageError("Usage: wh sub pause <name> (--repo org/repo | --org org)", "wh sub pause signal-hook --repo myorg/myrepo");
45951
46058
  }
45952
- const scope = resolveSubScope(ctx, flags);
46059
+ const scope = resolveSubScope(ctx, flags, "wh sub pause signal-hook --repo myorg/myrepo");
45953
46060
  const result = await ctx.client.subscription.pause({ ...scope, name });
45954
46061
  writeOutput(ctx, result, () => {
45955
46062
  const c = ctx.colors;
@@ -45961,7 +46068,7 @@ var handleResume = async (ctx, { args, flags }) => {
45961
46068
  if (!name) {
45962
46069
  usageError("Usage: wh sub resume <name> (--repo org/repo | --org org)", "wh sub resume signal-hook --repo myorg/myrepo");
45963
46070
  }
45964
- const scope = resolveSubScope(ctx, flags);
46071
+ const scope = resolveSubScope(ctx, flags, "wh sub resume signal-hook --repo myorg/myrepo");
45965
46072
  const result = await ctx.client.subscription.resume({ ...scope, name });
45966
46073
  writeOutput(ctx, result, () => {
45967
46074
  const c = ctx.colors;
@@ -45973,7 +46080,7 @@ var handleDelete3 = async (ctx, { args, flags }) => {
45973
46080
  if (!name) {
45974
46081
  usageError("Usage: wh sub delete <name> (--repo org/repo | --org org)", "wh sub delete signal-hook --repo myorg/myrepo");
45975
46082
  }
45976
- const scope = resolveSubScope(ctx, flags);
46083
+ const scope = resolveSubScope(ctx, flags, "wh sub delete signal-hook --repo myorg/myrepo");
45977
46084
  const result = await ctx.client.subscription.remove({ ...scope, name });
45978
46085
  writeOutput(ctx, result, () => {
45979
46086
  const c = ctx.colors;
@@ -45986,7 +46093,7 @@ var handleBind = async (ctx, { flags, args }) => {
45986
46093
  if (!name || !setName) {
45987
46094
  usageError("Usage: wh sub bind <name> --credentials <setName> (--repo org/repo | --org org)", "wh sub bind signal-hook --credentials webhook-keys --repo myorg/myrepo");
45988
46095
  }
45989
- const scope = resolveSubScope(ctx, flags);
46096
+ const scope = resolveSubScope(ctx, flags, "wh sub bind signal-hook --credentials webhook-keys --repo myorg/myrepo");
45990
46097
  const result = await ctx.client.subscription.bindCredentials({
45991
46098
  ...scope,
45992
46099
  subscriptionName: name,
@@ -46002,7 +46109,7 @@ var handleUnbind = async (ctx, { args, flags }) => {
46002
46109
  if (!name) {
46003
46110
  usageError("Usage: wh sub unbind <name> (--repo org/repo | --org org)", "wh sub unbind signal-hook --repo myorg/myrepo");
46004
46111
  }
46005
- const scope = resolveSubScope(ctx, flags);
46112
+ const scope = resolveSubScope(ctx, flags, "wh sub unbind signal-hook --repo myorg/myrepo");
46006
46113
  const result = await ctx.client.subscription.unbindCredentials({
46007
46114
  ...scope,
46008
46115
  subscriptionName: name
@@ -46017,7 +46124,7 @@ var handleLog = async (ctx, { flags, args }) => {
46017
46124
  if (!name) {
46018
46125
  usageError("Usage: wh sub log <name> [--repo org/repo]", "wh sub log my-sub");
46019
46126
  }
46020
- const scope = resolveSubScope(ctx, flags);
46127
+ const scope = resolveSubScope(ctx, flags, "wh sub log my-sub --repo myorg/myrepo");
46021
46128
  if (!scope.repoName) {
46022
46129
  usageError("Usage: wh sub log <name> [--repo org/repo]", "wh sub log my-sub --repo myorg/myrepo");
46023
46130
  }
@@ -48801,7 +48908,7 @@ function resolveLogLevel(flagLevel, env) {
48801
48908
  // package.json
48802
48909
  var package_default3 = {
48803
48910
  name: "@warmhub/cli",
48804
- version: "0.76.0",
48911
+ version: "0.77.0",
48805
48912
  private: false,
48806
48913
  type: "module",
48807
48914
  description: "The wh CLI for WarmHub — create repos, commit and query data, and compound knowledge with your AI agents.",
@@ -49399,4 +49506,4 @@ process.exitCode = interceptedExitCode === undefined ? await runPreparedCli(laun
49399
49506
  version: package_default3.version
49400
49507
  }) : interceptedExitCode;
49401
49508
 
49402
- //# debugId=4AC624B4C136D1A764756E2164756E21
49509
+ //# debugId=3CF608ED13A4149264756E2164756E21
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@warmhub/cli",
3
- "version": "0.76.0",
3
+ "version": "0.77.0",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "The wh CLI for WarmHub — create repos, commit and query data, and compound knowledge with your AI agents.",