@warmhub/sdk-ts 0.66.0 → 0.68.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.
@@ -3,10 +3,21 @@ import { TRPCClientError, createTRPCProxyClient, splitLink, httpBatchLink, httpL
3
3
  // src/index.ts
4
4
 
5
5
  // ../rules/src/builtin-shapes.ts
6
- var BUILTIN_SHAPE_NAMES = ["Pair", "Triple", "Set", "List"];
6
+ var BUILTIN_SHAPE_NAMES = ["Pair", "Set", "List"];
7
+ var RETIRED_COLLECTION_SHAPE_NAMES = ["Triple"];
8
+ var RESERVED_COLLECTION_SHAPE_NAMES = [
9
+ ...BUILTIN_SHAPE_NAMES,
10
+ ...RETIRED_COLLECTION_SHAPE_NAMES
11
+ ];
7
12
  function isBuiltinCollectionShape(name) {
8
13
  return BUILTIN_SHAPE_NAMES.includes(name);
9
14
  }
15
+ function isRetiredCollectionShape(name) {
16
+ return RETIRED_COLLECTION_SHAPE_NAMES.includes(name);
17
+ }
18
+ function isReservedCollectionShape(name) {
19
+ return RESERVED_COLLECTION_SHAPE_NAMES.includes(name);
20
+ }
10
21
  var BUILTIN_CONTENT_SHAPE_NAMES = ["Content"];
11
22
  var STORED_CONTENT_NAMES = ["Readme", "Agents"];
12
23
  var SYNTHESIZED_CONTENT_NAMES = ["LlmsTxt"];
@@ -29,29 +40,6 @@ var DEFAULT_STREAM_APPEND_CHUNK_SIZE = 1e3;
29
40
  var MAX_STREAM_APPEND_OPERATION_COUNT = 1e4;
30
41
 
31
42
  // ../rules/src/commit-types.ts
32
- function isCollectionAbout(value) {
33
- if (typeof value !== "object" || value === null || Array.isArray(value))
34
- return false;
35
- const record = value;
36
- const keys = Object.keys(record);
37
- if (keys.length !== 1) return false;
38
- const key = keys[0];
39
- if (key !== "pair" && key !== "triple" && key !== "set" && key !== "list")
40
- return false;
41
- return Array.isArray(record[key]);
42
- }
43
- function collectionAboutType(about) {
44
- if ("pair" in about) return "pair";
45
- if ("triple" in about) return "triple";
46
- if ("set" in about) return "set";
47
- return "list";
48
- }
49
- function collectionAboutMembers(about) {
50
- if ("pair" in about) return about.pair;
51
- if ("triple" in about) return about.triple;
52
- if ("set" in about) return about.set;
53
- return about.list;
54
- }
55
43
  function splitLocalPath(name) {
56
44
  const idx = name.indexOf("/");
57
45
  if (idx === -1) return null;
@@ -364,23 +352,8 @@ var PLATFORM_STATUS_STATUSES = [
364
352
  enum: PLATFORM_STATUS_STATUSES.map((status) => status.key)}});
365
353
 
366
354
  // ../rules/src/tokens.ts
367
- var ALLOC_TOKEN_RE = /\$(\d+)/g;
368
- var REF_TOKEN_RE = /#(\d+)/g;
355
+ var COMMIT_TOKEN_SYNTAX_REMOVED_MESSAGE = "$N/#N commit-token syntax is no longer supported. Use explicit names and explicit wrefs. For assertions about newly created things, create the thing with a deterministic name and set about to that wref in the same commit.";
369
356
  var ANY_TOKEN_RE = /[$#]\d+/;
370
- function findAllocTokens(s) {
371
- const tokens = [];
372
- for (const m of s.matchAll(ALLOC_TOKEN_RE)) {
373
- tokens.push(Number.parseInt(m[1], 10));
374
- }
375
- return tokens;
376
- }
377
- function findRefTokens(s) {
378
- const tokens = [];
379
- for (const m of s.matchAll(REF_TOKEN_RE)) {
380
- tokens.push(Number.parseInt(m[1], 10));
381
- }
382
- return tokens;
383
- }
384
357
  function hasAnyTokens(s) {
385
358
  return ANY_TOKEN_RE.test(s);
386
359
  }
@@ -388,146 +361,35 @@ function hasAnyTokens(s) {
388
361
  // ../rules/src/preflight-commit.ts
389
362
  function preflightCommitDiagnostics(operations, options) {
390
363
  const errors = [];
391
- tokenHygiene(operations, errors);
392
- illegalOpSequences(operations, errors);
364
+ rejectCommitTokenSyntax(operations, errors);
365
+ illegalOpSequences(operations, errors, options?.checkAddAdd ?? true);
393
366
  return errors;
394
367
  }
395
368
  function getOpName(op) {
396
369
  return op.name;
397
370
  }
398
- function collectionAboutMembersOrEmpty(about) {
399
- if (about && typeof about !== "string" && isCollectionAbout(about)) {
400
- return collectionAboutMembers(about);
401
- }
402
- return [];
403
- }
404
371
  function tokenStringFields(op) {
405
- const fields = [getOpName(op)];
372
+ const fields = [getOpName(op), op.newName];
406
373
  if (typeof op.about === "string") {
407
374
  fields.push(op.about);
408
- } else {
409
- fields.push(...collectionAboutMembersOrEmpty(op.about));
410
375
  }
411
376
  if (op.members) {
412
377
  fields.push(...op.members);
413
378
  }
414
379
  return fields;
415
380
  }
416
- function collectMisusedAllocFields(op) {
417
- const result = [];
418
- if (op.operation === "add") {
419
- if (typeof op.about === "string") {
420
- result.push({ value: op.about });
421
- }
422
- for (const m of collectionAboutMembersOrEmpty(op.about)) {
423
- result.push({ value: m, context: "collection member" });
424
- }
425
- if (op.members) {
426
- for (const m of op.members) {
427
- result.push({ value: m, context: "collection member" });
428
- }
429
- }
430
- } else {
431
- const name = getOpName(op);
432
- if (name) {
433
- result.push({ value: name });
434
- }
435
- }
436
- return result;
437
- }
438
- function tokenHygiene(operations, errors) {
439
- let anyTokens = false;
440
- for (const op of operations) {
441
- for (const f of tokenStringFields(op)) {
442
- if (f && hasAnyTokens(f)) {
443
- anyTokens = true;
444
- break;
445
- }
446
- }
447
- if (anyTokens) break;
448
- }
449
- if (!anyTokens) return;
450
- const allocations = /* @__PURE__ */ new Map();
451
- for (let i = 0; i < operations.length; i++) {
452
- const op = operations[i];
453
- if (!op || op.operation !== "add" || !op.name) continue;
454
- const local = splitLocalPath(op.name);
455
- if (!local) {
456
- const allocs = findAllocTokens(op.name);
457
- if (allocs.length > 0) {
458
- errors.push({
459
- code: "ALLOC_TOKEN_IN_SHAPE_NAME",
460
- operationIndex: i,
461
- message: `Allocation token $${allocs[0]} not allowed in shape name "${op.name}"`
462
- });
463
- }
464
- continue;
465
- }
466
- const segments = local.bareName.split("/");
467
- const lastSegment = segments[segments.length - 1];
468
- const lastSegAllocs = lastSegment ? findAllocTokens(lastSegment) : [];
469
- for (let s = 0; s < segments.length - 1; s++) {
470
- const seg = segments[s];
471
- if (!seg) continue;
472
- const earlyAllocs = findAllocTokens(seg);
473
- if (earlyAllocs.length > 0) {
474
- errors.push({
475
- code: "ALLOC_TOKEN_WRONG_SEGMENT",
476
- operationIndex: i,
477
- message: `Allocation token $${earlyAllocs[0]} must be in the last segment of ADD name "${op.name}"`
478
- });
479
- }
480
- }
481
- for (const tokenNum of lastSegAllocs) {
482
- if (tokenNum <= 0) {
483
- errors.push({
484
- code: "INVALID_TOKEN_NUMBER",
485
- operationIndex: i,
486
- message: `Token number must be positive: $${tokenNum}`
487
- });
488
- }
489
- if (allocations.has(tokenNum)) {
490
- errors.push({
491
- code: "DUPLICATE_ALLOC_TOKEN",
492
- operationIndex: i,
493
- message: `Token $${tokenNum} allocated more than once`
494
- });
495
- }
496
- allocations.set(tokenNum, { opIndex: i });
497
- }
498
- }
381
+ function rejectCommitTokenSyntax(operations, errors) {
499
382
  for (let i = 0; i < operations.length; i++) {
500
383
  const op = operations[i];
501
384
  if (!op) continue;
502
385
  for (const field of tokenStringFields(op)) {
503
- if (!field) continue;
504
- const refs = findRefTokens(field);
505
- for (const tokenNum of refs) {
506
- if (tokenNum <= 0) {
507
- errors.push({
508
- code: "INVALID_TOKEN_NUMBER",
509
- operationIndex: i,
510
- message: `Token number must be positive: #${tokenNum}`
511
- });
512
- }
513
- if (!allocations.has(tokenNum)) {
514
- errors.push({
515
- code: "UNRESOLVED_REF_TOKEN",
516
- operationIndex: i,
517
- message: `Reference #${tokenNum} has no matching allocation $${tokenNum}`
518
- });
519
- }
520
- }
521
- }
522
- const misusedFields = collectMisusedAllocFields(op);
523
- for (const { value, context } of misusedFields) {
524
- const allocs = findAllocTokens(value);
525
- if (allocs.length > 0) {
386
+ if (field && hasAnyTokens(field)) {
526
387
  errors.push({
527
- code: "MISUSED_ALLOC_TOKEN",
388
+ code: "COMMIT_TOKEN_SYNTAX_REMOVED",
528
389
  operationIndex: i,
529
- message: context ? `Use #${allocs[0]} to reference token ${allocs[0]} in ${context}, not $${allocs[0]}` : `Use #${allocs[0]} to reference token ${allocs[0]}, not $${allocs[0]}`
390
+ message: COMMIT_TOKEN_SYNTAX_REMOVED_MESSAGE
530
391
  });
392
+ break;
531
393
  }
532
394
  }
533
395
  }
@@ -553,6 +415,13 @@ function illegalOpSequences(operations, errors, checkAddAdd) {
553
415
  const curr = history[i];
554
416
  if (!prev || !curr) continue;
555
417
  const pair = `${prev.operation}+${curr.operation}`;
418
+ if (checkAddAdd && pair === "add+add") {
419
+ errors.push({
420
+ code: "ILLEGAL_OP_SEQUENCE",
421
+ operationIndex: curr.index,
422
+ message: `Cannot add "${qualName}" twice in the same commit`
423
+ });
424
+ }
556
425
  if (pair === "revise+add") {
557
426
  errors.push({
558
427
  code: "ILLEGAL_OP_SEQUENCE",
@@ -565,8 +434,10 @@ function illegalOpSequences(operations, errors, checkAddAdd) {
565
434
  }
566
435
 
567
436
  // ../rules/src/preflight-operation.ts
568
- var collectionTypes = ["pair", "triple", "set", "list"];
437
+ var collectionTypes = ["pair", "set", "list"];
569
438
  var collectionOps = ["add", "revise"];
439
+ var COLLECTION_CREATE_REQUIRES_NAME_MESSAGE = "Collection create requires a name. Collections are ordinary named things (ADR 0004).";
440
+ var COLLECTION_ABOUT_REMOVED_MESSAGE = 'about accepts a wref. Create the collection as its own named operation, then point the assertion at it. Prefer deterministic relationship names, for example: [{"operation":"add","kind":"collection","type":"pair","name":"a-b-relationship","members":["A","B"]},{"operation":"add","kind":"assertion","about":"Pair/a-b-relationship","name":"Assertion/example","data":{}}]. For CLI usage, use wh commit submit --file with the two operations.';
570
441
  function preflightOpDiagnostics(op, operationIndex) {
571
442
  const errors = [];
572
443
  errors.push(...builtinShapeGuard(op, operationIndex));
@@ -579,17 +450,41 @@ function preflightOpDiagnostics(op, operationIndex) {
579
450
  function builtinShapeGuard(op, operationIndex) {
580
451
  const errors = [];
581
452
  const name = op.name;
582
- if (op.kind === "shape" && name && isBuiltinShape(name)) {
453
+ if (name && isRetiredCollectionShape(name)) {
454
+ errors.push({
455
+ code: "RESERVED_NAME",
456
+ operationIndex,
457
+ message: `Shape "${name}" is a retired collection shape and cannot be written manually`
458
+ });
459
+ }
460
+ if (op.operation === "rename" && (op.kind === "shape" || op.name !== void 0 && !splitLocalPath(op.name)) && op.newName && isRetiredCollectionShape(op.newName)) {
583
461
  errors.push({
584
462
  code: "RESERVED_NAME",
585
463
  operationIndex,
586
- message: `Shape "${name}" is a built-in shape and cannot be ${op.operation === "add" ? "created" : "revised"} manually`
464
+ message: `Shape "${op.newName}" is a retired collection shape and cannot be written manually`
587
465
  });
466
+ } else {
467
+ const isShapeRename = op.operation === "rename" && (op.kind === "shape" || op.name !== void 0 && !splitLocalPath(op.name));
468
+ const builtinShapeName = name && isBuiltinShape(name) ? name : isShapeRename && op.newName && isBuiltinShape(op.newName) ? op.newName : void 0;
469
+ if (builtinShapeName && (isShapeRename || op.operation !== "retract" && op.kind === "shape")) {
470
+ const action = op.operation === "add" ? "created" : op.operation === "rename" ? "renamed" : "revised";
471
+ errors.push({
472
+ code: "RESERVED_NAME",
473
+ operationIndex,
474
+ message: `Shape "${builtinShapeName}" is a built-in shape and cannot be ${action} manually`
475
+ });
476
+ }
588
477
  }
589
- if (op.kind === "thing" && name) {
478
+ if (name) {
590
479
  const local = splitLocalPath(name);
591
- if (local && isBuiltinCollectionShape(local.shapePrefix)) {
592
- const message = op.operation === "add" ? `Cannot add kind="thing" under built-in shape "${local.shapePrefix}". Use kind="collection" or the about sugar instead.` : `Cannot revise kind="thing" under built-in shape "${local.shapePrefix}". Collections are immutable.`;
480
+ if (local && isRetiredCollectionShape(local.shapePrefix)) {
481
+ errors.push({
482
+ code: "VALIDATION_ERROR",
483
+ operationIndex,
484
+ message: `Cannot ${op.operation} under retired collection shape "${local.shapePrefix}". Triple is read-only and retired for new collection writes.`
485
+ });
486
+ } else if (op.kind === "thing" && local && isBuiltinCollectionShape(local.shapePrefix)) {
487
+ const message = op.operation === "add" ? `Cannot add kind="thing" under built-in shape "${local.shapePrefix}". Use kind="collection" instead.` : `Cannot revise kind="thing" under built-in shape "${local.shapePrefix}". Use kind="collection" to revise a collection.`;
593
488
  errors.push({
594
489
  code: "VALIDATION_ERROR",
595
490
  operationIndex,
@@ -627,109 +522,100 @@ function contentNameGuard(op, operationIndex) {
627
522
  function plusSignGuard(op, operationIndex) {
628
523
  const errors = [];
629
524
  const name = op.name;
630
- if (op.kind === "collection") return errors;
631
- if (name?.includes("+")) {
632
- const local = splitLocalPath(name);
633
- if (local && isBuiltinCollectionShape(local.shapePrefix)) return errors;
634
- errors.push({
635
- code: "VALIDATION_ERROR",
636
- operationIndex,
637
- message: `Name "${name}" contains reserved character "+". The "+" character is reserved for collection names.`
638
- });
639
- }
640
- return errors;
641
- }
642
- function validateCollectionAbouts(op, operationIndex) {
643
- const errors = [];
644
- if (!op.about || typeof op.about === "string") return errors;
645
- if (!isCollectionAbout(op.about)) {
646
- const keys = typeof op.about === "object" && op.about !== null ? Object.keys(op.about) : [];
525
+ if (op.newName?.includes("+")) {
647
526
  errors.push({
648
527
  code: "VALIDATION_ERROR",
649
528
  operationIndex,
650
- message: `Structured about must have exactly one key: pair, triple, set, or list. Got: ${keys.join(", ") || typeof op.about}`
529
+ message: `Name "${op.newName}" contains reserved character "+". The "+" character is reserved for the historical collection auto-name namespace and is not allowed in user-supplied names.`
651
530
  });
652
531
  return errors;
653
532
  }
654
- const tag = collectionAboutType(op.about);
655
- const members = collectionAboutMembers(op.about);
656
- for (let i = 0; i < members.length; i++) {
657
- if (typeof members[i] !== "string") {
533
+ if (name?.includes("+")) {
534
+ if (op.kind === "collection" && op.operation === "add") {
658
535
  errors.push({
659
536
  code: "VALIDATION_ERROR",
660
537
  operationIndex,
661
- message: `Collection member at index ${i} must be a string, got ${typeof members[i]}`
538
+ message: `Name "${name}" contains reserved character "+". The "+" character is reserved for the historical collection auto-name namespace and is not allowed in user-supplied names.`
662
539
  });
540
+ return errors;
663
541
  }
664
- }
665
- const arityError = collectionArityError(tag, members);
666
- if (arityError) {
542
+ if (op.kind === "collection") return errors;
543
+ const local = splitLocalPath(name);
544
+ if (local && isReservedCollectionShape(local.shapePrefix)) return errors;
667
545
  errors.push({
668
546
  code: "VALIDATION_ERROR",
669
547
  operationIndex,
670
- message: arityError
548
+ message: `Name "${name}" contains reserved character "+". The "+" character is reserved for the historical collection auto-name namespace and is not allowed in user-supplied names.`
671
549
  });
672
550
  }
673
551
  return errors;
674
552
  }
553
+ function validateCollectionAbouts(op, operationIndex) {
554
+ const errors = [];
555
+ if (!op.about || typeof op.about === "string") return errors;
556
+ errors.push({
557
+ code: "VALIDATION_ERROR",
558
+ operationIndex,
559
+ message: COLLECTION_ABOUT_REMOVED_MESSAGE
560
+ });
561
+ return errors;
562
+ }
675
563
  function validateCollectionOps(op, operationIndex) {
676
564
  const errors = [];
677
565
  if (op.kind !== "collection") return errors;
678
566
  if (!collectionOps.includes(op.operation)) {
567
+ return errors;
568
+ }
569
+ if (op.operation === "add" && !op.name) {
679
570
  errors.push({
680
571
  code: "VALIDATION_ERROR",
681
572
  operationIndex,
682
- message: `Collection kind only supports "add" or "revise" operation, got "${op.operation}"`
573
+ message: COLLECTION_CREATE_REQUIRES_NAME_MESSAGE
683
574
  });
684
- return errors;
685
575
  }
686
- if (op.operation === "add") {
687
- if (!op.type || !collectionTypes.includes(op.type)) {
688
- errors.push({
689
- code: "VALIDATION_ERROR",
690
- operationIndex,
691
- message: `Collection "type" must be one of: pair, triple, set, list. Got: "${op.type ?? ""}"`
692
- });
693
- }
694
- if (!op.members || !Array.isArray(op.members)) {
695
- errors.push({
696
- code: "VALIDATION_ERROR",
697
- operationIndex,
698
- message: 'Collection requires a "members" array'
699
- });
700
- } else {
701
- for (let i = 0; i < op.members.length; i++) {
702
- if (typeof op.members[i] !== "string") {
703
- errors.push({
704
- code: "VALIDATION_ERROR",
705
- operationIndex,
706
- message: `Collection member at index ${i} must be a string`
707
- });
708
- }
709
- }
710
- }
711
- if (op.type && op.members) {
712
- const arityError = collectionArityError(
713
- op.type,
714
- op.members
715
- );
716
- if (arityError) {
576
+ if (!op.type || !collectionTypes.includes(op.type)) {
577
+ errors.push({
578
+ code: "VALIDATION_ERROR",
579
+ operationIndex,
580
+ message: `Collection "type" must be one of: pair, set, list. Got: "${op.type ?? ""}"`
581
+ });
582
+ }
583
+ if (!op.members || !Array.isArray(op.members)) {
584
+ errors.push({
585
+ code: "VALIDATION_ERROR",
586
+ operationIndex,
587
+ message: 'Collection requires a "members" array'
588
+ });
589
+ } else {
590
+ for (let i = 0; i < op.members.length; i++) {
591
+ if (typeof op.members[i] !== "string") {
717
592
  errors.push({
718
593
  code: "VALIDATION_ERROR",
719
594
  operationIndex,
720
- message: arityError
595
+ message: `Collection member at index ${i} must be a string`
721
596
  });
722
597
  }
723
598
  }
724
599
  }
600
+ if (op.type && op.members) {
601
+ const arityError = collectionArityError(
602
+ op.type,
603
+ op.members
604
+ );
605
+ if (arityError) {
606
+ errors.push({
607
+ code: "VALIDATION_ERROR",
608
+ operationIndex,
609
+ message: arityError
610
+ });
611
+ }
612
+ }
725
613
  return errors;
726
614
  }
727
615
  function collectionArityError(tag, members) {
728
616
  switch (tag) {
729
617
  case "pair":
730
618
  return members.length !== 2 ? `Pair requires exactly 2 members, got ${members.length}` : null;
731
- case "triple":
732
- return members.length !== 3 ? `Triple requires exactly 3 members, got ${members.length}` : null;
733
619
  case "set":
734
620
  case "list":
735
621
  return members.length < 1 ? `${tag === "set" ? "Set" : "List"} requires at least 1 member, got 0` : null;
@@ -741,7 +627,7 @@ function preflightOpDiagnostics2(op, operationIndex) {
741
627
  return preflightOpDiagnostics(op, operationIndex);
742
628
  }
743
629
  function preflightCommitDiagnostics2(operations, options) {
744
- return preflightCommitDiagnostics(operations);
630
+ return preflightCommitDiagnostics(operations, options);
745
631
  }
746
632
 
747
633
  // ../rules/src/reserved-orgs.ts
@@ -7224,7 +7110,7 @@ function normalizeOptionalTypeSpec(spec) {
7224
7110
  return { spec, optionalByType: false };
7225
7111
  }
7226
7112
  function isFieldOptional(fieldKey, typeSpec) {
7227
- const optionalByKey = fieldKey !== void 0 && fieldKey.endsWith("?");
7113
+ const optionalByKey = fieldKey?.endsWith("?");
7228
7114
  return optionalByKey || normalizeOptionalTypeSpec(typeSpec).optionalByType;
7229
7115
  }
7230
7116
 
@@ -8034,17 +7920,39 @@ function shapeDefinitionPreflightError(name, data, verb) {
8034
7920
  }
8035
7921
 
8036
7922
  // src/collection-operation-normalize.ts
8037
- var collectionTypes2 = /* @__PURE__ */ new Set([
8038
- "pair",
8039
- "triple",
8040
- "set",
8041
- "list"
8042
- ]);
7923
+ var collectionTypes2 = /* @__PURE__ */ new Set(["pair", "set", "list"]);
8043
7924
  function normalizeBackendCollectionAdd(operation, source) {
7925
+ const normalized = normalizeCollectionWrite(operation, source, "add");
7926
+ return {
7927
+ operation: "add",
7928
+ kind: "collection",
7929
+ name: normalized.name,
7930
+ type: normalized.type,
7931
+ members: normalized.members,
7932
+ ...operation.skipExisting === true ? { skipExisting: true } : {}
7933
+ };
7934
+ }
7935
+ function normalizeBackendCollectionRevise(operation, source) {
7936
+ const normalized = normalizeCollectionWrite(operation, source, "revise");
7937
+ if (!normalized.name) {
7938
+ throw new Error(`${source}: collection revise requires a target name`);
7939
+ }
7940
+ return {
7941
+ operation: "revise",
7942
+ kind: "collection",
7943
+ name: normalized.name,
7944
+ type: normalized.type,
7945
+ members: normalized.members,
7946
+ ...typeof operation.expectedVersion === "number" ? { expectedVersion: operation.expectedVersion } : {},
7947
+ ...typeof operation.leaseId === "string" && operation.leaseId.length > 0 ? { leaseId: operation.leaseId } : {}
7948
+ };
7949
+ }
7950
+ function normalizeCollectionWrite(operation, source, writeOperation) {
8044
7951
  const diagnostics = preflightOpDiagnostics2(
8045
7952
  {
8046
- operation: "add",
7953
+ operation: writeOperation,
8047
7954
  kind: "collection",
7955
+ name: typeof operation.name === "string" ? operation.name : void 0,
8048
7956
  type: typeof operation.type === "string" ? operation.type : void 0,
8049
7957
  members: Array.isArray(operation.members) ? operation.members : void 0
8050
7958
  },
@@ -8058,35 +7966,40 @@ function normalizeBackendCollectionAdd(operation, source) {
8058
7966
  const type = normalizeCollectionType(operation.type);
8059
7967
  if (!type) {
8060
7968
  throw new Error(
8061
- `${source}: collection add requires 'type' to be one of: pair, triple, set, list`
7969
+ `${source}: collection ${writeOperation} requires 'type' to be one of: pair, set, list`
8062
7970
  );
8063
7971
  }
8064
7972
  if (!Array.isArray(operation.members)) {
8065
- throw new Error(`${source}: collection add requires a 'members' array`);
7973
+ throw new Error(
7974
+ `${source}: collection ${writeOperation} requires a 'members' array`
7975
+ );
8066
7976
  }
8067
7977
  const name = normalizeOptionalName(operation.name);
8068
- if (operation.name !== void 0 && !name) {
7978
+ if (!name) {
8069
7979
  throw new Error(
8070
- `${source}: collection add name must be a non-empty string when provided`
7980
+ `${source}: collection ${writeOperation} name must be a non-empty string`
8071
7981
  );
8072
7982
  }
8073
- assertNoUnsupportedCollectionAddFields(operation, source);
7983
+ assertNoUnsupportedCollectionFields(operation, source, writeOperation);
8074
7984
  return {
8075
- operation: "add",
8076
- kind: "collection",
8077
- ...name ? { name } : {},
7985
+ name,
8078
7986
  type,
8079
- members: operation.members,
8080
- ...operation.skipExisting === true ? { skipExisting: true } : {}
7987
+ members: operation.members
8081
7988
  };
8082
7989
  }
8083
- function assertNoUnsupportedCollectionAddFields(operation, source) {
8084
- const unsupportedFields = ["about", "aboutWref", "shapeWref", "data"].filter(
7990
+ function assertNoUnsupportedCollectionFields(operation, source, writeOperation) {
7991
+ const unsupportedFields = [
7992
+ "about",
7993
+ "aboutWref",
7994
+ "shapeWref",
7995
+ "data",
7996
+ ...writeOperation === "revise" ? ["skipExisting"] : []
7997
+ ].filter(
8085
7998
  (field) => operation[field] !== void 0
8086
7999
  );
8087
8000
  if (unsupportedFields.length > 0) {
8088
8001
  throw new Error(
8089
- `${source}: collection add does not support ${unsupportedFields.map((field) => `'${field}'`).join(", ")}`
8002
+ `${source}: collection ${writeOperation} does not support ${unsupportedFields.map((field) => `'${field}'`).join(", ")}`
8090
8003
  );
8091
8004
  }
8092
8005
  }
@@ -8137,14 +8050,12 @@ function toBackendStreamOperation(operation) {
8137
8050
  `${kind2} revise operation no longer supports 'active' \u2014 use retract('${name}') instead`
8138
8051
  );
8139
8052
  }
8053
+ if (kind2 === "collection") {
8054
+ return normalizeBackendCollectionRevise(operation, "commit.apply");
8055
+ }
8140
8056
  if (operation.data === void 0) {
8141
8057
  throw new Error(`${kind2} revise operation requires 'data'`);
8142
8058
  }
8143
- if (kind2 === "collection") {
8144
- throw new Error(
8145
- `collection revise is no longer supported \u2014 use retract('${name}') instead`
8146
- );
8147
- }
8148
8059
  if (kind2 === "assertion") {
8149
8060
  return {
8150
8061
  operation: "revise",
@@ -8184,6 +8095,9 @@ function toBackendStreamOperation(operation) {
8184
8095
  if (!("about" in operation) || operation.about === void 0) {
8185
8096
  throw new Error("assertion add operation requires 'about'");
8186
8097
  }
8098
+ if (typeof operation.about !== "string") {
8099
+ throw new Error(COLLECTION_ABOUT_REMOVED_MESSAGE);
8100
+ }
8187
8101
  if (operation.data === void 0) {
8188
8102
  throw new Error("assertion add operation requires 'data'");
8189
8103
  }
@@ -8333,10 +8247,9 @@ var DEFINITE_CLIENT_REJECT_CODES = /* @__PURE__ */ new Set([
8333
8247
  "CONFLICT",
8334
8248
  "ALREADY_RETRACTED",
8335
8249
  "ARCHIVED",
8336
- // Pre-apply rejections from stream/service.ts: applyRateLimit() and the
8337
- // unresolved-token check both throw before any operation lands, so the
8338
- // first-chunk wrapper would discard structured retry/validation detail
8339
- // (retryAfter, the failing token, etc.).
8250
+ // Pre-apply rejections from stream/service.ts throw before any operation
8251
+ // lands, so the first-chunk wrapper would discard structured
8252
+ // retry/validation detail (retryAfter, validation diagnostics, etc.).
8340
8253
  "RATE_LIMITED",
8341
8254
  "TOO_MANY_REQUESTS",
8342
8255
  "UNRESOLVED_TOKEN"
@@ -8390,34 +8303,14 @@ function computeBackoffDelayMs(attempt, policy) {
8390
8303
  function sleep(ms) {
8391
8304
  return new Promise((resolve) => setTimeout(resolve, ms));
8392
8305
  }
8393
- var TOKEN_REF_REGEX = /[$#]\d+/;
8394
- function stringHasTokenRef(value) {
8395
- return typeof value === "string" && TOKEN_REF_REGEX.test(value);
8396
- }
8397
- function structuralValueHasTokenRef(value, seen = /* @__PURE__ */ new WeakSet()) {
8398
- if (stringHasTokenRef(value)) return true;
8399
- if (value !== null && typeof value === "object") {
8400
- if (seen.has(value)) return false;
8401
- seen.add(value);
8402
- if (Array.isArray(value)) {
8403
- return value.some((entry) => structuralValueHasTokenRef(entry, seen));
8404
- }
8405
- return Object.values(value).some(
8406
- (entry) => structuralValueHasTokenRef(entry, seen)
8407
- );
8408
- }
8409
- return false;
8410
- }
8411
- function opUsesTokens(op) {
8412
- return stringHasTokenRef(op.name) || stringHasTokenRef(op.wref) || structuralValueHasTokenRef(op.about) || stringHasTokenRef(op.aboutWref) || structuralValueHasTokenRef(op.members) || structuralValueHasTokenRef(op.data);
8413
- }
8414
8306
 
8415
8307
  // src/stream-submit-submit.ts
8416
8308
  var StreamValidationError = class extends Error {
8417
- code = "VALIDATION_ERROR";
8309
+ code;
8418
8310
  status = 400;
8419
- constructor(message) {
8311
+ constructor(message, code = "VALIDATION_ERROR") {
8420
8312
  super(message);
8313
+ this.code = code;
8421
8314
  this.name = "WarmHubError";
8422
8315
  }
8423
8316
  };
@@ -8442,6 +8335,7 @@ async function submitOperationsViaStream(client, args) {
8442
8335
  }
8443
8336
  return streamOperation;
8444
8337
  });
8338
+ validateNormalizedOperations(operations);
8445
8339
  const chunkSize = normalizeChunkSize(args.chunkSize);
8446
8340
  let streamId = args.streamId ?? createStreamId();
8447
8341
  const policy = args.streamId !== void 0 ? false : resolveRetryPolicy(args.retry);
@@ -8456,7 +8350,6 @@ async function submitOperationsViaStream(client, args) {
8456
8350
  let attempt = 1;
8457
8351
  let priorAttemptAmbiguous = false;
8458
8352
  const chunkIsAtomic = chunk.length === 1;
8459
- const chunkUsesTokens = chunk.some(opUsesTokens);
8460
8353
  while (true) {
8461
8354
  try {
8462
8355
  const appendResult = await client.stream.append({
@@ -8481,7 +8374,7 @@ async function submitOperationsViaStream(client, args) {
8481
8374
  if (chunkResults.length === 0 && !priorAttemptAmbiguous && isDefiniteClientError(cause)) {
8482
8375
  throw cause;
8483
8376
  }
8484
- if (chunkResults.length === 0 && chunkIsAtomic && !chunkUsesTokens && policy !== false && attempt < policy.maxAttempts && isTransientStreamFailure(cause)) {
8377
+ if (chunkResults.length === 0 && chunkIsAtomic && policy !== false && attempt < policy.maxAttempts && isTransientStreamFailure(cause)) {
8485
8378
  await sleep(computeBackoffDelayMs(attempt, policy));
8486
8379
  attempt += 1;
8487
8380
  priorAttemptAmbiguous = true;
@@ -8531,6 +8424,20 @@ async function submitOperationsViaStream(client, args) {
8531
8424
  }
8532
8425
  return result;
8533
8426
  }
8427
+ function validateNormalizedOperations(operations) {
8428
+ const diagnostics = preflightCommitDiagnostics2(operations).filter(
8429
+ (diagnostic) => !isServerAuthoritativeSequenceDiagnostic(diagnostic)
8430
+ );
8431
+ const firstDiagnostic = diagnostics[0];
8432
+ if (!firstDiagnostic) return;
8433
+ throw new StreamValidationError(
8434
+ `Invalid operation at index ${firstDiagnostic.operationIndex}: ${firstDiagnostic.message}`,
8435
+ firstDiagnostic.code
8436
+ );
8437
+ }
8438
+ function isServerAuthoritativeSequenceDiagnostic(diagnostic) {
8439
+ return diagnostic.code === "ILLEGAL_OP_SEQUENCE" && diagnostic.message.includes("Cannot revise then add ");
8440
+ }
8534
8441
  function isAllSubmittedOperationsFailed(result, submittedOperationCount) {
8535
8442
  if (submittedOperationCount <= 0) {
8536
8443
  return false;
@@ -8867,6 +8774,9 @@ function toBackendOp(op) {
8867
8774
  `OperationBuilder: assertion add '${name2}' missing required 'about'`
8868
8775
  );
8869
8776
  }
8777
+ if (typeof about !== "string") {
8778
+ throw new Error(COLLECTION_ABOUT_REMOVED_MESSAGE);
8779
+ }
8870
8780
  return {
8871
8781
  operation: "add",
8872
8782
  kind: kind2,
@@ -8892,9 +8802,7 @@ function toBackendOp(op) {
8892
8802
  }
8893
8803
  const kind = normalizeReviseKind(op, name);
8894
8804
  if (kind === "collection") {
8895
- throw new Error(
8896
- `OperationBuilder: collection revise is no longer supported \u2014 use retract('${name}') instead`
8897
- );
8805
+ return normalizeBackendCollectionRevise({ ...op, name }, "OperationBuilder");
8898
8806
  }
8899
8807
  return {
8900
8808
  operation: "revise",
@@ -8919,7 +8827,9 @@ function toPreflightOp(op, kind) {
8919
8827
  return {
8920
8828
  operation: op.operation,
8921
8829
  kind,
8922
- name: op.name ?? op.wref
8830
+ name: op.name ?? op.wref,
8831
+ type: getCollectionType(op),
8832
+ members: getCollectionMembers(op)
8923
8833
  };
8924
8834
  }
8925
8835
  function throwAggregatedMessages(messages) {
@@ -8951,9 +8861,7 @@ function preflightCheckAdd(op, kind) {
8951
8861
  if (op.name) {
8952
8862
  messages.push(...preflightCheckCommon("ADD", kind, op.name, getAddData(op)));
8953
8863
  }
8954
- if (kind === "assertion" && getAddAbout(op) === void 0 && // Token-bearing names defer to validate() so the more specific token
8955
- // diagnostics surface instead of this eager check.
8956
- !(op.name && hasAnyTokens(op.name))) {
8864
+ if (kind === "assertion" && getAddAbout(op) === void 0) {
8957
8865
  messages.push(
8958
8866
  `ADD assertion '${op.name}' missing required 'about' \u2014 for hierarchical thing names set kind: 'thing' explicitly`
8959
8867
  );
@@ -8975,17 +8883,16 @@ function preflightCheckAdd(op, kind) {
8975
8883
  }
8976
8884
  throwAggregatedMessages(messages);
8977
8885
  }
8978
- function preflightCheckRevise(kind, name, data) {
8886
+ function preflightCheckRevise(kind, name, op) {
8979
8887
  const messages = [];
8980
- if (data === void 0) {
8888
+ if (kind !== "collection" && op.data === void 0) {
8981
8889
  messages.push(`OperationBuilder: ${kind} revise requires 'data'`);
8982
8890
  }
8983
8891
  messages.push(
8984
- ...preflightCheckCommon("REVISE", kind, name, data),
8985
- ...preflightOpDiagnostics2(
8986
- toPreflightOp({ operation: "revise", name, data }, kind),
8987
- 0
8988
- ).map((diagnostic) => diagnostic.message)
8892
+ ...preflightCheckCommon("REVISE", kind, name, op.data),
8893
+ ...preflightOpDiagnostics2(toPreflightOp({ ...op, name }, kind), 0).map(
8894
+ (diagnostic) => diagnostic.message
8895
+ )
8989
8896
  );
8990
8897
  throwAggregatedMessages(messages);
8991
8898
  }
@@ -9086,7 +8993,10 @@ var OperationBuilder = class {
9086
8993
  { ...normalized },
9087
8994
  target
9088
8995
  );
9089
- preflightCheckRevise(reviseKind, target, normalized.data);
8996
+ preflightCheckRevise(reviseKind, target, {
8997
+ operation: "revise",
8998
+ ...normalized
8999
+ });
9090
9000
  }
9091
9001
  const frozen = Object.freeze({
9092
9002
  operation: "revise",
@@ -9230,6 +9140,36 @@ var OperationBuilder = class {
9230
9140
  }
9231
9141
  }
9232
9142
  }
9143
+ const operationDiagnostics = this.ops.flatMap((op, operationIndex) => {
9144
+ if (op.operation === "add") {
9145
+ return preflightOpDiagnostics2(
9146
+ toPreflightOp(op, normalizeAddKind(op)),
9147
+ operationIndex
9148
+ );
9149
+ }
9150
+ if (op.operation === "revise") {
9151
+ const target = op.name ?? op.wref;
9152
+ return preflightOpDiagnostics2(
9153
+ toPreflightOp(op, target ? normalizeReviseKind(op, target) : "thing"),
9154
+ operationIndex
9155
+ );
9156
+ }
9157
+ return preflightOpDiagnostics2(
9158
+ {
9159
+ operation: "retract",
9160
+ kind: op.kind,
9161
+ name: op.name
9162
+ },
9163
+ operationIndex
9164
+ );
9165
+ });
9166
+ for (const diagnostic of operationDiagnostics) {
9167
+ errors.push({
9168
+ code: diagnostic.code,
9169
+ operationIndex: diagnostic.operationIndex,
9170
+ message: diagnostic.message
9171
+ });
9172
+ }
9233
9173
  const preflightOps = this.ops.filter((op) => op.operation !== "retract").map((op) => {
9234
9174
  if (op.operation === "add") {
9235
9175
  return toPreflightOp(op, normalizeAddKind(op));
@@ -9240,7 +9180,9 @@ var OperationBuilder = class {
9240
9180
  target ? normalizeReviseKind(op, target) : "thing"
9241
9181
  );
9242
9182
  });
9243
- const diagnostics = preflightCommitDiagnostics2(preflightOps);
9183
+ const diagnostics = preflightCommitDiagnostics2(preflightOps, {
9184
+ checkAddAdd: false
9185
+ });
9244
9186
  for (const diagnostic of diagnostics) {
9245
9187
  errors.push({
9246
9188
  code: diagnostic.code,
@@ -9341,7 +9283,7 @@ function validateWarmHubClientOptions(options) {
9341
9283
  throw new TypeError(`Unknown WarmHubClient option "${key}"${hint}`);
9342
9284
  }
9343
9285
  }
9344
- var SDK_VERSION = "0.66.0" ;
9286
+ var SDK_VERSION = "0.68.0" ;
9345
9287
  var DEFAULT_API_URL = "https://api.warmhub.ai";
9346
9288
  var UNBATCHED_TRPC_PATHS = /* @__PURE__ */ new Set([
9347
9289
  "repo.shapeInstanceCounts",
@@ -9460,6 +9402,47 @@ function sanitizeSubscriptionUpdateInput(input) {
9460
9402
  } = input;
9461
9403
  return supported;
9462
9404
  }
9405
+ function hasCollectionQuerySource(source) {
9406
+ return !!source && (!!source.shape || !!source.kind || !!source.about || !!source.match || !!source.componentRef || source.excludeComponents === true || (source.where?.length ?? 0) > 0);
9407
+ }
9408
+ function hasCollectionSelectorAnchor(source) {
9409
+ return !!source && (!!source.shape || !!source.about || !!source.match || !!source.componentRef || (source.where?.length ?? 0) > 0);
9410
+ }
9411
+ function hasExplicitCollectionMembers(opts) {
9412
+ const members = opts.members;
9413
+ return Array.isArray(members) && members.length > 0;
9414
+ }
9415
+ function collectionTypeFromWref(wref) {
9416
+ const local = wref.replace(/^wh:[^/]+\/[^/]+\//, "").replace(/@(?:HEAD|ALL|v\d+)$/, "");
9417
+ const shape = local.split("/")[0]?.toLowerCase();
9418
+ return shape === "pair" || shape === "set" || shape === "list" ? shape : void 0;
9419
+ }
9420
+ function assertSelectorBackedCollectionType(type, opts) {
9421
+ if (hasCollectionQuerySource(opts.query) && !hasCollectionSelectorAnchor(opts.query)) {
9422
+ throw new WarmHubError(
9423
+ "VALIDATION_ERROR",
9424
+ "Selector-backed collection sources require shape, about, match, componentRef, or where; kind and excludeComponents only narrow an existing selector."
9425
+ );
9426
+ }
9427
+ if (opts.sourceRepo && !hasCollectionSelectorAnchor(opts.query)) {
9428
+ throw new WarmHubError(
9429
+ "VALIDATION_ERROR",
9430
+ "sourceRepo requires a selector-backed collection query"
9431
+ );
9432
+ }
9433
+ if (opts.sourceRepo && hasExplicitCollectionMembers(opts)) {
9434
+ throw new WarmHubError(
9435
+ "VALIDATION_ERROR",
9436
+ "sourceRepo cannot be combined with explicit members; use canonical wh:org/repo/... member wrefs or omit sourceRepo."
9437
+ );
9438
+ }
9439
+ if (hasCollectionQuerySource(opts.query) && type !== "set") {
9440
+ throw new WarmHubError(
9441
+ "VALIDATION_ERROR",
9442
+ "Selector-backed collection sources are only supported for set collections"
9443
+ );
9444
+ }
9445
+ }
9463
9446
  function resolveFunctionLogMode(mode) {
9464
9447
  return mode ?? "off";
9465
9448
  }
@@ -10137,7 +10120,7 @@ var WarmHubClient = class _WarmHubClient {
10137
10120
  *
10138
10121
  * @param message Optional commit message stored with the submitted operations.
10139
10122
  * @param operations Add, revise, or retract operations to submit in order.
10140
- * @param opts.committer Optional wref identifying the actor on whose behalf the write is made. Must be a full wref string like `"Agent/bot-1"` (a thing that already exists), or a cross-repo wref like `"wh:other-org/other-repo/Agent/bot-1"`. Bare names such as `"eval-runner"` are rejected by the backend with a "Thing wref required" error — there is no implicit shape.
10123
+ * @param opts.committer Optional untyped wref identifying the actor on whose behalf the write is made. It may target an existing shape (`"Agent"`) or shaped thing (`"Agent/bot-1"`), locally or canonically (`"wh:other-org/other-repo/Agent"` or `"wh:other-org/other-repo/Agent/bot-1"`). A one-segment value is a shape wref, not a free-form label, and succeeds only when that shape exists. On success, `OperationSubmitResult.committer` echoes the supplied wref string; version reads expose the resolved target as `committerWref`.
10141
10124
  * @param opts.componentRef Attribute writes to an installed component, identified by its `Org/Name` ref, when the caller is allowed to claim it.
10142
10125
  * @param opts.chunkSize Maximum operations per stream append. Values are clamped by the SDK.
10143
10126
  * @param opts.skipExisting Return `noop` for add operations whose target already exists.
@@ -11364,6 +11347,165 @@ var WarmHubClient = class _WarmHubClient {
11364
11347
  }
11365
11348
  }
11366
11349
  };
11350
+ collection = {
11351
+ create: async (orgName, repoName, opts) => {
11352
+ try {
11353
+ assertSelectorBackedCollectionType(opts.type, opts);
11354
+ return await this.trpc.collection.create.mutate({
11355
+ orgName,
11356
+ repoName,
11357
+ type: opts.type,
11358
+ name: opts.name,
11359
+ members: opts.members,
11360
+ from: opts.from,
11361
+ add: opts.add,
11362
+ remove: opts.remove,
11363
+ replaceMembers: opts.replaceMembers,
11364
+ query: opts.query,
11365
+ sourceOrgName: opts.sourceRepo?.orgName,
11366
+ sourceRepoName: opts.sourceRepo?.repoName,
11367
+ skipExisting: opts.skipExisting,
11368
+ message: opts.message,
11369
+ committer: opts.committer
11370
+ });
11371
+ } catch (error) {
11372
+ throw toWarmHubError(error);
11373
+ }
11374
+ },
11375
+ members: async (orgName, repoName, wref, opts) => {
11376
+ try {
11377
+ return await this.trpc.collection.members.query({
11378
+ orgName,
11379
+ repoName,
11380
+ wref,
11381
+ version: opts?.version,
11382
+ limit: opts?.limit,
11383
+ cursor: opts?.cursor
11384
+ });
11385
+ } catch (error) {
11386
+ throw toWarmHubError(error);
11387
+ }
11388
+ },
11389
+ membersIter: (orgName, repoName, wref, opts) => {
11390
+ let snapshotVersion = opts?.version;
11391
+ return paginate(
11392
+ async (cursor) => {
11393
+ const page = await this.collection.members(orgName, repoName, wref, {
11394
+ ...opts,
11395
+ version: snapshotVersion,
11396
+ cursor
11397
+ });
11398
+ snapshotVersion ??= page.version;
11399
+ return page;
11400
+ },
11401
+ (page) => page.items,
11402
+ opts?.cursor
11403
+ );
11404
+ },
11405
+ membersAll: async (orgName, repoName, wref, opts) => {
11406
+ const { max, ...pageOpts } = opts ?? {};
11407
+ let snapshotVersion = pageOpts.version;
11408
+ return await collectPaginatedPages(
11409
+ async (cursor) => {
11410
+ const page = await this.collection.members(orgName, repoName, wref, {
11411
+ ...pageOpts,
11412
+ version: snapshotVersion,
11413
+ cursor
11414
+ });
11415
+ snapshotVersion ??= page.version;
11416
+ return page;
11417
+ },
11418
+ (page) => page.items,
11419
+ max,
11420
+ pageOpts.cursor
11421
+ );
11422
+ },
11423
+ contains: async (orgName, repoName, wref, members, opts) => {
11424
+ try {
11425
+ return await this.trpc.collection.contains.query({
11426
+ orgName,
11427
+ repoName,
11428
+ wref,
11429
+ version: opts?.version,
11430
+ members,
11431
+ position: opts?.position
11432
+ });
11433
+ } catch (error) {
11434
+ throw toWarmHubError(error);
11435
+ }
11436
+ },
11437
+ diff: async (orgName, repoName, leftWref, rightWref, opts) => {
11438
+ try {
11439
+ return await this.trpc.collection.diff.query({
11440
+ orgName,
11441
+ repoName,
11442
+ leftWref,
11443
+ rightWref,
11444
+ leftVersion: opts?.leftVersion,
11445
+ rightVersion: opts?.rightVersion,
11446
+ mode: opts?.mode
11447
+ });
11448
+ } catch (error) {
11449
+ throw toWarmHubError(error);
11450
+ }
11451
+ },
11452
+ revise: async (orgName, repoName, wref, opts) => {
11453
+ try {
11454
+ const targetType = collectionTypeFromWref(wref);
11455
+ if (hasCollectionQuerySource(opts.query) && !hasCollectionSelectorAnchor(opts.query)) {
11456
+ throw new WarmHubError(
11457
+ "VALIDATION_ERROR",
11458
+ "Selector-backed collection sources require shape, about, match, componentRef, or where; kind and excludeComponents only narrow an existing selector."
11459
+ );
11460
+ }
11461
+ if (opts.sourceRepo && !hasCollectionSelectorAnchor(opts.query)) {
11462
+ throw new WarmHubError(
11463
+ "VALIDATION_ERROR",
11464
+ "sourceRepo requires a selector-backed collection query"
11465
+ );
11466
+ }
11467
+ if (opts.sourceRepo && hasExplicitCollectionMembers(opts)) {
11468
+ throw new WarmHubError(
11469
+ "VALIDATION_ERROR",
11470
+ "sourceRepo cannot be combined with explicit members; use canonical wh:org/repo/... member wrefs or omit sourceRepo."
11471
+ );
11472
+ }
11473
+ if (hasCollectionQuerySource(opts.query) && targetType && targetType !== "set") {
11474
+ throw new WarmHubError(
11475
+ "VALIDATION_ERROR",
11476
+ "Selector-backed revise requires a Set/<name> target wref"
11477
+ );
11478
+ }
11479
+ return await this.trpc.collection.revise.mutate({
11480
+ orgName,
11481
+ repoName,
11482
+ wref,
11483
+ members: opts.members,
11484
+ add: opts.add,
11485
+ remove: opts.remove,
11486
+ query: opts.query,
11487
+ sourceOrgName: opts.sourceRepo?.orgName,
11488
+ sourceRepoName: opts.sourceRepo?.repoName,
11489
+ message: opts.message,
11490
+ committer: opts.committer
11491
+ });
11492
+ } catch (error) {
11493
+ throw toWarmHubError(error);
11494
+ }
11495
+ },
11496
+ stats: async (orgName, repoName, wref, opts) => {
11497
+ try {
11498
+ return await this.trpc.collection.stats.query({
11499
+ orgName,
11500
+ repoName,
11501
+ wref,
11502
+ version: opts?.version
11503
+ });
11504
+ } catch (error) {
11505
+ throw toWarmHubError(error);
11506
+ }
11507
+ }
11508
+ };
11367
11509
  /**
11368
11510
  * Read surface for things, assertions, histories, references, search, and in-place thing renames.
11369
11511
  */
@@ -11446,6 +11588,7 @@ var WarmHubClient = class _WarmHubClient {
11446
11588
  *
11447
11589
  * @param version Optional exact version to pin when the wref is not already version-qualified.
11448
11590
  * @param opts.includeRetracted Include retracted records instead of treating them as missing.
11591
+ * @param opts.dataMode Defaults to `auto`; pass `full` to force full collection bodies.
11449
11592
  */
11450
11593
  get: async (orgName, repoName, wref, version, opts) => {
11451
11594
  try {
@@ -11454,7 +11597,8 @@ var WarmHubClient = class _WarmHubClient {
11454
11597
  repoName,
11455
11598
  wref,
11456
11599
  version,
11457
- includeRetracted: opts?.includeRetracted
11600
+ includeRetracted: opts?.includeRetracted,
11601
+ dataMode: opts?.dataMode
11458
11602
  });
11459
11603
  } catch (error) {
11460
11604
  throw toWarmHubError(error);
@@ -11564,7 +11708,8 @@ var WarmHubClient = class _WarmHubClient {
11564
11708
  repoName,
11565
11709
  wrefs: chunkWrefs,
11566
11710
  version,
11567
- includeRetracted: opts?.includeRetracted
11711
+ includeRetracted: opts?.includeRetracted,
11712
+ dataMode: opts?.dataMode
11568
11713
  });
11569
11714
  };
11570
11715
  if (wrefs.length <= chunkSize) {
@@ -11704,7 +11849,7 @@ var WarmHubClient = class _WarmHubClient {
11704
11849
  }
11705
11850
  },
11706
11851
  /**
11707
- * Return assertions about a thing or collection target.
11852
+ * Return assertions about a shape, shaped thing, or collection target.
11708
11853
  *
11709
11854
  * Filter by assertion shape or glob `match` pattern, optionally resolve collection targets, and page through large assertion sets with `limit` and `cursor`.
11710
11855
  *
@@ -11746,7 +11891,7 @@ var WarmHubClient = class _WarmHubClient {
11746
11891
  }
11747
11892
  },
11748
11893
  /**
11749
- * Iterate every assertion about a thing or collection target.
11894
+ * Iterate every assertion about a shape, shaped thing, or collection target.
11750
11895
  *
11751
11896
  * Prefer this over hand-written cursor loops when scanning all matching assertions. The iterator reads the `assertions` envelope field and advances the cursor automatically; pass `opts.cursor` to resume from a saved cursor and `limit` to control page size.
11752
11897
  *
@@ -11764,7 +11909,7 @@ var WarmHubClient = class _WarmHubClient {
11764
11909
  );
11765
11910
  },
11766
11911
  /**
11767
- * Materialize every assertion about a thing or collection target.
11912
+ * Materialize every assertion about a shape, shaped thing, or collection target.
11768
11913
  *
11769
11914
  * Use `max` to guard memory usage; throws a `WarmHubError` with kind `VALIDATION_ERROR` once more than `max` assertions have actually been observed across pages.
11770
11915
  *
@@ -12176,7 +12321,7 @@ var WarmHubClient = class _WarmHubClient {
12176
12321
  /**
12177
12322
  * Append one non-empty chunk of stream operations to a repository.
12178
12323
  *
12179
- * Most callers should prefer `commit.apply` or `OperationBuilder`. Use this low-level surface only when you already have stream operations, a stream ID, and any allocated `$N` / `#N` token state you need to continue.
12324
+ * Most callers should prefer `commit.apply` or `OperationBuilder`. Use this low-level surface only when you already have backend-shaped stream operations and a caller-managed stream ID.
12180
12325
  */
12181
12326
  append: async (input) => {
12182
12327
  try {
@@ -12671,5 +12816,5 @@ re2js/build/index.js:
12671
12816
  */
12672
12817
 
12673
12818
  export { AllStreamOperationsFailedError, CLI_INSTALL_REPO_HEADER, CLI_SIGNATURE_HEADER, CLI_TIMESTAMP_HEADER, CONTENT_FIELD_LIMIT_ERROR, CliCallVerificationError, DEFAULT_API_URL, DEFAULT_STREAM_CHUNK_SIZE, MAX_CONTENT_FIELD_BYTES, MAX_STREAM_APPEND_OPERATION_COUNT2 as MAX_STREAM_APPEND_OPERATION_COUNT, OperationBuilder, PartialStreamSubmissionError, SDK_VERSION, WarmHubClient, WarmHubError, connectionErrorMessage, contentFieldLimitError, countStreamAppendResultStatuses, isConnectionError, isRetryable, isWarmHubError, normalizeWref, resolveFunctionLogMode, sanitizeErrorMessage, sdkVersionIsBelowMinimum, streamAppendResultStatus, submitOperationsViaStream, toWarmHubError, validateAgainstShape, verifyCliCall };
12674
- //# sourceMappingURL=chunk-U5Z6ZS6A.js.map
12675
- //# sourceMappingURL=chunk-U5Z6ZS6A.js.map
12819
+ //# sourceMappingURL=chunk-GNNCLRNC.js.map
12820
+ //# sourceMappingURL=chunk-GNNCLRNC.js.map