@warmhub/cli 0.95.0 → 0.97.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 +1086 -118
  2. package/package.json +8 -2
package/dist/wh.js CHANGED
@@ -19421,7 +19421,15 @@ function formatClientHeader(name, version) {
19421
19421
  var DEFAULT_MAX_OPS_PER_STREAM = 1e6;
19422
19422
  var DEFAULT_STREAM_APPEND_CHUNK_SIZE = 1000;
19423
19423
  var MAX_STREAM_APPEND_OPERATION_COUNT = 1e4;
19424
+ var MAX_STREAMING_SUBMISSION_LINE_BYTES = 1024 * 1024;
19424
19425
  // ../../packages/rules/src/commit-types.ts
19426
+ var COMMIT_OPERATIONS = [
19427
+ "add",
19428
+ "revise",
19429
+ "retract",
19430
+ "reaffirm",
19431
+ "rename"
19432
+ ];
19425
19433
  var COMMIT_OPERATION_KINDS = [
19426
19434
  "shape",
19427
19435
  "thing",
@@ -42109,47 +42117,41 @@ function normalizeOptionalTypeSpec(spec) {
42109
42117
  return { spec, optionalByType: false };
42110
42118
  }
42111
42119
 
42112
- // ../../packages/rules/src/shape-validation-runtime.ts
42113
- function validatePersistedStringFieldLimits(value, typeDef, errors3, path) {
42114
- const normalized = normalizeOptionalTypeSpec(typeDef).spec;
42120
+ // ../../packages/rules/src/shape-validation-content-limits.ts
42121
+ function validatePersistedContentLimits(value, typeDefs, errors3, path) {
42122
+ const declared = normalizedCandidates(typeDefs);
42115
42123
  if (typeof value === "string") {
42116
- if (isDeclaredStringType(normalized) || isDeclaredWrefType(normalized))
42117
- return;
42118
- if (normalized !== undefined)
42124
+ if (declared.length > 0)
42119
42125
  return;
42120
42126
  assertContentFieldWithinLimit(path ?? "<value>", value, errors3);
42121
42127
  return;
42122
42128
  }
42123
42129
  if (Array.isArray(value)) {
42124
- const elementType = arrayElementType(normalized);
42125
- if (normalized !== undefined && elementType === undefined && !isDeclaredArrayType(normalized)) {
42130
+ const arrayCandidates = declared.filter(isDeclaredArrayType);
42131
+ if (declared.length > 0 && arrayCandidates.length === 0)
42126
42132
  return;
42127
- }
42133
+ const elementTypes = definedOnly(arrayCandidates.map(arrayElementType));
42128
42134
  for (let i = 0;i < value.length; i++) {
42129
- validatePersistedStringFieldLimits(value[i], elementType, errors3, `${path ?? "<value>"}[${i}]`);
42135
+ validatePersistedContentLimits(value[i], elementTypes, errors3, `${path ?? "<value>"}[${i}]`);
42130
42136
  }
42131
42137
  return;
42132
42138
  }
42133
42139
  if (!isPlainObject2(value))
42134
42140
  return;
42135
- const fields = nestedObjectFields(normalized);
42136
- if (normalized !== undefined && fields === undefined)
42141
+ const objectCandidates = definedOnly(declared.map(nestedObjectFields));
42142
+ if (declared.length > 0 && objectCandidates.length === 0)
42137
42143
  return;
42138
42144
  for (const [key, nestedValue] of Object.entries(value)) {
42139
42145
  const keyPath = path ? joinFieldPath(path, key) : escapeFieldNameForDisplay(key);
42140
42146
  assertContentFieldWithinLimit(keyPath, key, errors3);
42141
- validatePersistedStringFieldLimits(nestedValue, fields?.get(key), errors3, keyPath);
42147
+ validatePersistedContentLimits(nestedValue, definedOnly(objectCandidates.map((fields) => fields.get(key))), errors3, keyPath);
42142
42148
  }
42143
42149
  }
42144
- function isDeclaredStringType(typeDef) {
42145
- if (typeDef === "string")
42146
- return true;
42147
- return isTypeSpecObject(typeDef) && typeDef.type === "string";
42150
+ function normalizedCandidates(typeDefs) {
42151
+ return definedOnly(typeDefs.map((typeDef) => normalizeOptionalTypeSpec(typeDef).spec));
42148
42152
  }
42149
- function isDeclaredWrefType(typeDef) {
42150
- if (typeDef === "wref")
42151
- return true;
42152
- return isTypeSpecObject(typeDef) && typeDef.type === "wref";
42153
+ function definedOnly(values) {
42154
+ return values.filter((value) => value !== undefined);
42153
42155
  }
42154
42156
  function arrayElementType(typeDef) {
42155
42157
  if (Array.isArray(typeDef))
@@ -42538,7 +42540,7 @@ function validateShapeDefinition(data, options = {}) {
42538
42540
  if ("description" in obj && typeof obj.description !== "string") {
42539
42541
  errors3.push('"description" must be a string');
42540
42542
  }
42541
- validatePersistedStringFieldLimits(obj, undefined, errors3);
42543
+ validatePersistedContentLimits(obj, [], errors3);
42542
42544
  if (errors3.length > 0) {
42543
42545
  return { valid: false, errors: errors3 };
42544
42546
  }
@@ -43382,7 +43384,7 @@ class OperationSourceError extends Error {
43382
43384
  }
43383
43385
  }
43384
43386
  async function submitOperationsViaStream(client, args) {
43385
- const chunkSize = normalizeChunkSize(args.chunkSize);
43387
+ const chunkSize = normalizeStreamChunkSize(args.chunkSize);
43386
43388
  const submissionId = args.submissionId ?? createOperationEventSubmissionId();
43387
43389
  const streamId = args.streamId ?? submissionId;
43388
43390
  const policy = resolveRetryPolicy(args.retry);
@@ -43482,7 +43484,7 @@ async function submitOperationsViaStream(client, args) {
43482
43484
  async function* normalizedChunks(source, chunkSize, skipExisting) {
43483
43485
  try {
43484
43486
  if (Array.isArray(source)) {
43485
- const operations = source.map((operation, index) => normalizeOperation(operation, index, skipExisting));
43487
+ const operations = source.map((operation, index) => normalizeStreamOperation(operation, index, skipExisting));
43486
43488
  validateNormalizedOperations(operations, 0);
43487
43489
  for (let start = 0;start < operations.length; start += chunkSize) {
43488
43490
  yield { operations: operations.slice(start, start + chunkSize), start };
@@ -43491,8 +43493,8 @@ async function* normalizedChunks(source, chunkSize, skipExisting) {
43491
43493
  }
43492
43494
  let normalizedCount = 0;
43493
43495
  let buffer = [];
43494
- for await (const operation of source) {
43495
- buffer.push(normalizeOperation(operation, normalizedCount, skipExisting));
43496
+ for await (const operation of normalizedOperationSource(source, skipExisting)) {
43497
+ buffer.push(operation);
43496
43498
  normalizedCount += 1;
43497
43499
  if (buffer.length < chunkSize)
43498
43500
  continue;
@@ -43510,7 +43512,7 @@ function preflightedChunk(operations, normalizedCount) {
43510
43512
  validateNormalizedOperations(operations, start);
43511
43513
  return { operations, start };
43512
43514
  }
43513
- function normalizeOperation(operation, index, skipExisting) {
43515
+ function normalizeStreamOperation(operation, index, skipExisting) {
43514
43516
  let streamOperation;
43515
43517
  try {
43516
43518
  streamOperation = toBackendStreamOperation(operation);
@@ -43523,6 +43525,57 @@ function normalizeOperation(operation, index, skipExisting) {
43523
43525
  }
43524
43526
  return streamOperation;
43525
43527
  }
43528
+ async function* normalizedOperationSource(source, skipExisting) {
43529
+ const iterator = createNormalizedOperationIterator(source, skipExisting);
43530
+ try {
43531
+ while (true) {
43532
+ const next = await iterator.next();
43533
+ if (next.done)
43534
+ return;
43535
+ yield next.value;
43536
+ }
43537
+ } finally {
43538
+ const returned = iterator.returnSourceOnce();
43539
+ if (returned)
43540
+ await returned;
43541
+ }
43542
+ }
43543
+ function createNormalizedOperationIterator(source, skipExisting) {
43544
+ let sourceIterator;
43545
+ let index = 0;
43546
+ let returned = false;
43547
+ let done = false;
43548
+ const acquire = () => {
43549
+ if (sourceIterator)
43550
+ return sourceIterator;
43551
+ sourceIterator = Symbol.asyncIterator in source ? source[Symbol.asyncIterator]() : source[Symbol.iterator]();
43552
+ return sourceIterator;
43553
+ };
43554
+ return {
43555
+ async next() {
43556
+ const next = await acquire().next();
43557
+ if (next.done) {
43558
+ done = true;
43559
+ return { done: true, value: undefined };
43560
+ }
43561
+ const value = normalizeStreamOperation(next.value, index, skipExisting);
43562
+ index += 1;
43563
+ return { done: false, value };
43564
+ },
43565
+ returnSourceOnce() {
43566
+ if (returned)
43567
+ return;
43568
+ returned = true;
43569
+ if (!done)
43570
+ return sourceIterator?.return?.();
43571
+ }
43572
+ };
43573
+ }
43574
+ function encodeStreamOperation(operation) {
43575
+ return streamOperationEncoder.encode(`${JSON.stringify(operation)}
43576
+ `);
43577
+ }
43578
+ var streamOperationEncoder = new TextEncoder;
43526
43579
  function receiptRepoSeq(receipt) {
43527
43580
  const repoSeq = receipt.event?.repoSeq;
43528
43581
  if (repoSeq === undefined)
@@ -43539,15 +43592,579 @@ function validateNormalizedOperations(operations, indexOffset) {
43539
43592
  function isServerAuthoritativeSequenceDiagnostic(diagnostic) {
43540
43593
  return diagnostic.code === "ILLEGAL_OP_SEQUENCE" && diagnostic.message.includes("Cannot revise then add ");
43541
43594
  }
43542
- function normalizeChunkSize(chunkSize) {
43595
+ function normalizeStreamChunkSize(chunkSize) {
43543
43596
  if (!Number.isFinite(chunkSize))
43544
43597
  return DEFAULT_STREAM_CHUNK_SIZE;
43545
43598
  return Math.max(1, Math.min(MAX_STREAM_APPEND_OPERATION_COUNT2, Math.trunc(chunkSize)));
43546
43599
  }
43600
+ // ../../packages/sdk-ts/src/streaming-submission-protocol.ts
43601
+ var MANIFEST_DOMAIN = "warmhub/streaming-submission-manifest/v1";
43602
+ var manifestEncoder = new TextEncoder;
43603
+ var digestSchema = exports_external.string().regex(/^sha256:[0-9a-f]{64}$/);
43604
+ var positionShape = {
43605
+ type: exports_external.literal("result"),
43606
+ chunkOrdinal: exports_external.number().int().nonnegative(),
43607
+ opIndex: exports_external.number().int().nonnegative(),
43608
+ submissionIndex: exports_external.number().int().nonnegative(),
43609
+ name: exports_external.string()
43610
+ };
43611
+ var currentOperationSchema = exports_external.enum(COMMIT_OPERATIONS);
43612
+ var legacyOperationSchema = exports_external.enum([...COMMIT_OPERATIONS, "noop"]);
43613
+ var issueSchema = exports_external.object({ path: exports_external.string(), message: exports_external.string() });
43614
+ var warningSchema = exports_external.object({
43615
+ undeclaredFields: exports_external.array(exports_external.string()).optional(),
43616
+ undeclaredFieldsTruncated: exports_external.literal(true).optional(),
43617
+ totalUndeclared: exports_external.number().int().nonnegative().optional(),
43618
+ coalescedWrefs: exports_external.array(exports_external.object({
43619
+ fieldPath: exports_external.string(),
43620
+ wref: exports_external.string(),
43621
+ reason: exports_external.string()
43622
+ })).optional(),
43623
+ coalescedWrefsTruncated: exports_external.literal(true).optional(),
43624
+ totalCoalescedWrefs: exports_external.number().int().nonnegative().optional(),
43625
+ deprecations: exports_external.array(exports_external.object({
43626
+ shape: exports_external.string(),
43627
+ message: exports_external.string(),
43628
+ removalMilestone: exports_external.string()
43629
+ })).optional()
43630
+ }).optional();
43631
+ var affirmationSchema = exports_external.object({
43632
+ added: exports_external.array(exports_external.string()),
43633
+ removed: exports_external.array(exports_external.string()),
43634
+ ignored: exports_external.array(exports_external.string())
43635
+ });
43636
+ var legacyErrorDetailsSchema = exports_external.discriminatedUnion("reason", [
43637
+ exports_external.object({
43638
+ reason: exports_external.literal("expected_version_mismatch"),
43639
+ expectedVersion: exports_external.number().int().positive(),
43640
+ currentVersion: exports_external.number().int().positive()
43641
+ }),
43642
+ exports_external.object({
43643
+ reason: exports_external.literal("lease_held"),
43644
+ leaseExpiresAt: exports_external.string().datetime()
43645
+ }),
43646
+ exports_external.object({
43647
+ reason: exports_external.literal("validation_failed"),
43648
+ issues: exports_external.array(issueSchema)
43649
+ }),
43650
+ exports_external.object({
43651
+ reason: exports_external.literal("rate_limit_reset"),
43652
+ retryAfterSeconds: exports_external.number().int().positive(),
43653
+ resetAt: exports_external.string().datetime()
43654
+ }),
43655
+ exports_external.object({
43656
+ reason: exports_external.literal("cursor_fence_unavailable"),
43657
+ cause: exports_external.enum(["not_ready", "below_floor", "above_head"]),
43658
+ retryFromStart: exports_external.literal(true)
43659
+ })
43660
+ ]);
43661
+ var currentErrorDetailsSchema = exports_external.discriminatedUnion("reason", [
43662
+ exports_external.object({
43663
+ reason: exports_external.literal("expected_version_mismatch"),
43664
+ expectedVersion: exports_external.number().int().nonnegative(),
43665
+ currentVersion: exports_external.number().int().nonnegative()
43666
+ }).strict(),
43667
+ exports_external.object({
43668
+ reason: exports_external.literal("lease_held"),
43669
+ leaseExpiresAt: exports_external.string().datetime()
43670
+ }).strict(),
43671
+ exports_external.object({
43672
+ reason: exports_external.literal("validation_failed"),
43673
+ issues: exports_external.array(issueSchema.strict())
43674
+ }).strict(),
43675
+ exports_external.object({
43676
+ reason: exports_external.literal("rate_limit_reset"),
43677
+ retryAfterSeconds: exports_external.number().nonnegative(),
43678
+ resetAt: exports_external.string().datetime()
43679
+ }).strict(),
43680
+ exports_external.object({
43681
+ reason: exports_external.literal("cursor_fence_unavailable"),
43682
+ cause: exports_external.enum(["not_ready", "below_floor", "above_head"]),
43683
+ retryFromStart: exports_external.literal(true)
43684
+ }).strict(),
43685
+ exports_external.object({
43686
+ reason: exports_external.literal("dependency_failed"),
43687
+ producerOpIndexes: exports_external.array(exports_external.number().int().nonnegative()).min(1)
43688
+ }).strict()
43689
+ ]);
43690
+ var currentBaseShape = {
43691
+ ...positionShape,
43692
+ operation: currentOperationSchema,
43693
+ submittedName: exports_external.string().optional(),
43694
+ resolvedName: exports_external.string().optional(),
43695
+ warnings: warningSchema,
43696
+ affirmations: affirmationSchema.optional()
43697
+ };
43698
+ var resultSchema = exports_external.union([
43699
+ exports_external.object({
43700
+ ...positionShape,
43701
+ operation: legacyOperationSchema.optional(),
43702
+ version: exports_external.number().optional(),
43703
+ dataHash: exports_external.string().optional(),
43704
+ status: exports_external.enum(["success", "noop", "failed"]).optional(),
43705
+ error: exports_external.object({
43706
+ code: exports_external.string(),
43707
+ message: exports_external.string(),
43708
+ details: legacyErrorDetailsSchema.optional()
43709
+ }).optional(),
43710
+ resolvedName: exports_external.string().optional(),
43711
+ retryable: exports_external.boolean().optional(),
43712
+ warnings: warningSchema,
43713
+ affirmations: affirmationSchema.optional()
43714
+ }).passthrough(),
43715
+ exports_external.object({
43716
+ ...currentBaseShape,
43717
+ status: exports_external.enum(["applied", "noop"]),
43718
+ version: exports_external.number().int().positive().optional(),
43719
+ dataHash: exports_external.string().min(1).optional()
43720
+ }).passthrough(),
43721
+ exports_external.object({
43722
+ ...currentBaseShape,
43723
+ status: exports_external.literal("error"),
43724
+ errors: exports_external.array(exports_external.object({
43725
+ code: exports_external.string().min(1),
43726
+ message: exports_external.string(),
43727
+ path: exports_external.string().min(1).optional(),
43728
+ details: currentErrorDetailsSchema.optional(),
43729
+ retryable: exports_external.boolean().optional()
43730
+ }).strict()).min(1)
43731
+ }).passthrough()
43732
+ ]);
43733
+ var operationCountsSchema = exports_external.object({
43734
+ applied: exports_external.number().int().nonnegative(),
43735
+ noop: exports_external.number().int().nonnegative(),
43736
+ failed: exports_external.number().int().nonnegative()
43737
+ });
43738
+ var groupSchema = exports_external.object({
43739
+ type: exports_external.literal("group"),
43740
+ chunkOrdinal: exports_external.number().int().nonnegative(),
43741
+ eventRequestId: exports_external.string().uuid(),
43742
+ requestDigest: digestSchema,
43743
+ outcome: exports_external.enum(["event", "no_event"]),
43744
+ repoSeq: exports_external.number().int().nonnegative().optional(),
43745
+ operations: operationCountsSchema,
43746
+ manifestDigest: digestSchema
43747
+ }).passthrough();
43748
+ var summarySchema = exports_external.object({
43749
+ type: exports_external.literal("summary"),
43750
+ submissionId: exports_external.string().uuid(),
43751
+ streamId: exports_external.string().min(1),
43752
+ groupSize: exports_external.number().int().positive(),
43753
+ groups: exports_external.number().int().nonnegative(),
43754
+ operations: operationCountsSchema.extend({
43755
+ total: exports_external.number().int().nonnegative()
43756
+ }),
43757
+ repoSeq: exports_external.object({
43758
+ first: exports_external.number().int().nonnegative().nullable(),
43759
+ last: exports_external.number().int().nonnegative().nullable()
43760
+ }),
43761
+ verdict: exports_external.string().min(1),
43762
+ durationMs: exports_external.number().nonnegative(),
43763
+ truncatedAt: exports_external.object({
43764
+ lineNumber: exports_external.number().int().positive(),
43765
+ message: exports_external.string()
43766
+ }).optional(),
43767
+ manifest: exports_external.object({
43768
+ groups: exports_external.number().int().nonnegative(),
43769
+ digest: digestSchema
43770
+ })
43771
+ }).passthrough();
43772
+ var errorSchema = exports_external.object({
43773
+ type: exports_external.literal("error"),
43774
+ code: exports_external.string().min(1),
43775
+ message: exports_external.string().optional()
43776
+ }).passthrough();
43777
+ var rowSchema = exports_external.union([
43778
+ resultSchema,
43779
+ groupSchema,
43780
+ summarySchema,
43781
+ errorSchema
43782
+ ]);
43783
+ var emptyCounts = () => ({ applied: 0, noop: 0, failed: 0 });
43784
+ var countsMatch = (left, right) => left.applied === right.applied && left.noop === right.noop && left.failed === right.failed;
43785
+ var exactTotalVerdicts = new Set([
43786
+ "complete",
43787
+ "operation-limit-reached",
43788
+ "group-limit-reached"
43789
+ ]);
43790
+
43791
+ class StreamingSubmissionProtocolError extends Error {
43792
+ rowIndex;
43793
+ constructor(message, rowIndex) {
43794
+ super(`Streaming submission protocol error at row ${rowIndex}: ${message}`);
43795
+ this.rowIndex = rowIndex;
43796
+ this.name = "StreamingSubmissionProtocolError";
43797
+ }
43798
+ }
43799
+ async function sha256(value) {
43800
+ const bytes = manifestEncoder.encode(value);
43801
+ const digest = await globalThis.crypto.subtle.digest("SHA-256", bytes);
43802
+ return `sha256:${Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, "0")).join("")}`;
43803
+ }
43804
+ async function advanceManifest(previous, chunkOrdinal, requestDigest) {
43805
+ return sha256(`${MANIFEST_DOMAIN}\x00${previous}\x00${chunkOrdinal}\x00${requestDigest}`);
43806
+ }
43807
+ function resultOutcome(row) {
43808
+ if (row.status === "failed" || row.status === "error")
43809
+ return "failed";
43810
+ if (row.status === "noop" || row.operation === "noop")
43811
+ return "noop";
43812
+ return "applied";
43813
+ }
43814
+
43815
+ class SequenceValidator {
43816
+ index = 0;
43817
+ groupCount = 0;
43818
+ resultCount = 0;
43819
+ pendingCount = 0;
43820
+ pendingCounts = emptyCounts();
43821
+ totalCounts = emptyCounts();
43822
+ firstRepoSeq = null;
43823
+ lastRepoSeq = null;
43824
+ manifestDigest = sha256(MANIFEST_DOMAIN);
43825
+ terminalSeen = false;
43826
+ accept(row) {
43827
+ const fail = (message) => {
43828
+ throw new StreamingSubmissionProtocolError(message, this.index);
43829
+ };
43830
+ if (this.terminalSeen)
43831
+ fail("No row may follow the terminal row");
43832
+ if (row.type === "result") {
43833
+ if (row.chunkOrdinal !== this.groupCount)
43834
+ fail(`Expected result chunkOrdinal ${this.groupCount}`);
43835
+ if (row.opIndex !== this.pendingCount)
43836
+ fail(`Expected result opIndex ${this.pendingCount}`);
43837
+ if (row.submissionIndex !== this.resultCount)
43838
+ fail(`Expected submissionIndex ${this.resultCount}`);
43839
+ const outcome = resultOutcome(row);
43840
+ this.pendingCounts[outcome] += 1;
43841
+ this.totalCounts[outcome] += 1;
43842
+ this.pendingCount += 1;
43843
+ this.resultCount += 1;
43844
+ this.index += 1;
43845
+ return;
43846
+ }
43847
+ if (row.type === "group") {
43848
+ if (row.chunkOrdinal !== this.groupCount)
43849
+ fail(`Expected group chunkOrdinal ${this.groupCount}`);
43850
+ if (this.pendingCount === 0)
43851
+ fail("A group must close result rows");
43852
+ if (!countsMatch(this.pendingCounts, row.operations))
43853
+ fail("Group operation counters do not match its result rows");
43854
+ return this.acceptGroup(row, fail);
43855
+ }
43856
+ this.terminalSeen = true;
43857
+ if (this.pendingCount > 0)
43858
+ fail("Terminal row cannot close a partial group");
43859
+ if (row.type === "summary") {
43860
+ return this.acceptSummary(row, fail);
43861
+ }
43862
+ this.index += 1;
43863
+ }
43864
+ async acceptGroup(row, fail) {
43865
+ this.manifestDigest = this.manifestDigest.then((previous) => advanceManifest(previous, row.chunkOrdinal, row.requestDigest));
43866
+ if (row.manifestDigest !== await this.manifestDigest)
43867
+ fail("Group manifest digest does not match the receipt chain");
43868
+ if (row.repoSeq !== undefined) {
43869
+ this.firstRepoSeq ??= row.repoSeq;
43870
+ this.lastRepoSeq = row.repoSeq;
43871
+ }
43872
+ this.groupCount += 1;
43873
+ this.pendingCount = 0;
43874
+ this.pendingCounts = emptyCounts();
43875
+ this.index += 1;
43876
+ }
43877
+ async acceptSummary(row, fail) {
43878
+ if (!countsMatch(this.totalCounts, row.operations))
43879
+ fail("Summary operation counters do not match result rows");
43880
+ if (row.groups !== this.groupCount || row.manifest.groups !== this.groupCount)
43881
+ fail("Summary group counters do not match group rows");
43882
+ if (row.manifest.digest !== await this.manifestDigest)
43883
+ fail("Summary manifest digest does not match the receipt chain");
43884
+ if (row.repoSeq.first !== this.firstRepoSeq || row.repoSeq.last !== this.lastRepoSeq)
43885
+ fail("Summary repo sequence does not match group rows");
43886
+ const totalIsInvalid = exactTotalVerdicts.has(row.verdict) ? row.operations.total !== this.resultCount : row.operations.total < this.resultCount;
43887
+ if (totalIsInvalid)
43888
+ fail("Summary total is incompatible with its verdict");
43889
+ if (row.verdict === "truncated-by-parse-error" !== (row.truncatedAt !== undefined))
43890
+ fail("truncatedAt must appear only for a parse-truncated verdict");
43891
+ this.index += 1;
43892
+ }
43893
+ finish() {
43894
+ if (!this.terminalSeen)
43895
+ throw new StreamingSubmissionProtocolError("Response must end with a summary or error row", this.index);
43896
+ }
43897
+ }
43898
+ function parseRow(line, index) {
43899
+ let value;
43900
+ try {
43901
+ value = JSON.parse(line);
43902
+ } catch (cause) {
43903
+ throw new StreamingSubmissionProtocolError(cause instanceof Error ? cause.message : "Invalid JSON", index);
43904
+ }
43905
+ const parsed = rowSchema.safeParse(value);
43906
+ if (!parsed.success) {
43907
+ throw new StreamingSubmissionProtocolError(parsed.error.issues[0]?.message ?? "Malformed row", index);
43908
+ }
43909
+ return parsed.data;
43910
+ }
43911
+ async function* readStreamingSubmissionRows(response, expectedIdentity) {
43912
+ const reader = response.body?.getReader();
43913
+ if (!reader)
43914
+ throw new StreamingSubmissionProtocolError("Missing response body", 0);
43915
+ const validator = new SequenceValidator;
43916
+ const decoder = new TextDecoder;
43917
+ let buffer = "";
43918
+ let rowIndex = 0;
43919
+ let finished = false;
43920
+ let terminalRow;
43921
+ const consume = (line) => {
43922
+ if (line.endsWith("\r"))
43923
+ line = line.slice(0, -1);
43924
+ if (line.length === 0)
43925
+ throw new StreamingSubmissionProtocolError("Blank response row", rowIndex);
43926
+ const row = parseRow(line, rowIndex);
43927
+ const pending = validator.accept(row);
43928
+ return { pending, row };
43929
+ };
43930
+ const validateIdentity = (row) => {
43931
+ if (row.type === "summary" && expectedIdentity !== undefined && (row.submissionId !== expectedIdentity.submissionId || row.streamId !== expectedIdentity.streamId || row.groupSize !== expectedIdentity.groupSize)) {
43932
+ throw new StreamingSubmissionProtocolError("Summary identity does not match the submission handle", rowIndex);
43933
+ }
43934
+ rowIndex += 1;
43935
+ };
43936
+ try {
43937
+ while (true) {
43938
+ const { done, value } = await reader.read();
43939
+ if (done)
43940
+ break;
43941
+ buffer += decoder.decode(value, { stream: true });
43942
+ while (true) {
43943
+ const newline = buffer.indexOf(`
43944
+ `);
43945
+ if (newline === -1)
43946
+ break;
43947
+ const line = buffer.slice(0, newline);
43948
+ buffer = buffer.slice(newline + 1);
43949
+ const { pending, row } = consume(line);
43950
+ if (pending)
43951
+ await pending;
43952
+ validateIdentity(row);
43953
+ if (row.type === "summary" || row.type === "error")
43954
+ terminalRow = row;
43955
+ else
43956
+ yield row;
43957
+ }
43958
+ }
43959
+ buffer += decoder.decode();
43960
+ if (buffer.length > 0) {
43961
+ const { pending, row } = consume(buffer);
43962
+ if (pending)
43963
+ await pending;
43964
+ validateIdentity(row);
43965
+ if (row.type === "summary" || row.type === "error")
43966
+ terminalRow = row;
43967
+ else
43968
+ yield row;
43969
+ }
43970
+ validator.finish();
43971
+ finished = true;
43972
+ if (terminalRow)
43973
+ yield terminalRow;
43974
+ } finally {
43975
+ if (!finished)
43976
+ await reader.cancel().catch(() => {
43977
+ return;
43978
+ });
43979
+ reader.releaseLock();
43980
+ }
43981
+ }
43982
+
43983
+ // ../../packages/sdk-ts/src/streaming-submission-types.ts
43984
+ class StreamingSubmissionOutcomeUnknownError extends Error {
43985
+ code = "STREAMING_SUBMISSION_OUTCOME_UNKNOWN";
43986
+ outcome = "unknown";
43987
+ retryable = false;
43988
+ retryIdentity;
43989
+ cause;
43990
+ constructor(retryIdentity, cause) {
43991
+ super(`Streaming submission outcome is unknown for ${retryIdentity.submissionId}. Reconstruct the original source and copy every retryIdentity field into the next applyStreaming call.`);
43992
+ this.name = "StreamingSubmissionOutcomeUnknownError";
43993
+ this.retryIdentity = retryIdentity;
43994
+ this.cause = cause;
43995
+ }
43996
+ }
43997
+
43998
+ // ../../packages/sdk-ts/src/streaming-submission-handle.ts
43999
+ function normalizedOptional(value) {
44000
+ return value === undefined || value === "" ? undefined : value;
44001
+ }
44002
+ function supportsStreamingRequests() {
44003
+ const runtime = globalThis;
44004
+ if (runtime.Bun !== undefined)
44005
+ return true;
44006
+ const node = runtime.process?.versions?.node;
44007
+ if (!node)
44008
+ return false;
44009
+ const [major = 0, minor = 0] = node.split(".").map(Number);
44010
+ return major > 22 || major === 22 && minor >= 2;
44011
+ }
44012
+ function submissionPath(identity2) {
44013
+ const query = new URLSearchParams({
44014
+ submissionId: identity2.submissionId,
44015
+ groupSize: String(identity2.groupSize)
44016
+ });
44017
+ if (identity2.message !== undefined)
44018
+ query.set("message", identity2.message);
44019
+ if (identity2.committer !== undefined)
44020
+ query.set("committer", identity2.committer);
44021
+ return `/api/repos/${encodeURIComponent(identity2.orgName)}/${encodeURIComponent(identity2.repoName)}/streams/${encodeURIComponent(identity2.streamId)}/submissions?${query}`;
44022
+ }
44023
+ function createRequestBody(source) {
44024
+ const iterator = createNormalizedOperationIterator(source, false);
44025
+ let closed = false;
44026
+ const returnSourceOnce = () => {
44027
+ if (closed)
44028
+ return;
44029
+ closed = true;
44030
+ const returned = iterator.returnSourceOnce();
44031
+ if (returned)
44032
+ Promise.resolve(returned).catch(() => {
44033
+ return;
44034
+ });
44035
+ };
44036
+ const stream = new ReadableStream({
44037
+ async pull(controller) {
44038
+ try {
44039
+ const next = await iterator.next();
44040
+ if (closed)
44041
+ return;
44042
+ if (next.done) {
44043
+ controller.close();
44044
+ return;
44045
+ }
44046
+ controller.enqueue(encodeStreamOperation(next.value));
44047
+ } catch (cause) {
44048
+ controller.error(cause);
44049
+ returnSourceOnce();
44050
+ }
44051
+ },
44052
+ cancel() {
44053
+ returnSourceOnce();
44054
+ }
44055
+ });
44056
+ return { stream, returnSourceOnce };
44057
+ }
44058
+ function linkSignal(input, controller) {
44059
+ if (!input)
44060
+ return () => {
44061
+ return;
44062
+ };
44063
+ const abort = () => controller.abort(input.reason);
44064
+ if (input.aborted)
44065
+ abort();
44066
+ else
44067
+ input.addEventListener("abort", abort, { once: true });
44068
+ return () => input.removeEventListener("abort", abort);
44069
+ }
44070
+ function createIdentity(input) {
44071
+ const submissionId = input.options?.submissionId ?? createOperationEventSubmissionId();
44072
+ return {
44073
+ orgName: input.orgName,
44074
+ repoName: input.repoName,
44075
+ streamId: input.options.streamId,
44076
+ submissionId,
44077
+ groupSize: normalizeStreamChunkSize(input.options.groupSize),
44078
+ ...normalizedOptional(input.message) !== undefined ? { message: normalizedOptional(input.message) } : {},
44079
+ ...normalizedOptional(input.options?.committer) !== undefined ? { committer: normalizedOptional(input.options?.committer) } : {}
44080
+ };
44081
+ }
44082
+ function createStreamingSubmissionHandle(input, deps) {
44083
+ if (!input.options.streamId) {
44084
+ throw deps.localError("VALIDATION_ERROR", "Streaming submissions require a non-empty streamId.");
44085
+ }
44086
+ const retryIdentity = createIdentity(input);
44087
+ const controller = new AbortController;
44088
+ let unlink = () => {
44089
+ return;
44090
+ };
44091
+ let iterator;
44092
+ let stopped = false;
44093
+ const consume = async function* () {
44094
+ let dispatched = false;
44095
+ let definiteError = false;
44096
+ let body;
44097
+ try {
44098
+ if (!(deps.runtimeSupported ?? supportsStreamingRequests)()) {
44099
+ throw deps.localError("VALIDATION_ERROR", "Streaming submissions require Bun or Node.js 22.2 or newer.");
44100
+ }
44101
+ unlink = linkSignal(input.options.signal, controller);
44102
+ if (controller.signal.aborted) {
44103
+ throw deps.localError("CANCELLED", "Streaming submission was aborted.");
44104
+ }
44105
+ const prepared = await deps.prepare(submissionPath(retryIdentity));
44106
+ if (controller.signal.aborted) {
44107
+ throw deps.localError("CANCELLED", "Streaming submission was aborted.");
44108
+ }
44109
+ body = createRequestBody(input.operations);
44110
+ dispatched = true;
44111
+ const response = await prepared.dispatch(body.stream, controller.signal);
44112
+ if (!response.ok) {
44113
+ definiteError = true;
44114
+ throw await prepared.httpError(response);
44115
+ }
44116
+ for await (const row of readStreamingSubmissionRows(response, retryIdentity)) {
44117
+ yield row;
44118
+ }
44119
+ } catch (cause) {
44120
+ if (cause instanceof StreamingSubmissionOutcomeUnknownError)
44121
+ throw cause;
44122
+ if (dispatched && !definiteError) {
44123
+ throw new StreamingSubmissionOutcomeUnknownError(retryIdentity, cause);
44124
+ }
44125
+ throw deps.normalizeLocalError(cause);
44126
+ } finally {
44127
+ controller.abort();
44128
+ body?.returnSourceOnce();
44129
+ unlink();
44130
+ stopped = true;
44131
+ }
44132
+ };
44133
+ return {
44134
+ retryIdentity,
44135
+ [Symbol.asyncIterator]() {
44136
+ return this;
44137
+ },
44138
+ next() {
44139
+ if (stopped)
44140
+ return Promise.resolve({ done: true, value: undefined });
44141
+ iterator ??= consume();
44142
+ return iterator.next();
44143
+ },
44144
+ async return(value) {
44145
+ controller.abort();
44146
+ if (!iterator) {
44147
+ stopped = true;
44148
+ unlink();
44149
+ return { done: true, value };
44150
+ }
44151
+ return iterator.return(value);
44152
+ },
44153
+ async throw(error51) {
44154
+ controller.abort(error51);
44155
+ if (!iterator) {
44156
+ stopped = true;
44157
+ unlink();
44158
+ throw error51;
44159
+ }
44160
+ return iterator.throw(error51);
44161
+ }
44162
+ };
44163
+ }
43547
44164
  // ../../packages/sdk-ts/package.json
43548
44165
  var package_default = {
43549
44166
  name: "@warmhub/sdk-ts",
43550
- version: "0.93.0",
44167
+ version: "0.95.0",
43551
44168
  private: false,
43552
44169
  type: "module",
43553
44170
  description: "The TypeScript SDK for WarmHub — create repos, commit and query data, and compound knowledge with your AI agents.",
@@ -43569,6 +44186,11 @@ var package_default = {
43569
44186
  url: "https://warmhub.ai"
43570
44187
  },
43571
44188
  homepage: "https://docs.warmhub.ai/get-started/quickstart/#connect-via-sdk",
44189
+ repository: {
44190
+ type: "git",
44191
+ url: "https://github.com/warmhub/warmhub-app.git",
44192
+ directory: "packages/sdk-ts"
44193
+ },
43572
44194
  bugs: {
43573
44195
  email: "support@warmhub.ai"
43574
44196
  },
@@ -43584,7 +44206,8 @@ var package_default = {
43584
44206
  ],
43585
44207
  publishConfig: {
43586
44208
  registry: "https://registry.npmjs.org",
43587
- access: "public"
44209
+ access: "public",
44210
+ tag: "latest"
43588
44211
  },
43589
44212
  exports: {
43590
44213
  ".": {
@@ -43602,7 +44225,7 @@ var package_default = {
43602
44225
  },
43603
44226
  scripts: {
43604
44227
  build: 'if [ "${WARMHUB_TEST_RUNTIME_BUILD:-}" = "1" ]; then bun run build:test-runtime; else bun run build:full; fi',
43605
- "build:full": "tsc --noEmit && bun run build:runtime && bun run build:types && bun run scripts/inject-doc-links.ts",
44228
+ "build:full": "bun run build:runtime && bun run build:types && bun run scripts/inject-doc-links.ts",
43606
44229
  "build:runtime": "tsup",
43607
44230
  "build:types": "NODE_OPTIONS=--max-old-space-size=4096 tsup --config tsup.dts-core.config.ts && NODE_OPTIONS=--max-old-space-size=4096 tsup --config tsup.dts-checkpoint.config.ts",
43608
44231
  "build:test-runtime": "tsup --config tsup.test-runtime.config.ts",
@@ -44431,6 +45054,11 @@ class WarmHubClient {
44431
45054
  throw toWarmHubError(error51);
44432
45055
  }
44433
45056
  },
45057
+ applyStreaming: (orgName, repoName, message, operations, opts) => createStreamingSubmissionHandle({ orgName, repoName, message, operations, options: opts }, {
45058
+ prepare: async (path) => await this.prepareStreamingSubmissionRequest(path),
45059
+ localError: (code, errorMessage) => new WarmHubError(code, errorMessage),
45060
+ normalizeLocalError: toWarmHubError
45061
+ }),
44434
45062
  getReceipt: async (orgName, repoName, eventRequestId) => {
44435
45063
  try {
44436
45064
  return await this.trpc.commit.getReceipt.query({
@@ -46186,32 +46814,54 @@ class WarmHubClient {
46186
46814
  }
46187
46815
  async requestResponse(path, init) {
46188
46816
  const response = await this.fetchWithAuth(`${this.apiUrl.replace(/\/$/, "")}${path}`, init);
46189
- if (!response.ok) {
46190
- let message = `Request failed with status ${response.status}`;
46191
- let code = httpStatusToWarmHubCode(response.status);
46192
- let errorCode;
46193
- let hint;
46194
- let retryAfter;
46195
- try {
46196
- const body = await response.json();
46197
- if (typeof body.error?.message === "string") {
46198
- message = body.error.message;
46199
- }
46200
- if (typeof body.error?.code === "string") {
46201
- code = body.error.code;
46202
- errorCode = body.error.code;
46203
- }
46204
- if (typeof body.error?.hint === "string") {
46205
- hint = body.error.hint;
46206
- }
46207
- if (typeof body.error?.retryAfter === "number") {
46208
- retryAfter = body.error.retryAfter;
46209
- }
46210
- } catch {}
46211
- throw new WarmHubError(code, message, response.status, hint, retryAfter, errorCode);
46212
- }
46817
+ if (!response.ok)
46818
+ throw await this.httpResponseError(response);
46213
46819
  return response;
46214
46820
  }
46821
+ async prepareStreamingSubmissionRequest(path) {
46822
+ const fetchImpl = this.fetchImpl ?? globalThis.fetch;
46823
+ const headers = new Headers({
46824
+ accept: "application/x-ndjson",
46825
+ "content-type": "application/x-ndjson"
46826
+ });
46827
+ const token = await resolveAccessToken(this.accessToken);
46828
+ if (token)
46829
+ headers.set("authorization", `Bearer ${token}`);
46830
+ this.applyClientHeader(headers);
46831
+ const url2 = `${this.apiUrl.replace(/\/$/, "")}${path}`;
46832
+ return {
46833
+ dispatch: async (body, signal) => await fetchImpl(url2, {
46834
+ method: "POST",
46835
+ headers,
46836
+ body,
46837
+ signal,
46838
+ duplex: "half"
46839
+ }),
46840
+ httpError: async (response) => await this.httpResponseError(response)
46841
+ };
46842
+ }
46843
+ async httpResponseError(response) {
46844
+ let message = `Request failed with status ${response.status}`;
46845
+ let code = httpStatusToWarmHubCode(response.status);
46846
+ let errorCode;
46847
+ let hint;
46848
+ let retryAfter;
46849
+ try {
46850
+ const body = await response.json();
46851
+ if (typeof body.error?.message === "string")
46852
+ message = body.error.message;
46853
+ if (typeof body.error?.code === "string") {
46854
+ code = body.error.code;
46855
+ errorCode = body.error.code;
46856
+ }
46857
+ if (typeof body.error?.hint === "string")
46858
+ hint = body.error.hint;
46859
+ if (typeof body.error?.retryAfter === "number") {
46860
+ retryAfter = body.error.retryAfter;
46861
+ }
46862
+ } catch {}
46863
+ return new WarmHubError(code, message, response.status, hint, retryAfter, errorCode);
46864
+ }
46215
46865
  async requestJson(path, init) {
46216
46866
  const response = await this.requestResponse(path, init);
46217
46867
  return await response.json();
@@ -46756,12 +47406,22 @@ function printCliError(err, errWriter, opts = {}) {
46756
47406
  function fromWh(exit, kind, err, hint = err.hint) {
46757
47407
  return new CliError(exit, kind, err.message, err, hint, undefined, err.errorCode);
46758
47408
  }
46759
- function authCliError(input) {
47409
+ function classifyAuthError(input) {
46760
47410
  if (input.code !== "UNAUTHENTICATED" && input.code !== "FORBIDDEN") {
46761
47411
  return;
46762
47412
  }
46763
47413
  const fallbackHint = input.code === "FORBIDDEN" ? "Check credentials and backend permissions." : unauthenticatedHint(input.message);
46764
- return new CliError(5 /* Auth */, "AUTH", input.message, input.cause, input.hint ?? fallbackHint, undefined, input.backendCode);
47414
+ return {
47415
+ exit: 5 /* Auth */,
47416
+ kind: "AUTH",
47417
+ hint: input.hint ?? fallbackHint
47418
+ };
47419
+ }
47420
+ function authCliError(input) {
47421
+ const classified = classifyAuthError(input);
47422
+ if (!classified)
47423
+ return;
47424
+ return new CliError(classified.exit, classified.kind, input.message, input.cause, classified.hint, undefined, input.backendCode);
46765
47425
  }
46766
47426
  function usageError(usage, ...examples) {
46767
47427
  const hint = examples.length === 0 ? undefined : examples.length === 1 ? `Example: ${examples[0]}` : `Examples:
@@ -46863,61 +47523,62 @@ var OP_USER_INPUT_CODES = new Set([
46863
47523
  "BUILTIN_SHAPE",
46864
47524
  "DEPENDENCY_FAILED"
46865
47525
  ]);
46866
- function cliErrorFromOpFailure(failure) {
47526
+ function classifyOpFailure(failure) {
46867
47527
  const diagnostic = failure.errors?.[0] ?? failure.error;
46868
47528
  const code = diagnostic?.code ?? "BACKEND";
46869
47529
  const message = diagnostic?.message ?? `Operation on "${failure.name}" failed`;
46870
47530
  const errorCode = diagnostic?.code;
46871
- const make = (exit, kind, hint) => new CliError(exit, kind, message, undefined, hint, undefined, errorCode);
46872
- const authError = authCliError({
46873
- code,
46874
- message,
46875
- backendCode: errorCode
46876
- });
47531
+ const classified = (exit, kind, hint) => ({ exit, kind, message, hint, errorCode });
47532
+ const authError = classifyAuthError({ code, message });
46877
47533
  if (authError)
46878
- return authError;
47534
+ return classified(authError.exit, authError.kind, authError.hint);
46879
47535
  if (CONFLICT_SHAPED_CODES.has(code)) {
46880
- return make(2 /* UserInput */, "CONFLICT", conflictHint(message, code));
47536
+ return classified(2 /* UserInput */, "CONFLICT", conflictHint(message, code));
46881
47537
  }
46882
47538
  if (OP_USER_INPUT_CODES.has(code)) {
46883
- return make(2 /* UserInput */, "USER_INPUT");
47539
+ return classified(2 /* UserInput */, "USER_INPUT");
46884
47540
  }
46885
47541
  if (isFieldIndexErrorCode(code)) {
46886
47542
  const exit = code === "FIELD_NOT_INDEXABLE" ? 2 /* UserInput */ : 4 /* Backend */;
46887
- return make(exit, code);
47543
+ return classified(exit, code);
46888
47544
  }
46889
47545
  if (code === "RATE_LIMITED") {
46890
- return make(4 /* Backend */, "RATE_LIMITED", "Rate limited. Wait for the Retry-After window before retrying.");
47546
+ return classified(4 /* Backend */, "RATE_LIMITED", "Rate limited. Wait for the Retry-After window before retrying.");
46891
47547
  }
46892
47548
  if (code === "QUERY_TOO_EXPENSIVE") {
46893
- return make(2 /* UserInput */, "QUERY_TOO_EXPENSIVE", "Narrow the query with a more selective field predicate or retry with a shallower page.");
47549
+ return classified(2 /* UserInput */, "QUERY_TOO_EXPENSIVE", "Narrow the query with a more selective field predicate or retry with a shallower page.");
46894
47550
  }
46895
- return make(4 /* Backend */, "BACKEND");
47551
+ return classified(4 /* Backend */, "BACKEND");
47552
+ }
47553
+ function cliErrorFromOpFailure(failure) {
47554
+ const classified = classifyOpFailure(failure);
47555
+ return new CliError(classified.exit, classified.kind, classified.message, undefined, classified.hint, undefined, classified.errorCode);
47556
+ }
47557
+ function opFailurePriority(failure) {
47558
+ const classified = classifyOpFailure(failure);
47559
+ if (classified.exit === 5 /* Auth */)
47560
+ return 4;
47561
+ if (classified.exit === 2 /* UserInput */)
47562
+ return 3;
47563
+ if (classified.kind === "RATE_LIMITED")
47564
+ return 2;
47565
+ return 1;
47566
+ }
47567
+ function preferMoreSevereOpFailure(current, candidate) {
47568
+ if (!current || opFailurePriority(candidate) > opFailurePriority(current)) {
47569
+ return candidate;
47570
+ }
47571
+ return current;
46896
47572
  }
46897
47573
  function cliErrorFromAllFailed(failures) {
46898
- const priorityOf = (err) => {
46899
- if (err.code === 5 /* Auth */)
46900
- return 4;
46901
- if (err.code === 2 /* UserInput */)
46902
- return 3;
46903
- if (err.kind === "RATE_LIMITED")
46904
- return 2;
46905
- return 1;
46906
- };
46907
- let bestErr;
46908
- let bestPriority = -1;
47574
+ let bestFailure;
46909
47575
  for (const failure of failures) {
46910
47576
  if (!isFailedOpStatus(failure.status))
46911
47577
  continue;
46912
- const err = cliErrorFromOpFailure(failure);
46913
- const priority = priorityOf(err);
46914
- if (priority > bestPriority) {
46915
- bestErr = err;
46916
- bestPriority = priority;
46917
- }
47578
+ bestFailure = preferMoreSevereOpFailure(bestFailure, failure);
46918
47579
  }
46919
- if (bestErr)
46920
- return bestErr;
47580
+ if (bestFailure)
47581
+ return cliErrorFromOpFailure(bestFailure);
46921
47582
  return new CliError(4 /* Backend */, "BACKEND", `All ${failures.length} operations failed`);
46922
47583
  }
46923
47584
  function requireSingleOpSuccess(result) {
@@ -55108,6 +55769,12 @@ var createFlags3 = {
55108
55769
  "chunk-size": flag.number({
55109
55770
  description: `Streamed ops per append chunk for --stream or .jsonl --file (default: ${DEFAULT_STREAM_APPEND_CHUNK_SIZE}, max: ${MAX_STREAM_APPEND_OPERATION_COUNT})`
55110
55771
  }),
55772
+ "server-stream": flag.boolean({
55773
+ description: "use the full-duplex server submission transport and emit results as groups commit"
55774
+ }),
55775
+ "group-size": flag.number({
55776
+ description: `operations per server-committed group with --server-stream (default: ${DEFAULT_STREAM_APPEND_CHUNK_SIZE}, max: ${MAX_STREAM_APPEND_OPERATION_COUNT})`
55777
+ }),
55111
55778
  "allow-nul-bytes": flag.boolean({
55112
55779
  description: "Skip the client-side pre-check that rejects literal U+0000 bytes in op data. PostgreSQL `text` columns still cannot store these — use only when the backend storage type is known to tolerate them."
55113
55780
  }),
@@ -55172,6 +55839,21 @@ var createFlags3 = {
55172
55839
  })
55173
55840
  };
55174
55841
 
55842
+ // ../../packages/warmhub-cli/src/domains/commit-stream-output-contract-id.ts
55843
+ var COMMIT_SUBMIT_STREAM_ROW_SCHEMA_ID = "wh.commit.submit.stream.row/v0.1";
55844
+ function identify(row) {
55845
+ if ("schema" in row) {
55846
+ throw new Error("Streaming submission row already defines a schema field");
55847
+ }
55848
+ return { schema: COMMIT_SUBMIT_STREAM_ROW_SCHEMA_ID, ...row };
55849
+ }
55850
+ function identifyCommitSubmitStreamStart(retryIdentity) {
55851
+ return identify({ type: "start", retryIdentity });
55852
+ }
55853
+ function identifyCommitSubmitStreamRow(row) {
55854
+ return identify(row);
55855
+ }
55856
+
55175
55857
  // ../../packages/warmhub-cli/src/domains/commit-submit-template.ts
55176
55858
  import { writeFile } from "node:fs/promises";
55177
55859
  var WRITE_TEMPLATE_KINDS = ["thing", "assertion"];
@@ -56514,6 +57196,284 @@ var handleSubmit = async (ctx, { flags, args }) => {
56514
57196
  }
56515
57197
  };
56516
57198
 
57199
+ // ../../packages/warmhub-cli/src/domains/commit-submit-server-source.ts
57200
+ import { createReadStream as createReadStream4 } from "node:fs";
57201
+ function parseOperationLine(rawLine, lineNumber, label, allowNulBytes) {
57202
+ const trimmed = rawLine.trim();
57203
+ if (!trimmed)
57204
+ return;
57205
+ const operation = safeParseJson(trimmed, `${label} JSONL line ${lineNumber}`);
57206
+ rejectLegacyLifecycleOperations([operation]);
57207
+ if (!allowNulBytes) {
57208
+ assertNoNulBytes("data" in operation ? operation.data : undefined, `${label} JSONL line ${lineNumber}`);
57209
+ }
57210
+ return operation;
57211
+ }
57212
+ async function* serverJsonlOperationSource(input, label, allowNulBytes) {
57213
+ const decoder = new TextDecoder;
57214
+ const encoder = new TextEncoder;
57215
+ let pending = new Uint8Array(0);
57216
+ let pendingLength = 0;
57217
+ let lineNumber = 0;
57218
+ const lineLimitError = (atLine = lineNumber + 1) => new CliError(2 /* UserInput */, "USER_INPUT", `${label} JSONL line ${atLine} exceeds the 1 MiB line limit.`, undefined, "wh commit submit --file operations.jsonl --server-stream --stream-id bulk-import --format jsonl --repo acme/world");
57219
+ const append = (bytes) => {
57220
+ const required2 = pendingLength + bytes.length;
57221
+ if (required2 > MAX_STREAMING_SUBMISSION_LINE_BYTES)
57222
+ throw lineLimitError();
57223
+ if (required2 > pending.length) {
57224
+ let capacity = Math.max(1024, pending.length);
57225
+ while (capacity < required2) {
57226
+ capacity = Math.min(MAX_STREAMING_SUBMISSION_LINE_BYTES, capacity * 2);
57227
+ }
57228
+ const grown = new Uint8Array(capacity);
57229
+ grown.set(pending.subarray(0, pendingLength));
57230
+ pending = grown;
57231
+ }
57232
+ pending.set(bytes, pendingLength);
57233
+ pendingLength = required2;
57234
+ };
57235
+ const decodeLine = (bytes) => {
57236
+ const required2 = pendingLength + bytes.length;
57237
+ if (required2 > MAX_STREAMING_SUBMISSION_LINE_BYTES) {
57238
+ throw lineLimitError(lineNumber);
57239
+ }
57240
+ if (pendingLength === 0)
57241
+ return decoder.decode(bytes);
57242
+ append(bytes);
57243
+ const line = decoder.decode(pending.subarray(0, pendingLength));
57244
+ pendingLength = 0;
57245
+ return line;
57246
+ };
57247
+ for await (const chunk of input) {
57248
+ const bytes = typeof chunk === "string" ? encoder.encode(chunk) : chunk;
57249
+ let lineStart = 0;
57250
+ let newline = bytes.indexOf(10, lineStart);
57251
+ while (newline >= 0) {
57252
+ lineNumber += 1;
57253
+ const operation = parseOperationLine(decodeLine(bytes.subarray(lineStart, newline)), lineNumber, label, allowNulBytes);
57254
+ if (operation)
57255
+ yield operation;
57256
+ lineStart = newline + 1;
57257
+ newline = bytes.indexOf(10, lineStart);
57258
+ }
57259
+ append(bytes.subarray(lineStart));
57260
+ }
57261
+ if (pendingLength > 0) {
57262
+ lineNumber += 1;
57263
+ const operation = parseOperationLine(decoder.decode(pending.subarray(0, pendingLength)), lineNumber, label, allowNulBytes);
57264
+ if (operation)
57265
+ yield operation;
57266
+ }
57267
+ }
57268
+ async function* jsonArrayFileSource(path2, allowNulBytes) {
57269
+ const raw = await readValidationJsonArrayFile(path2);
57270
+ const operations = parseJsonArray(raw, "--file contents");
57271
+ rejectLegacyLifecycleOperations(operations);
57272
+ for (const [index, operation] of operations.entries()) {
57273
+ if (!allowNulBytes) {
57274
+ assertNoNulBytes("data" in operation ? operation.data : undefined, `--file operation ${index + 1}`);
57275
+ }
57276
+ yield operation;
57277
+ }
57278
+ }
57279
+ function createServerStreamingOperationSource(args) {
57280
+ if (args.source === "--stream") {
57281
+ const input = args.ctx.stdin ?? process.stdin;
57282
+ if (isTTY(input)) {
57283
+ throw new CliError(2 /* UserInput */, "USER_INPUT", "No JSONL operations provided on stdin.", undefined, `printf '%s\\n' '{"operation":"add","kind":"thing","name":"Example/item","data":{}}' | wh commit submit --stream --server-stream --stream-id example --repo acme/world`);
57284
+ }
57285
+ return serverJsonlOperationSource(input, "--stream", args.allowNulBytes);
57286
+ }
57287
+ const path2 = args.file;
57288
+ if (!path2.endsWith(".jsonl")) {
57289
+ return jsonArrayFileSource(path2, args.allowNulBytes);
57290
+ }
57291
+ return async function* () {
57292
+ yield* serverJsonlOperationSource(createReadStream4(path2), "--file", args.allowNulBytes);
57293
+ }();
57294
+ }
57295
+
57296
+ // ../../packages/warmhub-cli/src/domains/commit-submit-server-stream.ts
57297
+ function userInput(message) {
57298
+ throw new CliError(2 /* UserInput */, "USER_INPUT", message, undefined, "wh commit submit --file operations.jsonl --server-stream --stream-id bulk-import --format jsonl --repo acme/world");
57299
+ }
57300
+ function parseGroupSize(value) {
57301
+ if (value === undefined)
57302
+ return;
57303
+ if (!Number.isInteger(value) || value < 1) {
57304
+ userInput("--group-size must be a positive integer.");
57305
+ }
57306
+ if (value > MAX_STREAM_APPEND_OPERATION_COUNT) {
57307
+ userInput(`--group-size must be at most ${MAX_STREAM_APPEND_OPERATION_COUNT}.`);
57308
+ }
57309
+ return value;
57310
+ }
57311
+ function resolveSource(flags) {
57312
+ return resolveCommitOperationSource({
57313
+ stream: flags.stream === true,
57314
+ ops: flags.ops !== undefined,
57315
+ file: flags.file !== undefined,
57316
+ add: (flags.add?.length ?? 0) > 0,
57317
+ revise: flags.revise !== undefined,
57318
+ retract: (flags.retract?.length ?? 0) > 0,
57319
+ collection: flags.type !== undefined
57320
+ });
57321
+ }
57322
+ function assertServerStreamOptions(ctx, flags, source) {
57323
+ if (ctx.dryRun)
57324
+ userInput("--server-stream cannot be combined with --dry-run.");
57325
+ if (ctx.format === "json") {
57326
+ userInput("--server-stream requires pretty output or --format jsonl; --json would buffer the response.");
57327
+ }
57328
+ if (source !== "--stream" && source !== "--file") {
57329
+ userInput("--server-stream requires --stream or --file.");
57330
+ }
57331
+ if (flags["submission-id"] !== undefined && !/^(?:00000000-0000-0000-0000-000000000000|[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12})$/i.test(flags["submission-id"])) {
57332
+ userInput("--submission-id must be a UUID.");
57333
+ }
57334
+ const incompatible = [
57335
+ ["--chunk-size", flags["chunk-size"] !== undefined],
57336
+ ["--skip-existing", flags["skip-existing"] === true],
57337
+ ["--progress", flags.progress === true],
57338
+ ["--return-repo-seq", flags["return-repo-seq"] === true],
57339
+ ["--timing-out", flags["timing-out"] !== undefined],
57340
+ ["--include-would-be-body", flags["include-would-be-body"] === true],
57341
+ ["--expected-version", flags["expected-version"] !== undefined],
57342
+ ["--lease-id", flags["lease-id"] !== undefined]
57343
+ ].find(([, present]) => present);
57344
+ if (incompatible) {
57345
+ userInput(`${incompatible[0]} cannot be combined with --server-stream.`);
57346
+ }
57347
+ assertFlagsApplyToCommitSource(source, {
57348
+ data: (flags.data?.length ?? 0) > 0,
57349
+ shape: (flags.shape?.length ?? 0) > 0,
57350
+ about: (flags.about?.length ?? 0) > 0,
57351
+ affirm: (flags.affirm?.length ?? 0) > 0,
57352
+ reason: (flags.reason?.length ?? 0) > 0,
57353
+ kind: (flags.kind?.length ?? 0) > 0,
57354
+ name: flags.name !== undefined,
57355
+ members: flags.members !== undefined
57356
+ });
57357
+ const streamId = flags["stream-id"];
57358
+ if (!streamId)
57359
+ userInput("--server-stream requires --stream-id.");
57360
+ if (source === "--stream")
57361
+ return { source, streamId };
57362
+ const file2 = flags.file;
57363
+ if (!file2)
57364
+ userInput("--server-stream with --file requires a file path.");
57365
+ return { source, file: file2, streamId };
57366
+ }
57367
+ function recoveryGuidance(identity2) {
57368
+ return `Reconstruct the identical operation source and retry only by copying every field from this retry identity: ${JSON.stringify(identity2)}`;
57369
+ }
57370
+ function failClosedStreamingOutput(ctx, identity2) {
57371
+ ctx.requestedExitCode = 4 /* Backend */;
57372
+ ctx.err(`Streaming submission output closed before completion. ${recoveryGuidance(identity2)}`);
57373
+ }
57374
+ async function writeStreamingRow(ctx, row) {
57375
+ writeOutput(ctx, identifyCommitSubmitStreamRow(row), () => renderPrettyStreamingRow(ctx, row));
57376
+ return await ctx.flushOut?.() ?? true;
57377
+ }
57378
+ function renderPrettyStreamingRow(ctx, row) {
57379
+ const c = ctx.colors;
57380
+ if (row.type === "result") {
57381
+ const failed = isFailedOpStatus(row.status);
57382
+ const marker = failed ? "!" : row.status === "noop" ? "=" : "+";
57383
+ const diagnostic = "errors" in row ? row.errors[0] : ("error" in row) ? row.error : undefined;
57384
+ ctx.out(` ${marker} ${displayName(c, row.name)}${failed ? ` ${diagnostic?.message ?? diagnostic?.code ?? "failed"}` : ""}`);
57385
+ renderWarningLine(ctx.out, c, ctx.chars, row);
57386
+ return;
57387
+ }
57388
+ if (row.type === "group") {
57389
+ ctx.out(`${c.dim}group ${row.chunkOrdinal}${c.reset} event request ${row.eventRequestId}`);
57390
+ return;
57391
+ }
57392
+ if (row.type === "summary") {
57393
+ ctx.out(`${c.dim}summary${c.reset} ${row.verdict} (${row.operations.applied} applied, ${row.operations.noop} noop, ${row.operations.failed} failed)`);
57394
+ return;
57395
+ }
57396
+ ctx.out(`${c.red}error${c.reset} ${row.code}${row.message ? `: ${row.message}` : ""}`);
57397
+ }
57398
+ async function runServerStreamingSubmit(ctx, invocation) {
57399
+ const flags = invocation.flags;
57400
+ const sourceKind = resolveSource(flags);
57401
+ const options = assertServerStreamOptions(ctx, flags, sourceKind);
57402
+ const groupSize = parseGroupSize(flags["group-size"]);
57403
+ const { org, repo } = parseOrgRepo(getRepoRef(ctx) ?? invocation.args[0], ctx.config);
57404
+ const operations = options.source === "--stream" ? createServerStreamingOperationSource({
57405
+ source: options.source,
57406
+ ctx,
57407
+ allowNulBytes: flags["allow-nul-bytes"] === true
57408
+ }) : createServerStreamingOperationSource({
57409
+ source: options.source,
57410
+ file: options.file,
57411
+ allowNulBytes: flags["allow-nul-bytes"] === true
57412
+ });
57413
+ const handle = ctx.client.commit.applyStreaming(org, repo, flags.message, operations, {
57414
+ streamId: options.streamId,
57415
+ submissionId: flags["submission-id"],
57416
+ groupSize,
57417
+ committer: flags.committer,
57418
+ signal: ctx.signal
57419
+ });
57420
+ const identity2 = handle.retryIdentity;
57421
+ ctx.err(`streaming submission retry identity ${JSON.stringify(identity2)}`);
57422
+ writeOutput(ctx, identifyCommitSubmitStreamStart(identity2), () => {
57423
+ return;
57424
+ });
57425
+ if (await ctx.flushOut?.() === false) {
57426
+ failClosedStreamingOutput(ctx, identity2);
57427
+ await handle.return?.();
57428
+ return;
57429
+ }
57430
+ let terminal;
57431
+ let bestFailure;
57432
+ try {
57433
+ for await (const row of handle) {
57434
+ if (row.type === "result") {
57435
+ if (isFailedOpStatus(row.status)) {
57436
+ bestFailure = preferMoreSevereOpFailure(bestFailure, row);
57437
+ }
57438
+ } else if (row.type === "summary" || row.type === "error") {
57439
+ terminal = row;
57440
+ }
57441
+ if (!await writeStreamingRow(ctx, row)) {
57442
+ failClosedStreamingOutput(ctx, identity2);
57443
+ return;
57444
+ }
57445
+ }
57446
+ } catch (error51) {
57447
+ if (error51 instanceof StreamingSubmissionOutcomeUnknownError) {
57448
+ throw new CliError(4 /* Backend */, "BACKEND", error51.message, error51, recoveryGuidance(error51.retryIdentity));
57449
+ }
57450
+ throw error51;
57451
+ }
57452
+ if (!terminal) {
57453
+ throw new CliError(4 /* Backend */, "BACKEND", "Streaming submission ended without a terminal row; its outcome is unknown.", undefined, recoveryGuidance(identity2));
57454
+ }
57455
+ if (terminal.type === "error" || terminal.verdict !== "complete") {
57456
+ ctx.requestedExitCode = 4 /* Backend */;
57457
+ ctx.err(`${terminal.type === "error" ? terminal.message ?? terminal.code : `submission stopped with verdict ${terminal.verdict}`}. ${recoveryGuidance(identity2)}`);
57458
+ return;
57459
+ }
57460
+ if (terminal.operations.total > 0 && terminal.operations.applied === 0 && terminal.operations.noop === 0) {
57461
+ const error51 = (bestFailure && cliErrorFromOpFailure(bestFailure)) ?? new CliError(4 /* Backend */, "BACKEND", "All streaming submission operations failed.");
57462
+ ctx.requestedExitCode = error51.code;
57463
+ ctx.err(`${error51.message}. ${recoveryGuidance(identity2)}`);
57464
+ }
57465
+ }
57466
+ var handleSubmitWithServerStreaming = async (ctx, invocation) => {
57467
+ if (invocation.flags["server-stream"] === true) {
57468
+ await runServerStreamingSubmit(ctx, invocation);
57469
+ return;
57470
+ }
57471
+ if (invocation.flags["group-size"] !== undefined) {
57472
+ userInput("--group-size requires --server-stream.");
57473
+ }
57474
+ await handleSubmit(ctx, invocation);
57475
+ };
57476
+
56517
57477
  // ../../packages/warmhub-cli/src/domains/commit-submit-domain.ts
56518
57478
  var COMMIT_DOMAIN = defineDomain({
56519
57479
  name: "commit",
@@ -56544,6 +57504,7 @@ var COMMIT_DOMAIN = defineDomain({
56544
57504
  `wh commit submit --ops '[{"operation":"add","kind":"thing","name":"Session/run-001","data":{}},{"operation":"add","kind":"assertion","name":"HypothesisCandidate/run-001-claim","about":"Session/run-001","data":{}}]' -m "Create session + assertion"`,
56545
57505
  `printf '%s\\n' '{"operation":"add","kind":"thing","name":"Player/alice","data":{"score":1}}' | wh commit submit --stream --stream-id bulk-2026-06-04 --skip-existing --repo acme/world -m "stdin stream"`,
56546
57506
  'wh commit submit --file dataset.jsonl --stream-id bulk-2026-06-04 --skip-existing --progress -m "bulk stream"',
57507
+ 'wh commit submit --file dataset.jsonl --server-stream --stream-id bulk-2026-08-14 --group-size 1000 --format jsonl -m "server stream"',
56547
57508
  "wh shape template Session HypothesisCandidate -o ops.json",
56548
57509
  "wh commit submit --type arc --name route --members Location/a,Location/b",
56549
57510
  "wh commit submit --type bond --name peers --members Person/alice,Person/bob",
@@ -56552,9 +57513,10 @@ var COMMIT_DOMAIN = defineDomain({
56552
57513
  notes: [
56553
57514
  "`--dry-run` evaluates the complete bounded input with the real server commit evaluator and makes no durable repository change.",
56554
57515
  "Need to build an ops file? Run `wh shape template <Shape>` to scaffold the JSON from a shape definition, edit the FILL_IN placeholders, then pass it to `--file`.",
56555
- "Inspect a shape's fields first with `wh thing view <Shape>` before authoring or editing an ops file."
57516
+ "Inspect a shape's fields first with `wh thing view <Shape>` before authoring or editing an ops file.",
57517
+ "`--server-stream` is an opt-in full-duplex transport. It preserves the default aggregate path and requires `--stream-id`; use `--format jsonl` for the versioned row stream."
56556
57518
  ],
56557
- handler: handleSubmit
57519
+ handler: handleSubmitWithServerStreaming
56558
57520
  }
56559
57521
  }
56560
57522
  });
@@ -56646,7 +57608,7 @@ for (const spec of PRE_TERMINATOR_CONTROLS) {
56646
57608
  if (spec.short)
56647
57609
  CONTROL_SHORTS.set(spec.short, { spec, constant: false });
56648
57610
  }
56649
- function userInput(message, hint) {
57611
+ function userInput2(message, hint) {
56650
57612
  return new CliError(2 /* UserInput */, "USER_INPUT", message, undefined, hint);
56651
57613
  }
56652
57614
  function hasAttachedValue(record2) {
@@ -56683,13 +57645,13 @@ function acceptedArgList(method) {
56683
57645
  function unknownArgumentError(method, record2) {
56684
57646
  const accepted = acceptedArgList(method);
56685
57647
  const suffix = record2.ownership === "post-terminator" ? ` (use \`--\` to pass globals as method args, e.g. \`-- --${record2.name} <value>\`)` : "";
56686
- return userInput(`Unknown argument: --${record2.name}`, `Method '${method.name}' accepts: ${accepted}${suffix}`);
57648
+ return userInput2(`Unknown argument: --${record2.name}`, `Method '${method.name}' accepts: ${accepted}${suffix}`);
56687
57649
  }
56688
57650
  function duplicateError(arg) {
56689
- return userInput(`Flag --${arg.name} may only be specified once`, `Remove the duplicate occurrence; every spelling of --${arg.name} counts as the same flag.`);
57651
+ return userInput2(`Flag --${arg.name} may only be specified once`, `Remove the duplicate occurrence; every spelling of --${arg.name} counts as the same flag.`);
56690
57652
  }
56691
57653
  function missingValueError(arg) {
56692
- return userInput(`Flag --${arg.name} requires a value`, arg.type === "string" ? `To pass a value starting with '-', use the attached form: --${arg.name}=<value>` : `Usage: --${arg.name} <${arg.type}>`);
57654
+ return userInput2(`Flag --${arg.name} requires a value`, arg.type === "string" ? `To pass a value starting with '-', use the attached form: --${arg.name}=<value>` : `Usage: --${arg.name} <${arg.type}>`);
56693
57655
  }
56694
57656
  function coerceArg(arg, value) {
56695
57657
  switch (arg.type) {
@@ -56697,7 +57659,7 @@ function coerceArg(arg, value) {
56697
57659
  if (typeof value !== "string") {
56698
57660
  return {
56699
57661
  ok: false,
56700
- error: userInput(`--${arg.name} requires a string value`)
57662
+ error: userInput2(`--${arg.name} requires a string value`)
56701
57663
  };
56702
57664
  }
56703
57665
  if (arg.pattern) {
@@ -56707,13 +57669,13 @@ function coerceArg(arg, value) {
56707
57669
  } catch {
56708
57670
  return {
56709
57671
  ok: false,
56710
- error: userInput(`invalid regex pattern for --${arg.name}: /${arg.pattern}/`)
57672
+ error: userInput2(`invalid regex pattern for --${arg.name}: /${arg.pattern}/`)
56711
57673
  };
56712
57674
  }
56713
57675
  if (!pattern.test(value)) {
56714
57676
  return {
56715
57677
  ok: false,
56716
- error: userInput(`--${arg.name} value '${value}' does not match pattern /${arg.pattern}/`)
57678
+ error: userInput2(`--${arg.name} value '${value}' does not match pattern /${arg.pattern}/`)
56717
57679
  };
56718
57680
  }
56719
57681
  }
@@ -56724,32 +57686,32 @@ function coerceArg(arg, value) {
56724
57686
  if (typeof value === "boolean") {
56725
57687
  return {
56726
57688
  ok: false,
56727
- error: userInput(`--${arg.name} requires a ${arg.type} value`)
57689
+ error: userInput2(`--${arg.name} requires a ${arg.type} value`)
56728
57690
  };
56729
57691
  }
56730
57692
  const numeric = typeof value === "number" ? Number.isFinite(value) ? value : undefined : typeof value === "string" ? parseCliNumber(value) : undefined;
56731
57693
  if (numeric === undefined) {
56732
57694
  return {
56733
57695
  ok: false,
56734
- error: userInput(`--${arg.name} value ${quoteUserValue(value)} is not a valid ${arg.type}`)
57696
+ error: userInput2(`--${arg.name} value ${quoteUserValue(value)} is not a valid ${arg.type}`)
56735
57697
  };
56736
57698
  }
56737
57699
  if (arg.type === "integer" && !Number.isInteger(numeric)) {
56738
57700
  return {
56739
57701
  ok: false,
56740
- error: userInput(`--${arg.name} value ${quoteUserValue(value)} is not an integer`)
57702
+ error: userInput2(`--${arg.name} value ${quoteUserValue(value)} is not an integer`)
56741
57703
  };
56742
57704
  }
56743
57705
  if (arg.min !== undefined && numeric < arg.min) {
56744
57706
  return {
56745
57707
  ok: false,
56746
- error: userInput(`--${arg.name} value ${numeric} is below min ${arg.min}`)
57708
+ error: userInput2(`--${arg.name} value ${numeric} is below min ${arg.min}`)
56747
57709
  };
56748
57710
  }
56749
57711
  if (arg.max !== undefined && numeric > arg.max) {
56750
57712
  return {
56751
57713
  ok: false,
56752
- error: userInput(`--${arg.name} value ${numeric} is above max ${arg.max}`)
57714
+ error: userInput2(`--${arg.name} value ${numeric} is above max ${arg.max}`)
56753
57715
  };
56754
57716
  }
56755
57717
  return { ok: true, value: numeric };
@@ -56763,7 +57725,7 @@ function coerceArg(arg, value) {
56763
57725
  return { ok: true, value: false };
56764
57726
  return {
56765
57727
  ok: false,
56766
- error: userInput(`--${arg.name} requires true|false`)
57728
+ error: userInput2(`--${arg.name} requires true|false`)
56767
57729
  };
56768
57730
  }
56769
57731
  }
@@ -56790,7 +57752,7 @@ function bindComponentMethodArgs(invocation, method) {
56790
57752
  continue;
56791
57753
  if (record2.kind === "malformed-short") {
56792
57754
  claimed.add(record2.index);
56793
- addError(record2.index, userInput(`Unknown argument: --${record2.source.slice(1)}`, `Method '${method.name}' accepts: ${acceptedArgList(method)}`));
57755
+ addError(record2.index, userInput2(`Unknown argument: --${record2.source.slice(1)}`, `Method '${method.name}' accepts: ${acceptedArgList(method)}`));
56794
57756
  continue;
56795
57757
  }
56796
57758
  if (record2.kind !== "option")
@@ -56844,7 +57806,7 @@ function bindComponentMethodArgs(invocation, method) {
56844
57806
  }
56845
57807
  for (const record2 of invocation.records) {
56846
57808
  if (record2.kind === "positional" && !claimed.has(record2.index) && record2.source !== "--") {
56847
- addError(record2.index, userInput(`Unexpected argument: '${record2.source}'`, "'wh component exec' accepts at most 2 positional arguments (<component> <method>); pass method inputs as flags"));
57809
+ addError(record2.index, userInput2(`Unexpected argument: '${record2.source}'`, "'wh component exec' accepts at most 2 positional arguments (<component> <method>); pass method inputs as flags"));
56848
57810
  }
56849
57811
  }
56850
57812
  for (const arg of method.args) {
@@ -56860,7 +57822,7 @@ function bindComponentMethodArgs(invocation, method) {
56860
57822
  continue;
56861
57823
  }
56862
57824
  if (arg.required && !invocation.help) {
56863
- addError(Number.POSITIVE_INFINITY, userInput(`Missing required argument: --${arg.name}`));
57825
+ addError(Number.POSITIVE_INFINITY, userInput2(`Missing required argument: --${arg.name}`));
56864
57826
  }
56865
57827
  }
56866
57828
  indexedErrors.sort((left, right) => left.index - right.index || left.order - right.order);
@@ -60556,7 +61518,7 @@ var PRIME_DOMAIN = defineDomain({
60556
61518
  });
60557
61519
 
60558
61520
  // ../../packages/warmhub-cli/src/domains/repo/checkpoint.ts
60559
- import { createReadStream as createReadStream5 } from "node:fs";
61521
+ import { createReadStream as createReadStream6 } from "node:fs";
60560
61522
  import { lstat as lstat3 } from "node:fs/promises";
60561
61523
 
60562
61524
  // ../../packages/sdk-ts/src/repository-checkpoint/types.ts
@@ -60931,7 +61893,7 @@ import { createHash as createHash3 } from "node:crypto";
60931
61893
 
60932
61894
  // ../../packages/sdk-ts/src/repository-checkpoint/identity-sort.ts
60933
61895
  import { once } from "node:events";
60934
- import { createReadStream as createReadStream4, createWriteStream } from "node:fs";
61896
+ import { createReadStream as createReadStream5, createWriteStream } from "node:fs";
60935
61897
  import { open as open3, rm } from "node:fs/promises";
60936
61898
  import { join as join10 } from "node:path";
60937
61899
  var CHECKPOINT_IDENTITY_SORT_BUDGET_BYTES = 4 * 1024 * 1024;
@@ -61205,7 +62167,7 @@ class RunCursor {
61205
62167
  #offset = 0;
61206
62168
  current;
61207
62169
  constructor(path2) {
61208
- this.#stream = createReadStream4(path2, {
62170
+ this.#stream = createReadStream5(path2, {
61209
62171
  highWaterMark: RUN_READ_BUFFER_BYTES
61210
62172
  });
61211
62173
  this.#iterator = this.#stream[Symbol.asyncIterator]();
@@ -61597,8 +62559,8 @@ async function writeAll(handle, bytes) {
61597
62559
  offset += bytesWritten;
61598
62560
  }
61599
62561
  }
61600
- function assertArtifactIntegrity(byteLength, sha256, descriptor) {
61601
- if (byteLength !== descriptor.byteLength || sha256 !== descriptor.sha256) {
62562
+ function assertArtifactIntegrity(byteLength, sha2562, descriptor) {
62563
+ if (byteLength !== descriptor.byteLength || sha2562 !== descriptor.sha256) {
61602
62564
  throw new CliError(4 /* Backend */, "BACKEND", "Downloaded checkpoint artifact did not match its access descriptor.");
61603
62565
  }
61604
62566
  }
@@ -61853,7 +62815,7 @@ var handleVerify = async (ctx, { args }) => {
61853
62815
  }
61854
62816
  try {
61855
62817
  await lstat3(archive);
61856
- const result = await verifyRepositoryCheckpointArchive(createReadStream5(archive));
62818
+ const result = await verifyRepositoryCheckpointArchive(createReadStream6(archive));
61857
62819
  writeOutput(ctx, result, () => {
61858
62820
  ctx.out(`Checkpoint: ${result.checkpointId}`);
61859
62821
  ctx.out(`Repository sequence: ${result.repoSeq}`);
@@ -66801,7 +67763,7 @@ function resolveLogLevel(flagLevel, env) {
66801
67763
  // package.json
66802
67764
  var package_default3 = {
66803
67765
  name: "@warmhub/cli",
66804
- version: "0.95.0",
67766
+ version: "0.97.0",
66805
67767
  private: false,
66806
67768
  type: "module",
66807
67769
  description: "The wh CLI for WarmHub — create repos, commit and query data, and compound knowledge with your AI agents.",
@@ -66823,6 +67785,11 @@ var package_default3 = {
66823
67785
  url: "https://warmhub.ai"
66824
67786
  },
66825
67787
  homepage: "https://docs.warmhub.ai/get-started/quickstart/#connect-via-cli",
67788
+ repository: {
67789
+ type: "git",
67790
+ url: "https://github.com/warmhub/warmhub-app.git",
67791
+ directory: "apps/cli"
67792
+ },
66826
67793
  bugs: {
66827
67794
  email: "support@warmhub.ai"
66828
67795
  },
@@ -66838,7 +67805,8 @@ var package_default3 = {
66838
67805
  ],
66839
67806
  publishConfig: {
66840
67807
  registry: "https://registry.npmjs.org",
66841
- access: "public"
67808
+ access: "public",
67809
+ tag: "latest"
66842
67810
  },
66843
67811
  scripts: {
66844
67812
  build: "bun run scripts/build.ts",
@@ -67420,5 +68388,5 @@ process.exitCode = interceptedExitCode === undefined ? await runPreparedCli(laun
67420
68388
  version: package_default3.version
67421
68389
  }) : interceptedExitCode;
67422
68390
 
67423
- //# debugId=E38898F8C9FABDFA64756E2164756E21
67424
- //# warmhub-cli-build-info {"cliVersion":"0.95.0","sdkVersion":"0.93.0"}
68391
+ //# debugId=52246A7D0DA1719964756E2164756E21
68392
+ //# warmhub-cli-build-info {"cliVersion":"0.97.0","sdkVersion":"0.95.0"}