@warmhub/cli 0.48.0 → 0.49.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 +426 -48
- package/package.json +1 -1
package/dist/wh.js
CHANGED
|
@@ -19527,7 +19527,7 @@ function findSystemComponent(componentId) {
|
|
|
19527
19527
|
// ../../packages/sdk-ts/package.json
|
|
19528
19528
|
var package_default = {
|
|
19529
19529
|
name: "@warmhub/sdk-ts",
|
|
19530
|
-
version: "0.
|
|
19530
|
+
version: "0.48.0",
|
|
19531
19531
|
private: false,
|
|
19532
19532
|
type: "module",
|
|
19533
19533
|
description: "The TypeScript SDK for WarmHub — create repos, commit and query data, and compound knowledge with your AI agents.",
|
|
@@ -19626,12 +19626,16 @@ var package_default = {
|
|
|
19626
19626
|
|
|
19627
19627
|
// ../../packages/sdk-ts/src/operation-normalize.ts
|
|
19628
19628
|
function toBackendStreamOperation(operation) {
|
|
19629
|
+
if (operation.expectedVersion !== undefined && operation.operation !== "revise") {
|
|
19630
|
+
throw new Error("expectedVersion is only valid on revise operations — set operation: 'revise'");
|
|
19631
|
+
}
|
|
19629
19632
|
if (operation.operation === "retract") {
|
|
19630
19633
|
return {
|
|
19631
19634
|
operation: "retract",
|
|
19632
19635
|
name: operation.name,
|
|
19633
19636
|
...operation.kind ? { kind: operation.kind } : {},
|
|
19634
|
-
...operation.reason ? { reason: operation.reason } : {}
|
|
19637
|
+
...operation.reason ? { reason: operation.reason } : {},
|
|
19638
|
+
...operation.leaseId ? { leaseId: operation.leaseId } : {}
|
|
19635
19639
|
};
|
|
19636
19640
|
}
|
|
19637
19641
|
if (operation.operation === "revise") {
|
|
@@ -19654,14 +19658,18 @@ function toBackendStreamOperation(operation) {
|
|
|
19654
19658
|
operation: "revise",
|
|
19655
19659
|
kind: "assertion",
|
|
19656
19660
|
name,
|
|
19657
|
-
data: operation.data
|
|
19661
|
+
data: operation.data,
|
|
19662
|
+
...operation.expectedVersion !== undefined ? { expectedVersion: operation.expectedVersion } : {},
|
|
19663
|
+
...operation.leaseId ? { leaseId: operation.leaseId } : {}
|
|
19658
19664
|
};
|
|
19659
19665
|
}
|
|
19660
19666
|
return {
|
|
19661
19667
|
operation: "revise",
|
|
19662
19668
|
kind: kind2,
|
|
19663
19669
|
name,
|
|
19664
|
-
data: operation.data
|
|
19670
|
+
data: operation.data,
|
|
19671
|
+
...operation.expectedVersion !== undefined ? { expectedVersion: operation.expectedVersion } : {},
|
|
19672
|
+
...operation.leaseId ? { leaseId: operation.leaseId } : {}
|
|
19665
19673
|
};
|
|
19666
19674
|
}
|
|
19667
19675
|
const kind = operation.kind ?? inferKind(operation.name, operation);
|
|
@@ -20155,7 +20163,8 @@ class WarmHubError extends Error {
|
|
|
20155
20163
|
hint;
|
|
20156
20164
|
retryAfter;
|
|
20157
20165
|
backendCode;
|
|
20158
|
-
|
|
20166
|
+
details;
|
|
20167
|
+
constructor(code, message, status, hint, retryAfter, backendCode, details) {
|
|
20159
20168
|
super(message);
|
|
20160
20169
|
this.name = "WarmHubError";
|
|
20161
20170
|
this.code = code;
|
|
@@ -20163,6 +20172,7 @@ class WarmHubError extends Error {
|
|
|
20163
20172
|
this.hint = hint;
|
|
20164
20173
|
this.retryAfter = retryAfter;
|
|
20165
20174
|
this.backendCode = backendCode;
|
|
20175
|
+
this.details = details;
|
|
20166
20176
|
}
|
|
20167
20177
|
get kind() {
|
|
20168
20178
|
return this.code;
|
|
@@ -20187,12 +20197,12 @@ function toWarmHubError(error) {
|
|
|
20187
20197
|
const data = error.data;
|
|
20188
20198
|
const wireCode = data?.warmhub?.code;
|
|
20189
20199
|
const message = data?.warmhub?.message ?? sanitizeErrorMessage(error.message);
|
|
20190
|
-
return new WarmHubError(wireCode ?? "BACKEND", message, data?.warmhub?.status, data?.warmhub?.hint, data?.warmhub?.retryAfter, wireCode);
|
|
20200
|
+
return new WarmHubError(wireCode ?? "BACKEND", message, data?.warmhub?.status, data?.warmhub?.hint, data?.warmhub?.retryAfter, wireCode, data?.warmhub?.details);
|
|
20191
20201
|
}
|
|
20192
20202
|
if (error instanceof Error) {
|
|
20193
20203
|
const warmhubLike = error;
|
|
20194
20204
|
if (error.name === "WarmHubError" && typeof warmhubLike.code === "string") {
|
|
20195
|
-
return new WarmHubError(warmhubLike.code, sanitizeErrorMessage(error.message), typeof warmhubLike.status === "number" ? warmhubLike.status : undefined, typeof warmhubLike.hint === "string" ? warmhubLike.hint : undefined, typeof warmhubLike.retryAfter === "number" ? warmhubLike.retryAfter : undefined, typeof warmhubLike.backendCode === "string" ? warmhubLike.backendCode : undefined);
|
|
20205
|
+
return new WarmHubError(warmhubLike.code, sanitizeErrorMessage(error.message), typeof warmhubLike.status === "number" ? warmhubLike.status : undefined, typeof warmhubLike.hint === "string" ? warmhubLike.hint : undefined, typeof warmhubLike.retryAfter === "number" ? warmhubLike.retryAfter : undefined, typeof warmhubLike.backendCode === "string" ? warmhubLike.backendCode : undefined, warmhubLike.details);
|
|
20196
20206
|
}
|
|
20197
20207
|
if (error.name === "AbortError") {
|
|
20198
20208
|
return new WarmHubError("CANCELLED", error.message);
|
|
@@ -21320,6 +21330,30 @@ class WarmHubClient {
|
|
|
21320
21330
|
throw toWarmHubError(error);
|
|
21321
21331
|
}
|
|
21322
21332
|
},
|
|
21333
|
+
getWithLease: async (orgName, repoName, wref, opts) => {
|
|
21334
|
+
try {
|
|
21335
|
+
return await this.trpc.thing.getWithLease.mutate({
|
|
21336
|
+
orgName,
|
|
21337
|
+
repoName,
|
|
21338
|
+
wref,
|
|
21339
|
+
ttlMs: opts?.ttlMs
|
|
21340
|
+
});
|
|
21341
|
+
} catch (error) {
|
|
21342
|
+
throw toWarmHubError(error);
|
|
21343
|
+
}
|
|
21344
|
+
},
|
|
21345
|
+
releaseLease: async (orgName, repoName, wref, leaseId) => {
|
|
21346
|
+
try {
|
|
21347
|
+
await this.trpc.thing.releaseLease.mutate({
|
|
21348
|
+
orgName,
|
|
21349
|
+
repoName,
|
|
21350
|
+
wref,
|
|
21351
|
+
leaseId
|
|
21352
|
+
});
|
|
21353
|
+
} catch (error) {
|
|
21354
|
+
throw toWarmHubError(error);
|
|
21355
|
+
}
|
|
21356
|
+
},
|
|
21323
21357
|
graph: async (orgName, repoName, wref, opts) => {
|
|
21324
21358
|
try {
|
|
21325
21359
|
return await this.trpc.thing.graph.query({
|
|
@@ -22057,6 +22091,10 @@ function classifyConflict(message, code) {
|
|
|
22057
22091
|
return "archived";
|
|
22058
22092
|
case "REPO_PENDING_DELETE":
|
|
22059
22093
|
return "pending-delete";
|
|
22094
|
+
case "LEASE_UNAVAILABLE":
|
|
22095
|
+
return "lease-held";
|
|
22096
|
+
default:
|
|
22097
|
+
break;
|
|
22060
22098
|
}
|
|
22061
22099
|
const lower = message.toLowerCase();
|
|
22062
22100
|
if (lower.includes("already exists") || lower.includes("already a member")) {
|
|
@@ -22086,6 +22124,8 @@ function conflictHint(message, code) {
|
|
|
22086
22124
|
return "Other things reference this. Retract those assertions first, or use a tombstone.";
|
|
22087
22125
|
case "pending-delete":
|
|
22088
22126
|
return "Repo is being deleted. Wait for the delete to finish or cancel it before retrying.";
|
|
22127
|
+
case "lease-held":
|
|
22128
|
+
return "This thing is leased by another holder. Back off until the lease expires (see leaseExpiresAt / retryAfter), then retry.";
|
|
22089
22129
|
case "other":
|
|
22090
22130
|
return "Resolve the conflicting existing state and try again.";
|
|
22091
22131
|
}
|
|
@@ -22109,7 +22149,8 @@ var CONFLICT_SHAPED_CODES = new Set([
|
|
|
22109
22149
|
"ARCHIVED",
|
|
22110
22150
|
"HAS_INBOUND_REFS",
|
|
22111
22151
|
"REPO_PENDING_DELETE",
|
|
22112
|
-
"ALREADY_RETRACTED"
|
|
22152
|
+
"ALREADY_RETRACTED",
|
|
22153
|
+
"LEASE_UNAVAILABLE"
|
|
22113
22154
|
]);
|
|
22114
22155
|
function fromWh(exit, kind, err, hint = err.hint) {
|
|
22115
22156
|
return new CliError(exit, kind, err.message, err, hint, undefined, err.backendCode);
|
|
@@ -22269,6 +22310,11 @@ function generateSuggestions(code, message, context, backendCode) {
|
|
|
22269
22310
|
action: "Wait for the repo delete to finish or cancel it before retrying"
|
|
22270
22311
|
});
|
|
22271
22312
|
break;
|
|
22313
|
+
case "lease-held":
|
|
22314
|
+
suggestions.push({
|
|
22315
|
+
action: "Another holder leased this thing. Back off until the lease expires (leaseExpiresAt / retryAfter), then retry"
|
|
22316
|
+
});
|
|
22317
|
+
break;
|
|
22272
22318
|
case "other":
|
|
22273
22319
|
suggestions.push({
|
|
22274
22320
|
action: "Resolve the conflicting existing state and retry"
|
|
@@ -22480,6 +22526,21 @@ function safeParseJson(input, label, options) {
|
|
|
22480
22526
|
throw new CliError(2 /* UserInput */, "USER_INPUT", `Invalid JSON for ${label}: ${input.length > 80 ? `${input.slice(0, 77)}...` : input}`, undefined, hint);
|
|
22481
22527
|
}
|
|
22482
22528
|
}
|
|
22529
|
+
function parsePositiveIntFlag(value, label, example) {
|
|
22530
|
+
if (value !== undefined && (!Number.isInteger(value) || value < 1)) {
|
|
22531
|
+
usageError(`${label} must be a positive integer`, example);
|
|
22532
|
+
}
|
|
22533
|
+
return value;
|
|
22534
|
+
}
|
|
22535
|
+
function requireLeaseIdFlag(raw, example = `wh thing revise Player/alice --data '{"score":2}' --lease-id <id>`) {
|
|
22536
|
+
if (raw === undefined)
|
|
22537
|
+
return;
|
|
22538
|
+
const trimmed = raw.trim();
|
|
22539
|
+
if (trimmed === "") {
|
|
22540
|
+
usageError("--lease-id must be a non-empty lease token from `wh thing lease`", example);
|
|
22541
|
+
}
|
|
22542
|
+
return trimmed;
|
|
22543
|
+
}
|
|
22483
22544
|
function parseArgs(argv) {
|
|
22484
22545
|
const positionals = [];
|
|
22485
22546
|
const flags = {};
|
|
@@ -23859,6 +23920,17 @@ function parseOrgRepo(ref, config) {
|
|
|
23859
23920
|
}
|
|
23860
23921
|
throw new CliError(3 /* Config */, "CONFIG", "No repo specified. Use --repo org/repo, set WARMHUB_REPO, or run: wh use org/repo");
|
|
23861
23922
|
}
|
|
23923
|
+
function parseOrgRepoOptional(ref, config) {
|
|
23924
|
+
try {
|
|
23925
|
+
return parseOrgRepo(ref, config);
|
|
23926
|
+
} catch (error) {
|
|
23927
|
+
const suppliedRepoInfo = ref !== undefined && ref !== "" || Boolean(config.defaultRepo);
|
|
23928
|
+
if (suppliedRepoInfo) {
|
|
23929
|
+
throw error;
|
|
23930
|
+
}
|
|
23931
|
+
return {};
|
|
23932
|
+
}
|
|
23933
|
+
}
|
|
23862
23934
|
|
|
23863
23935
|
// ../../packages/warmhub-cli/src/domain-registry.ts
|
|
23864
23936
|
class DomainRegistry {
|
|
@@ -24276,9 +24348,15 @@ function renderWarningLine(out, c, chars, op) {
|
|
|
24276
24348
|
const moreSuffix = remaining > 0 ? ` ${c.dim}(+${remaining} more)${c.reset}` : "";
|
|
24277
24349
|
out(` ${c.yellow}${chars.warn}${c.reset} ${total} ${noun} not declared in shape${shapeLabel}: ${c.dim}${fieldsList}${c.reset}${moreSuffix}`);
|
|
24278
24350
|
}
|
|
24351
|
+
function renderCommitterEcho(out, c, committer) {
|
|
24352
|
+
if (!committer)
|
|
24353
|
+
return;
|
|
24354
|
+
out(` ${c.dim}committer:${c.reset} ${pinnedWref(c, committer)}`);
|
|
24355
|
+
}
|
|
24279
24356
|
function renderSingleOpSuccess(out, c, chars, op, opts) {
|
|
24280
24357
|
const name = op.name ?? opts.fallbackName;
|
|
24281
24358
|
const suffix = opts.suffix ?? "";
|
|
24359
|
+
renderCommitterEcho(out, c, opts.committer);
|
|
24282
24360
|
out(`${opts.color}${opts.marker}${c.reset} ${displayName(c, name)}${suffix}`);
|
|
24283
24361
|
renderWarningLine(out, c, chars, op);
|
|
24284
24362
|
}
|
|
@@ -24357,6 +24435,10 @@ async function readContentInput(filePath, inline, stdinStream) {
|
|
|
24357
24435
|
}
|
|
24358
24436
|
|
|
24359
24437
|
// ../../packages/warmhub-cli/src/domains/thing.ts
|
|
24438
|
+
var DURABLE_ID_PATTERN_RE = /^[0-9a-zA-HJ-NP-Tv-z]{60}(@(v\d+|HEAD|ALL))?$/i;
|
|
24439
|
+
function looksLikeDurableId(wref) {
|
|
24440
|
+
return DURABLE_ID_PATTERN_RE.test(wref);
|
|
24441
|
+
}
|
|
24360
24442
|
function usageError2(usage, example) {
|
|
24361
24443
|
throw new CliError(2 /* UserInput */, "USER_INPUT", usage, undefined, `Example: ${example}`);
|
|
24362
24444
|
}
|
|
@@ -24453,6 +24535,10 @@ function renderHead(out, c, chars, result, org, repo, shape, kind) {
|
|
|
24453
24535
|
const truncated = preview.length > 80 ? `${preview.slice(0, 77)}...` : preview;
|
|
24454
24536
|
out(` ${c.dim}${truncated}${c.reset}`);
|
|
24455
24537
|
}
|
|
24538
|
+
const itemMeta = item.metadata;
|
|
24539
|
+
if (itemMeta?.durableId) {
|
|
24540
|
+
out(` ${c.dim}durableId:${c.reset} ${itemMeta.durableId}`);
|
|
24541
|
+
}
|
|
24456
24542
|
}
|
|
24457
24543
|
out(`${c.dim}${items.length} item(s)${c.reset}`);
|
|
24458
24544
|
}
|
|
@@ -24472,6 +24558,19 @@ function renderThing(out, c, result) {
|
|
|
24472
24558
|
if (aboutWref) {
|
|
24473
24559
|
out(` ${c.dim}about:${c.reset} ${String(aboutWref)}`);
|
|
24474
24560
|
}
|
|
24561
|
+
const meta = result.metadata;
|
|
24562
|
+
if (meta?.durableId || meta?.thingCreatedAt || meta?.versionCreatedAt) {
|
|
24563
|
+
const now = Date.now();
|
|
24564
|
+
if (meta.durableId) {
|
|
24565
|
+
out(` ${c.dim}durableId:${c.reset} ${meta.durableId}`);
|
|
24566
|
+
}
|
|
24567
|
+
if (meta.thingCreatedAt) {
|
|
24568
|
+
out(` ${c.dim}thingCreated:${c.reset} ${formatTime(meta.thingCreatedAt, now)}`);
|
|
24569
|
+
}
|
|
24570
|
+
if (meta.versionCreatedAt) {
|
|
24571
|
+
out(` ${c.dim}versionCreated:${c.reset}${formatTime(meta.versionCreatedAt, now)}`);
|
|
24572
|
+
}
|
|
24573
|
+
}
|
|
24475
24574
|
const fields = shapeName && result.data ? collectionFields(shapeName, result.data) : null;
|
|
24476
24575
|
if (fields) {
|
|
24477
24576
|
for (const field of fields) {
|
|
@@ -24562,6 +24661,10 @@ function renderHistory(out, c, result) {
|
|
|
24562
24661
|
const wref = result.thing.wref ?? result.thing.name ?? "(unknown)";
|
|
24563
24662
|
out(`${c.bold}History: ${pinnedWref(c, wref)}${c.reset} ${kindLabel(c, result.thing.kind ?? "thing")}`);
|
|
24564
24663
|
}
|
|
24664
|
+
const firstMeta = result.versions?.[0]?.metadata;
|
|
24665
|
+
if (firstMeta?.durableId) {
|
|
24666
|
+
out(` ${c.dim}durableId:${c.reset} ${firstMeta.durableId}`);
|
|
24667
|
+
}
|
|
24565
24668
|
const versions = result.versions ?? [];
|
|
24566
24669
|
const now = Date.now();
|
|
24567
24670
|
for (const ver of versions) {
|
|
@@ -24578,7 +24681,9 @@ function renderHistory(out, c, result) {
|
|
|
24578
24681
|
const wref = ver.wref ?? ver.thingName;
|
|
24579
24682
|
const wrefStr = wref ? pinnedWref(c, wref, ver.version) : "";
|
|
24580
24683
|
const by = ver.committerWref ? ` ${c.dim}by${c.reset} ${pinnedWref(c, ver.committerWref)}` : "";
|
|
24581
|
-
|
|
24684
|
+
const thingCreatedAt = ver.metadata?.thingCreatedAt;
|
|
24685
|
+
const thingCreatedStr = thingCreatedAt ? ` ${c.dim}born:${formatTime(thingCreatedAt, now)}${c.reset}` : "";
|
|
24686
|
+
out(` ${wrefStr} ${op} ${c.dim}${time}${c.reset}${by}${thingCreatedStr}`);
|
|
24582
24687
|
}
|
|
24583
24688
|
}
|
|
24584
24689
|
function renderRefs(out, c, result, wref, direction) {
|
|
@@ -24846,9 +24951,9 @@ async function collectWrefs(opts) {
|
|
|
24846
24951
|
]));
|
|
24847
24952
|
}
|
|
24848
24953
|
async function runSingleView(ctx, wref, flags) {
|
|
24849
|
-
const { org, repo } = parseOrgRepo(getRepoRef(ctx), ctx.config);
|
|
24850
24954
|
const version = flags.version;
|
|
24851
24955
|
const depth = flags.depth;
|
|
24956
|
+
const { org, repo } = looksLikeDurableId(wref) && depth === undefined ? parseOrgRepoOptional(getRepoRef(ctx), ctx.config) : parseOrgRepo(getRepoRef(ctx), ctx.config);
|
|
24852
24957
|
const includeRetracted = flags["include-retracted"] || version !== undefined;
|
|
24853
24958
|
if (depth !== undefined && (depth < 1 || depth > 5)) {
|
|
24854
24959
|
usageError2("Usage: wh thing view <wref> --depth <1-5>", "wh thing view Game/base --depth 2");
|
|
@@ -24892,7 +24997,8 @@ async function runSingleView(ctx, wref, flags) {
|
|
|
24892
24997
|
writeOutput(ctx, result, () => renderThing(ctx.out, ctx.colors, result));
|
|
24893
24998
|
}
|
|
24894
24999
|
async function runBatchView(ctx, wrefs, flags) {
|
|
24895
|
-
const
|
|
25000
|
+
const allDurable = wrefs.length > 0 && wrefs.every(looksLikeDurableId);
|
|
25001
|
+
const { org, repo } = allDurable ? parseOrgRepoOptional(getRepoRef(ctx), ctx.config) : parseOrgRepo(getRepoRef(ctx), ctx.config);
|
|
24896
25002
|
const includeRetracted = flags["include-retracted"] || flags.version !== undefined;
|
|
24897
25003
|
const result = await ctx.client.thing.getMany(org, repo, wrefs, flags.version, { includeRetracted });
|
|
24898
25004
|
if (ctx.format === "jsonl") {
|
|
@@ -24944,6 +25050,53 @@ var handleView = async (ctx, { flags, args, terminator }) => {
|
|
|
24944
25050
|
const singleWref = wrefs[0];
|
|
24945
25051
|
return runSingleView(ctx, singleWref, flags);
|
|
24946
25052
|
};
|
|
25053
|
+
var LEASE_MIN_TTL_MS = 1000;
|
|
25054
|
+
var leaseFlags = {
|
|
25055
|
+
ttl: flag.number({
|
|
25056
|
+
description: `Lease duration in ms (default 5000, min ${LEASE_MIN_TTL_MS}; max is operator-configured)`
|
|
25057
|
+
})
|
|
25058
|
+
};
|
|
25059
|
+
function renderLease(out, c, result) {
|
|
25060
|
+
renderThing(out, c, result);
|
|
25061
|
+
out("");
|
|
25062
|
+
out(` ${c.dim}lease id:${c.reset} ${result.lease.id}`);
|
|
25063
|
+
out(` ${c.dim}expires at:${c.reset} ${result.lease.expiresAt}`);
|
|
25064
|
+
}
|
|
25065
|
+
var handleLease = async (ctx, { flags, args }) => {
|
|
25066
|
+
const wref = args[0];
|
|
25067
|
+
if (!wref) {
|
|
25068
|
+
usageError2("Usage: wh thing lease <wref> [--ttl <ms>]", "wh thing lease Player/alice --ttl 5000");
|
|
25069
|
+
}
|
|
25070
|
+
const ttl = flags.ttl;
|
|
25071
|
+
if (ttl !== undefined && (!Number.isInteger(ttl) || ttl < LEASE_MIN_TTL_MS)) {
|
|
25072
|
+
usageError2(`--ttl must be an integer >= ${LEASE_MIN_TTL_MS} (ms)`, "wh thing lease Player/alice --ttl 5000");
|
|
25073
|
+
}
|
|
25074
|
+
const { org, repo } = parseOrgRepo(getRepoRef(ctx), ctx.config);
|
|
25075
|
+
const result = await ctx.client.thing.getWithLease(org, repo, wref, {
|
|
25076
|
+
ttlMs: ttl
|
|
25077
|
+
});
|
|
25078
|
+
writeOutput(ctx, result, () => renderLease(ctx.out, ctx.colors, result));
|
|
25079
|
+
};
|
|
25080
|
+
var releaseLeaseFlags = {
|
|
25081
|
+
"lease-id": flag.string({
|
|
25082
|
+
description: "Lease token from `wh thing lease` to release early"
|
|
25083
|
+
})
|
|
25084
|
+
};
|
|
25085
|
+
var handleReleaseLease = async (ctx, { flags, args }) => {
|
|
25086
|
+
const wref = args[0];
|
|
25087
|
+
if (!wref) {
|
|
25088
|
+
usageError2("Usage: wh thing release-lease <wref> --lease-id <id>", "wh thing release-lease Player/alice --lease-id <id>");
|
|
25089
|
+
}
|
|
25090
|
+
const leaseId = requireLeaseIdFlag(flags["lease-id"], "wh thing release-lease Player/alice --lease-id <id>");
|
|
25091
|
+
if (leaseId === undefined) {
|
|
25092
|
+
usageError2("--lease-id is required for release-lease", "wh thing release-lease Player/alice --lease-id <id>");
|
|
25093
|
+
}
|
|
25094
|
+
const { org, repo } = parseOrgRepo(getRepoRef(ctx), ctx.config);
|
|
25095
|
+
await ctx.client.thing.releaseLease(org, repo, wref, leaseId);
|
|
25096
|
+
writeOutput(ctx, { released: true, wref, leaseId }, () => {
|
|
25097
|
+
ctx.out(`Released lease ${leaseId} on ${wref}`);
|
|
25098
|
+
});
|
|
25099
|
+
};
|
|
24947
25100
|
var graphFlags = {
|
|
24948
25101
|
depth: flag.number({
|
|
24949
25102
|
description: "Resolve embedded graph to this depth (default: 2, max: 5)"
|
|
@@ -24983,7 +25136,7 @@ var historyFlags = {
|
|
|
24983
25136
|
};
|
|
24984
25137
|
var handleHistory = async (ctx, { flags, args }) => {
|
|
24985
25138
|
const wref = args[0];
|
|
24986
|
-
const { org, repo } = parseOrgRepo(getRepoRef(ctx), ctx.config);
|
|
25139
|
+
const { org, repo } = wref !== undefined && looksLikeDurableId(wref) ? parseOrgRepoOptional(getRepoRef(ctx), ctx.config) : parseOrgRepo(getRepoRef(ctx), ctx.config);
|
|
24987
25140
|
const shape = flags.shape;
|
|
24988
25141
|
const about = flags.about;
|
|
24989
25142
|
const limit = flags.limit;
|
|
@@ -25082,7 +25235,7 @@ var handleResolve = async (ctx, { args }) => {
|
|
|
25082
25235
|
if (!wref) {
|
|
25083
25236
|
usageError2("Usage: wh thing resolve <wref>", "wh thing resolve player");
|
|
25084
25237
|
}
|
|
25085
|
-
const { org, repo } = parseOrgRepo(getRepoRef(ctx), ctx.config);
|
|
25238
|
+
const { org, repo } = looksLikeDurableId(wref) ? parseOrgRepoOptional(getRepoRef(ctx), ctx.config) : parseOrgRepo(getRepoRef(ctx), ctx.config);
|
|
25086
25239
|
const c = ctx.colors;
|
|
25087
25240
|
const result = await ctx.client.thing.resolve(org, repo, wref);
|
|
25088
25241
|
writeOutput(ctx, result, () => {
|
|
@@ -25098,6 +25251,12 @@ var reviseFlags = {
|
|
|
25098
25251
|
message: flag.string({ short: "m", description: "Commit message" }),
|
|
25099
25252
|
committer: flag.string({
|
|
25100
25253
|
description: "Committer thing wref (e.g. Agent/bot-1)"
|
|
25254
|
+
}),
|
|
25255
|
+
"expected-version": flag.number({
|
|
25256
|
+
description: "Only apply if the target is still at this version (optimistic concurrency)"
|
|
25257
|
+
}),
|
|
25258
|
+
"lease-id": flag.string({
|
|
25259
|
+
description: "Read-lease token from `wh thing lease` (auto-released on success)"
|
|
25101
25260
|
})
|
|
25102
25261
|
};
|
|
25103
25262
|
var createFlags = {
|
|
@@ -25138,7 +25297,8 @@ var handleCreate = async (ctx, { flags, args }) => {
|
|
|
25138
25297
|
writeOutput(ctx, result, () => renderSingleOpSuccess(ctx.out, c, ctx.chars, result.operations[0] ?? {}, {
|
|
25139
25298
|
marker: "+",
|
|
25140
25299
|
color: c.green,
|
|
25141
|
-
fallbackName: name
|
|
25300
|
+
fallbackName: name,
|
|
25301
|
+
committer
|
|
25142
25302
|
}));
|
|
25143
25303
|
};
|
|
25144
25304
|
var handleRevise = async (ctx, { flags, args }) => {
|
|
@@ -25149,8 +25309,10 @@ var handleRevise = async (ctx, { flags, args }) => {
|
|
|
25149
25309
|
const { org, repo } = parseOrgRepo(getRepoRef(ctx), ctx.config);
|
|
25150
25310
|
const committer = flags.committer;
|
|
25151
25311
|
const message = flags.message;
|
|
25312
|
+
const leaseId = requireLeaseIdFlag(flags["lease-id"]);
|
|
25152
25313
|
const data = flags.data ? safeParseJson(flags.data, "--data") : undefined;
|
|
25153
25314
|
const c = ctx.colors;
|
|
25315
|
+
const expectedVersion = parsePositiveIntFlag(flags["expected-version"], "--expected-version", "wh thing revise Player/alice --data '{...}' --expected-version 3");
|
|
25154
25316
|
if (!data) {
|
|
25155
25317
|
usageError2("--data is required for revise", `wh thing revise Location/player --data '{"x":1}'`);
|
|
25156
25318
|
}
|
|
@@ -25159,13 +25321,16 @@ var handleRevise = async (ctx, { flags, args }) => {
|
|
|
25159
25321
|
operation: "revise",
|
|
25160
25322
|
kind: "thing",
|
|
25161
25323
|
name,
|
|
25162
|
-
data
|
|
25324
|
+
data,
|
|
25325
|
+
...expectedVersion !== undefined ? { expectedVersion } : {},
|
|
25326
|
+
...leaseId ? { leaseId } : {}
|
|
25163
25327
|
}
|
|
25164
25328
|
], { committer });
|
|
25165
25329
|
assertSingleOpSuccess(result);
|
|
25166
25330
|
writeOutput(ctx, result, () => renderSingleOpSuccess(ctx.out, c, ctx.chars, result.operations[0] ?? {}, {
|
|
25167
25331
|
marker: "~",
|
|
25168
|
-
color: c.yellow
|
|
25332
|
+
color: c.yellow,
|
|
25333
|
+
committer
|
|
25169
25334
|
}));
|
|
25170
25335
|
};
|
|
25171
25336
|
var retractFlags = {
|
|
@@ -25176,6 +25341,9 @@ var retractFlags = {
|
|
|
25176
25341
|
message: flag.string({ short: "m", description: "Commit message" }),
|
|
25177
25342
|
committer: flag.string({
|
|
25178
25343
|
description: "Committer thing wref (e.g. Agent/bot-1)"
|
|
25344
|
+
}),
|
|
25345
|
+
"lease-id": flag.string({
|
|
25346
|
+
description: "Read-lease token from `wh thing lease` (auto-released on success)"
|
|
25179
25347
|
})
|
|
25180
25348
|
};
|
|
25181
25349
|
var handleThingRetract = async (ctx, { flags, args }) => {
|
|
@@ -25188,18 +25356,21 @@ var handleThingRetract = async (ctx, { flags, args }) => {
|
|
|
25188
25356
|
const message = flags.message;
|
|
25189
25357
|
const kind = flags.kind;
|
|
25190
25358
|
const reason = flags.reason;
|
|
25359
|
+
const leaseId = requireLeaseIdFlag(flags["lease-id"], "wh thing retract Player/alice --lease-id <id>");
|
|
25191
25360
|
const c = ctx.colors;
|
|
25192
25361
|
const result = await ctx.client.commit.apply(org, repo, message ?? `retract ${name}`, [
|
|
25193
25362
|
{
|
|
25194
25363
|
operation: "retract",
|
|
25195
25364
|
name,
|
|
25196
25365
|
...kind ? { kind } : {},
|
|
25197
|
-
...reason ? { reason } : {}
|
|
25366
|
+
...reason ? { reason } : {},
|
|
25367
|
+
...leaseId ? { leaseId } : {}
|
|
25198
25368
|
}
|
|
25199
25369
|
], { committer });
|
|
25200
25370
|
assertSingleOpSuccess(result);
|
|
25201
25371
|
writeOutput(ctx, result, () => {
|
|
25202
25372
|
const op = result.operations[0];
|
|
25373
|
+
renderCommitterEcho(ctx.out, c, committer);
|
|
25203
25374
|
ctx.out(`${c.red}-${c.reset} ${displayName(c, op?.name ?? name)}`);
|
|
25204
25375
|
});
|
|
25205
25376
|
};
|
|
@@ -25542,7 +25713,7 @@ var handleAbout = async (ctx, { flags, args }) => {
|
|
|
25542
25713
|
if (!wref) {
|
|
25543
25714
|
usageError2("Usage: wh thing about <wref> [--shape] [--match] [--limit] [--include-retracted]", "wh thing about Location/cave");
|
|
25544
25715
|
}
|
|
25545
|
-
const { org, repo } = parseOrgRepo(getRepoRef(ctx), ctx.config);
|
|
25716
|
+
const { org, repo } = looksLikeDurableId(wref) ? parseOrgRepoOptional(getRepoRef(ctx), ctx.config) : parseOrgRepo(getRepoRef(ctx), ctx.config);
|
|
25546
25717
|
const includeRetracted = flags["include-retracted"];
|
|
25547
25718
|
const limit = flags.limit;
|
|
25548
25719
|
const cursor = flags.cursor;
|
|
@@ -25662,7 +25833,7 @@ var handleRefs = async (ctx, { flags, args }) => {
|
|
|
25662
25833
|
if (!wref) {
|
|
25663
25834
|
usageError2("Usage: wh thing refs <wref> [--inbound|--outbound] [--field FIELD] [--limit N]", "wh thing refs Loc/player");
|
|
25664
25835
|
}
|
|
25665
|
-
const { org, repo } = parseOrgRepo(getRepoRef(ctx), ctx.config);
|
|
25836
|
+
const { org, repo } = looksLikeDurableId(wref) ? parseOrgRepoOptional(getRepoRef(ctx), ctx.config) : parseOrgRepo(getRepoRef(ctx), ctx.config);
|
|
25666
25837
|
if (flags.inbound && flags.outbound) {
|
|
25667
25838
|
usageError2("Cannot specify both --inbound and --outbound", "wh thing refs Loc/player --outbound");
|
|
25668
25839
|
}
|
|
@@ -25743,6 +25914,25 @@ var THING_DOMAIN = defineDomain({
|
|
|
25743
25914
|
],
|
|
25744
25915
|
handler: handleView
|
|
25745
25916
|
},
|
|
25917
|
+
lease: {
|
|
25918
|
+
prime: true,
|
|
25919
|
+
summary: "Acquire a short, exclusive read lease on a thing (read + lease in one call)",
|
|
25920
|
+
args: "<wref>",
|
|
25921
|
+
flags: leaseFlags,
|
|
25922
|
+
examples: [
|
|
25923
|
+
"wh thing lease Player/alice",
|
|
25924
|
+
"wh thing lease Player/alice --ttl 5000"
|
|
25925
|
+
],
|
|
25926
|
+
handler: handleLease
|
|
25927
|
+
},
|
|
25928
|
+
"release-lease": {
|
|
25929
|
+
prime: true,
|
|
25930
|
+
summary: "Release a read lease early (idempotent)",
|
|
25931
|
+
args: "<wref>",
|
|
25932
|
+
flags: releaseLeaseFlags,
|
|
25933
|
+
examples: ["wh thing release-lease Player/alice --lease-id <id>"],
|
|
25934
|
+
handler: handleReleaseLease
|
|
25935
|
+
},
|
|
25746
25936
|
history: {
|
|
25747
25937
|
prime: true,
|
|
25748
25938
|
summary: "Show version history",
|
|
@@ -26056,7 +26246,8 @@ var handleRevise2 = async (ctx, { flags, args }) => {
|
|
|
26056
26246
|
assertSingleOpSuccess(result);
|
|
26057
26247
|
writeOutput(ctx, result, () => renderSingleOpSuccess(ctx.out, c, ctx.chars, result.operations[0] ?? {}, {
|
|
26058
26248
|
marker: "~",
|
|
26059
|
-
color: c.yellow
|
|
26249
|
+
color: c.yellow,
|
|
26250
|
+
committer: flags.committer
|
|
26060
26251
|
}));
|
|
26061
26252
|
};
|
|
26062
26253
|
var retractFlags2 = {
|
|
@@ -26085,6 +26276,7 @@ var handleRetract = async (ctx, { flags, args }) => {
|
|
|
26085
26276
|
assertSingleOpSuccess(result);
|
|
26086
26277
|
writeOutput(ctx, result, () => {
|
|
26087
26278
|
const op = result.operations[0];
|
|
26279
|
+
renderCommitterEcho(ctx.out, ctx.colors, flags.committer);
|
|
26088
26280
|
ctx.out(`${ctx.colors.red}-${ctx.colors.reset} ${displayName(ctx.colors, op?.name ?? name)}`);
|
|
26089
26281
|
});
|
|
26090
26282
|
};
|
|
@@ -26181,7 +26373,8 @@ var handleCreate2 = async (ctx, { flags, args }) => {
|
|
|
26181
26373
|
writeOutput(ctx, result, () => renderSingleOpSuccess(ctx.out, c, ctx.chars, result.operations[0] ?? {}, {
|
|
26182
26374
|
marker: "+",
|
|
26183
26375
|
color: c.green,
|
|
26184
|
-
suffix: ` ${c.dim}(${shape})${c.reset}
|
|
26376
|
+
suffix: ` ${c.dim}(${shape})${c.reset}`,
|
|
26377
|
+
committer
|
|
26185
26378
|
}));
|
|
26186
26379
|
};
|
|
26187
26380
|
var listFlags = {
|
|
@@ -27613,6 +27806,59 @@ import { createReadStream as createReadStream2 } from "node:fs";
|
|
|
27613
27806
|
import { readFile, writeFile } from "node:fs/promises";
|
|
27614
27807
|
import { createInterface as createInterface2 } from "node:readline";
|
|
27615
27808
|
|
|
27809
|
+
// ../../packages/warmhub-cli/src/commit-payload-validate.ts
|
|
27810
|
+
var NUL = String.fromCharCode(0);
|
|
27811
|
+
function findInvalidControlByte(data, rootLabel = "data") {
|
|
27812
|
+
const segs = [];
|
|
27813
|
+
const pos = visit(data, segs);
|
|
27814
|
+
return pos === -1 ? null : { path: buildPath(rootLabel, segs), position: pos };
|
|
27815
|
+
}
|
|
27816
|
+
function visit(value, segs) {
|
|
27817
|
+
if (typeof value === "string")
|
|
27818
|
+
return value.indexOf(NUL);
|
|
27819
|
+
if (value === null || typeof value !== "object")
|
|
27820
|
+
return -1;
|
|
27821
|
+
if (Array.isArray(value)) {
|
|
27822
|
+
for (let i = 0;i < value.length; i++) {
|
|
27823
|
+
segs.push(i);
|
|
27824
|
+
const p = visit(value[i], segs);
|
|
27825
|
+
if (p !== -1)
|
|
27826
|
+
return p;
|
|
27827
|
+
segs.pop();
|
|
27828
|
+
}
|
|
27829
|
+
return -1;
|
|
27830
|
+
}
|
|
27831
|
+
const keys = Object.keys(value);
|
|
27832
|
+
for (let i = 0;i < keys.length; i++) {
|
|
27833
|
+
const k = keys[i];
|
|
27834
|
+
segs.push(k);
|
|
27835
|
+
const p = visit(value[k], segs);
|
|
27836
|
+
if (p !== -1)
|
|
27837
|
+
return p;
|
|
27838
|
+
segs.pop();
|
|
27839
|
+
}
|
|
27840
|
+
return -1;
|
|
27841
|
+
}
|
|
27842
|
+
function buildPath(root, segs) {
|
|
27843
|
+
let out = root;
|
|
27844
|
+
for (const s of segs)
|
|
27845
|
+
out += typeof s === "number" ? `[${s}]` : `.${s}`;
|
|
27846
|
+
return out;
|
|
27847
|
+
}
|
|
27848
|
+
function formatInvalidControlByteMessage(hit, locator) {
|
|
27849
|
+
return {
|
|
27850
|
+
message: `${locator}: ${hit.path} contains literal U+0000 byte at position ${hit.position}, ` + "which PostgreSQL `text` cannot store (SQLSTATE 22P05).",
|
|
27851
|
+
hint: "Strip NUL bytes before submit, e.g. `.replace(/\\u0000/g, '')`, or pass --allow-nul-bytes to send anyway."
|
|
27852
|
+
};
|
|
27853
|
+
}
|
|
27854
|
+
function assertNoNulBytes(data, locator) {
|
|
27855
|
+
const hit = findInvalidControlByte(data);
|
|
27856
|
+
if (!hit)
|
|
27857
|
+
return;
|
|
27858
|
+
const { message, hint } = formatInvalidControlByteMessage(hit, locator);
|
|
27859
|
+
throw new CliError(2 /* UserInput */, "USER_INPUT", message, undefined, hint);
|
|
27860
|
+
}
|
|
27861
|
+
|
|
27616
27862
|
// ../../packages/warmhub-cli/src/domains/stream-progress.ts
|
|
27617
27863
|
import { createReadStream } from "node:fs";
|
|
27618
27864
|
import { createInterface } from "node:readline";
|
|
@@ -27914,7 +28160,9 @@ async function applyJsonlCommit(ctx, args) {
|
|
|
27914
28160
|
} catch (cause) {
|
|
27915
28161
|
const completed = operationOffset + opCount;
|
|
27916
28162
|
if (opCount > 0 || firstJsonlAppendErrorMayHaveCommitted(cause)) {
|
|
27917
|
-
|
|
28163
|
+
const backendCode = toWarmHubError(cause).backendCode;
|
|
28164
|
+
const suffix = backendCode ? ` (backend: ${backendCode})` : "";
|
|
28165
|
+
throw new CliError(4 /* Backend */, "BACKEND", `Stream append failed after ${completed} acknowledged operation(s).${suffix}`, cause, "The failed append may also have landed; inspect repository state before submitting any remaining JSONL operations.", undefined, backendCode);
|
|
27918
28166
|
}
|
|
27919
28167
|
throw cause;
|
|
27920
28168
|
}
|
|
@@ -27972,6 +28220,24 @@ async function applyJsonlCommit(ctx, args) {
|
|
|
27972
28220
|
continue;
|
|
27973
28221
|
assertWithinStreamOpLimit(parsedOpCount + 1);
|
|
27974
28222
|
const operation = safeParseJson(trimmed, `${args.lineLabel} JSONL line ${lineNumber}`);
|
|
28223
|
+
if (args.allowNulBytes !== true) {
|
|
28224
|
+
try {
|
|
28225
|
+
assertNoNulBytes("data" in operation ? operation.data : undefined, `${args.lineLabel} JSONL line ${lineNumber}`);
|
|
28226
|
+
} catch (cause) {
|
|
28227
|
+
if (cause instanceof CliError) {
|
|
28228
|
+
if (opCount > 0) {
|
|
28229
|
+
const completed = operationOffset + opCount;
|
|
28230
|
+
const baseHint = cause.hint && cause.hint.length > 0 ? `${cause.hint} ` : "";
|
|
28231
|
+
throw new CliError(4 /* Backend */, "BACKEND", `${cause.message} (${completed} earlier operation(s) already acknowledged by the server before this NUL-byte rejection).`, undefined, `${baseHint}The earlier chunks have landed; inspect repository state before submitting any remaining JSONL operations.`);
|
|
28232
|
+
}
|
|
28233
|
+
if (operationOffset > 0) {
|
|
28234
|
+
const baseHint = cause.hint && cause.hint.length > 0 ? `${cause.hint} ` : "";
|
|
28235
|
+
throw new CliError(cause.code, cause.kind, `${cause.message} (${operationOffset} earlier operation(s) already acknowledged by the server in a prior run; this run made no backend writes before the NUL-byte rejection).`, undefined, `${baseHint}Fix the offending input; the prior-run chunks remain landed and unaffected by this local validation failure.`);
|
|
28236
|
+
}
|
|
28237
|
+
}
|
|
28238
|
+
throw cause;
|
|
28239
|
+
}
|
|
28240
|
+
}
|
|
27975
28241
|
parsedOpCount += 1;
|
|
27976
28242
|
chunk.push(withSkipExisting(operation, args.skipExisting === true));
|
|
27977
28243
|
if (chunk.length < chunkSize)
|
|
@@ -28189,7 +28455,7 @@ function buildAddOperations(input) {
|
|
|
28189
28455
|
});
|
|
28190
28456
|
}
|
|
28191
28457
|
function buildRetractOperations(input) {
|
|
28192
|
-
const { retractNames, kinds, reasons } = input;
|
|
28458
|
+
const { retractNames, kinds, reasons, leaseId } = input;
|
|
28193
28459
|
const assertCardinality = (flagName, values) => {
|
|
28194
28460
|
if (values.length === 0)
|
|
28195
28461
|
return;
|
|
@@ -28215,7 +28481,8 @@ function buildRetractOperations(input) {
|
|
|
28215
28481
|
operation: "retract",
|
|
28216
28482
|
name,
|
|
28217
28483
|
...kind ? { kind } : {},
|
|
28218
|
-
...reason ? { reason } : {}
|
|
28484
|
+
...reason ? { reason } : {},
|
|
28485
|
+
...leaseId ? { leaseId } : {}
|
|
28219
28486
|
};
|
|
28220
28487
|
});
|
|
28221
28488
|
}
|
|
@@ -28272,6 +28539,9 @@ var createFlags3 = {
|
|
|
28272
28539
|
"chunk-size": flag.number({
|
|
28273
28540
|
description: `Streamed ops per append chunk for --stream or .jsonl --file (default: ${DEFAULT_STREAM_APPEND_CHUNK_SIZE}, max: ${MAX_STREAM_APPEND_OPERATION_COUNT})`
|
|
28274
28541
|
}),
|
|
28542
|
+
"allow-nul-bytes": flag.boolean({
|
|
28543
|
+
description: "Skip the client-side pre-check that rejects literal U+0000 bytes in op data. PostgreSQL `text` columns still cannot store these — use only when the backend storage type is known to tolerate them."
|
|
28544
|
+
}),
|
|
28275
28545
|
"timing-out": flag.string({
|
|
28276
28546
|
description: "Write per-append timing sidecar JSON to this path (debug/bench instrumentation)"
|
|
28277
28547
|
}),
|
|
@@ -28322,6 +28592,12 @@ var createFlags3 = {
|
|
|
28322
28592
|
}),
|
|
28323
28593
|
members: flag.string({
|
|
28324
28594
|
description: "Collection members (comma-separated wrefs)"
|
|
28595
|
+
}),
|
|
28596
|
+
"expected-version": flag.number({
|
|
28597
|
+
description: "Only apply if the --revise target is still at this version (optimistic concurrency). Requires --revise."
|
|
28598
|
+
}),
|
|
28599
|
+
"lease-id": flag.string({
|
|
28600
|
+
description: "Read-lease token from `wh thing lease`, bound to --revise/--retract (auto-released on success)"
|
|
28325
28601
|
})
|
|
28326
28602
|
};
|
|
28327
28603
|
var handleSubmit = async (ctx, { flags, args }) => {
|
|
@@ -28334,6 +28610,7 @@ var handleSubmit = async (ctx, { flags, args }) => {
|
|
|
28334
28610
|
const progressRequested = flags.progress === true;
|
|
28335
28611
|
const skipExisting = flags["skip-existing"] === true;
|
|
28336
28612
|
const chunkSize = flags["chunk-size"];
|
|
28613
|
+
const allowNulBytes = flags["allow-nul-bytes"] === true;
|
|
28337
28614
|
const timingOut = flags["timing-out"];
|
|
28338
28615
|
const resumeStreamId = flags["stream-id"];
|
|
28339
28616
|
const resumeAllocatedTokens = parseAllocatedTokensFlag(flags["allocated-tokens"]);
|
|
@@ -28347,6 +28624,14 @@ var handleSubmit = async (ctx, { flags, args }) => {
|
|
|
28347
28624
|
const abouts = flags.about ?? [];
|
|
28348
28625
|
const reasons = flags.reason ?? [];
|
|
28349
28626
|
const kinds = flags.kind ?? [];
|
|
28627
|
+
const expectedVersion = parsePositiveIntFlag(flags["expected-version"], "--expected-version", "wh commit submit --revise Player/alice --data '{...}' --expected-version 3");
|
|
28628
|
+
if (expectedVersion !== undefined && !reviseName) {
|
|
28629
|
+
usageError4("--expected-version requires --revise", "wh commit submit --revise Player/alice --data '{...}' --expected-version 3");
|
|
28630
|
+
}
|
|
28631
|
+
const leaseIdFlag = requireLeaseIdFlag(flags["lease-id"], `wh commit submit --revise Player/alice --data '{"score":2}' --lease-id <id>`);
|
|
28632
|
+
if (leaseIdFlag !== undefined && reviseName === undefined && retractNames.length === 0) {
|
|
28633
|
+
throw new CliError(2 /* UserInput */, "USER_INPUT", "--lease-id requires --revise or --retract.", undefined, 'For --ops/--file/--stream writes, carry "leaseId" inline on the revise/retract op.');
|
|
28634
|
+
}
|
|
28350
28635
|
const validKinds = [
|
|
28351
28636
|
"thing",
|
|
28352
28637
|
"assertion",
|
|
@@ -28438,7 +28723,8 @@ var handleSubmit = async (ctx, { flags, args }) => {
|
|
|
28438
28723
|
operations = buildRetractOperations({
|
|
28439
28724
|
retractNames,
|
|
28440
28725
|
kinds,
|
|
28441
|
-
reasons
|
|
28726
|
+
reasons,
|
|
28727
|
+
leaseId: leaseIdFlag
|
|
28442
28728
|
});
|
|
28443
28729
|
} else if (reviseName) {
|
|
28444
28730
|
if (dataJsons.length > 1) {
|
|
@@ -28451,13 +28737,30 @@ var handleSubmit = async (ctx, { flags, args }) => {
|
|
|
28451
28737
|
const data = rawData ? safeParseJson(rawData, "--data") : undefined;
|
|
28452
28738
|
const kindFlag = kinds[0];
|
|
28453
28739
|
const kind = kindFlag ?? "thing";
|
|
28454
|
-
operations = [
|
|
28740
|
+
operations = [
|
|
28741
|
+
{
|
|
28742
|
+
operation: "revise",
|
|
28743
|
+
kind,
|
|
28744
|
+
name: reviseName,
|
|
28745
|
+
data,
|
|
28746
|
+
...expectedVersion !== undefined ? { expectedVersion } : {},
|
|
28747
|
+
...leaseIdFlag ? { leaseId: leaseIdFlag } : {}
|
|
28748
|
+
}
|
|
28749
|
+
];
|
|
28455
28750
|
} else {
|
|
28456
28751
|
usageError4("Usage: wh commit submit --ops '<json>' or --add <name> [--data <json>]", `wh commit submit --add player --shape location --data '{"x":0,"y":0}'`);
|
|
28457
28752
|
}
|
|
28458
28753
|
if (!streamInput && operations.length > 0) {
|
|
28459
28754
|
rejectLegacyLifecycleOperations(operations);
|
|
28460
28755
|
assertWithinStreamOpLimit(operations.length);
|
|
28756
|
+
if (!allowNulBytes) {
|
|
28757
|
+
const source = opsJson ? "--ops" : opsFile ? opsFile : addNames.length > 0 ? "--add" : reviseName !== undefined ? "--revise" : collectionType ? "--type" : "op";
|
|
28758
|
+
for (let i = 0;i < operations.length; i++) {
|
|
28759
|
+
const op = operations[i];
|
|
28760
|
+
const namePart = op.name ? ` (${op.name})` : "";
|
|
28761
|
+
assertNoNulBytes("data" in op ? op.data : undefined, `${source} op ${i}${namePart}`);
|
|
28762
|
+
}
|
|
28763
|
+
}
|
|
28461
28764
|
}
|
|
28462
28765
|
const message = streamInput || jsonlFile ? messageFlag : messageFlag ?? synthesizeCommitMessage(operations);
|
|
28463
28766
|
let result;
|
|
@@ -28472,7 +28775,8 @@ var handleSubmit = async (ctx, { flags, args }) => {
|
|
|
28472
28775
|
skipExisting,
|
|
28473
28776
|
streamId: resumeStreamId,
|
|
28474
28777
|
allocatedTokens: resumeAllocatedTokens,
|
|
28475
|
-
operationOffset: resumeOperationOffset
|
|
28778
|
+
operationOffset: resumeOperationOffset,
|
|
28779
|
+
allowNulBytes
|
|
28476
28780
|
}) : jsonlFile ? await applyJsonlFileCommit(ctx, {
|
|
28477
28781
|
org,
|
|
28478
28782
|
repo,
|
|
@@ -28485,7 +28789,8 @@ var handleSubmit = async (ctx, { flags, args }) => {
|
|
|
28485
28789
|
skipExisting,
|
|
28486
28790
|
streamId: resumeStreamId,
|
|
28487
28791
|
allocatedTokens: resumeAllocatedTokens,
|
|
28488
|
-
operationOffset: resumeOperationOffset
|
|
28792
|
+
operationOffset: resumeOperationOffset,
|
|
28793
|
+
allowNulBytes
|
|
28489
28794
|
}) : await ctx.client.commit.apply(org, repo, message, operations, {
|
|
28490
28795
|
committer,
|
|
28491
28796
|
skipExisting
|
|
@@ -28502,6 +28807,7 @@ var handleSubmit = async (ctx, { flags, args }) => {
|
|
|
28502
28807
|
writeOutput(ctx, result, () => {
|
|
28503
28808
|
const failureSuffix = failedCount > 0 ? `, ${failedCount} failed` : "";
|
|
28504
28809
|
ctx.out(`${message ?? "(no message)"} ${c.dim}(${result.operationCount} ops${failureSuffix})${c.reset}`);
|
|
28810
|
+
renderCommitterEcho(ctx.out, c, committer);
|
|
28505
28811
|
for (const op of result.operations) {
|
|
28506
28812
|
const failed = isFailedOpStatus(op.status);
|
|
28507
28813
|
const marker = failed ? "!" : op.operation === "add" ? "+" : op.operation === "revise" ? "~" : "-";
|
|
@@ -31064,12 +31370,28 @@ var updateFlags = {
|
|
|
31064
31370
|
})
|
|
31065
31371
|
};
|
|
31066
31372
|
var validateFlags = {};
|
|
31067
|
-
var listFlags2 = {
|
|
31373
|
+
var listFlags2 = {
|
|
31374
|
+
limit: flag.number({
|
|
31375
|
+
description: "Maximum components per page (default: 50, max: 500)"
|
|
31376
|
+
}),
|
|
31377
|
+
cursor: flag.string({ description: "Opaque pagination cursor" }),
|
|
31378
|
+
all: flag.boolean({
|
|
31379
|
+
description: "Fetch all pages (auto-paginate until exhausted)"
|
|
31380
|
+
})
|
|
31381
|
+
};
|
|
31068
31382
|
var viewFlags3 = {};
|
|
31069
31383
|
var teardownFlags = {};
|
|
31070
31384
|
var doctorFlags = {};
|
|
31071
31385
|
var initFlags = {};
|
|
31072
|
-
var searchFlags2 = {
|
|
31386
|
+
var searchFlags2 = {
|
|
31387
|
+
limit: flag.number({
|
|
31388
|
+
description: "Maximum components per page (default: 50, max: 500)"
|
|
31389
|
+
}),
|
|
31390
|
+
cursor: flag.string({ description: "Opaque pagination cursor" }),
|
|
31391
|
+
all: flag.boolean({
|
|
31392
|
+
description: "Fetch all pages before filtering (auto-paginate until exhausted)"
|
|
31393
|
+
})
|
|
31394
|
+
};
|
|
31073
31395
|
var registerFlags = {
|
|
31074
31396
|
org: flag.string({ description: "Owner org for the registered component" }),
|
|
31075
31397
|
"source-url": flag.string({ description: "Source GitHub URL for installs" }),
|
|
@@ -31449,12 +31771,33 @@ function normalizeGithubRemote(remote) {
|
|
|
31449
31771
|
}
|
|
31450
31772
|
return;
|
|
31451
31773
|
}
|
|
31452
|
-
|
|
31774
|
+
async function fetchComponentPages(client, org, repo, opts) {
|
|
31775
|
+
const firstPage = await client.component.list(org, repo, {
|
|
31776
|
+
limit: opts.limit,
|
|
31777
|
+
cursor: opts.cursor
|
|
31778
|
+
});
|
|
31779
|
+
const items = [...firstPage.items ?? []];
|
|
31780
|
+
let nextCursor = firstPage.nextCursor;
|
|
31781
|
+
if (opts.all) {
|
|
31782
|
+
while (nextCursor) {
|
|
31783
|
+
const page = await client.component.list(org, repo, {
|
|
31784
|
+
limit: opts.limit,
|
|
31785
|
+
cursor: nextCursor
|
|
31786
|
+
});
|
|
31787
|
+
items.push(...page.items ?? []);
|
|
31788
|
+
nextCursor = page.nextCursor;
|
|
31789
|
+
}
|
|
31790
|
+
}
|
|
31791
|
+
return { items, nextCursor };
|
|
31792
|
+
}
|
|
31793
|
+
var handleList2 = async (ctx, { flags }) => {
|
|
31453
31794
|
const { org, repo } = parseOrgRepo(getRepoRef(ctx), ctx.config);
|
|
31454
|
-
const
|
|
31455
|
-
const items =
|
|
31795
|
+
const c = ctx.colors;
|
|
31796
|
+
const { items, nextCursor } = await fetchComponentPages(ctx.client, org, repo, { all: flags.all, limit: flags.limit, cursor: flags.cursor });
|
|
31797
|
+
if (!flags.all && nextCursor) {
|
|
31798
|
+
ctx.status(`${c.yellow}${items.length} shown, more available${c.reset} — use ${c.cyan}--all${c.reset} to fetch every page, ` + `or re-run the same command plus ${c.cyan}--cursor=${nextCursor}${c.reset} to resume from here.`);
|
|
31799
|
+
}
|
|
31456
31800
|
writeOutput(ctx, items, () => {
|
|
31457
|
-
const c = ctx.colors;
|
|
31458
31801
|
if (!items.length) {
|
|
31459
31802
|
ctx.status(`${c.dim}No components installed${c.reset}`);
|
|
31460
31803
|
return;
|
|
@@ -31470,17 +31813,20 @@ var handleList2 = async (ctx) => {
|
|
|
31470
31813
|
}
|
|
31471
31814
|
});
|
|
31472
31815
|
};
|
|
31473
|
-
var handleSearch2 = async (ctx, { args }) => {
|
|
31816
|
+
var handleSearch2 = async (ctx, { flags, args }) => {
|
|
31474
31817
|
const query = args[0]?.trim();
|
|
31475
31818
|
if (!query) {
|
|
31476
31819
|
usageError("Usage: wh component search <query> --repo org/repo", "wh component search research --repo myorg/myrepo");
|
|
31477
31820
|
}
|
|
31478
31821
|
const { org, repo } = parseOrgRepo(getRepoRef(ctx), ctx.config);
|
|
31479
|
-
const
|
|
31822
|
+
const c = ctx.colors;
|
|
31823
|
+
const { items: allItems, nextCursor } = await fetchComponentPages(ctx.client, org, repo, { all: flags.all, limit: flags.limit, cursor: flags.cursor });
|
|
31480
31824
|
const needle = query.toLowerCase();
|
|
31481
|
-
const items =
|
|
31825
|
+
const items = allItems.filter((item) => [item.componentId, item.componentName, item.source].filter((value) => typeof value === "string").some((value) => value.toLowerCase().includes(needle)));
|
|
31826
|
+
if (!flags.all && nextCursor) {
|
|
31827
|
+
ctx.status(`${c.yellow}${allItems.length} component(s) searched, more pages available${c.reset} — matches beyond this page were not searched. ` + `Use ${c.cyan}--all${c.reset} to search every page, ` + `or re-run the same command plus ${c.cyan}--cursor=${nextCursor}${c.reset} to continue from here.`);
|
|
31828
|
+
}
|
|
31482
31829
|
writeOutput(ctx, items, () => {
|
|
31483
|
-
const c = ctx.colors;
|
|
31484
31830
|
if (!items.length) {
|
|
31485
31831
|
ctx.status(`${c.dim}No components matching "${query}" in ${org}/${repo}${c.reset}`);
|
|
31486
31832
|
return;
|
|
@@ -33610,7 +33956,7 @@ cat wrefs.txt | wh thing view --format jsonl # one JSON line per *deduped
|
|
|
33610
33956
|
- \`wh thing history [wref] [--shape] [--about] [--include-retracted]\` — Version history
|
|
33611
33957
|
- \`wh thing resolve <wref>\` — Resolve wref
|
|
33612
33958
|
- \`wh thing create <name|Shape/name> --data <json> [--shape] [--message] [--committer]\` — Create
|
|
33613
|
-
- \`wh thing revise <name> [--data] [--message] [--committer]\` — Revise
|
|
33959
|
+
- \`wh thing revise <name> [--data] [--message] [--committer] [--expected-version]\` — Revise (CONFLICT if HEAD≠n)
|
|
33614
33960
|
- \`wh thing retract <wref> -m <message> [--reason] [--kind]\` — Retract
|
|
33615
33961
|
- \`wh thing query [--shape] [--kind] [--about] [--match]\` — Query by filters
|
|
33616
33962
|
- \`wh thing search <query> [--shape] [--kind] [--about] [--mode]\` — Search text
|
|
@@ -33619,7 +33965,7 @@ cat wrefs.txt | wh thing view --format jsonl # one JSON line per *deduped
|
|
|
33619
33965
|
- \`wh thing about <wref> [--shape] [--match] [--depth] [--resolve-collections] [--limit] [--include-retracted]\` — Show assertions about the target identity; \`--resolve-collections\` expands collection members for bare/@HEAD/@ALL inputs, not pinned @vN
|
|
33620
33966
|
|
|
33621
33967
|
### commit — Write operations
|
|
33622
|
-
- \`wh commit submit [--ops|--file|--add|--revise|--retract] [--kind] [--data] [--reason] [--chunk-size] [--skip-existing] [--progress] [--stream-id] [--allocated-tokens] [--operation-offset]\` — Submit operations (bare \`wh commit\` is equivalent). Use \`--file ops.jsonl --chunk-size 5000 --skip-existing\` for bulk ingest.
|
|
33968
|
+
- \`wh commit submit [--ops|--file|--add|--revise|--retract] [--kind] [--data] [--reason] [--expected-version] [--chunk-size] [--skip-existing] [--progress] [--stream-id] [--allocated-tokens] [--operation-offset]\` — Submit operations (bare \`wh commit\` is equivalent). Use \`--file ops.jsonl --chunk-size 5000 --skip-existing\` for bulk ingest.
|
|
33623
33969
|
- \`wh shape template <shape> [shape2 ...] [--kind] [--operation add|revise|retract] [-o file]\` — Generate sample ops
|
|
33624
33970
|
|
|
33625
33971
|
### assertion — Assertion operations
|
|
@@ -33941,6 +34287,13 @@ var handleCreate5 = async (ctx, { flags, args }) => {
|
|
|
33941
34287
|
var repoListFlags = {
|
|
33942
34288
|
"include-archived": flag.boolean({
|
|
33943
34289
|
description: "Include archived repositories"
|
|
34290
|
+
}),
|
|
34291
|
+
limit: flag.number({
|
|
34292
|
+
description: "Maximum repos per page (default: 50, max: 200)"
|
|
34293
|
+
}),
|
|
34294
|
+
cursor: flag.string({ description: "Opaque pagination cursor" }),
|
|
34295
|
+
all: flag.boolean({
|
|
34296
|
+
description: "Fetch all pages (auto-paginate until exhausted)"
|
|
33944
34297
|
})
|
|
33945
34298
|
};
|
|
33946
34299
|
var handleList5 = async (ctx, { flags, args }) => {
|
|
@@ -33949,16 +34302,36 @@ var handleList5 = async (ctx, { flags, args }) => {
|
|
|
33949
34302
|
usageError8("Usage: wh repo list <org> (or set WARMHUB_ORG)", "wh repo list myorg");
|
|
33950
34303
|
}
|
|
33951
34304
|
const c = ctx.colors;
|
|
33952
|
-
const
|
|
33953
|
-
|
|
34305
|
+
const all = flags.all;
|
|
34306
|
+
const includeArchived = flags["include-archived"];
|
|
34307
|
+
const firstPage = await ctx.client.repo.list(orgName, {
|
|
34308
|
+
includeArchived,
|
|
34309
|
+
limit: flags.limit,
|
|
34310
|
+
cursor: flags.cursor
|
|
33954
34311
|
});
|
|
33955
|
-
|
|
33956
|
-
|
|
34312
|
+
const items = [...firstPage.items];
|
|
34313
|
+
let nextCursor = firstPage.nextCursor;
|
|
34314
|
+
if (all) {
|
|
34315
|
+
while (nextCursor) {
|
|
34316
|
+
const page = await ctx.client.repo.list(orgName, {
|
|
34317
|
+
includeArchived,
|
|
34318
|
+
limit: flags.limit,
|
|
34319
|
+
cursor: nextCursor
|
|
34320
|
+
});
|
|
34321
|
+
items.push(...page.items);
|
|
34322
|
+
nextCursor = page.nextCursor;
|
|
34323
|
+
}
|
|
34324
|
+
}
|
|
34325
|
+
if (!all && nextCursor) {
|
|
34326
|
+
ctx.status(`${c.yellow}${items.length} shown, more available${c.reset} — use ${c.cyan}--all${c.reset} to fetch every page, ` + `or re-run the same command plus ${c.cyan}--cursor=${nextCursor}${c.reset} to resume from here.`);
|
|
34327
|
+
}
|
|
34328
|
+
writeOutput(ctx, items, () => {
|
|
34329
|
+
if (!items.length) {
|
|
33957
34330
|
ctx.status(`${c.dim}No repos in ${orgName}${c.reset}`);
|
|
33958
34331
|
return;
|
|
33959
34332
|
}
|
|
33960
34333
|
ctx.out(`${c.bold}Repos in ${orgName}:${c.reset}`);
|
|
33961
|
-
for (const r of
|
|
34334
|
+
for (const r of items) {
|
|
33962
34335
|
const display = r.displayName && r.displayName !== r.name ? ` ${c.dim}${r.displayName}${c.reset}` : "";
|
|
33963
34336
|
const desc = r.description ? ` ${c.dim}${r.description}${c.reset}` : "";
|
|
33964
34337
|
const archived = r.archivedAt ? ` ${c.yellow}[archived]${c.reset}` : "";
|
|
@@ -34388,6 +34761,8 @@ var handleContentSet = async (ctx, { args, flags }) => {
|
|
|
34388
34761
|
});
|
|
34389
34762
|
break;
|
|
34390
34763
|
}
|
|
34764
|
+
default:
|
|
34765
|
+
throw new CliError(2 /* UserInput */, "USER_INPUT", `--kind ${kind} does not support \`set\`.`);
|
|
34391
34766
|
}
|
|
34392
34767
|
};
|
|
34393
34768
|
var handleContentGenerate = async (ctx, { args, flags }) => {
|
|
@@ -34417,6 +34792,8 @@ var handleContentGenerate = async (ctx, { args, flags }) => {
|
|
|
34417
34792
|
});
|
|
34418
34793
|
break;
|
|
34419
34794
|
}
|
|
34795
|
+
default:
|
|
34796
|
+
throw new CliError(2 /* UserInput */, "USER_INPUT", `--kind ${kind} does not support \`generate\`.`);
|
|
34420
34797
|
}
|
|
34421
34798
|
};
|
|
34422
34799
|
var CONTENT_SUBDOMAIN = defineDomain({
|
|
@@ -34774,6 +35151,7 @@ var handleRetract2 = async (ctx, { flags, args }) => {
|
|
|
34774
35151
|
], { committer: flags.committer });
|
|
34775
35152
|
assertSingleOpSuccess(result);
|
|
34776
35153
|
writeOutput(ctx, result, () => {
|
|
35154
|
+
renderCommitterEcho(ctx.out, c, flags.committer);
|
|
34777
35155
|
ctx.out(`${c.red}Retracted${c.reset} ${c.magenta}${shapeName}${c.reset}`);
|
|
34778
35156
|
});
|
|
34779
35157
|
};
|
|
@@ -37203,7 +37581,7 @@ async function runCli(argv, opts) {
|
|
|
37203
37581
|
return exitCode;
|
|
37204
37582
|
}
|
|
37205
37583
|
if (globalHelpAllRequested) {
|
|
37206
|
-
printDomainHelp(out, { allFlags: true, allDomains: true });
|
|
37584
|
+
await printDomainHelp(out, { allFlags: true, allDomains: true });
|
|
37207
37585
|
exitCode = 0 /* Ok */;
|
|
37208
37586
|
return exitCode;
|
|
37209
37587
|
}
|
|
@@ -37355,7 +37733,7 @@ function resolveLogLevel(flags, env) {
|
|
|
37355
37733
|
// package.json
|
|
37356
37734
|
var package_default3 = {
|
|
37357
37735
|
name: "@warmhub/cli",
|
|
37358
|
-
version: "0.
|
|
37736
|
+
version: "0.49.0",
|
|
37359
37737
|
private: false,
|
|
37360
37738
|
type: "module",
|
|
37361
37739
|
description: "The wh CLI for WarmHub — create repos, commit and query data, and compound knowledge with your AI agents.",
|
|
@@ -38382,4 +38760,4 @@ if (!updateCheckSuppressedByArgv && shouldRunUpdateCheck(updateEligibility)) {
|
|
|
38382
38760
|
var interceptedExitCode = await maybeHandleComponentShellBoundary(dispatchArgv);
|
|
38383
38761
|
process.exitCode = interceptedExitCode === undefined ? await runCli(dispatchArgv, { version: package_default3.version }) : interceptedExitCode;
|
|
38384
38762
|
|
|
38385
|
-
//# debugId=
|
|
38763
|
+
//# debugId=7BEE2CF049FB035564756E2164756E21
|
package/package.json
CHANGED