@warmhub/cli 0.91.0 → 0.92.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 +343 -305
  2. package/package.json +1 -1
package/dist/wh.js CHANGED
@@ -42746,6 +42746,197 @@ function shapeDefinitionPreflightError(name, data, verb) {
42746
42746
  return `Invalid shape definition for "${name}": ${result.errors.join("; ")}`;
42747
42747
  }
42748
42748
 
42749
+ // ../../packages/sdk-ts/src/stream-submit-utils.ts
42750
+ function streamAppendResultStatus(result) {
42751
+ const status = "status" in result ? result.status : undefined;
42752
+ if (status === "failed") {
42753
+ return "error";
42754
+ }
42755
+ return status === "noop" || result.operation === "noop" ? "noop" : "applied";
42756
+ }
42757
+ var DEFAULT_RETRY_POLICY = {
42758
+ maxAttempts: 3,
42759
+ baseDelayMs: 250,
42760
+ maxDelayMs: 8000
42761
+ };
42762
+ var MAX_ATTEMPTS_HARD_CAP = 10;
42763
+ var MAX_DELAY_HARD_CAP_MS = 60000;
42764
+ function resolveRetryPolicy(retry) {
42765
+ if (retry === false)
42766
+ return false;
42767
+ const overrides = {};
42768
+ if (retry !== undefined) {
42769
+ if (Number.isFinite(retry.maxAttempts))
42770
+ overrides.maxAttempts = retry.maxAttempts;
42771
+ if (Number.isFinite(retry.baseDelayMs))
42772
+ overrides.baseDelayMs = retry.baseDelayMs;
42773
+ if (Number.isFinite(retry.maxDelayMs))
42774
+ overrides.maxDelayMs = retry.maxDelayMs;
42775
+ }
42776
+ const merged = { ...DEFAULT_RETRY_POLICY, ...overrides };
42777
+ return {
42778
+ maxAttempts: Math.min(MAX_ATTEMPTS_HARD_CAP, Math.max(1, Math.trunc(merged.maxAttempts))),
42779
+ baseDelayMs: Math.min(MAX_DELAY_HARD_CAP_MS, Math.max(0, Math.trunc(merged.baseDelayMs))),
42780
+ maxDelayMs: Math.min(MAX_DELAY_HARD_CAP_MS, Math.max(0, Math.trunc(merged.maxDelayMs)))
42781
+ };
42782
+ }
42783
+ var DEFINITE_CLIENT_REJECT_CODES = new Set([
42784
+ "BAD_REQUEST",
42785
+ "METHOD_NOT_SUPPORTED",
42786
+ "PARSE_ERROR",
42787
+ "PAYLOAD_TOO_LARGE",
42788
+ "PRECONDITION_FAILED",
42789
+ "UNAUTHORIZED",
42790
+ "UNPROCESSABLE_CONTENT",
42791
+ "UNSUPPORTED_MEDIA_TYPE",
42792
+ "UNAUTHENTICATED",
42793
+ "FORBIDDEN",
42794
+ "VALIDATION_ERROR",
42795
+ "SHAPE_MISMATCH",
42796
+ "RESERVED_NAME",
42797
+ "ILLEGAL_OP_SEQUENCE",
42798
+ "NOT_FOUND",
42799
+ "KIND_MISMATCH",
42800
+ "CONFLICT",
42801
+ "ALREADY_RETRACTED",
42802
+ "ARCHIVED",
42803
+ "RATE_LIMITED",
42804
+ "TOO_MANY_REQUESTS",
42805
+ "UNRESOLVED_TOKEN"
42806
+ ]);
42807
+ var TERMINAL_AMBIGUOUS_CODES = new Set(["COMMIT_OUTCOME_UNKNOWN"]);
42808
+ function extractErrorCode(cause) {
42809
+ if (!cause || typeof cause !== "object")
42810
+ return;
42811
+ const direct = cause.code;
42812
+ if (typeof direct === "string")
42813
+ return direct;
42814
+ const data = cause.data;
42815
+ const wh = data?.warmhub?.code;
42816
+ if (typeof wh === "string")
42817
+ return wh;
42818
+ const dc = data?.code;
42819
+ if (typeof dc === "string")
42820
+ return dc;
42821
+ return;
42822
+ }
42823
+ function extractHttpStatus(cause) {
42824
+ if (!cause || typeof cause !== "object")
42825
+ return;
42826
+ const status = cause.data?.httpStatus;
42827
+ if (typeof status === "number")
42828
+ return status;
42829
+ const warmhubStatus = cause.data?.warmhub?.status;
42830
+ if (typeof warmhubStatus === "number")
42831
+ return warmhubStatus;
42832
+ const direct = cause.status;
42833
+ return typeof direct === "number" ? direct : undefined;
42834
+ }
42835
+ function isDefiniteClientRejectionStatus(status) {
42836
+ return status !== undefined && status >= 400 && status < 500 && status !== 408;
42837
+ }
42838
+ function isTerminalAmbiguousError(cause) {
42839
+ const code = extractErrorCode(cause);
42840
+ return code !== undefined && TERMINAL_AMBIGUOUS_CODES.has(code);
42841
+ }
42842
+ function isDefiniteStreamAppendRejection(cause) {
42843
+ if (isTerminalAmbiguousError(cause))
42844
+ return false;
42845
+ const code = extractErrorCode(cause);
42846
+ return code !== undefined && DEFINITE_CLIENT_REJECT_CODES.has(code) || isDefiniteClientRejectionStatus(extractHttpStatus(cause));
42847
+ }
42848
+ function isTransientStreamFailure(cause) {
42849
+ if (isTerminalAmbiguousError(cause))
42850
+ return false;
42851
+ if (isDefiniteStreamAppendRejection(cause))
42852
+ return false;
42853
+ if (isFetchNetworkTypeError(cause))
42854
+ return true;
42855
+ if (cause instanceof TypeError)
42856
+ return false;
42857
+ if (cause instanceof SyntaxError)
42858
+ return false;
42859
+ const inner = cause?.cause;
42860
+ if (isFetchNetworkTypeError(inner))
42861
+ return true;
42862
+ if (inner instanceof TypeError)
42863
+ return false;
42864
+ if (inner instanceof SyntaxError)
42865
+ return false;
42866
+ return true;
42867
+ }
42868
+ function isFetchNetworkTypeError(cause) {
42869
+ return cause instanceof TypeError && /fetch/i.test(cause.message);
42870
+ }
42871
+ function computeBackoffDelayMs(attempt, policy) {
42872
+ const exponential = policy.baseDelayMs * 2 ** Math.max(0, attempt - 1);
42873
+ const jitter = Math.random() * policy.baseDelayMs;
42874
+ return Math.min(policy.maxDelayMs, exponential + jitter);
42875
+ }
42876
+ function sleep2(ms) {
42877
+ return new Promise((resolve) => setTimeout(resolve, ms));
42878
+ }
42879
+
42880
+ // ../../packages/sdk-ts/src/stream-submit-aggregate.ts
42881
+ function toSubmittedOperation(result, opIndex, status, submittedName) {
42882
+ const row = {
42883
+ opIndex,
42884
+ name: result.name ?? "",
42885
+ operation: result.operation === "revise" || result.operation === "retract" || result.operation === "reaffirm" || result.operation === "rename" || result.operation === "noop" ? result.operation : "add",
42886
+ dataHash: result.dataHash ?? "",
42887
+ version: result.version ?? 0,
42888
+ status,
42889
+ error: result.error
42890
+ };
42891
+ if (result.affirmations)
42892
+ row.affirmations = result.affirmations;
42893
+ if (result.status === "failed" && submittedName !== undefined) {
42894
+ row.submittedName = submittedName;
42895
+ }
42896
+ if (result.resolvedName !== undefined)
42897
+ row.resolvedName = result.resolvedName;
42898
+ if (result.retryable !== undefined)
42899
+ row.retryable = result.retryable;
42900
+ if (result.warnings)
42901
+ row.warnings = result.warnings;
42902
+ return row;
42903
+ }
42904
+
42905
+ class StreamSubmissionAggregator {
42906
+ receipts = [];
42907
+ operations = [];
42908
+ statusCounts = { applied: 0, noop: 0, error: 0 };
42909
+ get allFailed() {
42910
+ return this.operations.length > 0 && this.statusCounts.error === this.operations.length;
42911
+ }
42912
+ addChunk(input) {
42913
+ input.results.forEach((result, position) => {
42914
+ const local = result.opIndex ?? position;
42915
+ const status = streamAppendResultStatus(result);
42916
+ this.statusCounts[status]++;
42917
+ this.operations.push(toSubmittedOperation(result, input.chunkStart + local, status, input.submittedNames?.[local]?.name));
42918
+ });
42919
+ }
42920
+ addReceipt(receipt) {
42921
+ this.receipts.push(receipt);
42922
+ }
42923
+ completedOperations() {
42924
+ return this.operations.filter((operation) => operation.status !== "error");
42925
+ }
42926
+ toResult(meta3) {
42927
+ const partial2 = this.statusCounts.error > 0;
42928
+ return {
42929
+ ...meta3.committer !== undefined ? { committer: meta3.committer } : {},
42930
+ ...meta3.createdByEmail !== undefined ? { createdByEmail: meta3.createdByEmail } : {},
42931
+ message: meta3.message,
42932
+ operationCount: this.operations.length,
42933
+ ...meta3.repoSeq !== undefined ? { repoSeq: meta3.repoSeq } : {},
42934
+ ...partial2 ? { partial: partial2, statusCounts: { ...this.statusCounts } } : {},
42935
+ operations: this.operations,
42936
+ receipts: this.receipts
42937
+ };
42938
+ }
42939
+ }
42749
42940
  // ../../packages/sdk-ts/src/operation-event-identity.ts
42750
42941
  var STREAM_CHUNK_NAMESPACE = "003e7e6c-2f1e-53ea-9dfa-627edd04a8cc";
42751
42942
  var CANONICAL_UUID = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
@@ -43114,148 +43305,6 @@ class AllStreamOperationsFailedError extends Error {
43114
43305
  }
43115
43306
  }
43116
43307
 
43117
- // ../../packages/sdk-ts/src/stream-submit-utils.ts
43118
- function streamAppendResultStatus(result) {
43119
- const status = "status" in result ? result.status : undefined;
43120
- if (status === "failed") {
43121
- return "error";
43122
- }
43123
- return status === "noop" || result.operation === "noop" ? "noop" : "applied";
43124
- }
43125
- function countStreamAppendResultStatuses(results) {
43126
- const statusCounts = {
43127
- applied: 0,
43128
- noop: 0,
43129
- error: 0
43130
- };
43131
- for (const result of results) {
43132
- statusCounts[streamAppendResultStatus(result)]++;
43133
- }
43134
- return statusCounts;
43135
- }
43136
- var DEFAULT_RETRY_POLICY = {
43137
- maxAttempts: 3,
43138
- baseDelayMs: 250,
43139
- maxDelayMs: 8000
43140
- };
43141
- var MAX_ATTEMPTS_HARD_CAP = 10;
43142
- var MAX_DELAY_HARD_CAP_MS = 60000;
43143
- function resolveRetryPolicy(retry) {
43144
- if (retry === false)
43145
- return false;
43146
- const overrides = {};
43147
- if (retry !== undefined) {
43148
- if (Number.isFinite(retry.maxAttempts))
43149
- overrides.maxAttempts = retry.maxAttempts;
43150
- if (Number.isFinite(retry.baseDelayMs))
43151
- overrides.baseDelayMs = retry.baseDelayMs;
43152
- if (Number.isFinite(retry.maxDelayMs))
43153
- overrides.maxDelayMs = retry.maxDelayMs;
43154
- }
43155
- const merged = { ...DEFAULT_RETRY_POLICY, ...overrides };
43156
- return {
43157
- maxAttempts: Math.min(MAX_ATTEMPTS_HARD_CAP, Math.max(1, Math.trunc(merged.maxAttempts))),
43158
- baseDelayMs: Math.min(MAX_DELAY_HARD_CAP_MS, Math.max(0, Math.trunc(merged.baseDelayMs))),
43159
- maxDelayMs: Math.min(MAX_DELAY_HARD_CAP_MS, Math.max(0, Math.trunc(merged.maxDelayMs)))
43160
- };
43161
- }
43162
- var DEFINITE_CLIENT_REJECT_CODES = new Set([
43163
- "BAD_REQUEST",
43164
- "METHOD_NOT_SUPPORTED",
43165
- "PARSE_ERROR",
43166
- "PAYLOAD_TOO_LARGE",
43167
- "PRECONDITION_FAILED",
43168
- "UNAUTHORIZED",
43169
- "UNPROCESSABLE_CONTENT",
43170
- "UNSUPPORTED_MEDIA_TYPE",
43171
- "UNAUTHENTICATED",
43172
- "FORBIDDEN",
43173
- "VALIDATION_ERROR",
43174
- "SHAPE_MISMATCH",
43175
- "RESERVED_NAME",
43176
- "ILLEGAL_OP_SEQUENCE",
43177
- "NOT_FOUND",
43178
- "KIND_MISMATCH",
43179
- "CONFLICT",
43180
- "ALREADY_RETRACTED",
43181
- "ARCHIVED",
43182
- "RATE_LIMITED",
43183
- "TOO_MANY_REQUESTS",
43184
- "UNRESOLVED_TOKEN"
43185
- ]);
43186
- var TERMINAL_AMBIGUOUS_CODES = new Set(["COMMIT_OUTCOME_UNKNOWN"]);
43187
- function extractErrorCode(cause) {
43188
- if (!cause || typeof cause !== "object")
43189
- return;
43190
- const direct = cause.code;
43191
- if (typeof direct === "string")
43192
- return direct;
43193
- const data = cause.data;
43194
- const wh = data?.warmhub?.code;
43195
- if (typeof wh === "string")
43196
- return wh;
43197
- const dc = data?.code;
43198
- if (typeof dc === "string")
43199
- return dc;
43200
- return;
43201
- }
43202
- function extractHttpStatus(cause) {
43203
- if (!cause || typeof cause !== "object")
43204
- return;
43205
- const status = cause.data?.httpStatus;
43206
- if (typeof status === "number")
43207
- return status;
43208
- const warmhubStatus = cause.data?.warmhub?.status;
43209
- if (typeof warmhubStatus === "number")
43210
- return warmhubStatus;
43211
- const direct = cause.status;
43212
- return typeof direct === "number" ? direct : undefined;
43213
- }
43214
- function isDefiniteClientRejectionStatus(status) {
43215
- return status !== undefined && status >= 400 && status < 500 && status !== 408;
43216
- }
43217
- function isTerminalAmbiguousError(cause) {
43218
- const code = extractErrorCode(cause);
43219
- return code !== undefined && TERMINAL_AMBIGUOUS_CODES.has(code);
43220
- }
43221
- function isDefiniteStreamAppendRejection(cause) {
43222
- if (isTerminalAmbiguousError(cause))
43223
- return false;
43224
- const code = extractErrorCode(cause);
43225
- return code !== undefined && DEFINITE_CLIENT_REJECT_CODES.has(code) || isDefiniteClientRejectionStatus(extractHttpStatus(cause));
43226
- }
43227
- function isTransientStreamFailure(cause) {
43228
- if (isTerminalAmbiguousError(cause))
43229
- return false;
43230
- if (isDefiniteStreamAppendRejection(cause))
43231
- return false;
43232
- if (isFetchNetworkTypeError(cause))
43233
- return true;
43234
- if (cause instanceof TypeError)
43235
- return false;
43236
- if (cause instanceof SyntaxError)
43237
- return false;
43238
- const inner = cause?.cause;
43239
- if (isFetchNetworkTypeError(inner))
43240
- return true;
43241
- if (inner instanceof TypeError)
43242
- return false;
43243
- if (inner instanceof SyntaxError)
43244
- return false;
43245
- return true;
43246
- }
43247
- function isFetchNetworkTypeError(cause) {
43248
- return cause instanceof TypeError && /fetch/i.test(cause.message);
43249
- }
43250
- function computeBackoffDelayMs(attempt, policy) {
43251
- const exponential = policy.baseDelayMs * 2 ** Math.max(0, attempt - 1);
43252
- const jitter = Math.random() * policy.baseDelayMs;
43253
- return Math.min(policy.maxDelayMs, exponential + jitter);
43254
- }
43255
- function sleep2(ms) {
43256
- return new Promise((resolve) => setTimeout(resolve, ms));
43257
- }
43258
-
43259
43308
  // ../../packages/sdk-ts/src/stream-submit-submit.ts
43260
43309
  class StreamValidationError extends Error {
43261
43310
  code;
@@ -43266,115 +43315,156 @@ class StreamValidationError extends Error {
43266
43315
  this.name = "WarmHubError";
43267
43316
  }
43268
43317
  }
43269
- async function submitOperationsViaStream(client, args) {
43270
- if (args.operations.length === 0) {
43271
- throw new StreamValidationError("At least one operation is required for stream submission.");
43318
+
43319
+ class OperationSourceError extends Error {
43320
+ reason;
43321
+ constructor(reason) {
43322
+ super("operation source failed");
43323
+ this.reason = reason;
43272
43324
  }
43273
- const operations = args.operations.map((operation, index) => {
43274
- let streamOperation;
43275
- try {
43276
- streamOperation = toBackendStreamOperation(operation);
43277
- } catch (cause) {
43278
- const message = cause instanceof Error ? cause.message : String(cause);
43279
- throw new StreamValidationError(`Invalid operation at index ${index}: ${message}`);
43280
- }
43281
- if (args.skipExisting === true && streamOperation.operation === "add") {
43282
- return { ...streamOperation, skipExisting: true };
43283
- }
43284
- return streamOperation;
43285
- });
43286
- validateNormalizedOperations(operations);
43325
+ }
43326
+ async function submitOperationsViaStream(client, args) {
43287
43327
  const chunkSize = normalizeChunkSize(args.chunkSize);
43288
43328
  const submissionId = args.submissionId ?? createOperationEventSubmissionId();
43289
43329
  const streamId = args.streamId ?? submissionId;
43290
43330
  const policy = resolveRetryPolicy(args.retry);
43331
+ const aggregate = new StreamSubmissionAggregator;
43291
43332
  let allocatedTokenRanges = [];
43292
43333
  let createdByEmail;
43293
43334
  let repoSeq;
43294
- const chunkResults = [];
43295
- const receipts = [];
43296
43335
  let acknowledgedOperationCount = 0;
43297
43336
  let lastAcknowledgedRepoSeq;
43298
- for (const [chunkOrdinal, chunk] of chunkOperations(operations, chunkSize).entries()) {
43299
- const eventRequestId = operationEventStreamRequestId(submissionId, chunkOrdinal);
43300
- let attempt = 1;
43301
- let priorAttemptAmbiguous = false;
43302
- while (true) {
43303
- try {
43304
- const appendResult = await client.stream.append({
43305
- allocatedTokenRanges,
43306
- chunkOrdinal,
43307
- orgName: args.orgName,
43308
- repoName: args.repoName,
43309
- streamId,
43310
- submissionId,
43311
- componentRef: args.componentRef,
43312
- committer: args.committer,
43313
- message: args.message,
43314
- ...args.returnRepoSeq !== undefined ? { returnRepoSeq: args.returnRepoSeq } : {},
43315
- operations: chunk.operations
43316
- });
43317
- const receipt = appendResult.receipt;
43318
- receipts.push(receipt);
43319
- allocatedTokenRanges = appendResult.allocatedTokenRanges;
43320
- createdByEmail = appendResult.createdByEmail ?? createdByEmail;
43321
- repoSeq = appendResult.repoSeq ?? repoSeq;
43322
- chunkResults.push(...offsetChunkResultIndexes(appendResult.results, chunk.start));
43323
- acknowledgedOperationCount += chunk.operations.length;
43324
- const acknowledgedRepoSeq = receiptRepoSeq(receipt);
43325
- if (acknowledgedRepoSeq !== undefined) {
43326
- lastAcknowledgedRepoSeq = acknowledgedRepoSeq;
43327
- }
43328
- break;
43329
- } catch (cause) {
43330
- const definiteFailure = isDefiniteStreamAppendRejection(cause);
43331
- if (receipts.length === 0 && !priorAttemptAmbiguous && definiteFailure) {
43332
- throw cause;
43333
- }
43334
- if (policy !== false && attempt < policy.maxAttempts && isTransientStreamFailure(cause)) {
43335
- await sleep2(computeBackoffDelayMs(attempt, policy));
43336
- attempt += 1;
43337
- priorAttemptAmbiguous = true;
43338
- continue;
43339
- }
43340
- const pendingOutcome = priorAttemptAmbiguous || !definiteFailure ? "unknown" : "absent";
43341
- throw new PartialStreamSubmissionError({
43342
- cause,
43343
- completedReceipts: receipts,
43344
- completedOperations: completedOperationsFrom(aggregateSubmittedStreamResult({
43337
+ let chunkOrdinal = 0;
43338
+ const partialSubmission = (input) => new PartialStreamSubmissionError({
43339
+ cause: input.cause,
43340
+ completedReceipts: aggregate.receipts,
43341
+ completedOperations: aggregate.completedOperations(),
43342
+ acknowledgedOperationCount,
43343
+ lastAcknowledgedRepoSeq,
43344
+ attemptedAppendOutcome: input.pendingOutcome === "absent" ? "not_applied" : "unknown",
43345
+ submissionId,
43346
+ eventRequestId: operationEventStreamRequestId(submissionId, chunkOrdinal),
43347
+ chunkOrdinal,
43348
+ pendingOutcome: input.pendingOutcome
43349
+ });
43350
+ try {
43351
+ for await (const chunk of normalizedChunks(args.operations, chunkSize, args.skipExisting === true)) {
43352
+ let attempt = 1;
43353
+ let priorAttemptAmbiguous = false;
43354
+ while (true) {
43355
+ try {
43356
+ const appendResult = await client.stream.append({
43357
+ allocatedTokenRanges,
43358
+ chunkOrdinal,
43359
+ orgName: args.orgName,
43360
+ repoName: args.repoName,
43361
+ streamId,
43362
+ submissionId,
43363
+ componentRef: args.componentRef,
43345
43364
  committer: args.committer,
43346
- createdByEmail,
43347
43365
  message: args.message,
43348
- operations,
43349
- repoSeq,
43350
- receipts,
43351
- results: chunkResults
43352
- })),
43353
- acknowledgedOperationCount,
43354
- lastAcknowledgedRepoSeq,
43355
- attemptedAppendOutcome: pendingOutcome === "absent" ? "not_applied" : "unknown",
43356
- submissionId,
43357
- eventRequestId,
43358
- chunkOrdinal,
43359
- pendingOutcome
43360
- });
43366
+ ...args.returnRepoSeq !== undefined ? { returnRepoSeq: args.returnRepoSeq } : {},
43367
+ operations: chunk.operations
43368
+ });
43369
+ aggregate.addReceipt(appendResult.receipt);
43370
+ allocatedTokenRanges = appendResult.allocatedTokenRanges;
43371
+ createdByEmail = appendResult.createdByEmail ?? createdByEmail;
43372
+ repoSeq = appendResult.repoSeq ?? repoSeq;
43373
+ aggregate.addChunk({
43374
+ results: appendResult.results,
43375
+ chunkStart: chunk.start,
43376
+ submittedNames: chunk.operations
43377
+ });
43378
+ acknowledgedOperationCount += chunk.operations.length;
43379
+ const acknowledgedRepoSeq = receiptRepoSeq(appendResult.receipt);
43380
+ if (acknowledgedRepoSeq !== undefined) {
43381
+ lastAcknowledgedRepoSeq = acknowledgedRepoSeq;
43382
+ }
43383
+ break;
43384
+ } catch (cause) {
43385
+ const definiteFailure = isDefiniteStreamAppendRejection(cause);
43386
+ if (aggregate.receipts.length === 0 && !priorAttemptAmbiguous && definiteFailure) {
43387
+ throw cause;
43388
+ }
43389
+ if (policy !== false && attempt < policy.maxAttempts && isTransientStreamFailure(cause)) {
43390
+ await sleep2(computeBackoffDelayMs(attempt, policy));
43391
+ attempt += 1;
43392
+ priorAttemptAmbiguous = true;
43393
+ continue;
43394
+ }
43395
+ throw partialSubmission({
43396
+ cause,
43397
+ pendingOutcome: priorAttemptAmbiguous || !definiteFailure ? "unknown" : "absent"
43398
+ });
43399
+ }
43361
43400
  }
43401
+ chunkOrdinal += 1;
43362
43402
  }
43403
+ } catch (error51) {
43404
+ if (!(error51 instanceof OperationSourceError))
43405
+ throw error51;
43406
+ if (aggregate.receipts.length === 0)
43407
+ throw error51.reason;
43408
+ throw partialSubmission({ cause: error51.reason, pendingOutcome: "absent" });
43409
+ }
43410
+ if (chunkOrdinal === 0) {
43411
+ throw new StreamValidationError("At least one operation is required for stream submission.");
43363
43412
  }
43364
- const result = aggregateSubmittedStreamResult({
43413
+ const result = aggregate.toResult({
43365
43414
  committer: args.committer,
43366
43415
  createdByEmail,
43367
43416
  message: args.message,
43368
- operations,
43369
- repoSeq,
43370
- receipts,
43371
- results: chunkResults
43417
+ repoSeq
43372
43418
  });
43373
- if (result.operations.length > 0 && result.operations.every((operation) => operation.status === "error")) {
43419
+ if (aggregate.allFailed) {
43374
43420
  throw new AllStreamOperationsFailedError(result);
43375
43421
  }
43376
43422
  return result;
43377
43423
  }
43424
+ async function* normalizedChunks(source, chunkSize, skipExisting) {
43425
+ try {
43426
+ if (Array.isArray(source)) {
43427
+ const operations = source.map((operation, index) => normalizeOperation(operation, index, skipExisting));
43428
+ validateNormalizedOperations(operations, 0);
43429
+ for (let start = 0;start < operations.length; start += chunkSize) {
43430
+ yield { operations: operations.slice(start, start + chunkSize), start };
43431
+ }
43432
+ return;
43433
+ }
43434
+ let normalizedCount = 0;
43435
+ let buffer = [];
43436
+ for await (const operation of source) {
43437
+ buffer.push(normalizeOperation(operation, normalizedCount, skipExisting));
43438
+ normalizedCount += 1;
43439
+ if (buffer.length < chunkSize)
43440
+ continue;
43441
+ yield preflightedChunk(buffer, normalizedCount);
43442
+ buffer = [];
43443
+ }
43444
+ if (buffer.length > 0)
43445
+ yield preflightedChunk(buffer, normalizedCount);
43446
+ } catch (cause) {
43447
+ throw new OperationSourceError(cause);
43448
+ }
43449
+ }
43450
+ function preflightedChunk(operations, normalizedCount) {
43451
+ const start = normalizedCount - operations.length;
43452
+ validateNormalizedOperations(operations, start);
43453
+ return { operations, start };
43454
+ }
43455
+ function normalizeOperation(operation, index, skipExisting) {
43456
+ let streamOperation;
43457
+ try {
43458
+ streamOperation = toBackendStreamOperation(operation);
43459
+ } catch (cause) {
43460
+ const message = cause instanceof Error ? cause.message : String(cause);
43461
+ throw new StreamValidationError(`Invalid operation at index ${index}: ${message}`);
43462
+ }
43463
+ if (skipExisting && streamOperation.operation === "add") {
43464
+ return { ...streamOperation, skipExisting: true };
43465
+ }
43466
+ return streamOperation;
43467
+ }
43378
43468
  function receiptRepoSeq(receipt) {
43379
43469
  const repoSeq = receipt.event?.repoSeq;
43380
43470
  if (repoSeq === undefined)
@@ -43382,12 +43472,11 @@ function receiptRepoSeq(receipt) {
43382
43472
  const parsed = Number(repoSeq);
43383
43473
  return Number.isSafeInteger(parsed) ? parsed : undefined;
43384
43474
  }
43385
- function validateNormalizedOperations(operations) {
43386
- const diagnostics = preflightCommitDiagnostics2(operations).filter((diagnostic) => !isServerAuthoritativeSequenceDiagnostic(diagnostic));
43387
- const firstDiagnostic = diagnostics[0];
43475
+ function validateNormalizedOperations(operations, indexOffset) {
43476
+ const firstDiagnostic = preflightCommitDiagnostics2(operations).find((diagnostic) => !isServerAuthoritativeSequenceDiagnostic(diagnostic));
43388
43477
  if (!firstDiagnostic)
43389
43478
  return;
43390
- throw new StreamValidationError(`Invalid operation at index ${firstDiagnostic.operationIndex}: ${firstDiagnostic.message}`, firstDiagnostic.code);
43479
+ throw new StreamValidationError(`Invalid operation at index ${indexOffset + firstDiagnostic.operationIndex}: ${firstDiagnostic.message}`, firstDiagnostic.code);
43391
43480
  }
43392
43481
  function isServerAuthoritativeSequenceDiagnostic(diagnostic) {
43393
43482
  return diagnostic.code === "ILLEGAL_OP_SEQUENCE" && diagnostic.message.includes("Cannot revise then add ");
@@ -43397,56 +43486,10 @@ function normalizeChunkSize(chunkSize) {
43397
43486
  return DEFAULT_STREAM_CHUNK_SIZE;
43398
43487
  return Math.max(1, Math.min(MAX_STREAM_APPEND_OPERATION_COUNT2, Math.trunc(chunkSize)));
43399
43488
  }
43400
- function chunkOperations(operations, chunkSize) {
43401
- const chunks = [];
43402
- for (let start = 0;start < operations.length; start += chunkSize) {
43403
- chunks.push({
43404
- operations: operations.slice(start, start + chunkSize),
43405
- start
43406
- });
43407
- }
43408
- return chunks;
43409
- }
43410
- function offsetChunkResultIndexes(results, chunkStart) {
43411
- return results.map((result, index) => ({
43412
- ...result,
43413
- opIndex: chunkStart + (result.opIndex ?? index)
43414
- }));
43415
- }
43416
- function aggregateSubmittedStreamResult(input) {
43417
- const statusCounts = countStreamAppendResultStatuses(input.results);
43418
- const partial2 = statusCounts.error > 0;
43419
- return {
43420
- ...input.committer !== undefined ? { committer: input.committer } : {},
43421
- ...input.createdByEmail !== undefined ? { createdByEmail: input.createdByEmail } : {},
43422
- message: input.message,
43423
- operationCount: input.results.length,
43424
- ...input.repoSeq !== undefined ? { repoSeq: input.repoSeq } : {},
43425
- ...partial2 ? { partial: partial2, statusCounts } : {},
43426
- operations: input.results.map((result) => ({
43427
- ...result.opIndex !== undefined ? { opIndex: result.opIndex } : {},
43428
- name: result.name ?? "",
43429
- operation: result.operation === "revise" || result.operation === "retract" || result.operation === "reaffirm" || result.operation === "rename" || result.operation === "noop" ? result.operation : "add",
43430
- dataHash: result.dataHash ?? "",
43431
- version: result.version ?? 0,
43432
- status: streamAppendResultStatus(result),
43433
- error: result.error,
43434
- ...result.affirmations ? { affirmations: result.affirmations } : {},
43435
- ...result.status === "failed" && result.opIndex !== undefined && input.operations[result.opIndex]?.name !== undefined ? { submittedName: input.operations[result.opIndex]?.name } : {},
43436
- ...result.resolvedName !== undefined ? { resolvedName: result.resolvedName } : {},
43437
- ...result.retryable !== undefined ? { retryable: result.retryable } : {},
43438
- ...result.warnings ? { warnings: result.warnings } : {}
43439
- })),
43440
- receipts: input.receipts
43441
- };
43442
- }
43443
- function completedOperationsFrom(result) {
43444
- return result.operations.filter((operation) => operation.status !== "error");
43445
- }
43446
43489
  // ../../packages/sdk-ts/package.json
43447
43490
  var package_default = {
43448
43491
  name: "@warmhub/sdk-ts",
43449
- version: "0.89.0",
43492
+ version: "0.90.0",
43450
43493
  private: false,
43451
43494
  type: "module",
43452
43495
  description: "The TypeScript SDK for WarmHub — create repos, commit and query data, and compound knowledge with your AI agents.",
@@ -55620,22 +55663,11 @@ async function applyJsonlCommit(ctx, args) {
55620
55663
  const tAppendStart = performance.now();
55621
55664
  progress.start(t0);
55622
55665
  let opCount = 0;
55623
- const receipts = [];
55624
- const chunkResults = [];
55625
- const submittedNames = [];
55666
+ const aggregate = new StreamSubmissionAggregator;
55626
55667
  let chunkCount = 0;
55627
55668
  let lastAcknowledgedRepoSeq;
55628
55669
  let repoSeq;
55629
55670
  let createdByEmail;
55630
- const aggregateSoFar = () => aggregateSubmittedStreamResult({
55631
- ...args.committer !== undefined ? { committer: args.committer } : {},
55632
- ...createdByEmail !== undefined ? { createdByEmail } : {},
55633
- message: args.message,
55634
- operations: submittedNames,
55635
- ...repoSeq !== undefined ? { repoSeq } : {},
55636
- receipts,
55637
- results: chunkResults
55638
- });
55639
55671
  try {
55640
55672
  let parsedOpCount = 0;
55641
55673
  let chunk = [];
@@ -55664,16 +55696,20 @@ async function applyJsonlCommit(ctx, args) {
55664
55696
  receipt = appendResult.receipt;
55665
55697
  createdByEmail = appendResult.createdByEmail ?? createdByEmail;
55666
55698
  repoSeq = appendResult.repoSeq ?? repoSeq;
55667
- chunkResults.push(...offsetChunkResultIndexes(appendResult.results, chunkStart));
55699
+ aggregate.addChunk({
55700
+ results: appendResult.results,
55701
+ chunkStart,
55702
+ submittedNames: operationsChunk
55703
+ });
55668
55704
  } catch (cause) {
55669
55705
  const pendingOutcome = isDefiniteStreamAppendRejection(cause) ? "absent" : "unknown";
55670
- if (receipts.length === 0 && pendingOutcome === "absent") {
55706
+ if (aggregate.receipts.length === 0 && pendingOutcome === "absent") {
55671
55707
  throw cause;
55672
55708
  }
55673
55709
  throw new PartialStreamSubmissionError({
55674
55710
  cause,
55675
- completedReceipts: receipts,
55676
- completedOperations: completedOperationsFrom(aggregateSoFar()),
55711
+ completedReceipts: aggregate.receipts,
55712
+ completedOperations: aggregate.completedOperations(),
55677
55713
  submissionId: args.submissionId,
55678
55714
  eventRequestId,
55679
55715
  chunkOrdinal,
@@ -55683,7 +55719,7 @@ async function applyJsonlCommit(ctx, args) {
55683
55719
  ...lastAcknowledgedRepoSeq === undefined ? {} : { lastAcknowledgedRepoSeq }
55684
55720
  });
55685
55721
  }
55686
- receipts.push(receipt);
55722
+ aggregate.addReceipt(receipt);
55687
55723
  const parsedRepoSeq = Number(receipt.event?.repoSeq);
55688
55724
  if (Number.isSafeInteger(parsedRepoSeq) && parsedRepoSeq >= 0) {
55689
55725
  lastAcknowledgedRepoSeq = parsedRepoSeq;
@@ -55714,9 +55750,6 @@ async function applyJsonlCommit(ctx, args) {
55714
55750
  assertNoNulBytes("data" in operation ? operation.data : undefined, `${args.lineLabel} JSONL line ${lineNumber}`);
55715
55751
  }
55716
55752
  parsedOpCount += 1;
55717
- submittedNames.push({
55718
- name: operation.name
55719
- });
55720
55753
  chunk.push(withSkipExisting(operation, args.skipExisting === true));
55721
55754
  if (chunk.length < chunkSize)
55722
55755
  continue;
@@ -55778,7 +55811,12 @@ async function applyJsonlCommit(ctx, args) {
55778
55811
  ctx.err(` warn: failed to write timing sidecar: ${String(err)}`);
55779
55812
  }
55780
55813
  }
55781
- return aggregateSoFar();
55814
+ return aggregate.toResult({
55815
+ committer: args.committer,
55816
+ createdByEmail,
55817
+ message: args.message,
55818
+ repoSeq
55819
+ });
55782
55820
  } catch (error51) {
55783
55821
  progress.onError();
55784
55822
  if (error51 instanceof PartialStreamSubmissionError || opCount === 0) {
@@ -55786,8 +55824,8 @@ async function applyJsonlCommit(ctx, args) {
55786
55824
  }
55787
55825
  throw new PartialStreamSubmissionError({
55788
55826
  cause: error51,
55789
- completedReceipts: receipts,
55790
- completedOperations: completedOperationsFrom(aggregateSoFar()),
55827
+ completedReceipts: aggregate.receipts,
55828
+ completedOperations: aggregate.completedOperations(),
55791
55829
  submissionId: args.submissionId,
55792
55830
  eventRequestId: operationEventStreamRequestId(args.submissionId, chunkCount),
55793
55831
  chunkOrdinal: chunkCount,
@@ -66388,7 +66426,7 @@ function resolveLogLevel(flagLevel, env) {
66388
66426
  // package.json
66389
66427
  var package_default3 = {
66390
66428
  name: "@warmhub/cli",
66391
- version: "0.91.0",
66429
+ version: "0.92.0",
66392
66430
  private: false,
66393
66431
  type: "module",
66394
66432
  description: "The wh CLI for WarmHub — create repos, commit and query data, and compound knowledge with your AI agents.",
@@ -67007,5 +67045,5 @@ process.exitCode = interceptedExitCode === undefined ? await runPreparedCli(laun
67007
67045
  version: package_default3.version
67008
67046
  }) : interceptedExitCode;
67009
67047
 
67010
- //# debugId=B83F4BF04D38984164756E2164756E21
67011
- //# warmhub-cli-build-info {"cliVersion":"0.91.0","sdkVersion":"0.89.0"}
67048
+ //# debugId=7FA9403B2F49037864756E2164756E21
67049
+ //# warmhub-cli-build-info {"cliVersion":"0.92.0","sdkVersion":"0.90.0"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@warmhub/cli",
3
- "version": "0.91.0",
3
+ "version": "0.92.0",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "The wh CLI for WarmHub — create repos, commit and query data, and compound knowledge with your AI agents.",