@warmhub/cli 0.93.0 → 0.95.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.
- package/dist/wh.js +866 -507
- package/package.json +1 -1
package/dist/wh.js
CHANGED
|
@@ -19392,10 +19392,13 @@ var ALL_BUILTIN_SHAPE_DEFS = {
|
|
|
19392
19392
|
// ../../packages/rules/src/client-flags.ts
|
|
19393
19393
|
var CLIENT_FLAGS_HEADER = "X-WarmHub-Client-Flags";
|
|
19394
19394
|
var CLIENT_FLAG_COMPATIBILITY_OVERRIDE = "compatibility-override";
|
|
19395
|
+
var CLIENT_FLAG_EDGE_CACHE_OPT_IN = "edge-cache-opt-in";
|
|
19395
19396
|
var KNOWN_CLIENT_FLAGS = new Set([
|
|
19396
|
-
CLIENT_FLAG_COMPATIBILITY_OVERRIDE
|
|
19397
|
+
CLIENT_FLAG_COMPATIBILITY_OVERRIDE,
|
|
19398
|
+
CLIENT_FLAG_EDGE_CACHE_OPT_IN
|
|
19397
19399
|
]);
|
|
19398
19400
|
var CLIENT_FLAG_TOKEN_RE = /^[a-z0-9-]+$/;
|
|
19401
|
+
var NO_FLAGS = new Set;
|
|
19399
19402
|
function isValidClientFlagToken(token) {
|
|
19400
19403
|
return CLIENT_FLAG_TOKEN_RE.test(token);
|
|
19401
19404
|
}
|
|
@@ -42600,6 +42603,257 @@ var SYSTEM_INFRA_SHAPE_NAMES = new Set(SYSTEM_COMPONENTS.filter((entry) => entry
|
|
|
42600
42603
|
function findSystemComponent(componentId) {
|
|
42601
42604
|
return SYSTEM_COMPONENTS.find((entry) => entry.componentId === componentId);
|
|
42602
42605
|
}
|
|
42606
|
+
// ../../packages/sdk-ts/src/collection-operation-normalize.ts
|
|
42607
|
+
var collectionTypes2 = new Set([
|
|
42608
|
+
"arc",
|
|
42609
|
+
"bond",
|
|
42610
|
+
"pair",
|
|
42611
|
+
"set",
|
|
42612
|
+
"list"
|
|
42613
|
+
]);
|
|
42614
|
+
function normalizeBackendCollectionAdd(operation, source) {
|
|
42615
|
+
const normalized = normalizeCollectionWrite(operation, source, "add");
|
|
42616
|
+
return {
|
|
42617
|
+
operation: "add",
|
|
42618
|
+
kind: "collection",
|
|
42619
|
+
name: normalized.name,
|
|
42620
|
+
type: normalized.type,
|
|
42621
|
+
members: normalized.members,
|
|
42622
|
+
...operation.skipExisting === true ? { skipExisting: true } : {}
|
|
42623
|
+
};
|
|
42624
|
+
}
|
|
42625
|
+
function normalizeBackendCollectionRevise(operation, source) {
|
|
42626
|
+
const normalized = normalizeCollectionWrite(operation, source, "revise");
|
|
42627
|
+
if (!normalized.name) {
|
|
42628
|
+
throw new Error(`${source}: collection revise requires a target name`);
|
|
42629
|
+
}
|
|
42630
|
+
return {
|
|
42631
|
+
operation: "revise",
|
|
42632
|
+
kind: "collection",
|
|
42633
|
+
name: normalized.name,
|
|
42634
|
+
type: normalized.type,
|
|
42635
|
+
members: normalized.members,
|
|
42636
|
+
...typeof operation.expectedVersion === "number" ? { expectedVersion: operation.expectedVersion } : {},
|
|
42637
|
+
...typeof operation.leaseId === "string" && operation.leaseId.length > 0 ? { leaseId: operation.leaseId } : {}
|
|
42638
|
+
};
|
|
42639
|
+
}
|
|
42640
|
+
function normalizeCollectionWrite(operation, source, writeOperation) {
|
|
42641
|
+
const diagnostics = preflightOpDiagnostics2({
|
|
42642
|
+
operation: writeOperation,
|
|
42643
|
+
kind: "collection",
|
|
42644
|
+
name: typeof operation.name === "string" ? operation.name : undefined,
|
|
42645
|
+
type: typeof operation.type === "string" ? operation.type : undefined,
|
|
42646
|
+
members: Array.isArray(operation.members) ? operation.members : undefined
|
|
42647
|
+
}, 0);
|
|
42648
|
+
if (diagnostics.length > 0) {
|
|
42649
|
+
throw new Error(`${source}: ${diagnostics.map((diagnostic) => diagnostic.message).join("; ")}`);
|
|
42650
|
+
}
|
|
42651
|
+
const type = normalizeCollectionType(operation.type);
|
|
42652
|
+
if (!type) {
|
|
42653
|
+
throw new Error(`${source}: collection ${writeOperation} requires 'type'. Use one of: arc, bond, set, list`);
|
|
42654
|
+
}
|
|
42655
|
+
if (!Array.isArray(operation.members)) {
|
|
42656
|
+
throw new Error(`${source}: collection ${writeOperation} requires a 'members' array`);
|
|
42657
|
+
}
|
|
42658
|
+
const name = normalizeOptionalName(operation.name);
|
|
42659
|
+
if (!name) {
|
|
42660
|
+
throw new Error(`${source}: collection ${writeOperation} name must be a non-empty string`);
|
|
42661
|
+
}
|
|
42662
|
+
assertNoUnsupportedCollectionFields(operation, source, writeOperation);
|
|
42663
|
+
return {
|
|
42664
|
+
name,
|
|
42665
|
+
type,
|
|
42666
|
+
members: operation.members
|
|
42667
|
+
};
|
|
42668
|
+
}
|
|
42669
|
+
function assertNoUnsupportedCollectionFields(operation, source, writeOperation) {
|
|
42670
|
+
const unsupportedFields = [
|
|
42671
|
+
"about",
|
|
42672
|
+
"aboutWref",
|
|
42673
|
+
"shapeWref",
|
|
42674
|
+
"data",
|
|
42675
|
+
...writeOperation === "revise" ? ["skipExisting"] : []
|
|
42676
|
+
].filter((field) => operation[field] !== undefined);
|
|
42677
|
+
if (unsupportedFields.length > 0) {
|
|
42678
|
+
throw new Error(`${source}: collection ${writeOperation} does not support ${unsupportedFields.map((field) => `'${field}'`).join(", ")}`);
|
|
42679
|
+
}
|
|
42680
|
+
}
|
|
42681
|
+
function normalizeCollectionType(value) {
|
|
42682
|
+
if (typeof value !== "string")
|
|
42683
|
+
return;
|
|
42684
|
+
const trimmed = value.trim();
|
|
42685
|
+
if (!collectionTypes2.has(trimmed))
|
|
42686
|
+
return;
|
|
42687
|
+
return trimmed;
|
|
42688
|
+
}
|
|
42689
|
+
function normalizeOptionalName(value) {
|
|
42690
|
+
if (typeof value !== "string")
|
|
42691
|
+
return;
|
|
42692
|
+
if (value.length === 0 || value.trim() !== value)
|
|
42693
|
+
return;
|
|
42694
|
+
return value;
|
|
42695
|
+
}
|
|
42696
|
+
|
|
42697
|
+
// ../../packages/sdk-ts/src/operation-normalize.ts
|
|
42698
|
+
function toBackendStreamOperation(operation) {
|
|
42699
|
+
if (operation.expectedVersion !== undefined && operation.operation !== "revise" && operation.operation !== "retract" && operation.operation !== "reaffirm") {
|
|
42700
|
+
throw new Error("expectedVersion is only valid on revise, retract, or reaffirm operations — set an explicit operation discriminator");
|
|
42701
|
+
}
|
|
42702
|
+
if (operation.operation === "retract") {
|
|
42703
|
+
return {
|
|
42704
|
+
operation: "retract",
|
|
42705
|
+
name: operation.name,
|
|
42706
|
+
...operation.kind ? { kind: operation.kind } : {},
|
|
42707
|
+
...operation.reason ? { reason: operation.reason } : {},
|
|
42708
|
+
...operation.expectedVersion !== undefined ? { expectedVersion: operation.expectedVersion } : {},
|
|
42709
|
+
...operation.leaseId ? { leaseId: operation.leaseId } : {}
|
|
42710
|
+
};
|
|
42711
|
+
}
|
|
42712
|
+
if (operation.operation === "reaffirm") {
|
|
42713
|
+
return {
|
|
42714
|
+
operation: "reaffirm",
|
|
42715
|
+
name: operation.name,
|
|
42716
|
+
...operation.expectedVersion !== undefined ? { expectedVersion: operation.expectedVersion } : {},
|
|
42717
|
+
...operation.kind ? { kind: operation.kind } : {},
|
|
42718
|
+
...operation.add ? { add: operation.add } : {},
|
|
42719
|
+
...operation.remove ? { remove: operation.remove } : {},
|
|
42720
|
+
...operation.leaseId ? { leaseId: operation.leaseId } : {}
|
|
42721
|
+
};
|
|
42722
|
+
}
|
|
42723
|
+
if (operation.operation === "rename") {
|
|
42724
|
+
return {
|
|
42725
|
+
operation: "rename",
|
|
42726
|
+
name: operation.name,
|
|
42727
|
+
newName: operation.newName,
|
|
42728
|
+
...operation.kind ? { kind: operation.kind } : {}
|
|
42729
|
+
};
|
|
42730
|
+
}
|
|
42731
|
+
if (operation.operation === "revise") {
|
|
42732
|
+
const name = operation.name ?? operation.wref;
|
|
42733
|
+
if (!name) {
|
|
42734
|
+
throw new Error("revise operation requires a target");
|
|
42735
|
+
}
|
|
42736
|
+
const kind2 = inferOperationKind({ kind: operation.kind, name });
|
|
42737
|
+
if (Object.hasOwn(operation, "active")) {
|
|
42738
|
+
throw new Error(`${kind2} revise operation no longer supports 'active' — use retract('${name}') instead`);
|
|
42739
|
+
}
|
|
42740
|
+
if (kind2 !== "assertion" && operation.affirmedTargets !== undefined) {
|
|
42741
|
+
throw new Error(`${kind2} revise operation does not support 'affirmedTargets' — it applies only to assertions; set kind: 'assertion' explicitly`);
|
|
42742
|
+
}
|
|
42743
|
+
if (kind2 === "collection") {
|
|
42744
|
+
return normalizeBackendCollectionRevise(operation, "commit.apply");
|
|
42745
|
+
}
|
|
42746
|
+
if (operation.data === undefined) {
|
|
42747
|
+
throw new Error(`${kind2} revise operation requires 'data'`);
|
|
42748
|
+
}
|
|
42749
|
+
if (kind2 === "assertion") {
|
|
42750
|
+
return {
|
|
42751
|
+
operation: "revise",
|
|
42752
|
+
kind: "assertion",
|
|
42753
|
+
name,
|
|
42754
|
+
data: operation.data,
|
|
42755
|
+
...operation.affirmedTargets ? { affirmedTargets: operation.affirmedTargets } : {},
|
|
42756
|
+
...operation.expectedVersion !== undefined ? { expectedVersion: operation.expectedVersion } : {},
|
|
42757
|
+
...operation.leaseId ? { leaseId: operation.leaseId } : {}
|
|
42758
|
+
};
|
|
42759
|
+
}
|
|
42760
|
+
return {
|
|
42761
|
+
operation: "revise",
|
|
42762
|
+
kind: kind2,
|
|
42763
|
+
name,
|
|
42764
|
+
data: operation.data,
|
|
42765
|
+
...operation.expectedVersion !== undefined ? { expectedVersion: operation.expectedVersion } : {},
|
|
42766
|
+
...operation.leaseId ? { leaseId: operation.leaseId } : {}
|
|
42767
|
+
};
|
|
42768
|
+
}
|
|
42769
|
+
const kind = inferOperationKind(operation);
|
|
42770
|
+
const skipExisting = "skipExisting" in operation ? operation.skipExisting : undefined;
|
|
42771
|
+
if (kind !== "collection" && (("type" in operation) && operation.type !== undefined || ("members" in operation) && operation.members !== undefined)) {
|
|
42772
|
+
throw new Error(`add operation '${operation.name ?? ""}' has collection fields but resolved kind '${kind}' — collection adds require both 'type' and 'members', or set kind: 'collection'`);
|
|
42773
|
+
}
|
|
42774
|
+
if (kind !== "assertion" && operation.affirmedTargets !== undefined) {
|
|
42775
|
+
throw new Error(`${kind} add operation does not support 'affirmedTargets' — it applies only to assertions; set kind: 'assertion' explicitly`);
|
|
42776
|
+
}
|
|
42777
|
+
if (kind === "collection") {
|
|
42778
|
+
return normalizeBackendCollectionAdd({ ...operation, skipExisting }, "commit.apply");
|
|
42779
|
+
}
|
|
42780
|
+
if (!operation.name) {
|
|
42781
|
+
throw new Error("add operation requires a name");
|
|
42782
|
+
}
|
|
42783
|
+
if (kind === "assertion") {
|
|
42784
|
+
if (!("about" in operation) || operation.about === undefined) {
|
|
42785
|
+
throw new Error("assertion add operation requires 'about'");
|
|
42786
|
+
}
|
|
42787
|
+
if (typeof operation.about !== "string") {
|
|
42788
|
+
throw new Error(COLLECTION_ABOUT_REMOVED_MESSAGE);
|
|
42789
|
+
}
|
|
42790
|
+
if (operation.data === undefined) {
|
|
42791
|
+
throw new Error("assertion add operation requires 'data'");
|
|
42792
|
+
}
|
|
42793
|
+
return {
|
|
42794
|
+
operation: "add",
|
|
42795
|
+
kind: "assertion",
|
|
42796
|
+
name: operation.name,
|
|
42797
|
+
about: operation.about,
|
|
42798
|
+
data: operation.data,
|
|
42799
|
+
...operation.affirmedTargets ? { affirmedTargets: operation.affirmedTargets } : {},
|
|
42800
|
+
...skipExisting === true ? { skipExisting } : {}
|
|
42801
|
+
};
|
|
42802
|
+
}
|
|
42803
|
+
if (operation.data === undefined) {
|
|
42804
|
+
throw new Error(`${kind} add operation requires 'data'`);
|
|
42805
|
+
}
|
|
42806
|
+
return {
|
|
42807
|
+
operation: "add",
|
|
42808
|
+
kind,
|
|
42809
|
+
name: operation.name,
|
|
42810
|
+
data: operation.data,
|
|
42811
|
+
...skipExisting === true ? { skipExisting } : {}
|
|
42812
|
+
};
|
|
42813
|
+
}
|
|
42814
|
+
|
|
42815
|
+
// ../../packages/sdk-ts/src/commit-validation.ts
|
|
42816
|
+
var MAX_COMMIT_VALIDATION_OPERATIONS = 1e4;
|
|
42817
|
+
var MAX_COMMIT_VALIDATION_ENCODED_BYTES = 4 * 1024 * 1024;
|
|
42818
|
+
|
|
42819
|
+
class CommitValidationInputError extends Error {
|
|
42820
|
+
code = "VALIDATION_ERROR";
|
|
42821
|
+
status = 400;
|
|
42822
|
+
constructor(message) {
|
|
42823
|
+
super(message);
|
|
42824
|
+
this.name = "WarmHubError";
|
|
42825
|
+
}
|
|
42826
|
+
}
|
|
42827
|
+
function normalizeCommitValidationOperations(operations, skipExisting) {
|
|
42828
|
+
return operations.map((operation, index) => {
|
|
42829
|
+
let normalized;
|
|
42830
|
+
try {
|
|
42831
|
+
normalized = toBackendStreamOperation(operation);
|
|
42832
|
+
} catch (error51) {
|
|
42833
|
+
const message = error51 instanceof Error ? error51.message : String(error51);
|
|
42834
|
+
throw new CommitValidationInputError(`Invalid operation at index ${index}: ${message}`);
|
|
42835
|
+
}
|
|
42836
|
+
return skipExisting === true && normalized.operation === "add" ? { ...normalized, skipExisting: true } : normalized;
|
|
42837
|
+
});
|
|
42838
|
+
}
|
|
42839
|
+
function createCommitValidateInput(orgName, repoName, operations, opts) {
|
|
42840
|
+
return {
|
|
42841
|
+
orgName,
|
|
42842
|
+
repoName,
|
|
42843
|
+
...opts?.committer !== undefined ? { committer: opts.committer } : {},
|
|
42844
|
+
...opts?.message !== undefined ? { message: opts.message } : {},
|
|
42845
|
+
...opts?.componentRef !== undefined ? { componentRef: opts.componentRef } : {},
|
|
42846
|
+
operations: normalizeCommitValidationOperations(operations, opts?.skipExisting),
|
|
42847
|
+
...opts?.includeWouldBeBody !== undefined ? { includeWouldBeBody: opts.includeWouldBeBody } : {}
|
|
42848
|
+
};
|
|
42849
|
+
}
|
|
42850
|
+
function encodeCommitValidateRequestBody(input) {
|
|
42851
|
+
return JSON.stringify(input);
|
|
42852
|
+
}
|
|
42853
|
+
function commitValidateRequestBodyBytes(input) {
|
|
42854
|
+
return new TextEncoder().encode(encodeCommitValidateRequestBody(input)).byteLength;
|
|
42855
|
+
}
|
|
42856
|
+
|
|
42603
42857
|
// ../../packages/sdk-ts/src/grant-client.ts
|
|
42604
42858
|
function createGrantClient(getTrpc, mapError) {
|
|
42605
42859
|
return {
|
|
@@ -42746,160 +43000,38 @@ function shapeDefinitionPreflightError(name, data, verb) {
|
|
|
42746
43000
|
return `Invalid shape definition for "${name}": ${result.errors.join("; ")}`;
|
|
42747
43001
|
}
|
|
42748
43002
|
|
|
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
43003
|
// ../../packages/sdk-ts/src/stream-submit-aggregate.ts
|
|
42881
|
-
function toSubmittedOperation(result, opIndex,
|
|
42882
|
-
const
|
|
43004
|
+
function toSubmittedOperation(result, opIndex, submitted) {
|
|
43005
|
+
const operation = result.operation === undefined || result.operation === "noop" ? submitted?.operation ?? "add" : result.operation;
|
|
43006
|
+
const base = {
|
|
42883
43007
|
opIndex,
|
|
42884
43008
|
name: result.name ?? "",
|
|
42885
|
-
operation
|
|
42886
|
-
|
|
42887
|
-
|
|
42888
|
-
|
|
42889
|
-
|
|
42890
|
-
|
|
42891
|
-
|
|
42892
|
-
|
|
42893
|
-
|
|
42894
|
-
|
|
42895
|
-
|
|
42896
|
-
|
|
42897
|
-
|
|
42898
|
-
|
|
42899
|
-
|
|
42900
|
-
|
|
42901
|
-
|
|
42902
|
-
|
|
43009
|
+
operation,
|
|
43010
|
+
...result.affirmations ? { affirmations: result.affirmations } : {},
|
|
43011
|
+
...result.resolvedName !== undefined ? { resolvedName: result.resolvedName } : {},
|
|
43012
|
+
...result.warnings ? { warnings: result.warnings } : {}
|
|
43013
|
+
};
|
|
43014
|
+
if (result.status === "failed") {
|
|
43015
|
+
return {
|
|
43016
|
+
...base,
|
|
43017
|
+
status: "error",
|
|
43018
|
+
errors: [
|
|
43019
|
+
{
|
|
43020
|
+
code: result.error?.code ?? "BACKEND",
|
|
43021
|
+
message: result.error?.message ?? `Operation on "${result.name}" failed`,
|
|
43022
|
+
...result.error?.details ? { details: result.error.details } : {},
|
|
43023
|
+
...result.retryable !== undefined ? { retryable: result.retryable } : {}
|
|
43024
|
+
}
|
|
43025
|
+
],
|
|
43026
|
+
...submitted?.name !== undefined ? { submittedName: submitted.name } : {}
|
|
43027
|
+
};
|
|
43028
|
+
}
|
|
43029
|
+
return {
|
|
43030
|
+
...base,
|
|
43031
|
+
status: result.status === "noop" || result.operation === "noop" ? "noop" : "applied",
|
|
43032
|
+
...result.version !== undefined ? { version: result.version } : {},
|
|
43033
|
+
...result.dataHash !== undefined ? { dataHash: result.dataHash } : {}
|
|
43034
|
+
};
|
|
42903
43035
|
}
|
|
42904
43036
|
|
|
42905
43037
|
class StreamSubmissionAggregator {
|
|
@@ -42910,11 +43042,22 @@ class StreamSubmissionAggregator {
|
|
|
42910
43042
|
return this.operations.length > 0 && this.statusCounts.error === this.operations.length;
|
|
42911
43043
|
}
|
|
42912
43044
|
addChunk(input) {
|
|
42913
|
-
input.
|
|
43045
|
+
if (input.result.schemaVersion === "operation-event-receipt/v2") {
|
|
43046
|
+
input.result.results.forEach((result) => {
|
|
43047
|
+
this.statusCounts[result.status]++;
|
|
43048
|
+
this.operations.push({
|
|
43049
|
+
...result,
|
|
43050
|
+
opIndex: input.chunkStart + result.opIndex
|
|
43051
|
+
});
|
|
43052
|
+
});
|
|
43053
|
+
return;
|
|
43054
|
+
}
|
|
43055
|
+
input.result.results.forEach((result, position) => {
|
|
42914
43056
|
const local = result.opIndex ?? position;
|
|
42915
|
-
const
|
|
42916
|
-
|
|
42917
|
-
this.
|
|
43057
|
+
const submitted = input.submittedOperations[local];
|
|
43058
|
+
const operation = toSubmittedOperation(result, input.chunkStart + local, submitted);
|
|
43059
|
+
this.statusCounts[operation.status]++;
|
|
43060
|
+
this.operations.push(operation);
|
|
42918
43061
|
});
|
|
42919
43062
|
}
|
|
42920
43063
|
addReceipt(receipt) {
|
|
@@ -43039,215 +43182,6 @@ function operationEventStreamRequestId(submissionId, chunkOrdinal) {
|
|
|
43039
43182
|
return formatUuid(digest);
|
|
43040
43183
|
}
|
|
43041
43184
|
|
|
43042
|
-
// ../../packages/sdk-ts/src/collection-operation-normalize.ts
|
|
43043
|
-
var collectionTypes2 = new Set([
|
|
43044
|
-
"arc",
|
|
43045
|
-
"bond",
|
|
43046
|
-
"pair",
|
|
43047
|
-
"set",
|
|
43048
|
-
"list"
|
|
43049
|
-
]);
|
|
43050
|
-
function normalizeBackendCollectionAdd(operation, source) {
|
|
43051
|
-
const normalized = normalizeCollectionWrite(operation, source, "add");
|
|
43052
|
-
return {
|
|
43053
|
-
operation: "add",
|
|
43054
|
-
kind: "collection",
|
|
43055
|
-
name: normalized.name,
|
|
43056
|
-
type: normalized.type,
|
|
43057
|
-
members: normalized.members,
|
|
43058
|
-
...operation.skipExisting === true ? { skipExisting: true } : {}
|
|
43059
|
-
};
|
|
43060
|
-
}
|
|
43061
|
-
function normalizeBackendCollectionRevise(operation, source) {
|
|
43062
|
-
const normalized = normalizeCollectionWrite(operation, source, "revise");
|
|
43063
|
-
if (!normalized.name) {
|
|
43064
|
-
throw new Error(`${source}: collection revise requires a target name`);
|
|
43065
|
-
}
|
|
43066
|
-
return {
|
|
43067
|
-
operation: "revise",
|
|
43068
|
-
kind: "collection",
|
|
43069
|
-
name: normalized.name,
|
|
43070
|
-
type: normalized.type,
|
|
43071
|
-
members: normalized.members,
|
|
43072
|
-
...typeof operation.expectedVersion === "number" ? { expectedVersion: operation.expectedVersion } : {},
|
|
43073
|
-
...typeof operation.leaseId === "string" && operation.leaseId.length > 0 ? { leaseId: operation.leaseId } : {}
|
|
43074
|
-
};
|
|
43075
|
-
}
|
|
43076
|
-
function normalizeCollectionWrite(operation, source, writeOperation) {
|
|
43077
|
-
const diagnostics = preflightOpDiagnostics2({
|
|
43078
|
-
operation: writeOperation,
|
|
43079
|
-
kind: "collection",
|
|
43080
|
-
name: typeof operation.name === "string" ? operation.name : undefined,
|
|
43081
|
-
type: typeof operation.type === "string" ? operation.type : undefined,
|
|
43082
|
-
members: Array.isArray(operation.members) ? operation.members : undefined
|
|
43083
|
-
}, 0);
|
|
43084
|
-
if (diagnostics.length > 0) {
|
|
43085
|
-
throw new Error(`${source}: ${diagnostics.map((diagnostic) => diagnostic.message).join("; ")}`);
|
|
43086
|
-
}
|
|
43087
|
-
const type = normalizeCollectionType(operation.type);
|
|
43088
|
-
if (!type) {
|
|
43089
|
-
throw new Error(`${source}: collection ${writeOperation} requires 'type'. Use one of: arc, bond, set, list`);
|
|
43090
|
-
}
|
|
43091
|
-
if (!Array.isArray(operation.members)) {
|
|
43092
|
-
throw new Error(`${source}: collection ${writeOperation} requires a 'members' array`);
|
|
43093
|
-
}
|
|
43094
|
-
const name = normalizeOptionalName(operation.name);
|
|
43095
|
-
if (!name) {
|
|
43096
|
-
throw new Error(`${source}: collection ${writeOperation} name must be a non-empty string`);
|
|
43097
|
-
}
|
|
43098
|
-
assertNoUnsupportedCollectionFields(operation, source, writeOperation);
|
|
43099
|
-
return {
|
|
43100
|
-
name,
|
|
43101
|
-
type,
|
|
43102
|
-
members: operation.members
|
|
43103
|
-
};
|
|
43104
|
-
}
|
|
43105
|
-
function assertNoUnsupportedCollectionFields(operation, source, writeOperation) {
|
|
43106
|
-
const unsupportedFields = [
|
|
43107
|
-
"about",
|
|
43108
|
-
"aboutWref",
|
|
43109
|
-
"shapeWref",
|
|
43110
|
-
"data",
|
|
43111
|
-
...writeOperation === "revise" ? ["skipExisting"] : []
|
|
43112
|
-
].filter((field) => operation[field] !== undefined);
|
|
43113
|
-
if (unsupportedFields.length > 0) {
|
|
43114
|
-
throw new Error(`${source}: collection ${writeOperation} does not support ${unsupportedFields.map((field) => `'${field}'`).join(", ")}`);
|
|
43115
|
-
}
|
|
43116
|
-
}
|
|
43117
|
-
function normalizeCollectionType(value) {
|
|
43118
|
-
if (typeof value !== "string")
|
|
43119
|
-
return;
|
|
43120
|
-
const trimmed = value.trim();
|
|
43121
|
-
if (!collectionTypes2.has(trimmed))
|
|
43122
|
-
return;
|
|
43123
|
-
return trimmed;
|
|
43124
|
-
}
|
|
43125
|
-
function normalizeOptionalName(value) {
|
|
43126
|
-
if (typeof value !== "string")
|
|
43127
|
-
return;
|
|
43128
|
-
if (value.length === 0 || value.trim() !== value)
|
|
43129
|
-
return;
|
|
43130
|
-
return value;
|
|
43131
|
-
}
|
|
43132
|
-
|
|
43133
|
-
// ../../packages/sdk-ts/src/operation-normalize.ts
|
|
43134
|
-
function toBackendStreamOperation(operation) {
|
|
43135
|
-
if (operation.expectedVersion !== undefined && operation.operation !== "revise" && operation.operation !== "retract" && operation.operation !== "reaffirm") {
|
|
43136
|
-
throw new Error("expectedVersion is only valid on revise, retract, or reaffirm operations — set an explicit operation discriminator");
|
|
43137
|
-
}
|
|
43138
|
-
if (operation.operation === "retract") {
|
|
43139
|
-
return {
|
|
43140
|
-
operation: "retract",
|
|
43141
|
-
name: operation.name,
|
|
43142
|
-
...operation.kind ? { kind: operation.kind } : {},
|
|
43143
|
-
...operation.reason ? { reason: operation.reason } : {},
|
|
43144
|
-
...operation.expectedVersion !== undefined ? { expectedVersion: operation.expectedVersion } : {},
|
|
43145
|
-
...operation.leaseId ? { leaseId: operation.leaseId } : {}
|
|
43146
|
-
};
|
|
43147
|
-
}
|
|
43148
|
-
if (operation.operation === "reaffirm") {
|
|
43149
|
-
return {
|
|
43150
|
-
operation: "reaffirm",
|
|
43151
|
-
name: operation.name,
|
|
43152
|
-
...operation.expectedVersion !== undefined ? { expectedVersion: operation.expectedVersion } : {},
|
|
43153
|
-
...operation.kind ? { kind: operation.kind } : {},
|
|
43154
|
-
...operation.add ? { add: operation.add } : {},
|
|
43155
|
-
...operation.remove ? { remove: operation.remove } : {},
|
|
43156
|
-
...operation.leaseId ? { leaseId: operation.leaseId } : {}
|
|
43157
|
-
};
|
|
43158
|
-
}
|
|
43159
|
-
if (operation.operation === "rename") {
|
|
43160
|
-
return {
|
|
43161
|
-
operation: "rename",
|
|
43162
|
-
name: operation.name,
|
|
43163
|
-
newName: operation.newName,
|
|
43164
|
-
...operation.kind ? { kind: operation.kind } : {}
|
|
43165
|
-
};
|
|
43166
|
-
}
|
|
43167
|
-
if (operation.operation === "revise") {
|
|
43168
|
-
const name = operation.name ?? operation.wref;
|
|
43169
|
-
if (!name) {
|
|
43170
|
-
throw new Error("revise operation requires a target");
|
|
43171
|
-
}
|
|
43172
|
-
const kind2 = inferOperationKind({ kind: operation.kind, name });
|
|
43173
|
-
if (Object.hasOwn(operation, "active")) {
|
|
43174
|
-
throw new Error(`${kind2} revise operation no longer supports 'active' — use retract('${name}') instead`);
|
|
43175
|
-
}
|
|
43176
|
-
if (kind2 !== "assertion" && operation.affirmedTargets !== undefined) {
|
|
43177
|
-
throw new Error(`${kind2} revise operation does not support 'affirmedTargets' — it applies only to assertions; set kind: 'assertion' explicitly`);
|
|
43178
|
-
}
|
|
43179
|
-
if (kind2 === "collection") {
|
|
43180
|
-
return normalizeBackendCollectionRevise(operation, "commit.apply");
|
|
43181
|
-
}
|
|
43182
|
-
if (operation.data === undefined) {
|
|
43183
|
-
throw new Error(`${kind2} revise operation requires 'data'`);
|
|
43184
|
-
}
|
|
43185
|
-
if (kind2 === "assertion") {
|
|
43186
|
-
return {
|
|
43187
|
-
operation: "revise",
|
|
43188
|
-
kind: "assertion",
|
|
43189
|
-
name,
|
|
43190
|
-
data: operation.data,
|
|
43191
|
-
...operation.affirmedTargets ? { affirmedTargets: operation.affirmedTargets } : {},
|
|
43192
|
-
...operation.expectedVersion !== undefined ? { expectedVersion: operation.expectedVersion } : {},
|
|
43193
|
-
...operation.leaseId ? { leaseId: operation.leaseId } : {}
|
|
43194
|
-
};
|
|
43195
|
-
}
|
|
43196
|
-
return {
|
|
43197
|
-
operation: "revise",
|
|
43198
|
-
kind: kind2,
|
|
43199
|
-
name,
|
|
43200
|
-
data: operation.data,
|
|
43201
|
-
...operation.expectedVersion !== undefined ? { expectedVersion: operation.expectedVersion } : {},
|
|
43202
|
-
...operation.leaseId ? { leaseId: operation.leaseId } : {}
|
|
43203
|
-
};
|
|
43204
|
-
}
|
|
43205
|
-
const kind = inferOperationKind(operation);
|
|
43206
|
-
const skipExisting = "skipExisting" in operation ? operation.skipExisting : undefined;
|
|
43207
|
-
if (kind !== "collection" && (("type" in operation) && operation.type !== undefined || ("members" in operation) && operation.members !== undefined)) {
|
|
43208
|
-
throw new Error(`add operation '${operation.name ?? ""}' has collection fields but resolved kind '${kind}' — collection adds require both 'type' and 'members', or set kind: 'collection'`);
|
|
43209
|
-
}
|
|
43210
|
-
if (kind !== "assertion" && operation.affirmedTargets !== undefined) {
|
|
43211
|
-
throw new Error(`${kind} add operation does not support 'affirmedTargets' — it applies only to assertions; set kind: 'assertion' explicitly`);
|
|
43212
|
-
}
|
|
43213
|
-
if (kind === "collection") {
|
|
43214
|
-
return normalizeBackendCollectionAdd({ ...operation, skipExisting }, "commit.apply");
|
|
43215
|
-
}
|
|
43216
|
-
if (!operation.name) {
|
|
43217
|
-
throw new Error("add operation requires a name");
|
|
43218
|
-
}
|
|
43219
|
-
if (kind === "assertion") {
|
|
43220
|
-
if (!("about" in operation) || operation.about === undefined) {
|
|
43221
|
-
throw new Error("assertion add operation requires 'about'");
|
|
43222
|
-
}
|
|
43223
|
-
if (typeof operation.about !== "string") {
|
|
43224
|
-
throw new Error(COLLECTION_ABOUT_REMOVED_MESSAGE);
|
|
43225
|
-
}
|
|
43226
|
-
if (operation.data === undefined) {
|
|
43227
|
-
throw new Error("assertion add operation requires 'data'");
|
|
43228
|
-
}
|
|
43229
|
-
return {
|
|
43230
|
-
operation: "add",
|
|
43231
|
-
kind: "assertion",
|
|
43232
|
-
name: operation.name,
|
|
43233
|
-
about: operation.about,
|
|
43234
|
-
data: operation.data,
|
|
43235
|
-
...operation.affirmedTargets ? { affirmedTargets: operation.affirmedTargets } : {},
|
|
43236
|
-
...skipExisting === true ? { skipExisting } : {}
|
|
43237
|
-
};
|
|
43238
|
-
}
|
|
43239
|
-
if (operation.data === undefined) {
|
|
43240
|
-
throw new Error(`${kind} add operation requires 'data'`);
|
|
43241
|
-
}
|
|
43242
|
-
return {
|
|
43243
|
-
operation: "add",
|
|
43244
|
-
kind,
|
|
43245
|
-
name: operation.name,
|
|
43246
|
-
data: operation.data,
|
|
43247
|
-
...skipExisting === true ? { skipExisting } : {}
|
|
43248
|
-
};
|
|
43249
|
-
}
|
|
43250
|
-
|
|
43251
43185
|
// ../../packages/sdk-ts/src/stream-submit-types.ts
|
|
43252
43186
|
var DEFAULT_STREAM_CHUNK_SIZE = DEFAULT_STREAM_APPEND_CHUNK_SIZE;
|
|
43253
43187
|
var MAX_STREAM_APPEND_OPERATION_COUNT2 = MAX_STREAM_APPEND_OPERATION_COUNT;
|
|
@@ -43290,7 +43224,7 @@ class AllStreamOperationsFailedError extends Error {
|
|
|
43290
43224
|
statusCounts;
|
|
43291
43225
|
cause;
|
|
43292
43226
|
constructor(result) {
|
|
43293
|
-
const primaryFailure = result.operations.find((operation) => operation.
|
|
43227
|
+
const primaryFailure = result.operations.find((operation) => operation.status === "error")?.errors[0];
|
|
43294
43228
|
super(primaryFailure ? `All ${result.operationCount} stream operations failed: ${primaryFailure.message}` : `All ${result.operationCount} stream operations failed.`);
|
|
43295
43229
|
this.name = "WarmHubError";
|
|
43296
43230
|
this.cause = primaryFailure;
|
|
@@ -43305,6 +43239,130 @@ class AllStreamOperationsFailedError extends Error {
|
|
|
43305
43239
|
}
|
|
43306
43240
|
}
|
|
43307
43241
|
|
|
43242
|
+
// ../../packages/sdk-ts/src/stream-submit-utils.ts
|
|
43243
|
+
var DEFAULT_RETRY_POLICY = {
|
|
43244
|
+
maxAttempts: 3,
|
|
43245
|
+
baseDelayMs: 250,
|
|
43246
|
+
maxDelayMs: 8000
|
|
43247
|
+
};
|
|
43248
|
+
var MAX_ATTEMPTS_HARD_CAP = 10;
|
|
43249
|
+
var MAX_DELAY_HARD_CAP_MS = 60000;
|
|
43250
|
+
function resolveRetryPolicy(retry) {
|
|
43251
|
+
if (retry === false)
|
|
43252
|
+
return false;
|
|
43253
|
+
const overrides = {};
|
|
43254
|
+
if (retry !== undefined) {
|
|
43255
|
+
if (Number.isFinite(retry.maxAttempts))
|
|
43256
|
+
overrides.maxAttempts = retry.maxAttempts;
|
|
43257
|
+
if (Number.isFinite(retry.baseDelayMs))
|
|
43258
|
+
overrides.baseDelayMs = retry.baseDelayMs;
|
|
43259
|
+
if (Number.isFinite(retry.maxDelayMs))
|
|
43260
|
+
overrides.maxDelayMs = retry.maxDelayMs;
|
|
43261
|
+
}
|
|
43262
|
+
const merged = { ...DEFAULT_RETRY_POLICY, ...overrides };
|
|
43263
|
+
return {
|
|
43264
|
+
maxAttempts: Math.min(MAX_ATTEMPTS_HARD_CAP, Math.max(1, Math.trunc(merged.maxAttempts))),
|
|
43265
|
+
baseDelayMs: Math.min(MAX_DELAY_HARD_CAP_MS, Math.max(0, Math.trunc(merged.baseDelayMs))),
|
|
43266
|
+
maxDelayMs: Math.min(MAX_DELAY_HARD_CAP_MS, Math.max(0, Math.trunc(merged.maxDelayMs)))
|
|
43267
|
+
};
|
|
43268
|
+
}
|
|
43269
|
+
var DEFINITE_CLIENT_REJECT_CODES = new Set([
|
|
43270
|
+
"BAD_REQUEST",
|
|
43271
|
+
"METHOD_NOT_SUPPORTED",
|
|
43272
|
+
"PARSE_ERROR",
|
|
43273
|
+
"PAYLOAD_TOO_LARGE",
|
|
43274
|
+
"PRECONDITION_FAILED",
|
|
43275
|
+
"UNAUTHORIZED",
|
|
43276
|
+
"UNPROCESSABLE_CONTENT",
|
|
43277
|
+
"UNSUPPORTED_MEDIA_TYPE",
|
|
43278
|
+
"UNAUTHENTICATED",
|
|
43279
|
+
"FORBIDDEN",
|
|
43280
|
+
"VALIDATION_ERROR",
|
|
43281
|
+
"SHAPE_MISMATCH",
|
|
43282
|
+
"RESERVED_NAME",
|
|
43283
|
+
"ILLEGAL_OP_SEQUENCE",
|
|
43284
|
+
"NOT_FOUND",
|
|
43285
|
+
"KIND_MISMATCH",
|
|
43286
|
+
"CONFLICT",
|
|
43287
|
+
"ALREADY_RETRACTED",
|
|
43288
|
+
"ARCHIVED",
|
|
43289
|
+
"RATE_LIMITED",
|
|
43290
|
+
"TOO_MANY_REQUESTS",
|
|
43291
|
+
"UNRESOLVED_TOKEN"
|
|
43292
|
+
]);
|
|
43293
|
+
var TERMINAL_AMBIGUOUS_CODES = new Set(["COMMIT_OUTCOME_UNKNOWN"]);
|
|
43294
|
+
function extractErrorCode(cause) {
|
|
43295
|
+
if (!cause || typeof cause !== "object")
|
|
43296
|
+
return;
|
|
43297
|
+
const direct = cause.code;
|
|
43298
|
+
if (typeof direct === "string")
|
|
43299
|
+
return direct;
|
|
43300
|
+
const data = cause.data;
|
|
43301
|
+
const wh = data?.warmhub?.code;
|
|
43302
|
+
if (typeof wh === "string")
|
|
43303
|
+
return wh;
|
|
43304
|
+
const dc = data?.code;
|
|
43305
|
+
if (typeof dc === "string")
|
|
43306
|
+
return dc;
|
|
43307
|
+
return;
|
|
43308
|
+
}
|
|
43309
|
+
function extractHttpStatus(cause) {
|
|
43310
|
+
if (!cause || typeof cause !== "object")
|
|
43311
|
+
return;
|
|
43312
|
+
const status = cause.data?.httpStatus;
|
|
43313
|
+
if (typeof status === "number")
|
|
43314
|
+
return status;
|
|
43315
|
+
const warmhubStatus = cause.data?.warmhub?.status;
|
|
43316
|
+
if (typeof warmhubStatus === "number")
|
|
43317
|
+
return warmhubStatus;
|
|
43318
|
+
const direct = cause.status;
|
|
43319
|
+
return typeof direct === "number" ? direct : undefined;
|
|
43320
|
+
}
|
|
43321
|
+
function isDefiniteClientRejectionStatus(status) {
|
|
43322
|
+
return status !== undefined && status >= 400 && status < 500 && status !== 408;
|
|
43323
|
+
}
|
|
43324
|
+
function isTerminalAmbiguousError(cause) {
|
|
43325
|
+
const code = extractErrorCode(cause);
|
|
43326
|
+
return code !== undefined && TERMINAL_AMBIGUOUS_CODES.has(code);
|
|
43327
|
+
}
|
|
43328
|
+
function isDefiniteStreamAppendRejection(cause) {
|
|
43329
|
+
if (isTerminalAmbiguousError(cause))
|
|
43330
|
+
return false;
|
|
43331
|
+
const code = extractErrorCode(cause);
|
|
43332
|
+
return code !== undefined && DEFINITE_CLIENT_REJECT_CODES.has(code) || isDefiniteClientRejectionStatus(extractHttpStatus(cause));
|
|
43333
|
+
}
|
|
43334
|
+
function isTransientStreamFailure(cause) {
|
|
43335
|
+
if (isTerminalAmbiguousError(cause))
|
|
43336
|
+
return false;
|
|
43337
|
+
if (isDefiniteStreamAppendRejection(cause))
|
|
43338
|
+
return false;
|
|
43339
|
+
if (isFetchNetworkTypeError(cause))
|
|
43340
|
+
return true;
|
|
43341
|
+
if (cause instanceof TypeError)
|
|
43342
|
+
return false;
|
|
43343
|
+
if (cause instanceof SyntaxError)
|
|
43344
|
+
return false;
|
|
43345
|
+
const inner = cause?.cause;
|
|
43346
|
+
if (isFetchNetworkTypeError(inner))
|
|
43347
|
+
return true;
|
|
43348
|
+
if (inner instanceof TypeError)
|
|
43349
|
+
return false;
|
|
43350
|
+
if (inner instanceof SyntaxError)
|
|
43351
|
+
return false;
|
|
43352
|
+
return true;
|
|
43353
|
+
}
|
|
43354
|
+
function isFetchNetworkTypeError(cause) {
|
|
43355
|
+
return cause instanceof TypeError && /fetch/i.test(cause.message);
|
|
43356
|
+
}
|
|
43357
|
+
function computeBackoffDelayMs(attempt, policy) {
|
|
43358
|
+
const exponential = policy.baseDelayMs * 2 ** Math.max(0, attempt - 1);
|
|
43359
|
+
const jitter = Math.random() * policy.baseDelayMs;
|
|
43360
|
+
return Math.min(policy.maxDelayMs, exponential + jitter);
|
|
43361
|
+
}
|
|
43362
|
+
function sleep2(ms) {
|
|
43363
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
43364
|
+
}
|
|
43365
|
+
|
|
43308
43366
|
// ../../packages/sdk-ts/src/stream-submit-submit.ts
|
|
43309
43367
|
class StreamValidationError extends Error {
|
|
43310
43368
|
code;
|
|
@@ -43371,9 +43429,9 @@ async function submitOperationsViaStream(client, args) {
|
|
|
43371
43429
|
createdByEmail = appendResult.createdByEmail ?? createdByEmail;
|
|
43372
43430
|
repoSeq = appendResult.repoSeq ?? repoSeq;
|
|
43373
43431
|
aggregate.addChunk({
|
|
43374
|
-
|
|
43432
|
+
result: appendResult,
|
|
43375
43433
|
chunkStart: chunk.start,
|
|
43376
|
-
|
|
43434
|
+
submittedOperations: chunk.operations
|
|
43377
43435
|
});
|
|
43378
43436
|
acknowledgedOperationCount += chunk.operations.length;
|
|
43379
43437
|
const acknowledgedRepoSeq = receiptRepoSeq(appendResult.receipt);
|
|
@@ -43489,7 +43547,7 @@ function normalizeChunkSize(chunkSize) {
|
|
|
43489
43547
|
// ../../packages/sdk-ts/package.json
|
|
43490
43548
|
var package_default = {
|
|
43491
43549
|
name: "@warmhub/sdk-ts",
|
|
43492
|
-
version: "0.
|
|
43550
|
+
version: "0.93.0",
|
|
43493
43551
|
private: false,
|
|
43494
43552
|
type: "module",
|
|
43495
43553
|
description: "The TypeScript SDK for WarmHub — create repos, commit and query data, and compound knowledge with your AI agents.",
|
|
@@ -43698,6 +43756,7 @@ function normalizeClientFlags(flags) {
|
|
|
43698
43756
|
}
|
|
43699
43757
|
var DEFAULT_API_URL = "https://api.warmhub.ai";
|
|
43700
43758
|
var UNBATCHED_TRPC_PATHS = new Set([
|
|
43759
|
+
"commit.validate",
|
|
43701
43760
|
"repo.shapeInstanceCounts",
|
|
43702
43761
|
"thing.getMany",
|
|
43703
43762
|
"thing.headVersions"
|
|
@@ -44062,8 +44121,9 @@ class WarmHubClient {
|
|
|
44062
44121
|
}
|
|
44063
44122
|
createCompatibilityLink() {
|
|
44064
44123
|
return () => ({ op, next }) => {
|
|
44065
|
-
if (op.type !== "mutation")
|
|
44124
|
+
if (op.type !== "mutation" || op.path === "commit.validate") {
|
|
44066
44125
|
return next(op);
|
|
44126
|
+
}
|
|
44067
44127
|
return observable((observer) => {
|
|
44068
44128
|
let cancelled = false;
|
|
44069
44129
|
let downstream;
|
|
@@ -44333,6 +44393,21 @@ class WarmHubClient {
|
|
|
44333
44393
|
}
|
|
44334
44394
|
};
|
|
44335
44395
|
commit = {
|
|
44396
|
+
validate: async (orgName, repoName, operations, opts) => {
|
|
44397
|
+
try {
|
|
44398
|
+
return await this.trpc.commit.validate.mutate({
|
|
44399
|
+
orgName,
|
|
44400
|
+
repoName,
|
|
44401
|
+
committer: opts?.committer,
|
|
44402
|
+
message: opts?.message,
|
|
44403
|
+
componentRef: opts?.componentRef,
|
|
44404
|
+
operations: normalizeCommitValidationOperations(operations, opts?.skipExisting),
|
|
44405
|
+
includeWouldBeBody: opts?.includeWouldBeBody
|
|
44406
|
+
}, { signal: opts?.signal });
|
|
44407
|
+
} catch (error51) {
|
|
44408
|
+
throw toWarmHubError(error51);
|
|
44409
|
+
}
|
|
44410
|
+
},
|
|
44336
44411
|
apply: async (orgName, repoName, message, operations, opts) => {
|
|
44337
44412
|
try {
|
|
44338
44413
|
return await submitOperationsViaStream(this, {
|
|
@@ -46334,7 +46409,8 @@ var TOP_LEVEL_USER_INPUT_CODES = new Set([
|
|
|
46334
46409
|
"ILLEGAL_OP_SEQUENCE",
|
|
46335
46410
|
"CURSOR_EPOCH_INVALID",
|
|
46336
46411
|
"BUILTIN_SHAPE",
|
|
46337
|
-
"KIND_MISMATCH"
|
|
46412
|
+
"KIND_MISMATCH",
|
|
46413
|
+
"DEPENDENCY_FAILED"
|
|
46338
46414
|
]);
|
|
46339
46415
|
var CONFLICT_SHAPED_CODES = new Set([
|
|
46340
46416
|
"CONFLICT",
|
|
@@ -46755,6 +46831,22 @@ function toCliError(err) {
|
|
|
46755
46831
|
const message = err instanceof Error ? err.message : String(err);
|
|
46756
46832
|
return new CliError(1 /* Runtime */, "UNKNOWN", message, err);
|
|
46757
46833
|
}
|
|
46834
|
+
function containedDiagnosticError(diagnostics) {
|
|
46835
|
+
let best;
|
|
46836
|
+
let bestPriority = -1;
|
|
46837
|
+
for (const diagnostic of diagnostics) {
|
|
46838
|
+
const candidate = cliErrorFromOpFailure({
|
|
46839
|
+
status: "error",
|
|
46840
|
+
errors: [diagnostic]
|
|
46841
|
+
});
|
|
46842
|
+
const priority = candidate.code === 5 /* Auth */ ? 3 : candidate.code === 2 /* UserInput */ ? 2 : 1;
|
|
46843
|
+
if (priority > bestPriority) {
|
|
46844
|
+
best = candidate;
|
|
46845
|
+
bestPriority = priority;
|
|
46846
|
+
}
|
|
46847
|
+
}
|
|
46848
|
+
return best;
|
|
46849
|
+
}
|
|
46758
46850
|
function isFailedOpStatus(status) {
|
|
46759
46851
|
return status === "failed" || status === "error" || status === "rejected";
|
|
46760
46852
|
}
|
|
@@ -46768,12 +46860,14 @@ var OP_USER_INPUT_CODES = new Set([
|
|
|
46768
46860
|
"ILLEGAL_OP_SEQUENCE",
|
|
46769
46861
|
"CURSOR_EPOCH_INVALID",
|
|
46770
46862
|
"KIND_MISMATCH",
|
|
46771
|
-
"BUILTIN_SHAPE"
|
|
46863
|
+
"BUILTIN_SHAPE",
|
|
46864
|
+
"DEPENDENCY_FAILED"
|
|
46772
46865
|
]);
|
|
46773
46866
|
function cliErrorFromOpFailure(failure) {
|
|
46774
|
-
const
|
|
46775
|
-
const
|
|
46776
|
-
const
|
|
46867
|
+
const diagnostic = failure.errors?.[0] ?? failure.error;
|
|
46868
|
+
const code = diagnostic?.code ?? "BACKEND";
|
|
46869
|
+
const message = diagnostic?.message ?? `Operation on "${failure.name}" failed`;
|
|
46870
|
+
const errorCode = diagnostic?.code;
|
|
46777
46871
|
const make = (exit, kind, hint) => new CliError(exit, kind, message, undefined, hint, undefined, errorCode);
|
|
46778
46872
|
const authError = authCliError({
|
|
46779
46873
|
code,
|
|
@@ -48967,7 +49061,7 @@ var FLAG_CATALOG = [
|
|
|
48967
49061
|
spec: {
|
|
48968
49062
|
long: "dry-run",
|
|
48969
49063
|
type: "boolean",
|
|
48970
|
-
description: "
|
|
49064
|
+
description: "Emit a dispatch plan; commit submit instead runs server validation"
|
|
48971
49065
|
}
|
|
48972
49066
|
},
|
|
48973
49067
|
{
|
|
@@ -49198,7 +49292,8 @@ class DomainRegistry {
|
|
|
49198
49292
|
args: def.args,
|
|
49199
49293
|
flags: this.flagsToSpecs(def.flags ?? {}),
|
|
49200
49294
|
examples: def.examples,
|
|
49201
|
-
notes: def.notes
|
|
49295
|
+
notes: def.notes,
|
|
49296
|
+
dryRunBehavior: def.dryRunBehavior ?? "dispatch"
|
|
49202
49297
|
};
|
|
49203
49298
|
if (def.globalFlagOverrides) {
|
|
49204
49299
|
Object.defineProperty(spec, "globalFlagOverrides", {
|
|
@@ -49219,7 +49314,8 @@ class DomainRegistry {
|
|
|
49219
49314
|
examples: v.examples,
|
|
49220
49315
|
notes: v.notes,
|
|
49221
49316
|
verbAliases: v.verbAliases,
|
|
49222
|
-
passthroughFlags: v.passthroughFlags
|
|
49317
|
+
passthroughFlags: v.passthroughFlags,
|
|
49318
|
+
dryRunBehavior: v.dryRunBehavior ?? "dispatch"
|
|
49223
49319
|
};
|
|
49224
49320
|
if (v.rejectedFlags) {
|
|
49225
49321
|
Object.defineProperty(verbSpec, "rejectedFlags", {
|
|
@@ -50243,7 +50339,7 @@ function emitPartialPageHint(ctx, count, _nextCursor, _limit) {
|
|
|
50243
50339
|
}
|
|
50244
50340
|
|
|
50245
50341
|
// ../../packages/warmhub-cli/src/domains/commit-output-contract-id.ts
|
|
50246
|
-
var COMMIT_SUBMIT_OUTPUT_SCHEMA_ID = "wh.commit.submit.result/v0.
|
|
50342
|
+
var COMMIT_SUBMIT_OUTPUT_SCHEMA_ID = "wh.commit.submit.result/v0.2";
|
|
50247
50343
|
function identifyCommitSubmitOutput(value) {
|
|
50248
50344
|
if ("schema" in value) {
|
|
50249
50345
|
if (value.schema === COMMIT_SUBMIT_OUTPUT_SCHEMA_ID) {
|
|
@@ -54216,7 +54312,7 @@ function renderMutation(ctx, result) {
|
|
|
54216
54312
|
if (!("version" in operation) || typeof operation.version !== "number") {
|
|
54217
54313
|
throw new Error("Collection mutation returned no version-bearing operation");
|
|
54218
54314
|
}
|
|
54219
|
-
const isNoop = operation.operation === "noop";
|
|
54315
|
+
const isNoop = operation.status === "noop" || operation.operation === "noop";
|
|
54220
54316
|
renderSingleOpSuccess(ctx.out, ctx.colors, ctx.chars, operation, {
|
|
54221
54317
|
marker: isNoop ? "=" : "+",
|
|
54222
54318
|
color: isNoop ? ctx.colors.dim : ctx.colors.green,
|
|
@@ -54932,26 +55028,40 @@ function renderPrettyReceipt(ctx, receipt, committer) {
|
|
|
54932
55028
|
const record2 = operation;
|
|
54933
55029
|
const operationKind = String(record2.operation ?? "operation");
|
|
54934
55030
|
const failed = isFailedOpStatus(record2.status);
|
|
54935
|
-
const marker = failed ? "!" : operationKind === "add" ? "+" : operationKind === "revise" ? "~" : operationKind === "reaffirm" ? "±" : "-";
|
|
54936
|
-
const
|
|
55031
|
+
const marker = failed ? "!" : record2.status === "noop" ? "-" : operationKind === "add" ? "+" : operationKind === "revise" ? "~" : operationKind === "reaffirm" ? "±" : "-";
|
|
55032
|
+
const errors3 = Array.isArray(record2.errors) ? record2.errors : undefined;
|
|
55033
|
+
const error51 = errors3?.[0] ?? (typeof record2.error === "object" && record2.error !== null ? record2.error : undefined);
|
|
54937
55034
|
const errorSummary = failed ? ` ${error51?.message ?? error51?.code ?? "failed"}` : "";
|
|
54938
55035
|
ctx.out(` ${marker} ${displayName(c, String(record2.name ?? record2.resolvedName ?? "(unnamed)"))}${errorSummary}`);
|
|
54939
55036
|
renderWarningLine(ctx.out, c, ctx.chars, operation);
|
|
54940
55037
|
}
|
|
54941
55038
|
}
|
|
54942
55039
|
function allReceiptOperationsFailed(receipts) {
|
|
54943
|
-
|
|
54944
|
-
|
|
55040
|
+
let operationCount = 0;
|
|
55041
|
+
for (const receipt of receipts) {
|
|
55042
|
+
for (const operation of receipt.operations) {
|
|
55043
|
+
operationCount++;
|
|
55044
|
+
if (!isFailedOpStatus(operation.status)) {
|
|
55045
|
+
return false;
|
|
55046
|
+
}
|
|
55047
|
+
}
|
|
55048
|
+
}
|
|
55049
|
+
return operationCount > 0;
|
|
54945
55050
|
}
|
|
54946
55051
|
function allFailedReceiptError(receipts) {
|
|
54947
|
-
|
|
54948
|
-
|
|
54949
|
-
|
|
54950
|
-
|
|
54951
|
-
|
|
54952
|
-
|
|
54953
|
-
|
|
54954
|
-
|
|
55052
|
+
const failures = [];
|
|
55053
|
+
for (const receipt of receipts) {
|
|
55054
|
+
for (const operation of receipt.operations) {
|
|
55055
|
+
const record2 = operation;
|
|
55056
|
+
failures.push({
|
|
55057
|
+
name: typeof record2.name === "string" ? record2.name : undefined,
|
|
55058
|
+
status: typeof record2.status === "string" ? record2.status : undefined,
|
|
55059
|
+
error: typeof record2.error === "object" && record2.error !== null ? record2.error : undefined,
|
|
55060
|
+
errors: Array.isArray(record2.errors) ? record2.errors : undefined
|
|
55061
|
+
});
|
|
55062
|
+
}
|
|
55063
|
+
}
|
|
55064
|
+
return cliErrorFromAllFailed(failures);
|
|
54955
55065
|
}
|
|
54956
55066
|
var handleReceiptLookup = async (ctx, { args }) => {
|
|
54957
55067
|
const eventRequestId = args[0];
|
|
@@ -54992,6 +55102,9 @@ var createFlags3 = {
|
|
|
54992
55102
|
"return-repo-seq": flag.boolean({
|
|
54993
55103
|
description: "return the sequence allocated to this caller's own successful write; omitted for noops and all-failed writes"
|
|
54994
55104
|
}),
|
|
55105
|
+
"include-would-be-body": flag.boolean({
|
|
55106
|
+
description: "Include projected resulting bodies in dry-run output when disclosure rules permit."
|
|
55107
|
+
}),
|
|
54995
55108
|
"chunk-size": flag.number({
|
|
54996
55109
|
description: `Streamed ops per append chunk for --stream or .jsonl --file (default: ${DEFAULT_STREAM_APPEND_CHUNK_SIZE}, max: ${MAX_STREAM_APPEND_OPERATION_COUNT})`
|
|
54997
55110
|
}),
|
|
@@ -55059,65 +55172,6 @@ var createFlags3 = {
|
|
|
55059
55172
|
})
|
|
55060
55173
|
};
|
|
55061
55174
|
|
|
55062
|
-
// ../../packages/warmhub-cli/src/domains/commit-submit-handler.ts
|
|
55063
|
-
import { readFile as readFile2 } from "node:fs/promises";
|
|
55064
|
-
|
|
55065
|
-
// ../../packages/warmhub-cli/src/commit-payload-validate.ts
|
|
55066
|
-
var NUL = String.fromCharCode(0);
|
|
55067
|
-
function findInvalidControlByte(data, rootLabel = "data") {
|
|
55068
|
-
const segs = [];
|
|
55069
|
-
const pos = visit(data, segs);
|
|
55070
|
-
return pos === -1 ? null : { path: buildPath(rootLabel, segs), position: pos };
|
|
55071
|
-
}
|
|
55072
|
-
function visit(value, segs) {
|
|
55073
|
-
if (typeof value === "string")
|
|
55074
|
-
return value.indexOf(NUL);
|
|
55075
|
-
if (value === null || typeof value !== "object")
|
|
55076
|
-
return -1;
|
|
55077
|
-
if (Array.isArray(value)) {
|
|
55078
|
-
for (let i = 0;i < value.length; i++) {
|
|
55079
|
-
segs.push(i);
|
|
55080
|
-
const p = visit(value[i], segs);
|
|
55081
|
-
if (p !== -1)
|
|
55082
|
-
return p;
|
|
55083
|
-
segs.pop();
|
|
55084
|
-
}
|
|
55085
|
-
return -1;
|
|
55086
|
-
}
|
|
55087
|
-
const keys = Object.keys(value);
|
|
55088
|
-
for (let i = 0;i < keys.length; i++) {
|
|
55089
|
-
const k = keys[i];
|
|
55090
|
-
segs.push(k);
|
|
55091
|
-
const ki = k.indexOf(NUL);
|
|
55092
|
-
if (ki !== -1)
|
|
55093
|
-
return ki;
|
|
55094
|
-
const p = visit(value[k], segs);
|
|
55095
|
-
if (p !== -1)
|
|
55096
|
-
return p;
|
|
55097
|
-
segs.pop();
|
|
55098
|
-
}
|
|
55099
|
-
return -1;
|
|
55100
|
-
}
|
|
55101
|
-
function buildPath(root, segs) {
|
|
55102
|
-
let out = root;
|
|
55103
|
-
for (const s of segs)
|
|
55104
|
-
out += typeof s === "number" ? `[${s}]` : `.${s}`;
|
|
55105
|
-
return out;
|
|
55106
|
-
}
|
|
55107
|
-
function formatInvalidControlByteMessage(hit, locator) {
|
|
55108
|
-
return {
|
|
55109
|
-
message: `${locator}: ${hit.path} contains literal U+0000 byte at position ${hit.position}, ` + "which PostgreSQL `text` cannot store (SQLSTATE 22P05).",
|
|
55110
|
-
hint: "Strip NUL bytes before submit, e.g. `.replace(/\\u0000/g, '')`, or pass --allow-nul-bytes to send anyway."
|
|
55111
|
-
};
|
|
55112
|
-
}
|
|
55113
|
-
function assertNoNulBytes(data, locator) {
|
|
55114
|
-
const hit = findInvalidControlByte(data);
|
|
55115
|
-
if (!hit)
|
|
55116
|
-
return;
|
|
55117
|
-
const { message, hint } = formatInvalidControlByteMessage(hit, locator);
|
|
55118
|
-
throw new CliError(2 /* UserInput */, "USER_INPUT", message, undefined, hint);
|
|
55119
|
-
}
|
|
55120
|
-
|
|
55121
55175
|
// ../../packages/warmhub-cli/src/domains/commit-submit-template.ts
|
|
55122
55176
|
import { writeFile } from "node:fs/promises";
|
|
55123
55177
|
var WRITE_TEMPLATE_KINDS = ["thing", "assertion"];
|
|
@@ -55369,7 +55423,7 @@ function buildRetractOperations(input) {
|
|
|
55369
55423
|
}
|
|
55370
55424
|
function rejectLegacyLifecycleOperations(operations) {
|
|
55371
55425
|
const legacy = operations.find((op) => {
|
|
55372
|
-
const operation = op
|
|
55426
|
+
const operation = op?.operation;
|
|
55373
55427
|
return operation === "remove" || operation === "deactivate";
|
|
55374
55428
|
});
|
|
55375
55429
|
if (!legacy)
|
|
@@ -55457,12 +55511,91 @@ function requireCommitSourceValue(source, value) {
|
|
|
55457
55511
|
return value;
|
|
55458
55512
|
throw new Error(`Missing value for selected commit operation source ${source}`);
|
|
55459
55513
|
}
|
|
55514
|
+
function assertSubmitDeliveryFlags(args) {
|
|
55515
|
+
if (args.dryRun)
|
|
55516
|
+
return;
|
|
55517
|
+
const streamed = args.streamInput || args.jsonlFile;
|
|
55518
|
+
if (args.chunkSize !== undefined && !streamed) {
|
|
55519
|
+
throw new CliError(2 /* UserInput */, "USER_INPUT", "--chunk-size requires --stream or a .jsonl --file.");
|
|
55520
|
+
}
|
|
55521
|
+
if (args.progressRequested && !streamed) {
|
|
55522
|
+
throw new CliError(2 /* UserInput */, "USER_INPUT", "--progress requires --stream or a .jsonl --file.");
|
|
55523
|
+
}
|
|
55524
|
+
if (args.streamId !== undefined && !streamed) {
|
|
55525
|
+
throw new CliError(2 /* UserInput */, "USER_INPUT", "--stream-id requires --stream or a .jsonl --file.");
|
|
55526
|
+
}
|
|
55527
|
+
if (args.timingOut !== undefined && !args.jsonlFile) {
|
|
55528
|
+
throw new CliError(2 /* UserInput */, "USER_INPUT", "--timing-out requires a .jsonl --file.", undefined, "wh commit submit --file ops.jsonl --timing-out timing.json --stream-id import-1 --skip-existing -m 'Import operations' --repo acme/world");
|
|
55529
|
+
}
|
|
55530
|
+
if (streamed && args.streamId === undefined) {
|
|
55531
|
+
throw new CliError(2 /* UserInput */, "USER_INPUT", "JSONL streaming requires --stream-id.", undefined, 'Example: wh commit submit --file ops.jsonl --stream-id bulk-2026-06-04 --skip-existing -m "Bulk import" --repo acme/world');
|
|
55532
|
+
}
|
|
55533
|
+
if (streamed && !args.skipExisting) {
|
|
55534
|
+
throw new CliError(2 /* UserInput */, "USER_INPUT", "JSONL streaming requires --skip-existing.", undefined, 'Example: wh commit submit --file ops.jsonl --stream-id bulk-2026-06-04 --skip-existing -m "Bulk import" --repo acme/world');
|
|
55535
|
+
}
|
|
55536
|
+
}
|
|
55460
55537
|
|
|
55461
55538
|
// ../../packages/warmhub-cli/src/domains/commit-submit-stream.ts
|
|
55462
55539
|
import { createReadStream as createReadStream2 } from "node:fs";
|
|
55463
55540
|
import { writeFile as writeFile2 } from "node:fs/promises";
|
|
55464
55541
|
import { createInterface as createInterface2 } from "node:readline";
|
|
55465
55542
|
|
|
55543
|
+
// ../../packages/warmhub-cli/src/commit-payload-validate.ts
|
|
55544
|
+
var NUL = String.fromCharCode(0);
|
|
55545
|
+
function findInvalidControlByte(data, rootLabel = "data") {
|
|
55546
|
+
const segs = [];
|
|
55547
|
+
const pos = visit(data, segs);
|
|
55548
|
+
return pos === -1 ? null : { path: buildPath(rootLabel, segs), position: pos };
|
|
55549
|
+
}
|
|
55550
|
+
function visit(value, segs) {
|
|
55551
|
+
if (typeof value === "string")
|
|
55552
|
+
return value.indexOf(NUL);
|
|
55553
|
+
if (value === null || typeof value !== "object")
|
|
55554
|
+
return -1;
|
|
55555
|
+
if (Array.isArray(value)) {
|
|
55556
|
+
for (let i = 0;i < value.length; i++) {
|
|
55557
|
+
segs.push(i);
|
|
55558
|
+
const p = visit(value[i], segs);
|
|
55559
|
+
if (p !== -1)
|
|
55560
|
+
return p;
|
|
55561
|
+
segs.pop();
|
|
55562
|
+
}
|
|
55563
|
+
return -1;
|
|
55564
|
+
}
|
|
55565
|
+
const keys = Object.keys(value);
|
|
55566
|
+
for (let i = 0;i < keys.length; i++) {
|
|
55567
|
+
const k = keys[i];
|
|
55568
|
+
segs.push(k);
|
|
55569
|
+
const ki = k.indexOf(NUL);
|
|
55570
|
+
if (ki !== -1)
|
|
55571
|
+
return ki;
|
|
55572
|
+
const p = visit(value[k], segs);
|
|
55573
|
+
if (p !== -1)
|
|
55574
|
+
return p;
|
|
55575
|
+
segs.pop();
|
|
55576
|
+
}
|
|
55577
|
+
return -1;
|
|
55578
|
+
}
|
|
55579
|
+
function buildPath(root, segs) {
|
|
55580
|
+
let out = root;
|
|
55581
|
+
for (const s of segs)
|
|
55582
|
+
out += typeof s === "number" ? `[${s}]` : `.${s}`;
|
|
55583
|
+
return out;
|
|
55584
|
+
}
|
|
55585
|
+
function formatInvalidControlByteMessage(hit, locator) {
|
|
55586
|
+
return {
|
|
55587
|
+
message: `${locator}: ${hit.path} contains literal U+0000 byte at position ${hit.position}, ` + "which PostgreSQL `text` cannot store (SQLSTATE 22P05).",
|
|
55588
|
+
hint: "Strip NUL bytes before submit, e.g. `.replace(/\\u0000/g, '')`, or pass --allow-nul-bytes to send anyway."
|
|
55589
|
+
};
|
|
55590
|
+
}
|
|
55591
|
+
function assertNoNulBytes(data, locator) {
|
|
55592
|
+
const hit = findInvalidControlByte(data);
|
|
55593
|
+
if (!hit)
|
|
55594
|
+
return;
|
|
55595
|
+
const { message, hint } = formatInvalidControlByteMessage(hit, locator);
|
|
55596
|
+
throw new CliError(2 /* UserInput */, "USER_INPUT", message, undefined, hint);
|
|
55597
|
+
}
|
|
55598
|
+
|
|
55466
55599
|
// ../../packages/warmhub-cli/src/domains/commit-submit-utils.ts
|
|
55467
55600
|
var DEFAULT_JSONL_STREAM_CHUNK_SIZE = Math.max(1, Math.min(MAX_STREAM_APPEND_OPERATION_COUNT, Number(process.env.WH_STREAM_CHUNK_SIZE) || DEFAULT_STREAM_APPEND_CHUNK_SIZE));
|
|
55468
55601
|
function resolveJsonlStreamChunkSize(chunkSize) {
|
|
@@ -55713,9 +55846,9 @@ async function applyJsonlCommit(ctx, args) {
|
|
|
55713
55846
|
createdByEmail = appendResult.createdByEmail ?? createdByEmail;
|
|
55714
55847
|
repoSeq = appendResult.repoSeq ?? repoSeq;
|
|
55715
55848
|
aggregate.addChunk({
|
|
55716
|
-
|
|
55849
|
+
result: appendResult,
|
|
55717
55850
|
chunkStart,
|
|
55718
|
-
|
|
55851
|
+
submittedOperations: operationsChunk
|
|
55719
55852
|
});
|
|
55720
55853
|
} catch (cause) {
|
|
55721
55854
|
const pendingOutcome = isDefiniteStreamAppendRejection(cause) ? "absent" : "unknown";
|
|
@@ -55894,6 +56027,219 @@ function isErrnoException(error51) {
|
|
|
55894
56027
|
return typeof code === "string" && /^E[A-Z0-9]+$/.test(code) && typeof syscall === "string";
|
|
55895
56028
|
}
|
|
55896
56029
|
|
|
56030
|
+
// ../../packages/warmhub-cli/src/domains/commit-validation-execute.ts
|
|
56031
|
+
import { writeFile as writeFile3 } from "node:fs/promises";
|
|
56032
|
+
|
|
56033
|
+
// ../../packages/warmhub-cli/src/domains/commit-validation-input.ts
|
|
56034
|
+
import { createReadStream as createReadStream3 } from "node:fs";
|
|
56035
|
+
import { readFile as readFile2 } from "node:fs/promises";
|
|
56036
|
+
import { createInterface as createInterface3 } from "node:readline";
|
|
56037
|
+
async function readValidationJsonlFile(path2, allowNulBytes) {
|
|
56038
|
+
try {
|
|
56039
|
+
return await readValidationJsonl(createReadStream3(path2, { encoding: "utf-8" }), "--file", allowNulBytes, `Operations file '${path2}' did not contain any JSONL operations`);
|
|
56040
|
+
} catch (error51) {
|
|
56041
|
+
if (isErrnoException(error51)) {
|
|
56042
|
+
throw new CliError(2 /* UserInput */, "USER_INPUT", `Cannot read file '${path2}': ${error51.message}`, undefined, "Check that the file path is correct and the file exists.");
|
|
56043
|
+
}
|
|
56044
|
+
throw error51;
|
|
56045
|
+
}
|
|
56046
|
+
}
|
|
56047
|
+
async function readValidationJsonlStdin(ctx, allowNulBytes) {
|
|
56048
|
+
const input = ctx.stdin ?? process.stdin;
|
|
56049
|
+
if (isTTY(input)) {
|
|
56050
|
+
throw new CliError(2 /* UserInput */, "USER_INPUT", "No JSONL operations provided on stdin.", undefined, "Pipe JSONL operations via stdin: producer | wh commit submit --stream --dry-run --repo acme/world");
|
|
56051
|
+
}
|
|
56052
|
+
return readValidationJsonl(input, "--stream", allowNulBytes, "No JSONL operations provided on stdin.");
|
|
56053
|
+
}
|
|
56054
|
+
async function readValidationJsonl(input, label, allowNulBytes, emptyMessage) {
|
|
56055
|
+
const operations = [];
|
|
56056
|
+
const lines = createInterface3({ input, crlfDelay: Infinity });
|
|
56057
|
+
let lineNumber = 0;
|
|
56058
|
+
try {
|
|
56059
|
+
for await (const rawLine of lines) {
|
|
56060
|
+
lineNumber += 1;
|
|
56061
|
+
const trimmed = rawLine.trim();
|
|
56062
|
+
if (!trimmed)
|
|
56063
|
+
continue;
|
|
56064
|
+
assertValidationOperationCount(operations.length + 1);
|
|
56065
|
+
const operation = safeParseJson(trimmed, `${label} JSONL line ${lineNumber}`);
|
|
56066
|
+
assertStructurallyValidOperation(operation, `${label} JSONL line ${lineNumber}`);
|
|
56067
|
+
rejectLegacyLifecycleOperations([operation]);
|
|
56068
|
+
assertValidationOperationData(operation, `${label} JSONL line ${lineNumber}`, allowNulBytes);
|
|
56069
|
+
operations.push(operation);
|
|
56070
|
+
}
|
|
56071
|
+
} finally {
|
|
56072
|
+
lines.close();
|
|
56073
|
+
}
|
|
56074
|
+
if (operations.length === 0) {
|
|
56075
|
+
throw new CliError(2 /* UserInput */, "USER_INPUT", emptyMessage);
|
|
56076
|
+
}
|
|
56077
|
+
return operations;
|
|
56078
|
+
}
|
|
56079
|
+
async function readValidationJsonArrayFile(path2) {
|
|
56080
|
+
try {
|
|
56081
|
+
return await readFile2(path2, "utf-8");
|
|
56082
|
+
} catch (error51) {
|
|
56083
|
+
throw new CliError(2 /* UserInput */, "USER_INPUT", `Cannot read file '${path2}': ${error51 instanceof Error ? error51.message : String(error51)}`, undefined, "Check that the file path is correct and the file exists.");
|
|
56084
|
+
}
|
|
56085
|
+
}
|
|
56086
|
+
function assertValidationOperationData(operation, source, allowNulBytes) {
|
|
56087
|
+
if (allowNulBytes)
|
|
56088
|
+
return;
|
|
56089
|
+
assertNoNulBytes("data" in operation ? operation.data : undefined, source);
|
|
56090
|
+
}
|
|
56091
|
+
function assertPreparedCommitOperations(args) {
|
|
56092
|
+
if (args.streamInput && !args.dryRun || args.operations.length === 0)
|
|
56093
|
+
return;
|
|
56094
|
+
rejectLegacyLifecycleOperations(args.operations);
|
|
56095
|
+
const source = args.operationSource === "--file" ? args.opsFile : args.operationSource;
|
|
56096
|
+
if (args.dryRun) {
|
|
56097
|
+
for (const [index, operation] of args.operations.entries()) {
|
|
56098
|
+
assertStructurallyValidOperation(operation, `${source} op ${index}`);
|
|
56099
|
+
}
|
|
56100
|
+
}
|
|
56101
|
+
if (args.dryRun)
|
|
56102
|
+
assertValidationOperationCount(args.operations.length);
|
|
56103
|
+
else
|
|
56104
|
+
assertWithinStreamOpLimit(args.operations.length);
|
|
56105
|
+
if (args.allowNulBytes)
|
|
56106
|
+
return;
|
|
56107
|
+
for (const [index, operation] of args.operations.entries()) {
|
|
56108
|
+
const namePart = operation.name ? ` (${operation.name})` : "";
|
|
56109
|
+
assertValidationOperationData(operation, `${source} op ${index}${namePart}`, false);
|
|
56110
|
+
}
|
|
56111
|
+
}
|
|
56112
|
+
function assertStructurallyValidOperation(operation, source) {
|
|
56113
|
+
try {
|
|
56114
|
+
createCommitValidateInput("_", "_", [operation]);
|
|
56115
|
+
} catch (error51) {
|
|
56116
|
+
throw new CliError(2 /* UserInput */, "USER_INPUT", `${source}: ${error51 instanceof Error ? error51.message : String(error51)}`);
|
|
56117
|
+
}
|
|
56118
|
+
}
|
|
56119
|
+
function assertValidationOperationCount(operationCount) {
|
|
56120
|
+
if (operationCount <= MAX_COMMIT_VALIDATION_OPERATIONS)
|
|
56121
|
+
return;
|
|
56122
|
+
throw new CliError(2 /* UserInput */, "USER_INPUT", `Commit validation accepts at most ${MAX_COMMIT_VALIDATION_OPERATIONS} operations (${operationCount} requested).`, undefined, "Split the preview into smaller current-commit units.");
|
|
56123
|
+
}
|
|
56124
|
+
function createBoundedCommitValidateInput(org, repo, operations, options) {
|
|
56125
|
+
assertValidationOperationCount(operations.length);
|
|
56126
|
+
const input = createCommitValidateInput(org, repo, operations, options);
|
|
56127
|
+
const encodedBytes = commitValidateRequestBodyBytes(input);
|
|
56128
|
+
if (encodedBytes > MAX_COMMIT_VALIDATION_ENCODED_BYTES) {
|
|
56129
|
+
throw new CliError(2 /* UserInput */, "USER_INPUT", `Commit validation request exceeds the ${MAX_COMMIT_VALIDATION_ENCODED_BYTES}-byte encoded limit (${encodedBytes} bytes).`, undefined, "Split the preview into smaller current-commit units.");
|
|
56130
|
+
}
|
|
56131
|
+
return input;
|
|
56132
|
+
}
|
|
56133
|
+
|
|
56134
|
+
// ../../packages/warmhub-cli/src/domains/commit-validation-render.ts
|
|
56135
|
+
function renderCommitValidation(ctx, result) {
|
|
56136
|
+
if (ctx.format === "json") {
|
|
56137
|
+
ctx.out(JSON.stringify(result));
|
|
56138
|
+
} else if (ctx.format === "jsonl") {
|
|
56139
|
+
for (const operation of result.operations) {
|
|
56140
|
+
ctx.out(JSON.stringify({ type: "operation", ...operation }));
|
|
56141
|
+
}
|
|
56142
|
+
const { operations: _operations, ...summary } = result;
|
|
56143
|
+
ctx.out(JSON.stringify({ type: "summary", ...summary }));
|
|
56144
|
+
} else {
|
|
56145
|
+
renderPrettyValidation(ctx, result);
|
|
56146
|
+
}
|
|
56147
|
+
const error51 = containedDiagnosticError(validationDiagnostics(result));
|
|
56148
|
+
if (error51)
|
|
56149
|
+
ctx.requestedExitCode = error51.code;
|
|
56150
|
+
}
|
|
56151
|
+
function renderPrettyValidation(ctx, result) {
|
|
56152
|
+
const c = ctx.colors;
|
|
56153
|
+
const baseline = result.baseline.kind === "repo_seq" ? `repo sequence ${result.baseline.repoSeq}` : "withheld";
|
|
56154
|
+
ctx.out(`${c.dim}validation baseline${c.reset} ${baseline}`);
|
|
56155
|
+
for (const caveat of result.caveats) {
|
|
56156
|
+
ctx.out(` ${ctx.chars.warn} ${c.dim}${caveat.code}${c.reset} ${caveat.message}`);
|
|
56157
|
+
}
|
|
56158
|
+
for (const operation of result.operations) {
|
|
56159
|
+
const marker = markerFor(operation.status, ctx);
|
|
56160
|
+
ctx.out(`${marker} [${operation.opIndex}] ${operation.operation} ${displayName(c, operation.name)} ${operation.status}`);
|
|
56161
|
+
renderDiagnostics(ctx, operation.status === "error" ? operation.errors : undefined);
|
|
56162
|
+
for (const effect of operation.effects ?? []) {
|
|
56163
|
+
renderEffect(ctx, effect);
|
|
56164
|
+
}
|
|
56165
|
+
}
|
|
56166
|
+
ctx.out(`${c.bold}${result.canCommit ? "can commit" : "cannot commit"}${c.reset} — ${result.counts.wouldApply} would apply, ${result.counts.noop} noop, ${result.counts.error} error`);
|
|
56167
|
+
}
|
|
56168
|
+
function renderEffect(ctx, effect) {
|
|
56169
|
+
ctx.out(` ${markerFor(effect.status, ctx)} effect ${effect.effectIndex}: ${effect.operation} ${displayName(ctx.colors, effect.name)} ${effect.status}`);
|
|
56170
|
+
renderDiagnostics(ctx, "errors" in effect ? effect.errors : undefined, 6);
|
|
56171
|
+
}
|
|
56172
|
+
function renderDiagnostics(ctx, diagnostics, indent = 4) {
|
|
56173
|
+
for (const diagnostic of diagnostics ?? []) {
|
|
56174
|
+
ctx.out(`${" ".repeat(indent)}${diagnostic.code}: ${diagnostic.message}`);
|
|
56175
|
+
}
|
|
56176
|
+
}
|
|
56177
|
+
function markerFor(status, ctx) {
|
|
56178
|
+
if (status === "error" || status === "discarded")
|
|
56179
|
+
return ctx.chars.cross;
|
|
56180
|
+
if (status === "noop")
|
|
56181
|
+
return ctx.chars.warn;
|
|
56182
|
+
return ctx.chars.check;
|
|
56183
|
+
}
|
|
56184
|
+
function validationDiagnostics(result) {
|
|
56185
|
+
const diagnostics = [];
|
|
56186
|
+
for (const operation of result.operations) {
|
|
56187
|
+
if (operation.status === "error")
|
|
56188
|
+
diagnostics.push(...operation.errors);
|
|
56189
|
+
for (const effect of operation.effects ?? []) {
|
|
56190
|
+
if ("errors" in effect)
|
|
56191
|
+
diagnostics.push(...effect.errors);
|
|
56192
|
+
}
|
|
56193
|
+
}
|
|
56194
|
+
return diagnostics;
|
|
56195
|
+
}
|
|
56196
|
+
|
|
56197
|
+
// ../../packages/warmhub-cli/src/domains/commit-validation-execute.ts
|
|
56198
|
+
async function executeCommitValidation(ctx, args) {
|
|
56199
|
+
const options = {
|
|
56200
|
+
...args.message !== undefined ? { message: args.message } : {},
|
|
56201
|
+
...args.committer !== undefined ? { committer: args.committer } : {},
|
|
56202
|
+
...args.skipExisting ? { skipExisting: true } : {},
|
|
56203
|
+
...args.includeWouldBeBody ? { includeWouldBeBody: true } : {},
|
|
56204
|
+
...ctx.signal ? { signal: ctx.signal } : {}
|
|
56205
|
+
};
|
|
56206
|
+
createBoundedCommitValidateInput(args.org, args.repo, args.operations, options);
|
|
56207
|
+
const unusedDeliveryControls = [
|
|
56208
|
+
args.chunkSize !== undefined ? "--chunk-size" : undefined,
|
|
56209
|
+
args.streamId !== undefined ? "--stream-id" : undefined,
|
|
56210
|
+
args.submissionId !== undefined ? "--submission-id" : undefined,
|
|
56211
|
+
args.returnRepoSeq ? "--return-repo-seq" : undefined
|
|
56212
|
+
].filter((value) => value !== undefined);
|
|
56213
|
+
if (unusedDeliveryControls.length > 0) {
|
|
56214
|
+
ctx.err(`dry-run validates one complete request; delivery controls are unused: ${unusedDeliveryControls.join(", ")}`);
|
|
56215
|
+
}
|
|
56216
|
+
if (args.progressRequested) {
|
|
56217
|
+
ctx.err("validation: waiting for server evaluation");
|
|
56218
|
+
}
|
|
56219
|
+
const startedAt = performance.now();
|
|
56220
|
+
const validation = await ctx.client.commit.validate(args.org, args.repo, args.operations, options);
|
|
56221
|
+
const validationMs = performance.now() - startedAt;
|
|
56222
|
+
if (args.progressRequested)
|
|
56223
|
+
ctx.err("validation: complete");
|
|
56224
|
+
if (args.timingOut) {
|
|
56225
|
+
try {
|
|
56226
|
+
await writeFile3(args.timingOut, JSON.stringify({
|
|
56227
|
+
benchmarkId: process.env.WH_BENCHMARK_ID ?? undefined,
|
|
56228
|
+
org: args.org,
|
|
56229
|
+
repo: args.repo,
|
|
56230
|
+
opCount: args.operations.length,
|
|
56231
|
+
chunkCount: 1,
|
|
56232
|
+
validationMs,
|
|
56233
|
+
totalMs: validationMs,
|
|
56234
|
+
phases: { validationMs }
|
|
56235
|
+
}));
|
|
56236
|
+
} catch (error51) {
|
|
56237
|
+
ctx.err(` warn: failed to write timing sidecar: ${String(error51)}`);
|
|
56238
|
+
}
|
|
56239
|
+
}
|
|
56240
|
+
renderCommitValidation(ctx, validation);
|
|
56241
|
+
}
|
|
56242
|
+
|
|
55897
56243
|
// ../../packages/warmhub-cli/src/domains/commit-submit-handler.ts
|
|
55898
56244
|
var handleSubmit = async (ctx, { flags, args }) => {
|
|
55899
56245
|
const { org, repo } = parseOrgRepo(getRepoRef(ctx) ?? args[0], ctx.config);
|
|
@@ -55909,7 +56255,10 @@ var handleSubmit = async (ctx, { flags, args }) => {
|
|
|
55909
56255
|
const allowNulBytes = flags["allow-nul-bytes"] === true;
|
|
55910
56256
|
const timingOut = flags["timing-out"];
|
|
55911
56257
|
const streamId = flags["stream-id"];
|
|
55912
|
-
const
|
|
56258
|
+
const submissionIdFlag = flags["submission-id"];
|
|
56259
|
+
if (flags["include-would-be-body"] === true && !ctx.dryRun) {
|
|
56260
|
+
throw new CliError(2 /* UserInput */, "USER_INPUT", "--include-would-be-body requires --dry-run.", undefined, "Add --dry-run to preview projected bodies, or remove --include-would-be-body for a real commit.");
|
|
56261
|
+
}
|
|
55913
56262
|
const addNames = flags.add ?? [];
|
|
55914
56263
|
const reviseName = flags.revise;
|
|
55915
56264
|
const retractNames = flags.retract ?? [];
|
|
@@ -55970,27 +56319,22 @@ var handleSubmit = async (ctx, { flags, args }) => {
|
|
|
55970
56319
|
name: flags.name !== undefined,
|
|
55971
56320
|
members: flags.members !== undefined
|
|
55972
56321
|
});
|
|
55973
|
-
|
|
55974
|
-
|
|
55975
|
-
|
|
55976
|
-
|
|
55977
|
-
|
|
55978
|
-
|
|
55979
|
-
|
|
55980
|
-
|
|
55981
|
-
|
|
55982
|
-
|
|
55983
|
-
throw new CliError(2 /* UserInput */, "USER_INPUT", "--timing-out requires a .jsonl --file.", undefined, "wh commit submit --file ops.jsonl --timing-out timing.json --stream-id import-1 --skip-existing -m 'Import operations' --repo acme/world");
|
|
55984
|
-
}
|
|
55985
|
-
if ((streamInput || jsonlFile) && streamId === undefined) {
|
|
55986
|
-
throw new CliError(2 /* UserInput */, "USER_INPUT", "JSONL streaming requires --stream-id.", undefined, 'Example: wh commit submit --file ops.jsonl --stream-id bulk-2026-06-04 --skip-existing -m "Bulk import" --repo acme/world');
|
|
55987
|
-
}
|
|
55988
|
-
if ((streamInput || jsonlFile) && !skipExisting) {
|
|
55989
|
-
throw new CliError(2 /* UserInput */, "USER_INPUT", "JSONL streaming requires --skip-existing.", undefined, 'Example: wh commit submit --file ops.jsonl --stream-id bulk-2026-06-04 --skip-existing -m "Bulk import" --repo acme/world');
|
|
55990
|
-
}
|
|
56322
|
+
assertSubmitDeliveryFlags({
|
|
56323
|
+
dryRun: ctx.dryRun === true,
|
|
56324
|
+
streamInput,
|
|
56325
|
+
jsonlFile,
|
|
56326
|
+
chunkSize,
|
|
56327
|
+
progressRequested,
|
|
56328
|
+
streamId,
|
|
56329
|
+
timingOut,
|
|
56330
|
+
skipExisting
|
|
56331
|
+
});
|
|
55991
56332
|
let operations;
|
|
56333
|
+
if (ctx.dryRun && progressRequested) {
|
|
56334
|
+
ctx.err("validation: acquiring operations");
|
|
56335
|
+
}
|
|
55992
56336
|
if (operationSource === "--stream") {
|
|
55993
|
-
operations = [];
|
|
56337
|
+
operations = ctx.dryRun ? await readValidationJsonlStdin(ctx, allowNulBytes) : [];
|
|
55994
56338
|
} else if (operationSource === "--type") {
|
|
55995
56339
|
const selectedCollectionType = requireCommitSourceValue(operationSource, collectionType);
|
|
55996
56340
|
if (!flags.name) {
|
|
@@ -56026,14 +56370,9 @@ var handleSubmit = async (ctx, { flags, args }) => {
|
|
|
56026
56370
|
} else if (operationSource === "--file") {
|
|
56027
56371
|
const selectedOpsFile = requireCommitSourceValue(operationSource, opsFile);
|
|
56028
56372
|
if (selectedOpsFile.endsWith(".jsonl")) {
|
|
56029
|
-
operations = [];
|
|
56373
|
+
operations = ctx.dryRun ? await readValidationJsonlFile(selectedOpsFile, allowNulBytes) : [];
|
|
56030
56374
|
} else {
|
|
56031
|
-
|
|
56032
|
-
try {
|
|
56033
|
-
file2 = await readFile2(selectedOpsFile, "utf-8");
|
|
56034
|
-
} catch (e) {
|
|
56035
|
-
throw new CliError(2 /* UserInput */, "USER_INPUT", `Cannot read file '${selectedOpsFile}': ${e instanceof Error ? e.message : String(e)}`, undefined, "Check that the file path is correct and the file exists.");
|
|
56036
|
-
}
|
|
56375
|
+
const file2 = await readValidationJsonArrayFile(selectedOpsFile);
|
|
56037
56376
|
operations = parseJsonArray(file2, "--file contents");
|
|
56038
56377
|
}
|
|
56039
56378
|
} else if (operationSource === "--add") {
|
|
@@ -56081,19 +56420,34 @@ var handleSubmit = async (ctx, { flags, args }) => {
|
|
|
56081
56420
|
} else {
|
|
56082
56421
|
operations = [];
|
|
56083
56422
|
}
|
|
56084
|
-
|
|
56085
|
-
|
|
56086
|
-
|
|
56087
|
-
|
|
56088
|
-
|
|
56089
|
-
|
|
56090
|
-
|
|
56091
|
-
|
|
56092
|
-
assertNoNulBytes("data" in op ? op.data : undefined, `${source} op ${i}${namePart}`);
|
|
56093
|
-
}
|
|
56094
|
-
}
|
|
56095
|
-
}
|
|
56423
|
+
assertPreparedCommitOperations({
|
|
56424
|
+
operations,
|
|
56425
|
+
operationSource,
|
|
56426
|
+
opsFile,
|
|
56427
|
+
streamInput,
|
|
56428
|
+
dryRun: ctx.dryRun === true,
|
|
56429
|
+
allowNulBytes
|
|
56430
|
+
});
|
|
56096
56431
|
const message = streamInput || jsonlFile ? messageFlag : messageFlag ?? synthesizeCommitMessage(operations);
|
|
56432
|
+
if (ctx.dryRun) {
|
|
56433
|
+
await executeCommitValidation(ctx, {
|
|
56434
|
+
org,
|
|
56435
|
+
repo,
|
|
56436
|
+
operations,
|
|
56437
|
+
message,
|
|
56438
|
+
committer,
|
|
56439
|
+
skipExisting,
|
|
56440
|
+
includeWouldBeBody: flags["include-would-be-body"] === true,
|
|
56441
|
+
progressRequested,
|
|
56442
|
+
timingOut,
|
|
56443
|
+
chunkSize,
|
|
56444
|
+
streamId,
|
|
56445
|
+
submissionId: submissionIdFlag,
|
|
56446
|
+
returnRepoSeq: returnRepoSeq === true
|
|
56447
|
+
});
|
|
56448
|
+
return;
|
|
56449
|
+
}
|
|
56450
|
+
const submissionId = submissionIdFlag ?? createOperationEventSubmissionId();
|
|
56097
56451
|
if (streamInput || jsonlFile) {
|
|
56098
56452
|
ctx.err(`submission ${submissionId}`);
|
|
56099
56453
|
}
|
|
@@ -56178,6 +56532,7 @@ var COMMIT_DOMAIN = defineDomain({
|
|
|
56178
56532
|
},
|
|
56179
56533
|
submit: {
|
|
56180
56534
|
prime: true,
|
|
56535
|
+
dryRunBehavior: "execute",
|
|
56181
56536
|
summary: "Submit write operations",
|
|
56182
56537
|
args: "",
|
|
56183
56538
|
flags: createFlags3,
|
|
@@ -56185,6 +56540,7 @@ var COMMIT_DOMAIN = defineDomain({
|
|
|
56185
56540
|
`wh commit submit --add player --shape location --data '{"x":0,"y":0}'`,
|
|
56186
56541
|
`wh commit submit --add alice --data '{"score":1}' --add bob --data '{"score":2}' --shape Player -m "seed players"`,
|
|
56187
56542
|
'wh commit submit -f operations.json -m "Batch update"',
|
|
56543
|
+
"wh commit submit -f operations.json --dry-run --format jsonl",
|
|
56188
56544
|
`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"`,
|
|
56189
56545
|
`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"`,
|
|
56190
56546
|
'wh commit submit --file dataset.jsonl --stream-id bulk-2026-06-04 --skip-existing --progress -m "bulk stream"',
|
|
@@ -56194,6 +56550,7 @@ var COMMIT_DOMAIN = defineDomain({
|
|
|
56194
56550
|
'wh commit submit --type set --name active-locations --members Location/a,Location/b,Location/c -m "Create location set"'
|
|
56195
56551
|
],
|
|
56196
56552
|
notes: [
|
|
56553
|
+
"`--dry-run` evaluates the complete bounded input with the real server commit evaluator and makes no durable repository change.",
|
|
56197
56554
|
"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`.",
|
|
56198
56555
|
"Inspect a shape's fields first with `wh thing view <Shape>` before authoring or editing an ops file."
|
|
56199
56556
|
],
|
|
@@ -60126,7 +60483,7 @@ var ORG_DOMAIN = defineDomain({
|
|
|
60126
60483
|
});
|
|
60127
60484
|
|
|
60128
60485
|
// ../../packages/warmhub-cli/src/domains/prime-content.md
|
|
60129
|
-
var prime_content_default = "# WarmHub CLI Context\n> **Context Recovery**: Run `wh prime` after compaction or new session\n\n## Environment\n{{REPO_LINE}}\n\n## Core Concepts\n- **Thing**: A named entity versioned by writes. **Assertion**: A thing that makes a shape-validated claim about another thing.\n- **Shape**: A thing defining data structure; every other thing has one. **Write**: One or more add/revise/retract operations with per-operation results.\n- **wref**: A reference to a thing. Local: `Player` (the shape) or `Player/alice` (a thing with that shape). Cross-repo: `wh:org/repo/Shape` or `wh:org/repo/Shape/name`.\n\n## Versioned Wrefs\n- `Shape` addresses the shape itself; `Shape/name` addresses a thing with that shape. `@vN` pins either.\n- Floating write refs to retracted targets fail; existing pinned versions remain valid.\n- Rename invalidates old spellings, including `@vN`; the new name resolves history.\n- Untyped wrefs accept any thing. `wref<T>` requires the target's shape to be `T`; a shape has no shape, so never satisfies it. `wref?` coalesces only `thing_absent`, never a missing shape.\n\n## Key Workflows\n\n**Write data** (discover shapes → scaffold ops → submit):\n```bash\nwh shape list --repo org/repo # list available shapes\nwh shape view ShapeName --repo org/repo # inspect fields\nwh shape template ShapeName -o ops.json --repo org/repo # scaffold write ops (supports --kind assertion)\n# edit ops.json — fill FILL_IN placeholders — then:\nwh commit submit --file ops.json -m \"msg\" --repo org/repo # submit operations (bare `wh commit` also works)\n# or single assertion (no file needed):\nwh assertion create --shape ShapeName --about Target/name --name my-assertion --data '{\"field\":1}' --repo org/repo\n# Relay failed operation details when present. Never hand-guess ops JSON — use `wh shape template <Shape>`.\n```\n\n**Read data:**\n```bash\nwh thing list --repo org/repo # all things at HEAD\nwh thing view Shape/name --repo org/repo # inspect a thing\nwh thing query --shape MyShape --repo org/repo # find things by shape\nwh thing about Shape --repo org/repo # assertions about a shape\nwh assertion list --repo org/repo # all assertions at HEAD\nwh thing history Shape/name --repo org/repo # version history\n\n# Batch read — wh thing view is variadic (max 500 wrefs/call):\nwh thing view Player/alice Player/bob # variadic positionals\nwh thing view --file wrefs.txt --json # one wref per line\ncat wrefs.txt | wh thing view --format jsonl # one JSON line per *deduped* requested wref\n```\n\n## Wref Quick Reference\n\nWrites use explicit names and wrefs. Untyped fields, collection members,\nassertion `about`, and committers accept any thing. Create a deterministic\ntarget before referencing it in the same commit.\n\n## Command Reference\n\n**Global flags**: `--repo`, `--format`, `--json`, `--live`\n### thing — Things\n- `wh thing list [--shape] [--kind] [--match] [--include-retracted]` — Current HEAD state\n- `wh thing view [<wref>...] [--file <path>] [--version] [--depth] [--include-retracted] [--data-mode auto|full]` — Thing details. Variadic (max 500). `--version` implies `--include-retracted`. Batch JSON returns `{ requested, items, missing }`; jsonl emits one row per deduped requested wref. Large Set/List bodies summarize by default; use `--data-mode full` for canonical collection JSON.\n- `wh thing history [wref] [--shape] [--about] [--include-retracted]` — Version history\n- `wh thing resolve <wref>` — Resolve a wref to its canonical thing identity\n- `wh thing create <name|Shape/name> (--data|--file) [--shape]` — Create\n- `wh thing revise <name> [--data] [--message] [--committer] [--expected-version]` — Revise (CONFLICT if HEAD≠n)\n- `wh thing retract <wref> -m <message> [--reason] [--kind] [--expected-version]` — Retract\n- `wh thing query [--shape] [--kind] [--about] [--match]` — Query by filters\n- `wh thing search <query> [--shape] [--kind] [--about] [--mode]` — Search text\n- `wh thing rename <Shape/oldName> <newName>` — Rename\n- `wh thing refs <wref> [--inbound] [--outbound] [--field]` — Show field references; use `wh thing about` for assertions about the target thing\n- `wh thing about <wref> [--shape] [--match] [--depth] [--resolve-collections] [--role from|to|ends] [--limit] [--include-retracted]` — Show assertions about the target identity; `--resolve-collections` expands bare/@HEAD/@ALL members, `--role` filters direction; not pinned @vN\n\n- `wh view evaluate VIEW [--limit N] [--cursor TOK] [--all]`\n### commit — Write operations\n- `wh commit submit [--ops|--file|--add|--revise|--retract] [--kind] [--data] [--reason] [--expected-version] [--chunk-size] [--skip-existing] [--progress] [--stream-id]` — Submit operations (bare `wh commit` is equivalent). Use `--file ops.jsonl --stream-id <id> --chunk-size 5000 --skip-existing` for bulk ingest.\n- `wh shape template <shape> [shape2 ...] [--kind] [--operation add|revise|retract] [-o file]` — Generate sample ops\n\n### assertion — Assertion operations\n- `wh assertion list [--about wref] [--shape] [--match] [--include-retracted]` — Browse assertions\n- `wh assertion view <wref> [--version] [--include-retracted]` — Assertion details\n- `wh assertion create --shape <s> --name <n> --about <wref> [--data] [-m] [--committer]` — Create assertion\n- `wh assertion revise <wref> --data <json> [--message] [--committer]` — Revise assertion\n- `wh assertion retract <wref> -m <message> [--reason] [--committer] [--expected-version]` — Retract assertion\n- `wh assertion history <wref> [--include-retracted]` — Assertion history\n\n### shape — Shape management\n- `wh shape list [--match] [--include-retracted]` — List all shapes\n- `wh shape view <name> [--include-retracted]` — Shape details\n- `wh shape revise <name> (--fields|--file)`\n- `wh shape create <name> (--fields|--file)`\n- `wh shape retract <name> -m <message> [--reason] [--expected-version]` — Retract shape\n- `wh shape history <name> [--include-retracted]` — Shape history\n- `wh shape rename <oldName> <newName>` — Rename shape\n\n### repo — Repository management\n- `wh repo create <org/name> [--display-name] [--description] [--visibility]` — Create repo\n- `wh repo list [org]` — List repos\n- `wh repo view [org/repo]` — Repo details\n\n### org — Organization management\n- `wh org create <name> [--display-name]` — Create a new organization\n- `wh org view <name>` — View organization details (alias: info)\n- `wh org list` — List all organizations\n\n### sub — Subscription management\n- `wh sub create <name> [flags]` — Create a subscription\n- `wh sub view <name>` — View subscription details\n- `wh sub list` — List all subscriptions\n- `wh sub log <name>` — Tail subscription delivery feed\n- `wh sub attempts <runId>` — Show attempt history for a run\n- `wh sub pause <name>` — Pause a subscription\n- `wh sub resume <name>` — Resume a paused subscription\n- `wh sub bind <name> [--credentials]` — Bind a credential set to a subscription for webhook auth\n- `wh sub unbind <name>` — Remove credential binding from a subscription\n- `wh sub delete <name>` — Retire; name reserved\n\n### notifications — Action notification listing\n- `wh notifications [--limit] [--since]` — List repo-scoped action notifications\n\n### credential — Credential set management\n- `wh credential create <name> [--repo org/repo | --org org] [--scope] [--description]` — Create an empty credential set\n- `wh credential list [--repo org/repo | --org org]` — List credential sets accessible from a repo or org\n- `wh credential view <name> [--repo org/repo | --org org]` — View a credential set (key names only, no values)\n- `wh credential delete <name> [--repo org/repo | --org org]` — Delete a credential set and its Vault object\n- `wh credential set <setName> [<keyName>] [--repo org/repo | --org org] [--value]` — Set credential key(s). With `<keyName>`: single-key form (reads value from `--value` or stdin). Without `<keyName>`: batch form (reads JSON object from stdin, e.g. `{\"KEY\":\"val\"}`)\n- `wh credential unset <setName> <keyName> [--repo org/repo | --org org]` — Remove a key from a credential set\n- `wh credential audit <setName> [--repo org/repo | --org org]` — View audit log for a credential set\n- `wh credential revoke <setName> [--repo org/repo | --org org] [--reason]` — Revoke a credential set (blocks new binds and stops bound webhook deliveries)\n\n### component — Component management\n- `wh component validate <path>` — Validate package\n- `wh component install <org/name>` — Install a registered component\n- `wh component register <name> --org <org> --manifest <path> [flags]` — Register component identity\n- `wh component unregister <org/name>` — Remove a registered component identity\n- `wh component registry list --org <org>` — List registered components\n- `wh component registry view <org/name>` — View a registered component\n- `wh component registry update <org/name> [flags]` — Update a registered component\n- `wh component list` — List installed components\n- `wh component update <org/name>` — Update installed component\n- `wh component view <org/name>` — Show component details (alias: show)\n- `wh component doctor <org/name>` — Run component health checks\n- `wh component teardown <org/name>` — Pause component subscriptions\n\n### Getting More Info\n- `wh help` — help overview\n- `wh <domain>` — domain verbs\n- `wh <domain> <verb> --help` — verb flags and examples\n- `wh help --format json` — `CliSpecV2` (`schemaVersion: 2`): global/contextual/root tables and command overrides\n\n## Common Workflows\n\n**Explore a repo:**\n```bash\nwh thing list --repo org/repo # see all things in HEAD\nwh thing view Shape/name --repo org/repo # inspect a specific thing\nwh thing history Shape/name --repo org/repo # inspect version history\nwh thing about Shape/name # assertions about thing/shape\n```\n\n**Create an assertion** (most common write):\n```bash\n# --about takes an untyped target wref: Shape or Shape/name.\nwh assertion create --shape MyShape --about TargetShape/target-name \\\n --name my-assertion --data '{\"field_a\":1,\"field_b\":\"value\"}' --repo org/repo\n# Output includes per-operation status; relay failures when present.\n```\n\n**Create via write entrypoint** (alternative, supports batches and streams):\n```bash\nwh commit submit --add my-item --shape MyShape --kind assertion \\\n --about TargetShape/target-name --data '{\"field_a\":1}' --repo org/repo\n```\n\n**Batch write via file** (generate template → edit → submit):\n```bash\nwh shape template Hypothesis Evidence -o ops.json # add --kind assertion --about TargetShape/name for assertions\n# edit ops.json — fill FILL_IN placeholders\nwh commit submit --file ops.json -m \"batch update\" # submit all operations (bare `wh commit` is equivalent)\n# --file format: docs.warmhub.ai/cli-reference/commit-operations\n```\n\n**Bulk write (JSONL stream, >1k ops)** — one chunked stream beats per-record commits (~60× faster):\n```bash\nwh shape template MyShape -o ops.jsonl # one op per line (.jsonl)\nID=\"bulk-$(date +%s)\" # caller id for chunk correlation\nwh commit submit --file ops.jsonl --stream-id \"$ID\" --chunk-size 5000 \\\n --skip-existing --progress -m \"bulk ingest\" --repo org/repo\n# --chunk-size: ops per append chunk (default 1000, max 10000); chunk≈1 is ~60× slower\n# --skip-existing: skips already-written add ops (drops per-row read-before-write)\n# --stream-id identifies the submission but provides no receipt or resume.\n# After an outcome-unknown append, stop writes and reconcile attempted + unsent\n# work from a later verified checkpoint; never blindly replay revise/retract.\n```\n\n**Create collections:**\n```bash\nwh commit submit --type arc --name route --members Location/a,Location/b --repo org/repo\nwh assertion create --shape Supports --name route-support --about Arc/route --data '{\"confidence\":0.8}' --repo org/repo\n```\n\n**Modify data:**\n```bash\nwh thing revise Shape/name --data '{\"x\":5,\"y\":3}' -m \"update\" --repo org/repo\nwh thing retract Shape/old-item -m \"withdrawn\" --reason \"data feed contaminated\" --repo org/repo\n```\n\n**Query and filter:**\n```bash\nwh thing query --shape MyShape # by shape\nwh thing query --kind assertion --about Shape/name # by kind + target\nwh thing history Shape/name --limit 10 # version history\n```\n\n## Built-in Content shape\n\nWarmHub repos expose three well-known content wrefs:\n- `Content/Readme` — stored markdown for humans\n- `Content/Agents` — stored markdown guidance for AI agents\n- `Content/LlmsTxt` — synthesized per-request sitemap (read-only)\n\nFetch via `wh repo content get --kind readme|agents|llms-txt`,\n`client.repo.getReadme/getAgents/getLlmsTxt`, MCP `warmhub_repo_content_get`,\nor raw HTTP `GET /{org}/{repo}/readme.md|agents.md|llms.txt`.\nSee `wh repo describe` → `additionalInformation` for the discovery field.\n\n## Query Discipline\n- Plan the repo, shapes, and wrefs you need before the first query.\n- Gather the needed facts from one repo before switching to another.\n- Do the queries first, then write one complete answer.\n\n## Agent Tips\n- **Always run commands for live data** — this context describes the CLI, not repo contents\n- **Before writing, discover wrefs** — run `wh thing list` or `wh shape list`\n- **Shape field types**: `string`, `number`, `boolean`, `wref`, arrays, optionals, nested objects\n- **Write commands return per-operation results** — relay failures and affected wrefs to the user\n- **Pass data inline** with `--data '{...}'` — do NOT create temp files\n- Add `--json` to any command for machine-readable JSON output\n- **Aliases teach canonical commands** — executing aliases emit a status hint; misleading lifecycle aliases reject and point to `retract`\n- Writes go through `wh commit submit` (or bare `wh commit`) or wrappers (`create`, `revise`, `retract`, `assertion create`). `retract` irreversibly withdraws an identity and creates a history entry.\n- Use `wh doctor` to check environment health\n";
|
|
60486
|
+
var prime_content_default = "# WarmHub CLI Context\n> **Context Recovery**: Run `wh prime` after compaction or new session\n\n## Environment\n{{REPO_LINE}}\n\n## Core Concepts\n- **Thing**: A named entity versioned by writes. **Assertion**: A thing that makes a shape-validated claim about another thing.\n- **Shape**: A thing defining data structure; every other thing has one. **Write**: One or more add/revise/retract operations with per-operation results.\n- **wref**: A reference to a thing. Local: `Player` (the shape) or `Player/alice` (a thing with that shape). Cross-repo: `wh:org/repo/Shape` or `wh:org/repo/Shape/name`.\n\n## Versioned Wrefs\n- `Shape` addresses the shape itself; `Shape/name` addresses a thing with that shape. `@vN` pins either.\n- Floating write refs to retracted targets fail; existing pinned versions remain valid.\n- Rename invalidates old spellings, including `@vN`; the new name resolves history.\n- Untyped wrefs accept any thing. `wref<T>` requires the target's shape to be `T`; a shape has no shape, so never satisfies it. `wref?` coalesces only `thing_absent`, never a missing shape.\n\n## Key Workflows\n\n**Write data** (discover shapes → scaffold ops → submit):\n```bash\nwh shape list --repo org/repo # list available shapes\nwh shape view ShapeName --repo org/repo # inspect fields\nwh shape template ShapeName -o ops.json --repo org/repo # scaffold write ops (supports --kind assertion)\n# edit ops.json — fill FILL_IN placeholders — then:\nwh commit submit --file ops.json --dry-run --repo org/repo # preview; remove --dry-run to submit\n# or single assertion (no file needed):\nwh assertion create --shape ShapeName --about Target/name --name my-assertion --data '{\"field\":1}' --repo org/repo\n# Relay failed operation details when present. Never hand-guess ops JSON — use `wh shape template <Shape>`.\n```\n\n**Read data:**\n```bash\nwh thing list --repo org/repo # all things at HEAD\nwh thing view Shape/name --repo org/repo # inspect a thing\nwh thing query --shape MyShape --repo org/repo # find things by shape\nwh thing about Shape --repo org/repo # assertions about a shape\nwh assertion list --repo org/repo # all assertions at HEAD\nwh thing history Shape/name --repo org/repo # version history\n\n# Batch read — wh thing view is variadic (max 500 wrefs/call):\nwh thing view Player/alice Player/bob # variadic positionals\nwh thing view --file wrefs.txt --json # one wref per line\ncat wrefs.txt | wh thing view --format jsonl # one JSON line per *deduped* requested wref\n```\n\n## Wref Quick Reference\n\nWrites use explicit names and wrefs. Untyped fields, collection members,\nassertion `about`, and committers accept any thing. Create a deterministic\ntarget before referencing it in the same commit.\n\n## Command Reference\n\n**Global flags**: `--repo`, `--format`, `--json`, `--live`\n### thing — Things\n- `wh thing list [--shape] [--kind] [--match] [--include-retracted]` — Current HEAD state\n- `wh thing view [<wref>...] [--file <path>] [--version] [--depth] [--include-retracted] [--data-mode auto|full]` — Thing details. Variadic (max 500). `--version` implies `--include-retracted`. Batch JSON returns `{ requested, items, missing }`; jsonl emits one row per deduped requested wref. Large Set/List bodies summarize by default; use `--data-mode full` for canonical collection JSON.\n- `wh thing history [wref] [--shape] [--about] [--include-retracted]` — Version history\n- `wh thing resolve <wref>` — Resolve a wref to its canonical thing identity\n- `wh thing create <name|Shape/name> (--data|--file) [--shape]` — Create\n- `wh thing revise <name> [--data] [--message] [--committer] [--expected-version]` — Revise (CONFLICT if HEAD≠n)\n- `wh thing retract <wref> -m <message> [--reason] [--kind] [--expected-version]` — Retract\n- `wh thing query [--shape] [--kind] [--about] [--match]` — Query by filters\n- `wh thing search <query> [--shape] [--kind] [--about] [--mode]` — Search text\n- `wh thing rename <Shape/oldName> <newName>` — Rename\n- `wh thing refs <wref> [--inbound] [--outbound] [--field]` — Show field references; use `wh thing about` for assertions about the target thing\n- `wh thing about <wref> [--shape] [--match] [--depth] [--resolve-collections] [--role from|to|ends] [--limit] [--include-retracted]` — Show assertions about the target identity; `--resolve-collections` expands bare/@HEAD/@ALL members, `--role` filters direction; not pinned @vN\n\n- `wh view evaluate VIEW [--limit N] [--cursor TOK] [--all]`\n### commit — Write operations\n- `wh commit submit [--ops|--file|--add|--revise|--retract] [--dry-run] [--skip-existing]` — Submit operations, or evaluate the complete bounded input without durable changes under `--dry-run`. JSONL preview emits one operation row per input plus one summary.\n- `wh shape template <shape> [shape2 ...] [--kind] [--operation add|revise|retract] [-o file]` — Generate sample ops\n\n### assertion — Assertion operations\n- `wh assertion list [--about wref] [--shape] [--match] [--include-retracted]` — Browse assertions\n- `wh assertion view <wref> [--version] [--include-retracted]` — Assertion details\n- `wh assertion create --shape <s> --name <n> --about <wref> [--data] [-m] [--committer]` — Create assertion\n- `wh assertion revise <wref> --data <json> [--message] [--committer]` — Revise assertion\n- `wh assertion retract <wref> -m <message> [--reason] [--committer] [--expected-version]` — Retract assertion\n- `wh assertion history <wref> [--include-retracted]` — Assertion history\n\n### shape — Shape management\n- `wh shape list [--match] [--include-retracted]` — List all shapes\n- `wh shape view <name> [--include-retracted]` — Shape details\n- `wh shape revise <name> (--fields|--file)`\n- `wh shape create <name> (--fields|--file)`\n- `wh shape retract <name> -m <message> [--reason] [--expected-version]` — Retract shape\n- `wh shape history <name> [--include-retracted]` — Shape history\n- `wh shape rename <oldName> <newName>` — Rename shape\n\n### repo — Repository management\n- `wh repo create <org/name> [--display-name] [--description] [--visibility]` — Create repo\n- `wh repo list [org]` — List repos\n- `wh repo view [org/repo]` — Repo details\n\n### org — Organization management\n- `wh org create <name> [--display-name]` — Create a new organization\n- `wh org view <name>` — View organization details (alias: info)\n- `wh org list` — List all organizations\n\n### sub — Subscription management\n- `wh sub create <name> [flags]` — Create a subscription\n- `wh sub view <name>` — View subscription details\n- `wh sub list` — List all subscriptions\n- `wh sub log <name>` — Tail subscription delivery feed\n- `wh sub attempts <runId>` — Show attempt history for a run\n- `wh sub pause <name>` — Pause a subscription\n- `wh sub resume <name>` — Resume a paused subscription\n- `wh sub bind <name> [--credentials]` — Bind a credential set to a subscription for webhook auth\n- `wh sub unbind <name>` — Remove credential binding from a subscription\n- `wh sub delete <name>` — Retire; name reserved\n\n### notifications — Action notification listing\n- `wh notifications [--limit] [--since]` — List repo-scoped action notifications\n\n### credential — Credential set management\n- `wh credential create <name> [--repo org/repo | --org org] [--scope] [--description]` — Create an empty credential set\n- `wh credential list [--repo org/repo | --org org]` — List credential sets accessible from a repo or org\n- `wh credential view <name> [--repo org/repo | --org org]` — View a credential set (key names only, no values)\n- `wh credential delete <name> [--repo org/repo | --org org]` — Delete a credential set and its Vault object\n- `wh credential set <setName> [<keyName>] [--repo org/repo | --org org] [--value]` — Set credential key(s). With `<keyName>`: single-key form (reads value from `--value` or stdin). Without `<keyName>`: batch form (reads JSON object from stdin, e.g. `{\"KEY\":\"val\"}`)\n- `wh credential unset <setName> <keyName> [--repo org/repo | --org org]` — Remove a key from a credential set\n- `wh credential audit <setName> [--repo org/repo | --org org]` — View audit log for a credential set\n- `wh credential revoke <setName> [--repo org/repo | --org org] [--reason]` — Revoke a credential set (blocks new binds and stops bound webhook deliveries)\n\n### component — Component management\n- `wh component validate <path>` — Validate package\n- `wh component install <org/name>` — Install a registered component\n- `wh component register <name> --org <org> --manifest <path> [flags]` — Register component identity\n- `wh component unregister <org/name>` — Remove a registered component identity\n- `wh component registry list --org <org>` — List registered components\n- `wh component registry view <org/name>` — View a registered component\n- `wh component registry update <org/name> [flags]` — Update a registered component\n- `wh component list` — List installed components\n- `wh component update <org/name>` — Update installed component\n- `wh component view <org/name>` — Show component details (alias: show)\n- `wh component doctor <org/name>` — Run component health checks\n- `wh component teardown <org/name>` — Pause component subscriptions\n\n### Getting More Info\n- `wh help` — help overview\n- `wh <domain>` — domain verbs\n- `wh <domain> <verb> --help` — verb flags and examples\n- `wh help --format json` — `CliSpecV2` (`schemaVersion: 2`): global/contextual/root tables and command overrides\n\n## Common Workflows\n\n**Explore a repo:**\n```bash\nwh thing list --repo org/repo # see all things in HEAD\nwh thing view Shape/name --repo org/repo # inspect a specific thing\nwh thing history Shape/name --repo org/repo # inspect version history\nwh thing about Shape/name # assertions about thing/shape\n```\n\n**Create an assertion** (most common write):\n```bash\n# --about takes an untyped target wref: Shape or Shape/name.\nwh assertion create --shape MyShape --about TargetShape/target-name \\\n --name my-assertion --data '{\"field_a\":1,\"field_b\":\"value\"}' --repo org/repo\n# Output includes per-operation status; relay failures when present.\n```\n\n**Create via write entrypoint** (alternative, supports batches and streams):\n```bash\nwh commit submit --add my-item --shape MyShape --kind assertion \\\n --about TargetShape/target-name --data '{\"field_a\":1}' --repo org/repo\n```\n\n**Batch write via file** (generate template → edit → submit):\n```bash\nwh shape template Hypothesis Evidence -o ops.json # add --kind assertion --about TargetShape/name for assertions\n# edit ops.json — fill FILL_IN placeholders\nwh commit submit --file ops.json -m \"batch update\" # submit all operations (bare `wh commit` is equivalent)\n# --file format: docs.warmhub.ai/cli-reference/commit-operations\n```\n\n**Bulk write (JSONL stream, >1k ops)** — one chunked stream beats per-record commits (~60× faster):\n```bash\nwh shape template MyShape -o ops.jsonl # one op per line (.jsonl)\nID=\"bulk-$(date +%s)\" # caller id for chunk correlation\nwh commit submit --file ops.jsonl --stream-id \"$ID\" --chunk-size 5000 \\\n --skip-existing --progress -m \"bulk ingest\" --repo org/repo\n# --chunk-size: ops per append chunk (default 1000, max 10000); chunk≈1 is ~60× slower\n# --skip-existing: skips already-written add ops (drops per-row read-before-write)\n# --stream-id identifies the submission but provides no receipt or resume.\n# After an outcome-unknown append, stop writes and reconcile attempted + unsent\n# work from a later verified checkpoint; never blindly replay revise/retract.\n```\n\n**Create collections:**\n```bash\nwh commit submit --type arc --name route --members Location/a,Location/b --repo org/repo\nwh assertion create --shape Supports --name route-support --about Arc/route --data '{\"confidence\":0.8}' --repo org/repo\n```\n\n**Modify data:**\n```bash\nwh thing revise Shape/name --data '{\"x\":5,\"y\":3}' -m \"update\" --repo org/repo\nwh thing retract Shape/old-item -m \"withdrawn\" --reason \"data feed contaminated\" --repo org/repo\n```\n\n**Query and filter:**\n```bash\nwh thing query --shape MyShape # by shape\nwh thing query --kind assertion --about Shape/name # by kind + target\nwh thing history Shape/name --limit 10 # version history\n```\n\n## Built-in Content shape\n\nWarmHub repos expose three well-known content wrefs:\n- `Content/Readme` — stored markdown for humans\n- `Content/Agents` — stored markdown guidance for AI agents\n- `Content/LlmsTxt` — synthesized per-request sitemap (read-only)\n\nFetch via `wh repo content get --kind readme|agents|llms-txt`,\n`client.repo.getReadme/getAgents/getLlmsTxt`, MCP `warmhub_repo_content_get`,\nor raw HTTP `GET /{org}/{repo}/readme.md|agents.md|llms.txt`.\nSee `wh repo describe` → `additionalInformation` for the discovery field.\n\n## Query Discipline\n- Plan the repo, shapes, and wrefs you need before the first query.\n- Gather the needed facts from one repo before switching to another.\n- Do the queries first, then write one complete answer.\n\n## Agent Tips\n- **Always run commands for live data** — this context describes the CLI, not repo contents\n- **Before writing, discover wrefs** — run `wh thing list` or `wh shape list`\n- **Shape field types**: `string`, `number`, `boolean`, `wref`, arrays, optionals, nested objects\n- **Write commands return per-operation results** — relay failures and affected wrefs to the user\n- **Pass data inline** with `--data '{...}'` — do NOT create temp files\n- Add `--json` to any command for machine-readable JSON output\n- **Aliases teach canonical commands** — executing aliases emit a status hint; misleading lifecycle aliases reject and point to `retract`\n- Writes go through `wh commit submit` (or bare `wh commit`) or wrappers (`create`, `revise`, `retract`, `assertion create`). `retract` irreversibly withdraws an identity and creates a history entry.\n- Use `wh doctor` to check environment health\n";
|
|
60130
60487
|
|
|
60131
60488
|
// ../../packages/warmhub-cli/src/domains/prime.ts
|
|
60132
60489
|
function buildMarkdown(config2) {
|
|
@@ -60199,7 +60556,7 @@ var PRIME_DOMAIN = defineDomain({
|
|
|
60199
60556
|
});
|
|
60200
60557
|
|
|
60201
60558
|
// ../../packages/warmhub-cli/src/domains/repo/checkpoint.ts
|
|
60202
|
-
import { createReadStream as
|
|
60559
|
+
import { createReadStream as createReadStream5 } from "node:fs";
|
|
60203
60560
|
import { lstat as lstat3 } from "node:fs/promises";
|
|
60204
60561
|
|
|
60205
60562
|
// ../../packages/sdk-ts/src/repository-checkpoint/types.ts
|
|
@@ -60574,7 +60931,7 @@ import { createHash as createHash3 } from "node:crypto";
|
|
|
60574
60931
|
|
|
60575
60932
|
// ../../packages/sdk-ts/src/repository-checkpoint/identity-sort.ts
|
|
60576
60933
|
import { once } from "node:events";
|
|
60577
|
-
import { createReadStream as
|
|
60934
|
+
import { createReadStream as createReadStream4, createWriteStream } from "node:fs";
|
|
60578
60935
|
import { open as open3, rm } from "node:fs/promises";
|
|
60579
60936
|
import { join as join10 } from "node:path";
|
|
60580
60937
|
var CHECKPOINT_IDENTITY_SORT_BUDGET_BYTES = 4 * 1024 * 1024;
|
|
@@ -60848,7 +61205,7 @@ class RunCursor {
|
|
|
60848
61205
|
#offset = 0;
|
|
60849
61206
|
current;
|
|
60850
61207
|
constructor(path2) {
|
|
60851
|
-
this.#stream =
|
|
61208
|
+
this.#stream = createReadStream4(path2, {
|
|
60852
61209
|
highWaterMark: RUN_READ_BUFFER_BYTES
|
|
60853
61210
|
});
|
|
60854
61211
|
this.#iterator = this.#stream[Symbol.asyncIterator]();
|
|
@@ -61496,7 +61853,7 @@ var handleVerify = async (ctx, { args }) => {
|
|
|
61496
61853
|
}
|
|
61497
61854
|
try {
|
|
61498
61855
|
await lstat3(archive);
|
|
61499
|
-
const result = await verifyRepositoryCheckpointArchive(
|
|
61856
|
+
const result = await verifyRepositoryCheckpointArchive(createReadStream5(archive));
|
|
61500
61857
|
writeOutput(ctx, result, () => {
|
|
61501
61858
|
ctx.out(`Checkpoint: ${result.checkpointId}`);
|
|
61502
61859
|
ctx.out(`Repository sequence: ${result.repoSeq}`);
|
|
@@ -64897,7 +65254,7 @@ async function dispatchDomain(ctx, invocation, dispatchRegistry = productionRegi
|
|
|
64897
65254
|
]);
|
|
64898
65255
|
return;
|
|
64899
65256
|
}
|
|
64900
|
-
if (ctx.dryRun) {
|
|
65257
|
+
if (ctx.dryRun && pathSpec.dryRunBehavior === "dispatch") {
|
|
64901
65258
|
emitDryRun(ctx, invocation, undefined, pathSpec.flags);
|
|
64902
65259
|
return;
|
|
64903
65260
|
}
|
|
@@ -64939,7 +65296,7 @@ async function dispatchDomain(ctx, invocation, dispatchRegistry = productionRegi
|
|
|
64939
65296
|
if (!handler) {
|
|
64940
65297
|
throw new CliError(1 /* Runtime */, "UNKNOWN", `No handler registered for ${invocation.commandPath.join(".")}`);
|
|
64941
65298
|
}
|
|
64942
|
-
if (ctx.dryRun) {
|
|
65299
|
+
if (ctx.dryRun && verbSpec.dryRunBehavior === "dispatch") {
|
|
64943
65300
|
emitDryRun(ctx, invocation, canonicalVerb, verbSpec.flags);
|
|
64944
65301
|
return;
|
|
64945
65302
|
}
|
|
@@ -65750,7 +66107,8 @@ function resolveCommand(records, resolver, sourceRecords = records) {
|
|
|
65750
66107
|
name: "help",
|
|
65751
66108
|
summary: "Show command help",
|
|
65752
66109
|
args: "[domain]",
|
|
65753
|
-
flags: [...HELP_FLAGS2]
|
|
66110
|
+
flags: [...HELP_FLAGS2],
|
|
66111
|
+
dryRunBehavior: "dispatch"
|
|
65754
66112
|
},
|
|
65755
66113
|
flags: HELP_FLAGS2,
|
|
65756
66114
|
args: "[domain]",
|
|
@@ -66319,7 +66677,7 @@ async function runPreparedCli(rawArgv, prepared, opts) {
|
|
|
66319
66677
|
});
|
|
66320
66678
|
const chars = makeChars();
|
|
66321
66679
|
const signal = abortController.signal;
|
|
66322
|
-
|
|
66680
|
+
const commandContext = {
|
|
66323
66681
|
client,
|
|
66324
66682
|
config: config2,
|
|
66325
66683
|
invocation,
|
|
@@ -66347,8 +66705,9 @@ async function runPreparedCli(rawArgv, prepared, opts) {
|
|
|
66347
66705
|
signal,
|
|
66348
66706
|
rawFetch: opts?.rawFetch ?? fetch,
|
|
66349
66707
|
confirm: (message) => confirmPrompt(message, { signal })
|
|
66350
|
-
}
|
|
66351
|
-
|
|
66708
|
+
};
|
|
66709
|
+
await dispatch(commandContext);
|
|
66710
|
+
exitCode = cancelledExitCode ?? commandContext.requestedExitCode ?? 0 /* Ok */;
|
|
66352
66711
|
return exitCode;
|
|
66353
66712
|
} catch (error51) {
|
|
66354
66713
|
if (cancelledExitCode !== undefined) {
|
|
@@ -66442,7 +66801,7 @@ function resolveLogLevel(flagLevel, env) {
|
|
|
66442
66801
|
// package.json
|
|
66443
66802
|
var package_default3 = {
|
|
66444
66803
|
name: "@warmhub/cli",
|
|
66445
|
-
version: "0.
|
|
66804
|
+
version: "0.95.0",
|
|
66446
66805
|
private: false,
|
|
66447
66806
|
type: "module",
|
|
66448
66807
|
description: "The wh CLI for WarmHub — create repos, commit and query data, and compound knowledge with your AI agents.",
|
|
@@ -67061,5 +67420,5 @@ process.exitCode = interceptedExitCode === undefined ? await runPreparedCli(laun
|
|
|
67061
67420
|
version: package_default3.version
|
|
67062
67421
|
}) : interceptedExitCode;
|
|
67063
67422
|
|
|
67064
|
-
//# debugId=
|
|
67065
|
-
//# warmhub-cli-build-info {"cliVersion":"0.
|
|
67423
|
+
//# debugId=E38898F8C9FABDFA64756E2164756E21
|
|
67424
|
+
//# warmhub-cli-build-info {"cliVersion":"0.95.0","sdkVersion":"0.93.0"}
|