@warmhub/cli 0.85.0 → 0.86.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 +269 -139
- package/package.json +1 -1
package/dist/wh.js
CHANGED
|
@@ -27993,8 +27993,8 @@ function normalizeOptionalName(value) {
|
|
|
27993
27993
|
|
|
27994
27994
|
// ../../packages/sdk-ts/src/operation-normalize.ts
|
|
27995
27995
|
function toBackendStreamOperation(operation) {
|
|
27996
|
-
if (operation.expectedVersion !== undefined && operation.operation !== "revise") {
|
|
27997
|
-
throw new Error("expectedVersion is only valid on revise operations — set operation
|
|
27996
|
+
if (operation.expectedVersion !== undefined && operation.operation !== "revise" && operation.operation !== "retract") {
|
|
27997
|
+
throw new Error("expectedVersion is only valid on revise or retract operations — set an explicit operation discriminator");
|
|
27998
27998
|
}
|
|
27999
27999
|
if (operation.operation === "retract") {
|
|
28000
28000
|
return {
|
|
@@ -28002,6 +28002,7 @@ function toBackendStreamOperation(operation) {
|
|
|
28002
28002
|
name: operation.name,
|
|
28003
28003
|
...operation.kind ? { kind: operation.kind } : {},
|
|
28004
28004
|
...operation.reason ? { reason: operation.reason } : {},
|
|
28005
|
+
...operation.expectedVersion !== undefined ? { expectedVersion: operation.expectedVersion } : {},
|
|
28005
28006
|
...operation.leaseId ? { leaseId: operation.leaseId } : {}
|
|
28006
28007
|
};
|
|
28007
28008
|
}
|
|
@@ -28097,13 +28098,19 @@ class PartialStreamSubmissionError extends Error {
|
|
|
28097
28098
|
code = "PARTIAL_STREAM_SUBMISSION";
|
|
28098
28099
|
completedOperations;
|
|
28099
28100
|
acknowledgedOperationCount;
|
|
28101
|
+
lastAcknowledgedRepoSeq;
|
|
28102
|
+
attemptedAppendOutcome;
|
|
28100
28103
|
cause;
|
|
28101
28104
|
constructor(input) {
|
|
28102
|
-
super("Stream submission
|
|
28105
|
+
super("Stream submission outcome is incomplete or unknown. Stop sending writes; once any outstanding append can no longer apply, obtain a later verified checkpoint and reconcile before replanning.");
|
|
28103
28106
|
this.name = "WarmHubError";
|
|
28104
28107
|
this.cause = input.cause;
|
|
28105
28108
|
this.completedOperations = input.completedOperations;
|
|
28106
28109
|
this.acknowledgedOperationCount = input.acknowledgedOperationCount ?? input.completedOperations.length;
|
|
28110
|
+
this.attemptedAppendOutcome = input.attemptedAppendOutcome;
|
|
28111
|
+
if (input.lastAcknowledgedRepoSeq !== undefined) {
|
|
28112
|
+
this.lastAcknowledgedRepoSeq = input.lastAcknowledgedRepoSeq;
|
|
28113
|
+
}
|
|
28107
28114
|
}
|
|
28108
28115
|
}
|
|
28109
28116
|
|
|
@@ -28260,6 +28267,9 @@ function isTransientStreamFailure(cause) {
|
|
|
28260
28267
|
function isFetchNetworkTypeError(cause) {
|
|
28261
28268
|
return cause instanceof TypeError && /fetch/i.test(cause.message);
|
|
28262
28269
|
}
|
|
28270
|
+
function isReplaySafeOperation(operation) {
|
|
28271
|
+
return operation.operation !== "revise" || operation.expectedVersion !== undefined;
|
|
28272
|
+
}
|
|
28263
28273
|
function computeBackoffDelayMs(attempt, policy) {
|
|
28264
28274
|
const exponential = policy.baseDelayMs * 2 ** Math.max(0, attempt - 1);
|
|
28265
28275
|
const jitter = Math.random() * policy.baseDelayMs;
|
|
@@ -28309,7 +28319,8 @@ async function submitOperationsViaStream(client, args) {
|
|
|
28309
28319
|
for (const { operations: chunk, start: chunkStart } of chunkOperations(operations, chunkSize)) {
|
|
28310
28320
|
let attempt = 1;
|
|
28311
28321
|
let priorAttemptAmbiguous = false;
|
|
28312
|
-
const
|
|
28322
|
+
const chunkIsSingleOperation = chunk.length === 1;
|
|
28323
|
+
const chunkIsReplaySafe = chunk.every(isReplaySafeOperation);
|
|
28313
28324
|
while (true) {
|
|
28314
28325
|
try {
|
|
28315
28326
|
const appendResult = await client.stream.append({
|
|
@@ -28337,7 +28348,7 @@ async function submitOperationsViaStream(client, args) {
|
|
|
28337
28348
|
if (acknowledgedOperationCount === 0 && !priorAttemptAmbiguous && isDefiniteClientError(cause)) {
|
|
28338
28349
|
throw cause;
|
|
28339
28350
|
}
|
|
28340
|
-
if (acknowledgedOperationCount === 0 &&
|
|
28351
|
+
if (acknowledgedOperationCount === 0 && chunkIsSingleOperation && chunkIsReplaySafe && policy !== false && attempt < policy.maxAttempts && isTransientStreamFailure(cause)) {
|
|
28341
28352
|
await sleep2(computeBackoffDelayMs(attempt, policy));
|
|
28342
28353
|
attempt += 1;
|
|
28343
28354
|
priorAttemptAmbiguous = true;
|
|
@@ -28352,7 +28363,9 @@ async function submitOperationsViaStream(client, args) {
|
|
|
28352
28363
|
throw new PartialStreamSubmissionError({
|
|
28353
28364
|
cause,
|
|
28354
28365
|
completedOperations,
|
|
28355
|
-
acknowledgedOperationCount
|
|
28366
|
+
acknowledgedOperationCount,
|
|
28367
|
+
lastAcknowledgedRepoSeq: repoSeq,
|
|
28368
|
+
attemptedAppendOutcome: !priorAttemptAmbiguous && isDefiniteClientError(cause) ? "not_applied" : "unknown"
|
|
28356
28369
|
});
|
|
28357
28370
|
}
|
|
28358
28371
|
}
|
|
@@ -28366,7 +28379,9 @@ async function submitOperationsViaStream(client, args) {
|
|
|
28366
28379
|
throw new PartialStreamSubmissionError({
|
|
28367
28380
|
cause: failure,
|
|
28368
28381
|
completedOperations: completedOperationsFrom(result),
|
|
28369
|
-
acknowledgedOperationCount
|
|
28382
|
+
acknowledgedOperationCount,
|
|
28383
|
+
lastAcknowledgedRepoSeq: repoSeq,
|
|
28384
|
+
attemptedAppendOutcome: "unknown"
|
|
28370
28385
|
});
|
|
28371
28386
|
}
|
|
28372
28387
|
throw failure;
|
|
@@ -28480,7 +28495,7 @@ function dedupeDeprecationsByShape(results) {
|
|
|
28480
28495
|
// ../../packages/sdk-ts/package.json
|
|
28481
28496
|
var package_default = {
|
|
28482
28497
|
name: "@warmhub/sdk-ts",
|
|
28483
|
-
version: "0.
|
|
28498
|
+
version: "0.84.0",
|
|
28484
28499
|
private: false,
|
|
28485
28500
|
type: "module",
|
|
28486
28501
|
description: "The TypeScript SDK for WarmHub — create repos, commit and query data, and compound knowledge with your AI agents.",
|
|
@@ -28709,6 +28724,9 @@ function chunkArray(items, chunkSize) {
|
|
|
28709
28724
|
}
|
|
28710
28725
|
return chunks;
|
|
28711
28726
|
}
|
|
28727
|
+
function narrowKind(kind) {
|
|
28728
|
+
return kind !== undefined && COMMIT_OPERATION_KINDS.includes(kind) ? kind : undefined;
|
|
28729
|
+
}
|
|
28712
28730
|
function toSubscriptionRef(args) {
|
|
28713
28731
|
const [first, repoName, name] = args;
|
|
28714
28732
|
return typeof first === "string" ? { orgName: first, repoName, name } : first;
|
|
@@ -30047,6 +30065,7 @@ class WarmHubClient {
|
|
|
30047
30065
|
return await this.trpc.action.listRuns.query({
|
|
30048
30066
|
orgName,
|
|
30049
30067
|
repoName,
|
|
30068
|
+
runId: opts?.runId,
|
|
30050
30069
|
subscriptionName: opts?.subscriptionName,
|
|
30051
30070
|
status: opts?.status,
|
|
30052
30071
|
outcome: opts?.outcome,
|
|
@@ -30257,12 +30276,11 @@ class WarmHubClient {
|
|
|
30257
30276
|
thing = {
|
|
30258
30277
|
head: async (orgName, repoName, opts) => {
|
|
30259
30278
|
try {
|
|
30260
|
-
const kind = opts?.kind === "shape" || opts?.kind === "thing" || opts?.kind === "assertion" || opts?.kind === "collection" ? opts.kind : undefined;
|
|
30261
30279
|
return await this.trpc.thing.head.query({
|
|
30262
30280
|
orgName,
|
|
30263
30281
|
repoName,
|
|
30264
30282
|
shape: opts?.shape,
|
|
30265
|
-
kind,
|
|
30283
|
+
kind: narrowKind(opts?.kind),
|
|
30266
30284
|
match: opts?.match,
|
|
30267
30285
|
dataMode: opts?.dataMode,
|
|
30268
30286
|
includeRetracted: opts?.includeRetracted,
|
|
@@ -30496,13 +30514,12 @@ class WarmHubClient {
|
|
|
30496
30514
|
},
|
|
30497
30515
|
query: async (orgName, repoName, opts) => {
|
|
30498
30516
|
try {
|
|
30499
|
-
const kind = opts?.kind === "shape" || opts?.kind === "thing" || opts?.kind === "assertion" || opts?.kind === "collection" ? opts.kind : undefined;
|
|
30500
30517
|
return await this.trpc.thing.query.query({
|
|
30501
30518
|
orgName,
|
|
30502
30519
|
repoName,
|
|
30503
30520
|
shape: opts?.shape,
|
|
30504
30521
|
about: opts?.about,
|
|
30505
|
-
kind,
|
|
30522
|
+
kind: narrowKind(opts?.kind),
|
|
30506
30523
|
match: opts?.match,
|
|
30507
30524
|
includeRetracted: opts?.includeRetracted,
|
|
30508
30525
|
resolveCollections: opts?.resolveCollections,
|
|
@@ -30536,14 +30553,13 @@ class WarmHubClient {
|
|
|
30536
30553
|
},
|
|
30537
30554
|
search: async (orgName, repoName, query, opts) => {
|
|
30538
30555
|
try {
|
|
30539
|
-
const kind = opts?.kind === "shape" || opts?.kind === "thing" || opts?.kind === "assertion" || opts?.kind === "collection" ? opts.kind : undefined;
|
|
30540
30556
|
return await this.trpc.thing.search.query({
|
|
30541
30557
|
orgName,
|
|
30542
30558
|
repoName,
|
|
30543
30559
|
query,
|
|
30544
30560
|
shape: opts?.shape,
|
|
30545
30561
|
about: opts?.about,
|
|
30546
|
-
kind,
|
|
30562
|
+
kind: narrowKind(opts?.kind),
|
|
30547
30563
|
match: opts?.match,
|
|
30548
30564
|
includeRetracted: opts?.includeRetracted,
|
|
30549
30565
|
resolveCollections: opts?.resolveCollections,
|
|
@@ -30571,13 +30587,12 @@ class WarmHubClient {
|
|
|
30571
30587
|
},
|
|
30572
30588
|
count: async (orgName, repoName, opts) => {
|
|
30573
30589
|
try {
|
|
30574
|
-
const kind = opts?.kind === "shape" || opts?.kind === "thing" || opts?.kind === "assertion" || opts?.kind === "collection" ? opts.kind : undefined;
|
|
30575
30590
|
return await this.trpc.thing.count.query({
|
|
30576
30591
|
orgName,
|
|
30577
30592
|
repoName,
|
|
30578
30593
|
shape: opts?.shape,
|
|
30579
30594
|
about: opts?.about,
|
|
30580
|
-
kind,
|
|
30595
|
+
kind: narrowKind(opts?.kind),
|
|
30581
30596
|
match: opts?.match,
|
|
30582
30597
|
includeRetracted: opts?.includeRetracted,
|
|
30583
30598
|
resolveCollections: opts?.resolveCollections,
|
|
@@ -31215,20 +31230,101 @@ class CliError extends Error {
|
|
|
31215
31230
|
cause;
|
|
31216
31231
|
hint;
|
|
31217
31232
|
backendCode;
|
|
31233
|
+
recovery;
|
|
31218
31234
|
context;
|
|
31219
|
-
constructor(code, kind, message, cause, hint, context, backendCode) {
|
|
31235
|
+
constructor(code, kind, message, cause, hint, context, backendCode, recovery) {
|
|
31220
31236
|
super(message);
|
|
31221
31237
|
this.code = code;
|
|
31222
31238
|
this.kind = kind;
|
|
31223
31239
|
this.cause = cause;
|
|
31224
31240
|
this.hint = hint;
|
|
31225
31241
|
this.backendCode = backendCode;
|
|
31242
|
+
this.recovery = recovery;
|
|
31226
31243
|
this.context = context;
|
|
31227
31244
|
}
|
|
31228
31245
|
get errorCode() {
|
|
31229
31246
|
return this.backendCode;
|
|
31230
31247
|
}
|
|
31231
31248
|
}
|
|
31249
|
+
|
|
31250
|
+
// ../../packages/warmhub-cli/src/stream-recovery.ts
|
|
31251
|
+
function failureCode(error) {
|
|
31252
|
+
if (typeof error !== "object" || error === null)
|
|
31253
|
+
return;
|
|
31254
|
+
const typed = error;
|
|
31255
|
+
if (typeof typed.errorCode === "string")
|
|
31256
|
+
return typed.errorCode;
|
|
31257
|
+
if (typeof typed.backendCode === "string")
|
|
31258
|
+
return typed.backendCode;
|
|
31259
|
+
if (typeof typed.data?.warmhub?.code === "string") {
|
|
31260
|
+
return typed.data.warmhub.code;
|
|
31261
|
+
}
|
|
31262
|
+
if (typeof typed.data?.code === "string")
|
|
31263
|
+
return typed.data.code;
|
|
31264
|
+
return failureCode(typed.cause);
|
|
31265
|
+
}
|
|
31266
|
+
function failureStatus(error) {
|
|
31267
|
+
if (typeof error !== "object" || error === null)
|
|
31268
|
+
return;
|
|
31269
|
+
const typed = error;
|
|
31270
|
+
if (typeof typed.status === "number")
|
|
31271
|
+
return typed.status;
|
|
31272
|
+
if (typeof typed.data?.warmhub?.status === "number") {
|
|
31273
|
+
return typed.data.warmhub.status;
|
|
31274
|
+
}
|
|
31275
|
+
if (typeof typed.data?.status === "number")
|
|
31276
|
+
return typed.data.status;
|
|
31277
|
+
if (typeof typed.data?.httpStatus === "number") {
|
|
31278
|
+
return typed.data.httpStatus;
|
|
31279
|
+
}
|
|
31280
|
+
return failureStatus(typed.cause);
|
|
31281
|
+
}
|
|
31282
|
+
function streamAppendWasExplicitlyRejected(cause) {
|
|
31283
|
+
const normalized = toWarmHubError(cause);
|
|
31284
|
+
const code = failureCode(cause) ?? normalized.errorCode ?? normalized.code;
|
|
31285
|
+
if (code === "COMMIT_OUTCOME_UNKNOWN")
|
|
31286
|
+
return false;
|
|
31287
|
+
const status = failureStatus(cause) ?? normalized.status;
|
|
31288
|
+
return status !== undefined && status >= 400 && status < 500 && status !== 408;
|
|
31289
|
+
}
|
|
31290
|
+
function streamFailureCode(cause) {
|
|
31291
|
+
const normalized = toWarmHubError(cause);
|
|
31292
|
+
const wireCode = failureCode(cause) ?? normalized.errorCode;
|
|
31293
|
+
if (wireCode !== undefined)
|
|
31294
|
+
return wireCode;
|
|
31295
|
+
return normalized.status !== undefined && normalized.code !== "BACKEND" ? normalized.code : undefined;
|
|
31296
|
+
}
|
|
31297
|
+
function buildStreamRecoveryReceipt(args) {
|
|
31298
|
+
const {
|
|
31299
|
+
acknowledgedOperationCount,
|
|
31300
|
+
lastAcknowledgedRepoSeq,
|
|
31301
|
+
cause,
|
|
31302
|
+
attemptedAppendOutcome
|
|
31303
|
+
} = args;
|
|
31304
|
+
const sequenceReceipt = lastAcknowledgedRepoSeq === undefined ? "" : ` Last acknowledged repo sequence: ${lastAcknowledgedRepoSeq}.`;
|
|
31305
|
+
const errorCode = streamFailureCode(cause);
|
|
31306
|
+
const backendSuffix = errorCode ? ` (backend: ${errorCode})` : "";
|
|
31307
|
+
const recovery = {
|
|
31308
|
+
acknowledgedOperationCount,
|
|
31309
|
+
...lastAcknowledgedRepoSeq === undefined ? {} : { lastAcknowledgedRepoSeq },
|
|
31310
|
+
attemptedAppendOutcome
|
|
31311
|
+
};
|
|
31312
|
+
if (attemptedAppendOutcome === "unknown") {
|
|
31313
|
+
return {
|
|
31314
|
+
message: `Stream append outcome is unknown after ${acknowledgedOperationCount} acknowledged operation(s).${sequenceReceipt}${backendSuffix}`,
|
|
31315
|
+
hint: "Stop submitting writes. The attempted append may have landed after the last acknowledgement; once it can no longer apply, obtain and verify a later checkpoint, then reconcile the attempted append and unsent work.",
|
|
31316
|
+
errorCode,
|
|
31317
|
+
recovery
|
|
31318
|
+
};
|
|
31319
|
+
}
|
|
31320
|
+
const causeMessage = cause instanceof Error ? cause.message : String(cause);
|
|
31321
|
+
return {
|
|
31322
|
+
message: `${causeMessage} (${acknowledgedOperationCount} earlier operation(s) already acknowledged before this failure).${sequenceReceipt}${backendSuffix}`,
|
|
31323
|
+
hint: "The failed input or rejected append was not applied. Keep the acknowledged prefix receipt, then correct or replan the rejected and unsent operations.",
|
|
31324
|
+
errorCode,
|
|
31325
|
+
recovery
|
|
31326
|
+
};
|
|
31327
|
+
}
|
|
31232
31328
|
// ../../packages/warmhub-cli/src/errors-logging.ts
|
|
31233
31329
|
function shouldLogToErrorTier(err) {
|
|
31234
31330
|
switch (err.kind) {
|
|
@@ -31453,7 +31549,8 @@ function printCliError(err, errWriter, opts = {}) {
|
|
|
31453
31549
|
message: err.message,
|
|
31454
31550
|
...err.hint ? { hint: err.hint } : {},
|
|
31455
31551
|
...suggestions.length > 0 ? { suggestions } : {},
|
|
31456
|
-
...err.context ? { context: err.context } : {}
|
|
31552
|
+
...err.context ? { context: err.context } : {},
|
|
31553
|
+
...err.recovery ? { recovery: err.recovery } : {}
|
|
31457
31554
|
}
|
|
31458
31555
|
};
|
|
31459
31556
|
errWriter(JSON.stringify(envelope));
|
|
@@ -31493,8 +31590,13 @@ function toCliError(err) {
|
|
|
31493
31590
|
return cliErrorFromAllFailed(err.operations);
|
|
31494
31591
|
}
|
|
31495
31592
|
if (err instanceof PartialStreamSubmissionError) {
|
|
31496
|
-
const
|
|
31497
|
-
|
|
31593
|
+
const receipt = buildStreamRecoveryReceipt({
|
|
31594
|
+
acknowledgedOperationCount: err.acknowledgedOperationCount,
|
|
31595
|
+
lastAcknowledgedRepoSeq: err.lastAcknowledgedRepoSeq,
|
|
31596
|
+
cause: err.cause,
|
|
31597
|
+
attemptedAppendOutcome: err.attemptedAppendOutcome
|
|
31598
|
+
});
|
|
31599
|
+
return new CliError(4 /* Backend */, "BACKEND", receipt.message, err, receipt.hint, undefined, receipt.errorCode, receipt.recovery);
|
|
31498
31600
|
}
|
|
31499
31601
|
if (err instanceof WarmHubError) {
|
|
31500
31602
|
if (err.code === "CURSOR_EPOCH_INVALID" || err.errorCode === "CURSOR_EPOCH_INVALID") {
|
|
@@ -34966,6 +35068,7 @@ function pageEnvelope(items, opts) {
|
|
|
34966
35068
|
const nextCursor = opts.nextCursor ?? null;
|
|
34967
35069
|
return {
|
|
34968
35070
|
items,
|
|
35071
|
+
...opts.repoSeq === undefined ? {} : { repoSeq: opts.repoSeq },
|
|
34969
35072
|
page: {
|
|
34970
35073
|
limit: opts.limit,
|
|
34971
35074
|
count: items.length,
|
|
@@ -35118,6 +35221,9 @@ var reviseFlags = {
|
|
|
35118
35221
|
};
|
|
35119
35222
|
var retractFlags = {
|
|
35120
35223
|
reason: flag.string({ description: "Reason for retraction (<=500 chars)" }),
|
|
35224
|
+
"expected-version": flag.number({
|
|
35225
|
+
description: "only retract if the target is still at this version (optimistic concurrency)"
|
|
35226
|
+
}),
|
|
35121
35227
|
message: flag.string({ short: "m", description: "Commit message" }),
|
|
35122
35228
|
committer: flag.string({
|
|
35123
35229
|
description: "Committer wref (shape or shaped thing; e.g. Agent/bot-1)"
|
|
@@ -35152,15 +35258,17 @@ var handleRevise = async (ctx, { flags, args }) => {
|
|
|
35152
35258
|
var handleRetract = async (ctx, { flags, args }) => {
|
|
35153
35259
|
const name = args[0];
|
|
35154
35260
|
if (!name) {
|
|
35155
|
-
usageError("Usage: wh assertion retract <wref> -m <message>", 'wh assertion retract Belief/cave-safe -m "withdraw claim"');
|
|
35261
|
+
usageError("Usage: wh assertion retract <wref> -m <message> [--expected-version <n>]", 'wh assertion retract Belief/cave-safe -m "withdraw claim"');
|
|
35156
35262
|
}
|
|
35157
35263
|
const { org, repo } = parseOrgRepo(getRepoRef(ctx), ctx.config);
|
|
35264
|
+
const expectedVersion = parsePositiveIntFlag(flags["expected-version"], "--expected-version", "wh assertion retract Belief/cave-safe --expected-version 3");
|
|
35158
35265
|
const result = await ctx.client.commit.apply(org, repo, flags.message ?? `retract ${name}`, [
|
|
35159
35266
|
{
|
|
35160
35267
|
operation: "retract",
|
|
35161
35268
|
kind: "assertion",
|
|
35162
35269
|
name,
|
|
35163
|
-
...flags.reason ? { reason: flags.reason } : {}
|
|
35270
|
+
...flags.reason ? { reason: flags.reason } : {},
|
|
35271
|
+
...expectedVersion !== undefined ? { expectedVersion } : {}
|
|
35164
35272
|
}
|
|
35165
35273
|
], {
|
|
35166
35274
|
committer: flags.committer
|
|
@@ -35235,6 +35343,47 @@ function parseCollectionRoleFlag(value, example) {
|
|
|
35235
35343
|
return value;
|
|
35236
35344
|
usageError("Invalid --role. Expected from, to, or ends.", example);
|
|
35237
35345
|
}
|
|
35346
|
+
function parseSinceRepoSeqFlag(value) {
|
|
35347
|
+
if (value === undefined)
|
|
35348
|
+
return;
|
|
35349
|
+
if (Number.isSafeInteger(value) && value >= -1)
|
|
35350
|
+
return value;
|
|
35351
|
+
usageError("--since-repo-seq must be -1 or a nonnegative safe integer.", "wh thing list --since-repo-seq -1 --all --format json");
|
|
35352
|
+
}
|
|
35353
|
+
function requireIncrementalCheckpoint(repoSeq, required) {
|
|
35354
|
+
if (required && repoSeq === undefined) {
|
|
35355
|
+
throw new CliError(4 /* Backend */, "BACKEND", "Incremental read completed without repoSeq", undefined, "Retry the read. If the checkpoint remains absent, report a backend incremental-read contract violation.");
|
|
35356
|
+
}
|
|
35357
|
+
}
|
|
35358
|
+
async function collectThingPages(args) {
|
|
35359
|
+
const items = [];
|
|
35360
|
+
let cursor = args.initialCursor;
|
|
35361
|
+
const seenCursors = new Set(cursor ? [cursor] : []);
|
|
35362
|
+
while (true) {
|
|
35363
|
+
const page = await args.fetchPage(cursor);
|
|
35364
|
+
const pageItems = page.items ?? [];
|
|
35365
|
+
if (args.onPage) {
|
|
35366
|
+
if (!await args.onPage(pageItems)) {
|
|
35367
|
+
return { items, nextCursor: undefined };
|
|
35368
|
+
}
|
|
35369
|
+
} else {
|
|
35370
|
+
items.push(...pageItems);
|
|
35371
|
+
}
|
|
35372
|
+
if (!page.nextCursor) {
|
|
35373
|
+
requireIncrementalCheckpoint(page.repoSeq, args.requireRepoSeq);
|
|
35374
|
+
return {
|
|
35375
|
+
items,
|
|
35376
|
+
nextCursor: undefined,
|
|
35377
|
+
...page.repoSeq === undefined ? {} : { repoSeq: page.repoSeq }
|
|
35378
|
+
};
|
|
35379
|
+
}
|
|
35380
|
+
if (seenCursors.has(page.nextCursor)) {
|
|
35381
|
+
throw new CliError(4 /* Backend */, "BACKEND", `${args.title} pagination cursor repeated; aborting --all to avoid an infinite loop.`, undefined, "Retry without --all to fetch one page and inspect page.nextCursor. If cursors repeat, report this as a backend pagination issue.");
|
|
35382
|
+
}
|
|
35383
|
+
seenCursors.add(page.nextCursor);
|
|
35384
|
+
cursor = page.nextCursor;
|
|
35385
|
+
}
|
|
35386
|
+
}
|
|
35238
35387
|
async function handleCount(ctx, org, repo, opts) {
|
|
35239
35388
|
const result = await ctx.client.thing.count(org, repo, opts);
|
|
35240
35389
|
writeOutput(ctx, result, () => ctx.out(`${result.count}`));
|
|
@@ -36190,6 +36339,9 @@ var headFlags = {
|
|
|
36190
36339
|
description: "Max items per page (default: 50, max: 500)"
|
|
36191
36340
|
}),
|
|
36192
36341
|
cursor: flag.string({ description: "Opaque pagination cursor" }),
|
|
36342
|
+
"since-repo-seq": flag.number({
|
|
36343
|
+
description: "Return identities changed after this repository sequence"
|
|
36344
|
+
}),
|
|
36193
36345
|
all: flag.boolean({ description: "Fetch all pages" }),
|
|
36194
36346
|
match: flag.string({ description: "Filter by wref glob pattern" }),
|
|
36195
36347
|
count: flag.boolean({ description: "Return count of matching items" }),
|
|
@@ -36213,15 +36365,19 @@ var handleHead = async (ctx, { flags, args }) => {
|
|
|
36213
36365
|
const kind = validateKind(flags.kind);
|
|
36214
36366
|
const limit = flags.limit;
|
|
36215
36367
|
const cursor = flags.cursor;
|
|
36368
|
+
const sinceRepoSeq = parseSinceRepoSeqFlag(flags["since-repo-seq"]);
|
|
36216
36369
|
const all = flags.all;
|
|
36217
36370
|
const match = flags.match;
|
|
36218
36371
|
const count = flags.count;
|
|
36219
36372
|
const includeRetracted = flags["include-retracted"];
|
|
36220
36373
|
const whereRaw = flags.where ?? [];
|
|
36221
36374
|
const where = whereRaw.map(parseWhereFlag);
|
|
36375
|
+
if (ctx.liveMode && sinceRepoSeq !== undefined) {
|
|
36376
|
+
usageError("--since-repo-seq cannot be used with --live.", "wh thing list --since-repo-seq 42 --all --format json");
|
|
36377
|
+
}
|
|
36222
36378
|
if (count) {
|
|
36223
36379
|
if (cursor || all || limit || ctx.liveMode) {
|
|
36224
|
-
usageError("Usage: wh thing list --count [--shape SHAPE] [--kind KIND] [--match PATTERN]", "wh thing list --shape Player --count");
|
|
36380
|
+
usageError("Usage: wh thing list --count [--shape SHAPE] [--kind KIND] [--match PATTERN] [--since-repo-seq N]", "wh thing list --shape Player --count --since-repo-seq 42");
|
|
36225
36381
|
}
|
|
36226
36382
|
const componentRef2 = flags.component;
|
|
36227
36383
|
const strictExclude2 = !!flags["exclude-components"];
|
|
@@ -36234,7 +36390,8 @@ var handleHead = async (ctx, { flags, args }) => {
|
|
|
36234
36390
|
componentRef: componentRef2,
|
|
36235
36391
|
excludeComponents: strictExclude2,
|
|
36236
36392
|
excludeInfraShapes: !strictExclude2 && !shape,
|
|
36237
|
-
where: where.length > 0 ? where : undefined
|
|
36393
|
+
where: where.length > 0 ? where : undefined,
|
|
36394
|
+
...sinceRepoSeq === undefined ? {} : { sinceRepoSeq }
|
|
36238
36395
|
});
|
|
36239
36396
|
}
|
|
36240
36397
|
if (cursor && !limit) {
|
|
@@ -36261,7 +36418,8 @@ var handleHead = async (ctx, { flags, args }) => {
|
|
|
36261
36418
|
componentRef,
|
|
36262
36419
|
excludeComponents,
|
|
36263
36420
|
excludeInfraShapes,
|
|
36264
|
-
where: where.length > 0 ? where : undefined
|
|
36421
|
+
where: where.length > 0 ? where : undefined,
|
|
36422
|
+
...sinceRepoSeq === undefined ? {} : { sinceRepoSeq }
|
|
36265
36423
|
};
|
|
36266
36424
|
if (ctx.liveMode) {
|
|
36267
36425
|
await runLive({
|
|
@@ -36294,7 +36452,8 @@ var handleHead = async (ctx, { flags, args }) => {
|
|
|
36294
36452
|
componentRef,
|
|
36295
36453
|
excludeComponents,
|
|
36296
36454
|
excludeInfraShapes,
|
|
36297
|
-
where: where.length > 0 ? where : undefined
|
|
36455
|
+
where: where.length > 0 ? where : undefined,
|
|
36456
|
+
...sinceRepoSeq === undefined ? {} : { sinceRepoSeq }
|
|
36298
36457
|
}, streamJsonl ? async (items) => {
|
|
36299
36458
|
writePageOutput(ctx, items, { limit: pageLimit }, () => {});
|
|
36300
36459
|
return await ctx.flushOut?.() ?? true;
|
|
@@ -36308,23 +36467,25 @@ var handleHead = async (ctx, { flags, args }) => {
|
|
|
36308
36467
|
componentRef,
|
|
36309
36468
|
excludeComponents,
|
|
36310
36469
|
excludeInfraShapes,
|
|
36311
|
-
where: where.length > 0 ? where : undefined
|
|
36470
|
+
where: where.length > 0 ? where : undefined,
|
|
36471
|
+
...sinceRepoSeq === undefined ? {} : { sinceRepoSeq }
|
|
36312
36472
|
});
|
|
36313
36473
|
if (streamJsonl)
|
|
36314
36474
|
return;
|
|
36475
|
+
requireIncrementalCheckpoint(result.repoSeq, sinceRepoSeq !== undefined && !result.nextCursor);
|
|
36315
36476
|
if (!all && result.nextCursor) {
|
|
36316
36477
|
emitPartialPageHint(ctx, (result.items ?? []).length, result.nextCursor, boundedLimit);
|
|
36317
36478
|
}
|
|
36318
36479
|
writePageOutput(ctx, result.items ?? [], {
|
|
36319
36480
|
limit: all ? pageLimit : boundedLimit,
|
|
36320
|
-
nextCursor: result.nextCursor ?? null
|
|
36481
|
+
nextCursor: result.nextCursor ?? null,
|
|
36482
|
+
...result.repoSeq === undefined ? {} : { repoSeq: result.repoSeq }
|
|
36321
36483
|
}, () => renderHead(ctx.out, ctx.colors, ctx.chars, result, org, repo, shape, kind));
|
|
36322
36484
|
};
|
|
36323
36485
|
async function fetchAllHeadPages(ctx, org, repo, opts, onPage) {
|
|
36324
|
-
|
|
36325
|
-
|
|
36326
|
-
|
|
36327
|
-
const page = await ctx.client.thing.head(org, repo, {
|
|
36486
|
+
return collectThingPages({
|
|
36487
|
+
initialCursor: opts.cursor,
|
|
36488
|
+
fetchPage: (cursor) => ctx.client.thing.head(org, repo, {
|
|
36328
36489
|
shape: opts.shape,
|
|
36329
36490
|
kind: opts.kind,
|
|
36330
36491
|
match: opts.match,
|
|
@@ -36334,20 +36495,13 @@ async function fetchAllHeadPages(ctx, org, repo, opts, onPage) {
|
|
|
36334
36495
|
componentRef: opts.componentRef,
|
|
36335
36496
|
excludeComponents: opts.excludeComponents,
|
|
36336
36497
|
excludeInfraShapes: opts.excludeInfraShapes,
|
|
36337
|
-
where: opts.where
|
|
36338
|
-
|
|
36339
|
-
|
|
36340
|
-
|
|
36341
|
-
|
|
36342
|
-
|
|
36343
|
-
|
|
36344
|
-
items.push(...pageItems);
|
|
36345
|
-
}
|
|
36346
|
-
if (!page.nextCursor)
|
|
36347
|
-
break;
|
|
36348
|
-
cursor = page.nextCursor;
|
|
36349
|
-
}
|
|
36350
|
-
return { items, nextCursor: undefined };
|
|
36498
|
+
where: opts.where,
|
|
36499
|
+
...opts.sinceRepoSeq === undefined ? {} : { sinceRepoSeq: opts.sinceRepoSeq }
|
|
36500
|
+
}),
|
|
36501
|
+
onPage,
|
|
36502
|
+
requireRepoSeq: opts.sinceRepoSeq !== undefined,
|
|
36503
|
+
title: "Thing list"
|
|
36504
|
+
});
|
|
36351
36505
|
}
|
|
36352
36506
|
|
|
36353
36507
|
// ../../packages/warmhub-cli/src/domains/thing/query.ts
|
|
@@ -36359,6 +36513,9 @@ var queryFlags = {
|
|
|
36359
36513
|
description: "Max results per page (default: 50, max: 500)"
|
|
36360
36514
|
}),
|
|
36361
36515
|
cursor: flag.string({ description: "Opaque pagination cursor" }),
|
|
36516
|
+
"since-repo-seq": flag.number({
|
|
36517
|
+
description: "Return identities changed after this repository sequence"
|
|
36518
|
+
}),
|
|
36362
36519
|
all: flag.boolean({ description: "Fetch all pages" }),
|
|
36363
36520
|
match: flag.string({ description: "Filter by wref glob pattern" }),
|
|
36364
36521
|
count: flag.boolean({ description: "Return count of matching items" }),
|
|
@@ -36389,6 +36546,7 @@ var handleQuery = async (ctx, { flags }) => {
|
|
|
36389
36546
|
const kind = validateKind(flags.kind);
|
|
36390
36547
|
const limit = flags.limit;
|
|
36391
36548
|
const cursor = flags.cursor;
|
|
36549
|
+
const sinceRepoSeq = parseSinceRepoSeqFlag(flags["since-repo-seq"]);
|
|
36392
36550
|
const all = flags.all;
|
|
36393
36551
|
const match = flags.match;
|
|
36394
36552
|
const count = flags.count;
|
|
@@ -36404,9 +36562,12 @@ var handleQuery = async (ctx, { flags }) => {
|
|
|
36404
36562
|
const c = ctx.colors;
|
|
36405
36563
|
const whereRaw = flags.where ?? [];
|
|
36406
36564
|
const where = whereRaw.map(parseWhereFlag);
|
|
36565
|
+
if (ctx.liveMode && sinceRepoSeq !== undefined) {
|
|
36566
|
+
usageError("--since-repo-seq cannot be used with --live.", "wh thing query --since-repo-seq 42 --all --format json");
|
|
36567
|
+
}
|
|
36407
36568
|
if (count) {
|
|
36408
36569
|
if (cursor || all || limit || ctx.liveMode || role) {
|
|
36409
|
-
usageError("Usage: wh thing query --count [--shape SHAPE] [--about WREF] [--kind KIND] [--match PATTERN]", "wh thing query --kind assertion --about Player/alice --count");
|
|
36570
|
+
usageError("Usage: wh thing query --count [--shape SHAPE] [--about WREF] [--kind KIND] [--match PATTERN] [--since-repo-seq N]", "wh thing query --kind assertion --about Player/alice --count --since-repo-seq 42");
|
|
36410
36571
|
}
|
|
36411
36572
|
return handleCount(ctx, org, repo, {
|
|
36412
36573
|
shape,
|
|
@@ -36418,7 +36579,8 @@ var handleQuery = async (ctx, { flags }) => {
|
|
|
36418
36579
|
componentRef,
|
|
36419
36580
|
excludeComponents,
|
|
36420
36581
|
excludeInfraShapes,
|
|
36421
|
-
where: where.length > 0 ? where : undefined
|
|
36582
|
+
where: where.length > 0 ? where : undefined,
|
|
36583
|
+
...sinceRepoSeq === undefined ? {} : { sinceRepoSeq }
|
|
36422
36584
|
});
|
|
36423
36585
|
}
|
|
36424
36586
|
if (role && (!about || !resolveCollections)) {
|
|
@@ -36445,7 +36607,8 @@ var handleQuery = async (ctx, { flags }) => {
|
|
|
36445
36607
|
componentRef,
|
|
36446
36608
|
excludeComponents,
|
|
36447
36609
|
excludeInfraShapes,
|
|
36448
|
-
where: where.length > 0 ? where : undefined
|
|
36610
|
+
where: where.length > 0 ? where : undefined,
|
|
36611
|
+
...sinceRepoSeq === undefined ? {} : { sinceRepoSeq }
|
|
36449
36612
|
};
|
|
36450
36613
|
if (ctx.liveMode) {
|
|
36451
36614
|
await runLive({
|
|
@@ -36481,7 +36644,8 @@ var handleQuery = async (ctx, { flags }) => {
|
|
|
36481
36644
|
componentRef,
|
|
36482
36645
|
excludeComponents,
|
|
36483
36646
|
excludeInfraShapes,
|
|
36484
|
-
where: where.length > 0 ? where : undefined
|
|
36647
|
+
where: where.length > 0 ? where : undefined,
|
|
36648
|
+
...sinceRepoSeq === undefined ? {} : { sinceRepoSeq }
|
|
36485
36649
|
}, streamJsonl ? async (items) => {
|
|
36486
36650
|
writePageOutput(ctx, items, { limit: pageLimit }, () => {});
|
|
36487
36651
|
return await ctx.flushOut?.() ?? true;
|
|
@@ -36498,23 +36662,25 @@ var handleQuery = async (ctx, { flags }) => {
|
|
|
36498
36662
|
componentRef,
|
|
36499
36663
|
excludeComponents,
|
|
36500
36664
|
excludeInfraShapes,
|
|
36501
|
-
where: where.length > 0 ? where : undefined
|
|
36665
|
+
where: where.length > 0 ? where : undefined,
|
|
36666
|
+
...sinceRepoSeq === undefined ? {} : { sinceRepoSeq }
|
|
36502
36667
|
});
|
|
36503
36668
|
if (streamJsonl)
|
|
36504
36669
|
return;
|
|
36670
|
+
requireIncrementalCheckpoint(result.repoSeq, sinceRepoSeq !== undefined && !result.nextCursor);
|
|
36505
36671
|
if (!all && result.nextCursor) {
|
|
36506
36672
|
emitPartialPageHint(ctx, (result.items ?? []).length, result.nextCursor, boundedLimit);
|
|
36507
36673
|
}
|
|
36508
36674
|
writePageOutput(ctx, result.items ?? [], {
|
|
36509
36675
|
limit: all ? pageLimit : boundedLimit,
|
|
36510
|
-
nextCursor: result.nextCursor ?? null
|
|
36676
|
+
nextCursor: result.nextCursor ?? null,
|
|
36677
|
+
...result.repoSeq === undefined ? {} : { repoSeq: result.repoSeq }
|
|
36511
36678
|
}, () => renderQueryResults(ctx.out, c, result));
|
|
36512
36679
|
};
|
|
36513
36680
|
async function fetchAllQueryPages(ctx, org, repo, opts, onPage) {
|
|
36514
|
-
|
|
36515
|
-
|
|
36516
|
-
|
|
36517
|
-
const page = await ctx.client.thing.query(org, repo, {
|
|
36681
|
+
return collectThingPages({
|
|
36682
|
+
initialCursor: opts.cursor,
|
|
36683
|
+
fetchPage: (cursor) => ctx.client.thing.query(org, repo, {
|
|
36518
36684
|
shape: opts.shape,
|
|
36519
36685
|
about: opts.about,
|
|
36520
36686
|
kind: opts.kind,
|
|
@@ -36527,20 +36693,13 @@ async function fetchAllQueryPages(ctx, org, repo, opts, onPage) {
|
|
|
36527
36693
|
componentRef: opts.componentRef,
|
|
36528
36694
|
excludeComponents: opts.excludeComponents,
|
|
36529
36695
|
excludeInfraShapes: opts.excludeInfraShapes,
|
|
36530
|
-
where: opts.where
|
|
36531
|
-
|
|
36532
|
-
|
|
36533
|
-
|
|
36534
|
-
|
|
36535
|
-
|
|
36536
|
-
|
|
36537
|
-
items.push(...pageItems);
|
|
36538
|
-
}
|
|
36539
|
-
if (!page.nextCursor)
|
|
36540
|
-
break;
|
|
36541
|
-
cursor = page.nextCursor;
|
|
36542
|
-
}
|
|
36543
|
-
return { items, nextCursor: undefined };
|
|
36696
|
+
where: opts.where,
|
|
36697
|
+
...opts.sinceRepoSeq === undefined ? {} : { sinceRepoSeq: opts.sinceRepoSeq }
|
|
36698
|
+
}),
|
|
36699
|
+
onPage,
|
|
36700
|
+
requireRepoSeq: opts.sinceRepoSeq !== undefined,
|
|
36701
|
+
title: "Thing query"
|
|
36702
|
+
});
|
|
36544
36703
|
}
|
|
36545
36704
|
function renderQueryResults(out, c, result) {
|
|
36546
36705
|
const items = result.items ?? [];
|
|
@@ -36709,6 +36868,9 @@ var retractFlags2 = {
|
|
|
36709
36868
|
description: "Optional safety check: thing|assertion|shape|collection (errors on mismatch)"
|
|
36710
36869
|
}),
|
|
36711
36870
|
reason: flag.string({ description: "Reason for retraction (<=500 chars)" }),
|
|
36871
|
+
"expected-version": flag.number({
|
|
36872
|
+
description: "only retract if the target is still at this version (optimistic concurrency)"
|
|
36873
|
+
}),
|
|
36712
36874
|
message: flag.string({ short: "m", description: "Commit message" }),
|
|
36713
36875
|
committer: flag.string({
|
|
36714
36876
|
description: "Committer wref (shape or shaped thing; e.g. Agent/bot-1)"
|
|
@@ -36720,13 +36882,14 @@ var retractFlags2 = {
|
|
|
36720
36882
|
var handleThingRetract = async (ctx, { flags, args }) => {
|
|
36721
36883
|
const name = args[0];
|
|
36722
36884
|
if (!name) {
|
|
36723
|
-
usageError("Usage: wh thing retract <wref> -m <message> [--reason <text>] [--kind thing|assertion|shape|collection]", 'wh thing retract Measurement/m1 -m "cleanup" --reason "bad source"');
|
|
36885
|
+
usageError("Usage: wh thing retract <wref> -m <message> [--reason <text>] [--kind thing|assertion|shape|collection] [--expected-version <n>]", 'wh thing retract Measurement/m1 -m "cleanup" --reason "bad source"');
|
|
36724
36886
|
}
|
|
36725
36887
|
const { org, repo } = parseOrgRepo(getRepoRef(ctx), ctx.config);
|
|
36726
36888
|
const committer = flags.committer;
|
|
36727
36889
|
const message = flags.message;
|
|
36728
36890
|
const kind = flags.kind;
|
|
36729
36891
|
const reason = flags.reason;
|
|
36892
|
+
const expectedVersion = parsePositiveIntFlag(flags["expected-version"], "--expected-version", "wh thing retract Player/alice --expected-version 3");
|
|
36730
36893
|
const leaseId = requireLeaseIdFlag(flags["lease-id"], "wh thing retract Player/alice --lease-id <id>");
|
|
36731
36894
|
const c = ctx.colors;
|
|
36732
36895
|
const result = await ctx.client.commit.apply(org, repo, message ?? `retract ${name}`, [
|
|
@@ -36735,6 +36898,7 @@ var handleThingRetract = async (ctx, { flags, args }) => {
|
|
|
36735
36898
|
name,
|
|
36736
36899
|
...kind ? { kind } : {},
|
|
36737
36900
|
...reason ? { reason } : {},
|
|
36901
|
+
...expectedVersion !== undefined ? { expectedVersion } : {},
|
|
36738
36902
|
...leaseId ? { leaseId } : {}
|
|
36739
36903
|
}
|
|
36740
36904
|
], { committer });
|
|
@@ -39319,7 +39483,7 @@ var createFlags3 = {
|
|
|
39319
39483
|
description: "collection members (comma-separated wrefs)"
|
|
39320
39484
|
}),
|
|
39321
39485
|
"expected-version": flag.number({
|
|
39322
|
-
description: "
|
|
39486
|
+
description: "only apply if the --revise or single --retract target is still at this version (optimistic concurrency)."
|
|
39323
39487
|
}),
|
|
39324
39488
|
"lease-id": flag.string({
|
|
39325
39489
|
description: "read-lease token from `wh thing lease`, bound to --revise or one --retract target (auto-released on success)"
|
|
@@ -39582,7 +39746,7 @@ function buildAddOperations(input) {
|
|
|
39582
39746
|
});
|
|
39583
39747
|
}
|
|
39584
39748
|
function buildRetractOperations(input) {
|
|
39585
|
-
const { retractNames, kinds, reasons, leaseId } = input;
|
|
39749
|
+
const { retractNames, kinds, reasons, expectedVersion, leaseId } = input;
|
|
39586
39750
|
if (leaseId !== undefined && retractNames.length !== 1) {
|
|
39587
39751
|
throw new CliError(2 /* UserInput */, "USER_INPUT", `--lease-id requires exactly one --retract target; received ${retractNames.length}.`, undefined, "wh commit submit --retract Player/alice --lease-id lease-xyz --repo acme/world");
|
|
39588
39752
|
}
|
|
@@ -39612,6 +39776,7 @@ function buildRetractOperations(input) {
|
|
|
39612
39776
|
name,
|
|
39613
39777
|
...kind ? { kind } : {},
|
|
39614
39778
|
...reason ? { reason } : {},
|
|
39779
|
+
...expectedVersion !== undefined ? { expectedVersion } : {},
|
|
39615
39780
|
...leaseId ? { leaseId } : {}
|
|
39616
39781
|
};
|
|
39617
39782
|
});
|
|
@@ -39711,15 +39876,14 @@ import { createInterface as createInterface2 } from "node:readline";
|
|
|
39711
39876
|
class JsonlPartialSubmissionError extends CliError {
|
|
39712
39877
|
}
|
|
39713
39878
|
function jsonlPartialSubmissionError(args) {
|
|
39714
|
-
const
|
|
39715
|
-
|
|
39716
|
-
|
|
39717
|
-
|
|
39718
|
-
|
|
39719
|
-
}
|
|
39720
|
-
const
|
|
39721
|
-
|
|
39722
|
-
return new JsonlPartialSubmissionError(4 /* Backend */, "BACKEND", `${message} (${acknowledgedOperationCount} earlier operation(s) already acknowledged by the server before this input failure).`, cause, `${causeHint}Earlier chunks have landed; inspect repository state before submitting any remaining JSONL operations.`);
|
|
39879
|
+
const receipt = buildStreamRecoveryReceipt({
|
|
39880
|
+
acknowledgedOperationCount: args.acknowledgedOperationCount,
|
|
39881
|
+
lastAcknowledgedRepoSeq: args.lastAcknowledgedRepoSeq,
|
|
39882
|
+
cause: args.cause,
|
|
39883
|
+
attemptedAppendOutcome: args.failedAppendMayHaveLanded === true ? "unknown" : "not_applied"
|
|
39884
|
+
});
|
|
39885
|
+
const causeHint = args.cause instanceof CliError && args.cause.hint ? `${args.cause.hint} ` : "";
|
|
39886
|
+
return new JsonlPartialSubmissionError(4 /* Backend */, "BACKEND", receipt.message, args.cause, `${causeHint}${receipt.hint}`, undefined, receipt.errorCode, receipt.recovery);
|
|
39723
39887
|
}
|
|
39724
39888
|
|
|
39725
39889
|
// ../../packages/warmhub-cli/src/domains/commit-submit-utils.ts
|
|
@@ -39804,50 +39968,6 @@ function toCommitSubmitResult(args) {
|
|
|
39804
39968
|
operations
|
|
39805
39969
|
};
|
|
39806
39970
|
}
|
|
39807
|
-
function backendErrorCode(error) {
|
|
39808
|
-
if (typeof error !== "object" || error === null) {
|
|
39809
|
-
return;
|
|
39810
|
-
}
|
|
39811
|
-
const typed = error;
|
|
39812
|
-
if (typeof typed.data === "object" && typed.data !== null) {
|
|
39813
|
-
const data = typed.data;
|
|
39814
|
-
if (typeof data.code === "string") {
|
|
39815
|
-
return data.code;
|
|
39816
|
-
}
|
|
39817
|
-
}
|
|
39818
|
-
const causeCode = backendErrorCode(typed.cause);
|
|
39819
|
-
if (causeCode !== undefined) {
|
|
39820
|
-
return causeCode;
|
|
39821
|
-
}
|
|
39822
|
-
return typeof typed.code === "string" ? typed.code : undefined;
|
|
39823
|
-
}
|
|
39824
|
-
function backendErrorStatus(error) {
|
|
39825
|
-
if (typeof error !== "object" || error === null) {
|
|
39826
|
-
return;
|
|
39827
|
-
}
|
|
39828
|
-
const typed = error;
|
|
39829
|
-
if (typeof typed.status === "number") {
|
|
39830
|
-
return typed.status;
|
|
39831
|
-
}
|
|
39832
|
-
if (typeof typed.data === "object" && typed.data !== null) {
|
|
39833
|
-
const data = typed.data;
|
|
39834
|
-
if (typeof data.status === "number") {
|
|
39835
|
-
return data.status;
|
|
39836
|
-
}
|
|
39837
|
-
if (typeof data.httpStatus === "number") {
|
|
39838
|
-
return data.httpStatus;
|
|
39839
|
-
}
|
|
39840
|
-
if (typeof data.warmhub?.status === "number") {
|
|
39841
|
-
return data.warmhub.status;
|
|
39842
|
-
}
|
|
39843
|
-
}
|
|
39844
|
-
return backendErrorStatus(typed.cause);
|
|
39845
|
-
}
|
|
39846
|
-
function firstJsonlAppendErrorMayHaveCommitted(error) {
|
|
39847
|
-
const errorCode = backendErrorCode(error);
|
|
39848
|
-
const errorStatus = backendErrorStatus(error);
|
|
39849
|
-
return errorCode === undefined || errorCode === "COMMIT_OUTCOME_UNKNOWN" || errorCode === "INTERNAL_ERROR" || errorCode === "NETWORK" || errorCode === "SERVICE_UNAVAILABLE" || errorCode === "BACKEND" && errorStatus !== undefined && errorStatus >= 500;
|
|
39850
|
-
}
|
|
39851
39971
|
|
|
39852
39972
|
// ../../packages/warmhub-cli/src/domains/stream-progress.ts
|
|
39853
39973
|
import { createReadStream } from "node:fs";
|
|
@@ -40032,12 +40152,12 @@ async function applyJsonlCommit(ctx, args) {
|
|
|
40032
40152
|
const tAppendStart = performance.now();
|
|
40033
40153
|
progress.start(t0);
|
|
40034
40154
|
let opCount = 0;
|
|
40155
|
+
let repoSeq;
|
|
40035
40156
|
try {
|
|
40036
40157
|
const operations = [];
|
|
40037
40158
|
const submittedOperations = [];
|
|
40038
40159
|
let allocatedTokenRanges = [];
|
|
40039
40160
|
let createdByEmail;
|
|
40040
|
-
let repoSeq;
|
|
40041
40161
|
let parsedOpCount = 0;
|
|
40042
40162
|
let chunk = [];
|
|
40043
40163
|
let lineNumber = 0;
|
|
@@ -40060,11 +40180,13 @@ async function applyJsonlCommit(ctx, args) {
|
|
|
40060
40180
|
});
|
|
40061
40181
|
} catch (cause) {
|
|
40062
40182
|
const completed = opCount;
|
|
40063
|
-
|
|
40183
|
+
const failedAppendMayHaveLanded = !streamAppendWasExplicitlyRejected(cause);
|
|
40184
|
+
if (opCount > 0 || failedAppendMayHaveLanded) {
|
|
40064
40185
|
throw jsonlPartialSubmissionError({
|
|
40065
40186
|
acknowledgedOperationCount: completed,
|
|
40066
40187
|
cause,
|
|
40067
|
-
failedAppendMayHaveLanded
|
|
40188
|
+
failedAppendMayHaveLanded,
|
|
40189
|
+
lastAcknowledgedRepoSeq: repoSeq
|
|
40068
40190
|
});
|
|
40069
40191
|
}
|
|
40070
40192
|
throw cause;
|
|
@@ -40259,7 +40381,8 @@ async function applyJsonlCommit(ctx, args) {
|
|
|
40259
40381
|
}
|
|
40260
40382
|
throw jsonlPartialSubmissionError({
|
|
40261
40383
|
acknowledgedOperationCount: opCount,
|
|
40262
|
-
cause: error
|
|
40384
|
+
cause: error,
|
|
40385
|
+
lastAcknowledgedRepoSeq: repoSeq
|
|
40263
40386
|
});
|
|
40264
40387
|
}
|
|
40265
40388
|
}
|
|
@@ -40329,9 +40452,10 @@ var handleSubmit = async (ctx, { flags, args }) => {
|
|
|
40329
40452
|
const abouts = flags.about ?? [];
|
|
40330
40453
|
const reasons = flags.reason ?? [];
|
|
40331
40454
|
const kinds = flags.kind ?? [];
|
|
40332
|
-
const
|
|
40333
|
-
|
|
40334
|
-
|
|
40455
|
+
const expectedVersionExample = retractNames.length > 0 ? "wh commit submit --retract Player/alice --expected-version 3" : "wh commit submit --revise Player/alice --data '{...}' --expected-version 3";
|
|
40456
|
+
const expectedVersion = parsePositiveIntFlag(flags["expected-version"], "--expected-version", expectedVersionExample);
|
|
40457
|
+
if (expectedVersion !== undefined && reviseName === undefined && retractNames.length !== 1) {
|
|
40458
|
+
usageError("--expected-version requires --revise or exactly one --retract", "wh commit submit --retract Player/alice --expected-version 3");
|
|
40335
40459
|
}
|
|
40336
40460
|
const leaseIdFlag = requireLeaseIdFlag(flags["lease-id"], `wh commit submit --revise Player/alice --data '{"score":2}' --lease-id <id>`);
|
|
40337
40461
|
if (leaseIdFlag !== undefined && reviseName === undefined && retractNames.length === 0) {
|
|
@@ -40455,6 +40579,7 @@ var handleSubmit = async (ctx, { flags, args }) => {
|
|
|
40455
40579
|
retractNames,
|
|
40456
40580
|
kinds,
|
|
40457
40581
|
reasons,
|
|
40582
|
+
expectedVersion,
|
|
40458
40583
|
leaseId: leaseIdFlag
|
|
40459
40584
|
});
|
|
40460
40585
|
} else if (operationSource === "--revise") {
|
|
@@ -44376,7 +44501,7 @@ var ORG_DOMAIN = defineDomain({
|
|
|
44376
44501
|
});
|
|
44377
44502
|
|
|
44378
44503
|
// ../../packages/warmhub-cli/src/domains/prime-content.md
|
|
44379
|
-
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 — Thing operations\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]` — 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### 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]` — 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]` — 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>` — Delete a subscription\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# Add-only restart: rerun the WHOLE file. --skip-existing makes fixed-name adds\n# idempotent; --stream-id only identifies the submission. Mid-stream resume is\n# not a CLI mode. Revise/retract JSONL is not full-rerun safe after an ambiguous\n# append; inspect repo state and reconcile.\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";
|
|
44504
|
+
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 — Thing operations\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### 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>` — Delete a subscription\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";
|
|
44380
44505
|
|
|
44381
44506
|
// ../../packages/warmhub-cli/src/domains/prime.ts
|
|
44382
44507
|
function buildMarkdown(config) {
|
|
@@ -45605,6 +45730,9 @@ function renderShapeFieldDiff(out, diff) {
|
|
|
45605
45730
|
}
|
|
45606
45731
|
var retractFlags3 = {
|
|
45607
45732
|
reason: flag.string({ description: "Reason for retraction (<=500 chars)" }),
|
|
45733
|
+
"expected-version": flag.number({
|
|
45734
|
+
description: "only retract if the target is still at this version (optimistic concurrency)"
|
|
45735
|
+
}),
|
|
45608
45736
|
message: flag.string({ short: "m", description: "Commit message" }),
|
|
45609
45737
|
committer: flag.string({
|
|
45610
45738
|
description: "Committer wref (shape or shaped thing; e.g. Agent/bot-1)"
|
|
@@ -45681,16 +45809,18 @@ var handleRevise3 = async (ctx, { flags, args }) => {
|
|
|
45681
45809
|
var handleRetract2 = async (ctx, { flags, args }) => {
|
|
45682
45810
|
const shapeName = args[0];
|
|
45683
45811
|
if (!shapeName) {
|
|
45684
|
-
usageError("Usage: wh shape retract <name>", "wh shape retract Location");
|
|
45812
|
+
usageError("Usage: wh shape retract <name> [--expected-version <n>]", "wh shape retract Location");
|
|
45685
45813
|
}
|
|
45686
45814
|
const { org, repo } = parseOrgRepo(getRepoRef(ctx), ctx.config);
|
|
45815
|
+
const expectedVersion = parsePositiveIntFlag(flags["expected-version"], "--expected-version", "wh shape retract Location --expected-version 3");
|
|
45687
45816
|
const c = ctx.colors;
|
|
45688
45817
|
const result = await ctx.client.commit.apply(org, repo, flags.message ?? `retract shape ${shapeName}`, [
|
|
45689
45818
|
{
|
|
45690
45819
|
operation: "retract",
|
|
45691
45820
|
kind: "shape",
|
|
45692
45821
|
name: shapeName,
|
|
45693
|
-
...flags.reason ? { reason: flags.reason } : {}
|
|
45822
|
+
...flags.reason ? { reason: flags.reason } : {},
|
|
45823
|
+
...expectedVersion !== undefined ? { expectedVersion } : {}
|
|
45694
45824
|
}
|
|
45695
45825
|
], { committer: flags.committer });
|
|
45696
45826
|
assertSingleOpSuccess(result);
|
|
@@ -49203,7 +49333,7 @@ function resolveLogLevel(flagLevel, env) {
|
|
|
49203
49333
|
// package.json
|
|
49204
49334
|
var package_default3 = {
|
|
49205
49335
|
name: "@warmhub/cli",
|
|
49206
|
-
version: "0.
|
|
49336
|
+
version: "0.86.0",
|
|
49207
49337
|
private: false,
|
|
49208
49338
|
type: "module",
|
|
49209
49339
|
description: "The wh CLI for WarmHub — create repos, commit and query data, and compound knowledge with your AI agents.",
|
|
@@ -49820,5 +49950,5 @@ process.exitCode = interceptedExitCode === undefined ? await runPreparedCli(laun
|
|
|
49820
49950
|
version: package_default3.version
|
|
49821
49951
|
}) : interceptedExitCode;
|
|
49822
49952
|
|
|
49823
|
-
//# debugId=
|
|
49824
|
-
//# warmhub-cli-build-info {"cliVersion":"0.
|
|
49953
|
+
//# debugId=864ACFE03DA5766664756E2164756E21
|
|
49954
|
+
//# warmhub-cli-build-info {"cliVersion":"0.86.0","sdkVersion":"0.84.0"}
|
package/package.json
CHANGED