@warmhub/cli 0.96.0 → 0.98.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 +1070 -96
  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",
@@ -43376,7 +43384,7 @@ class OperationSourceError extends Error {
43376
43384
  }
43377
43385
  }
43378
43386
  async function submitOperationsViaStream(client, args) {
43379
- const chunkSize = normalizeChunkSize(args.chunkSize);
43387
+ const chunkSize = normalizeStreamChunkSize(args.chunkSize);
43380
43388
  const submissionId = args.submissionId ?? createOperationEventSubmissionId();
43381
43389
  const streamId = args.streamId ?? submissionId;
43382
43390
  const policy = resolveRetryPolicy(args.retry);
@@ -43476,7 +43484,7 @@ async function submitOperationsViaStream(client, args) {
43476
43484
  async function* normalizedChunks(source, chunkSize, skipExisting) {
43477
43485
  try {
43478
43486
  if (Array.isArray(source)) {
43479
- const operations = source.map((operation, index) => normalizeOperation(operation, index, skipExisting));
43487
+ const operations = source.map((operation, index) => normalizeStreamOperation(operation, index, skipExisting));
43480
43488
  validateNormalizedOperations(operations, 0);
43481
43489
  for (let start = 0;start < operations.length; start += chunkSize) {
43482
43490
  yield { operations: operations.slice(start, start + chunkSize), start };
@@ -43485,8 +43493,8 @@ async function* normalizedChunks(source, chunkSize, skipExisting) {
43485
43493
  }
43486
43494
  let normalizedCount = 0;
43487
43495
  let buffer = [];
43488
- for await (const operation of source) {
43489
- buffer.push(normalizeOperation(operation, normalizedCount, skipExisting));
43496
+ for await (const operation of normalizedOperationSource(source, skipExisting)) {
43497
+ buffer.push(operation);
43490
43498
  normalizedCount += 1;
43491
43499
  if (buffer.length < chunkSize)
43492
43500
  continue;
@@ -43504,7 +43512,7 @@ function preflightedChunk(operations, normalizedCount) {
43504
43512
  validateNormalizedOperations(operations, start);
43505
43513
  return { operations, start };
43506
43514
  }
43507
- function normalizeOperation(operation, index, skipExisting) {
43515
+ function normalizeStreamOperation(operation, index, skipExisting) {
43508
43516
  let streamOperation;
43509
43517
  try {
43510
43518
  streamOperation = toBackendStreamOperation(operation);
@@ -43517,6 +43525,57 @@ function normalizeOperation(operation, index, skipExisting) {
43517
43525
  }
43518
43526
  return streamOperation;
43519
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;
43520
43579
  function receiptRepoSeq(receipt) {
43521
43580
  const repoSeq = receipt.event?.repoSeq;
43522
43581
  if (repoSeq === undefined)
@@ -43533,15 +43592,579 @@ function validateNormalizedOperations(operations, indexOffset) {
43533
43592
  function isServerAuthoritativeSequenceDiagnostic(diagnostic) {
43534
43593
  return diagnostic.code === "ILLEGAL_OP_SEQUENCE" && diagnostic.message.includes("Cannot revise then add ");
43535
43594
  }
43536
- function normalizeChunkSize(chunkSize) {
43595
+ function normalizeStreamChunkSize(chunkSize) {
43537
43596
  if (!Number.isFinite(chunkSize))
43538
43597
  return DEFAULT_STREAM_CHUNK_SIZE;
43539
43598
  return Math.max(1, Math.min(MAX_STREAM_APPEND_OPERATION_COUNT2, Math.trunc(chunkSize)));
43540
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
+ }
43541
44164
  // ../../packages/sdk-ts/package.json
43542
44165
  var package_default = {
43543
44166
  name: "@warmhub/sdk-ts",
43544
- version: "0.94.0",
44167
+ version: "0.96.0",
43545
44168
  private: false,
43546
44169
  type: "module",
43547
44170
  description: "The TypeScript SDK for WarmHub — create repos, commit and query data, and compound knowledge with your AI agents.",
@@ -43563,6 +44186,11 @@ var package_default = {
43563
44186
  url: "https://warmhub.ai"
43564
44187
  },
43565
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
+ },
43566
44194
  bugs: {
43567
44195
  email: "support@warmhub.ai"
43568
44196
  },
@@ -43578,7 +44206,8 @@ var package_default = {
43578
44206
  ],
43579
44207
  publishConfig: {
43580
44208
  registry: "https://registry.npmjs.org",
43581
- access: "public"
44209
+ access: "public",
44210
+ tag: "latest"
43582
44211
  },
43583
44212
  exports: {
43584
44213
  ".": {
@@ -43596,7 +44225,7 @@ var package_default = {
43596
44225
  },
43597
44226
  scripts: {
43598
44227
  build: 'if [ "${WARMHUB_TEST_RUNTIME_BUILD:-}" = "1" ]; then bun run build:test-runtime; else bun run build:full; fi',
43599
- "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",
43600
44229
  "build:runtime": "tsup",
43601
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",
43602
44231
  "build:test-runtime": "tsup --config tsup.test-runtime.config.ts",
@@ -44425,6 +45054,11 @@ class WarmHubClient {
44425
45054
  throw toWarmHubError(error51);
44426
45055
  }
44427
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
+ }),
44428
45062
  getReceipt: async (orgName, repoName, eventRequestId) => {
44429
45063
  try {
44430
45064
  return await this.trpc.commit.getReceipt.query({
@@ -46180,32 +46814,54 @@ class WarmHubClient {
46180
46814
  }
46181
46815
  async requestResponse(path, init) {
46182
46816
  const response = await this.fetchWithAuth(`${this.apiUrl.replace(/\/$/, "")}${path}`, init);
46183
- if (!response.ok) {
46184
- let message = `Request failed with status ${response.status}`;
46185
- let code = httpStatusToWarmHubCode(response.status);
46186
- let errorCode;
46187
- let hint;
46188
- let retryAfter;
46189
- try {
46190
- const body = await response.json();
46191
- if (typeof body.error?.message === "string") {
46192
- message = body.error.message;
46193
- }
46194
- if (typeof body.error?.code === "string") {
46195
- code = body.error.code;
46196
- errorCode = body.error.code;
46197
- }
46198
- if (typeof body.error?.hint === "string") {
46199
- hint = body.error.hint;
46200
- }
46201
- if (typeof body.error?.retryAfter === "number") {
46202
- retryAfter = body.error.retryAfter;
46203
- }
46204
- } catch {}
46205
- throw new WarmHubError(code, message, response.status, hint, retryAfter, errorCode);
46206
- }
46817
+ if (!response.ok)
46818
+ throw await this.httpResponseError(response);
46207
46819
  return response;
46208
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
+ }
46209
46865
  async requestJson(path, init) {
46210
46866
  const response = await this.requestResponse(path, init);
46211
46867
  return await response.json();
@@ -46750,12 +47406,22 @@ function printCliError(err, errWriter, opts = {}) {
46750
47406
  function fromWh(exit, kind, err, hint = err.hint) {
46751
47407
  return new CliError(exit, kind, err.message, err, hint, undefined, err.errorCode);
46752
47408
  }
46753
- function authCliError(input) {
47409
+ function classifyAuthError(input) {
46754
47410
  if (input.code !== "UNAUTHENTICATED" && input.code !== "FORBIDDEN") {
46755
47411
  return;
46756
47412
  }
46757
47413
  const fallbackHint = input.code === "FORBIDDEN" ? "Check credentials and backend permissions." : unauthenticatedHint(input.message);
46758
- 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);
46759
47425
  }
46760
47426
  function usageError(usage, ...examples) {
46761
47427
  const hint = examples.length === 0 ? undefined : examples.length === 1 ? `Example: ${examples[0]}` : `Examples:
@@ -46857,61 +47523,62 @@ var OP_USER_INPUT_CODES = new Set([
46857
47523
  "BUILTIN_SHAPE",
46858
47524
  "DEPENDENCY_FAILED"
46859
47525
  ]);
46860
- function cliErrorFromOpFailure(failure) {
47526
+ function classifyOpFailure(failure) {
46861
47527
  const diagnostic = failure.errors?.[0] ?? failure.error;
46862
47528
  const code = diagnostic?.code ?? "BACKEND";
46863
47529
  const message = diagnostic?.message ?? `Operation on "${failure.name}" failed`;
46864
47530
  const errorCode = diagnostic?.code;
46865
- const make = (exit, kind, hint) => new CliError(exit, kind, message, undefined, hint, undefined, errorCode);
46866
- const authError = authCliError({
46867
- code,
46868
- message,
46869
- backendCode: errorCode
46870
- });
47531
+ const classified = (exit, kind, hint) => ({ exit, kind, message, hint, errorCode });
47532
+ const authError = classifyAuthError({ code, message });
46871
47533
  if (authError)
46872
- return authError;
47534
+ return classified(authError.exit, authError.kind, authError.hint);
46873
47535
  if (CONFLICT_SHAPED_CODES.has(code)) {
46874
- return make(2 /* UserInput */, "CONFLICT", conflictHint(message, code));
47536
+ return classified(2 /* UserInput */, "CONFLICT", conflictHint(message, code));
46875
47537
  }
46876
47538
  if (OP_USER_INPUT_CODES.has(code)) {
46877
- return make(2 /* UserInput */, "USER_INPUT");
47539
+ return classified(2 /* UserInput */, "USER_INPUT");
46878
47540
  }
46879
47541
  if (isFieldIndexErrorCode(code)) {
46880
47542
  const exit = code === "FIELD_NOT_INDEXABLE" ? 2 /* UserInput */ : 4 /* Backend */;
46881
- return make(exit, code);
47543
+ return classified(exit, code);
46882
47544
  }
46883
47545
  if (code === "RATE_LIMITED") {
46884
- 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.");
46885
47547
  }
46886
47548
  if (code === "QUERY_TOO_EXPENSIVE") {
46887
- 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.");
47550
+ }
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;
46888
47570
  }
46889
- return make(4 /* Backend */, "BACKEND");
47571
+ return current;
46890
47572
  }
46891
47573
  function cliErrorFromAllFailed(failures) {
46892
- const priorityOf = (err) => {
46893
- if (err.code === 5 /* Auth */)
46894
- return 4;
46895
- if (err.code === 2 /* UserInput */)
46896
- return 3;
46897
- if (err.kind === "RATE_LIMITED")
46898
- return 2;
46899
- return 1;
46900
- };
46901
- let bestErr;
46902
- let bestPriority = -1;
47574
+ let bestFailure;
46903
47575
  for (const failure of failures) {
46904
47576
  if (!isFailedOpStatus(failure.status))
46905
47577
  continue;
46906
- const err = cliErrorFromOpFailure(failure);
46907
- const priority = priorityOf(err);
46908
- if (priority > bestPriority) {
46909
- bestErr = err;
46910
- bestPriority = priority;
46911
- }
47578
+ bestFailure = preferMoreSevereOpFailure(bestFailure, failure);
46912
47579
  }
46913
- if (bestErr)
46914
- return bestErr;
47580
+ if (bestFailure)
47581
+ return cliErrorFromOpFailure(bestFailure);
46915
47582
  return new CliError(4 /* Backend */, "BACKEND", `All ${failures.length} operations failed`);
46916
47583
  }
46917
47584
  function requireSingleOpSuccess(result) {
@@ -55102,6 +55769,12 @@ var createFlags3 = {
55102
55769
  "chunk-size": flag.number({
55103
55770
  description: `Streamed ops per append chunk for --stream or .jsonl --file (default: ${DEFAULT_STREAM_APPEND_CHUNK_SIZE}, max: ${MAX_STREAM_APPEND_OPERATION_COUNT})`
55104
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
+ }),
55105
55778
  "allow-nul-bytes": flag.boolean({
55106
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."
55107
55780
  }),
@@ -55166,6 +55839,21 @@ var createFlags3 = {
55166
55839
  })
55167
55840
  };
55168
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
+
55169
55857
  // ../../packages/warmhub-cli/src/domains/commit-submit-template.ts
55170
55858
  import { writeFile } from "node:fs/promises";
55171
55859
  var WRITE_TEMPLATE_KINDS = ["thing", "assertion"];
@@ -56508,6 +57196,284 @@ var handleSubmit = async (ctx, { flags, args }) => {
56508
57196
  }
56509
57197
  };
56510
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
+
56511
57477
  // ../../packages/warmhub-cli/src/domains/commit-submit-domain.ts
56512
57478
  var COMMIT_DOMAIN = defineDomain({
56513
57479
  name: "commit",
@@ -56538,6 +57504,7 @@ var COMMIT_DOMAIN = defineDomain({
56538
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"`,
56539
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"`,
56540
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"',
56541
57508
  "wh shape template Session HypothesisCandidate -o ops.json",
56542
57509
  "wh commit submit --type arc --name route --members Location/a,Location/b",
56543
57510
  "wh commit submit --type bond --name peers --members Person/alice,Person/bob",
@@ -56546,9 +57513,10 @@ var COMMIT_DOMAIN = defineDomain({
56546
57513
  notes: [
56547
57514
  "`--dry-run` evaluates the complete bounded input with the real server commit evaluator and makes no durable repository change.",
56548
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`.",
56549
- "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."
56550
57518
  ],
56551
- handler: handleSubmit
57519
+ handler: handleSubmitWithServerStreaming
56552
57520
  }
56553
57521
  }
56554
57522
  });
@@ -56640,7 +57608,7 @@ for (const spec of PRE_TERMINATOR_CONTROLS) {
56640
57608
  if (spec.short)
56641
57609
  CONTROL_SHORTS.set(spec.short, { spec, constant: false });
56642
57610
  }
56643
- function userInput(message, hint) {
57611
+ function userInput2(message, hint) {
56644
57612
  return new CliError(2 /* UserInput */, "USER_INPUT", message, undefined, hint);
56645
57613
  }
56646
57614
  function hasAttachedValue(record2) {
@@ -56677,13 +57645,13 @@ function acceptedArgList(method) {
56677
57645
  function unknownArgumentError(method, record2) {
56678
57646
  const accepted = acceptedArgList(method);
56679
57647
  const suffix = record2.ownership === "post-terminator" ? ` (use \`--\` to pass globals as method args, e.g. \`-- --${record2.name} <value>\`)` : "";
56680
- 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}`);
56681
57649
  }
56682
57650
  function duplicateError(arg) {
56683
- 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.`);
56684
57652
  }
56685
57653
  function missingValueError(arg) {
56686
- 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}>`);
56687
57655
  }
56688
57656
  function coerceArg(arg, value) {
56689
57657
  switch (arg.type) {
@@ -56691,7 +57659,7 @@ function coerceArg(arg, value) {
56691
57659
  if (typeof value !== "string") {
56692
57660
  return {
56693
57661
  ok: false,
56694
- error: userInput(`--${arg.name} requires a string value`)
57662
+ error: userInput2(`--${arg.name} requires a string value`)
56695
57663
  };
56696
57664
  }
56697
57665
  if (arg.pattern) {
@@ -56701,13 +57669,13 @@ function coerceArg(arg, value) {
56701
57669
  } catch {
56702
57670
  return {
56703
57671
  ok: false,
56704
- error: userInput(`invalid regex pattern for --${arg.name}: /${arg.pattern}/`)
57672
+ error: userInput2(`invalid regex pattern for --${arg.name}: /${arg.pattern}/`)
56705
57673
  };
56706
57674
  }
56707
57675
  if (!pattern.test(value)) {
56708
57676
  return {
56709
57677
  ok: false,
56710
- 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}/`)
56711
57679
  };
56712
57680
  }
56713
57681
  }
@@ -56718,32 +57686,32 @@ function coerceArg(arg, value) {
56718
57686
  if (typeof value === "boolean") {
56719
57687
  return {
56720
57688
  ok: false,
56721
- error: userInput(`--${arg.name} requires a ${arg.type} value`)
57689
+ error: userInput2(`--${arg.name} requires a ${arg.type} value`)
56722
57690
  };
56723
57691
  }
56724
57692
  const numeric = typeof value === "number" ? Number.isFinite(value) ? value : undefined : typeof value === "string" ? parseCliNumber(value) : undefined;
56725
57693
  if (numeric === undefined) {
56726
57694
  return {
56727
57695
  ok: false,
56728
- 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}`)
56729
57697
  };
56730
57698
  }
56731
57699
  if (arg.type === "integer" && !Number.isInteger(numeric)) {
56732
57700
  return {
56733
57701
  ok: false,
56734
- error: userInput(`--${arg.name} value ${quoteUserValue(value)} is not an integer`)
57702
+ error: userInput2(`--${arg.name} value ${quoteUserValue(value)} is not an integer`)
56735
57703
  };
56736
57704
  }
56737
57705
  if (arg.min !== undefined && numeric < arg.min) {
56738
57706
  return {
56739
57707
  ok: false,
56740
- error: userInput(`--${arg.name} value ${numeric} is below min ${arg.min}`)
57708
+ error: userInput2(`--${arg.name} value ${numeric} is below min ${arg.min}`)
56741
57709
  };
56742
57710
  }
56743
57711
  if (arg.max !== undefined && numeric > arg.max) {
56744
57712
  return {
56745
57713
  ok: false,
56746
- error: userInput(`--${arg.name} value ${numeric} is above max ${arg.max}`)
57714
+ error: userInput2(`--${arg.name} value ${numeric} is above max ${arg.max}`)
56747
57715
  };
56748
57716
  }
56749
57717
  return { ok: true, value: numeric };
@@ -56757,7 +57725,7 @@ function coerceArg(arg, value) {
56757
57725
  return { ok: true, value: false };
56758
57726
  return {
56759
57727
  ok: false,
56760
- error: userInput(`--${arg.name} requires true|false`)
57728
+ error: userInput2(`--${arg.name} requires true|false`)
56761
57729
  };
56762
57730
  }
56763
57731
  }
@@ -56784,7 +57752,7 @@ function bindComponentMethodArgs(invocation, method) {
56784
57752
  continue;
56785
57753
  if (record2.kind === "malformed-short") {
56786
57754
  claimed.add(record2.index);
56787
- 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)}`));
56788
57756
  continue;
56789
57757
  }
56790
57758
  if (record2.kind !== "option")
@@ -56838,7 +57806,7 @@ function bindComponentMethodArgs(invocation, method) {
56838
57806
  }
56839
57807
  for (const record2 of invocation.records) {
56840
57808
  if (record2.kind === "positional" && !claimed.has(record2.index) && record2.source !== "--") {
56841
- 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"));
56842
57810
  }
56843
57811
  }
56844
57812
  for (const arg of method.args) {
@@ -56854,7 +57822,7 @@ function bindComponentMethodArgs(invocation, method) {
56854
57822
  continue;
56855
57823
  }
56856
57824
  if (arg.required && !invocation.help) {
56857
- addError(Number.POSITIVE_INFINITY, userInput(`Missing required argument: --${arg.name}`));
57825
+ addError(Number.POSITIVE_INFINITY, userInput2(`Missing required argument: --${arg.name}`));
56858
57826
  }
56859
57827
  }
56860
57828
  indexedErrors.sort((left, right) => left.index - right.index || left.order - right.order);
@@ -60550,7 +61518,7 @@ var PRIME_DOMAIN = defineDomain({
60550
61518
  });
60551
61519
 
60552
61520
  // ../../packages/warmhub-cli/src/domains/repo/checkpoint.ts
60553
- import { createReadStream as createReadStream5 } from "node:fs";
61521
+ import { createReadStream as createReadStream6 } from "node:fs";
60554
61522
  import { lstat as lstat3 } from "node:fs/promises";
60555
61523
 
60556
61524
  // ../../packages/sdk-ts/src/repository-checkpoint/types.ts
@@ -60925,7 +61893,7 @@ import { createHash as createHash3 } from "node:crypto";
60925
61893
 
60926
61894
  // ../../packages/sdk-ts/src/repository-checkpoint/identity-sort.ts
60927
61895
  import { once } from "node:events";
60928
- import { createReadStream as createReadStream4, createWriteStream } from "node:fs";
61896
+ import { createReadStream as createReadStream5, createWriteStream } from "node:fs";
60929
61897
  import { open as open3, rm } from "node:fs/promises";
60930
61898
  import { join as join10 } from "node:path";
60931
61899
  var CHECKPOINT_IDENTITY_SORT_BUDGET_BYTES = 4 * 1024 * 1024;
@@ -61199,7 +62167,7 @@ class RunCursor {
61199
62167
  #offset = 0;
61200
62168
  current;
61201
62169
  constructor(path2) {
61202
- this.#stream = createReadStream4(path2, {
62170
+ this.#stream = createReadStream5(path2, {
61203
62171
  highWaterMark: RUN_READ_BUFFER_BYTES
61204
62172
  });
61205
62173
  this.#iterator = this.#stream[Symbol.asyncIterator]();
@@ -61591,8 +62559,8 @@ async function writeAll(handle, bytes) {
61591
62559
  offset += bytesWritten;
61592
62560
  }
61593
62561
  }
61594
- function assertArtifactIntegrity(byteLength, sha256, descriptor) {
61595
- if (byteLength !== descriptor.byteLength || sha256 !== descriptor.sha256) {
62562
+ function assertArtifactIntegrity(byteLength, sha2562, descriptor) {
62563
+ if (byteLength !== descriptor.byteLength || sha2562 !== descriptor.sha256) {
61596
62564
  throw new CliError(4 /* Backend */, "BACKEND", "Downloaded checkpoint artifact did not match its access descriptor.");
61597
62565
  }
61598
62566
  }
@@ -61847,7 +62815,7 @@ var handleVerify = async (ctx, { args }) => {
61847
62815
  }
61848
62816
  try {
61849
62817
  await lstat3(archive);
61850
- const result = await verifyRepositoryCheckpointArchive(createReadStream5(archive));
62818
+ const result = await verifyRepositoryCheckpointArchive(createReadStream6(archive));
61851
62819
  writeOutput(ctx, result, () => {
61852
62820
  ctx.out(`Checkpoint: ${result.checkpointId}`);
61853
62821
  ctx.out(`Repository sequence: ${result.repoSeq}`);
@@ -66795,7 +67763,7 @@ function resolveLogLevel(flagLevel, env) {
66795
67763
  // package.json
66796
67764
  var package_default3 = {
66797
67765
  name: "@warmhub/cli",
66798
- version: "0.96.0",
67766
+ version: "0.98.0",
66799
67767
  private: false,
66800
67768
  type: "module",
66801
67769
  description: "The wh CLI for WarmHub — create repos, commit and query data, and compound knowledge with your AI agents.",
@@ -66817,6 +67785,11 @@ var package_default3 = {
66817
67785
  url: "https://warmhub.ai"
66818
67786
  },
66819
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
+ },
66820
67793
  bugs: {
66821
67794
  email: "support@warmhub.ai"
66822
67795
  },
@@ -66832,7 +67805,8 @@ var package_default3 = {
66832
67805
  ],
66833
67806
  publishConfig: {
66834
67807
  registry: "https://registry.npmjs.org",
66835
- access: "public"
67808
+ access: "public",
67809
+ tag: "latest"
66836
67810
  },
66837
67811
  scripts: {
66838
67812
  build: "bun run scripts/build.ts",
@@ -67414,5 +68388,5 @@ process.exitCode = interceptedExitCode === undefined ? await runPreparedCli(laun
67414
68388
  version: package_default3.version
67415
68389
  }) : interceptedExitCode;
67416
68390
 
67417
- //# debugId=575D3DBDBC81FCF364756E2164756E21
67418
- //# warmhub-cli-build-info {"cliVersion":"0.96.0","sdkVersion":"0.94.0"}
68391
+ //# debugId=8AF6B7466C2C7E3364756E2164756E21
68392
+ //# warmhub-cli-build-info {"cliVersion":"0.98.0","sdkVersion":"0.96.0"}