@warmhub/cli 0.47.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 +511 -89
- package/package.json +1 -1
package/dist/wh.js
CHANGED
|
@@ -19192,16 +19192,28 @@ var PLATFORM_STATUS_PROBE_ARTIFACT_FIELDS = {
|
|
|
19192
19192
|
}
|
|
19193
19193
|
};
|
|
19194
19194
|
// ../../packages/rules/src/reserved-orgs.ts
|
|
19195
|
+
var RESERVED_RAW_CONTENT_TOP_LEVEL_NAMES = [
|
|
19196
|
+
"_app",
|
|
19197
|
+
"_static",
|
|
19198
|
+
"api",
|
|
19199
|
+
"health",
|
|
19200
|
+
"healthz",
|
|
19201
|
+
"mcp",
|
|
19202
|
+
"readyz",
|
|
19203
|
+
"robots.txt",
|
|
19204
|
+
"sse",
|
|
19205
|
+
"trpc",
|
|
19206
|
+
"version"
|
|
19207
|
+
];
|
|
19195
19208
|
var RESERVED_ORG_NAMES = [
|
|
19209
|
+
...RESERVED_RAW_CONTENT_TOP_LEVEL_NAMES,
|
|
19196
19210
|
"admin",
|
|
19197
|
-
"api",
|
|
19198
19211
|
"billing",
|
|
19199
19212
|
"blog",
|
|
19200
19213
|
"docs",
|
|
19201
19214
|
"help",
|
|
19202
19215
|
"login",
|
|
19203
19216
|
"public",
|
|
19204
|
-
"robots.txt",
|
|
19205
19217
|
"settings",
|
|
19206
19218
|
"signup",
|
|
19207
19219
|
"status",
|
|
@@ -19515,7 +19527,7 @@ function findSystemComponent(componentId) {
|
|
|
19515
19527
|
// ../../packages/sdk-ts/package.json
|
|
19516
19528
|
var package_default = {
|
|
19517
19529
|
name: "@warmhub/sdk-ts",
|
|
19518
|
-
version: "0.
|
|
19530
|
+
version: "0.48.0",
|
|
19519
19531
|
private: false,
|
|
19520
19532
|
type: "module",
|
|
19521
19533
|
description: "The TypeScript SDK for WarmHub — create repos, commit and query data, and compound knowledge with your AI agents.",
|
|
@@ -19614,12 +19626,16 @@ var package_default = {
|
|
|
19614
19626
|
|
|
19615
19627
|
// ../../packages/sdk-ts/src/operation-normalize.ts
|
|
19616
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
|
+
}
|
|
19617
19632
|
if (operation.operation === "retract") {
|
|
19618
19633
|
return {
|
|
19619
19634
|
operation: "retract",
|
|
19620
19635
|
name: operation.name,
|
|
19621
19636
|
...operation.kind ? { kind: operation.kind } : {},
|
|
19622
|
-
...operation.reason ? { reason: operation.reason } : {}
|
|
19637
|
+
...operation.reason ? { reason: operation.reason } : {},
|
|
19638
|
+
...operation.leaseId ? { leaseId: operation.leaseId } : {}
|
|
19623
19639
|
};
|
|
19624
19640
|
}
|
|
19625
19641
|
if (operation.operation === "revise") {
|
|
@@ -19642,14 +19658,18 @@ function toBackendStreamOperation(operation) {
|
|
|
19642
19658
|
operation: "revise",
|
|
19643
19659
|
kind: "assertion",
|
|
19644
19660
|
name,
|
|
19645
|
-
data: operation.data
|
|
19661
|
+
data: operation.data,
|
|
19662
|
+
...operation.expectedVersion !== undefined ? { expectedVersion: operation.expectedVersion } : {},
|
|
19663
|
+
...operation.leaseId ? { leaseId: operation.leaseId } : {}
|
|
19646
19664
|
};
|
|
19647
19665
|
}
|
|
19648
19666
|
return {
|
|
19649
19667
|
operation: "revise",
|
|
19650
19668
|
kind: kind2,
|
|
19651
19669
|
name,
|
|
19652
|
-
data: operation.data
|
|
19670
|
+
data: operation.data,
|
|
19671
|
+
...operation.expectedVersion !== undefined ? { expectedVersion: operation.expectedVersion } : {},
|
|
19672
|
+
...operation.leaseId ? { leaseId: operation.leaseId } : {}
|
|
19653
19673
|
};
|
|
19654
19674
|
}
|
|
19655
19675
|
const kind = operation.kind ?? inferKind(operation.name, operation);
|
|
@@ -20143,7 +20163,8 @@ class WarmHubError extends Error {
|
|
|
20143
20163
|
hint;
|
|
20144
20164
|
retryAfter;
|
|
20145
20165
|
backendCode;
|
|
20146
|
-
|
|
20166
|
+
details;
|
|
20167
|
+
constructor(code, message, status, hint, retryAfter, backendCode, details) {
|
|
20147
20168
|
super(message);
|
|
20148
20169
|
this.name = "WarmHubError";
|
|
20149
20170
|
this.code = code;
|
|
@@ -20151,6 +20172,7 @@ class WarmHubError extends Error {
|
|
|
20151
20172
|
this.hint = hint;
|
|
20152
20173
|
this.retryAfter = retryAfter;
|
|
20153
20174
|
this.backendCode = backendCode;
|
|
20175
|
+
this.details = details;
|
|
20154
20176
|
}
|
|
20155
20177
|
get kind() {
|
|
20156
20178
|
return this.code;
|
|
@@ -20175,12 +20197,12 @@ function toWarmHubError(error) {
|
|
|
20175
20197
|
const data = error.data;
|
|
20176
20198
|
const wireCode = data?.warmhub?.code;
|
|
20177
20199
|
const message = data?.warmhub?.message ?? sanitizeErrorMessage(error.message);
|
|
20178
|
-
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);
|
|
20179
20201
|
}
|
|
20180
20202
|
if (error instanceof Error) {
|
|
20181
20203
|
const warmhubLike = error;
|
|
20182
20204
|
if (error.name === "WarmHubError" && typeof warmhubLike.code === "string") {
|
|
20183
|
-
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);
|
|
20184
20206
|
}
|
|
20185
20207
|
if (error.name === "AbortError") {
|
|
20186
20208
|
return new WarmHubError("CANCELLED", error.message);
|
|
@@ -21308,6 +21330,30 @@ class WarmHubClient {
|
|
|
21308
21330
|
throw toWarmHubError(error);
|
|
21309
21331
|
}
|
|
21310
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
|
+
},
|
|
21311
21357
|
graph: async (orgName, repoName, wref, opts) => {
|
|
21312
21358
|
try {
|
|
21313
21359
|
return await this.trpc.thing.graph.query({
|
|
@@ -22045,6 +22091,10 @@ function classifyConflict(message, code) {
|
|
|
22045
22091
|
return "archived";
|
|
22046
22092
|
case "REPO_PENDING_DELETE":
|
|
22047
22093
|
return "pending-delete";
|
|
22094
|
+
case "LEASE_UNAVAILABLE":
|
|
22095
|
+
return "lease-held";
|
|
22096
|
+
default:
|
|
22097
|
+
break;
|
|
22048
22098
|
}
|
|
22049
22099
|
const lower = message.toLowerCase();
|
|
22050
22100
|
if (lower.includes("already exists") || lower.includes("already a member")) {
|
|
@@ -22074,6 +22124,8 @@ function conflictHint(message, code) {
|
|
|
22074
22124
|
return "Other things reference this. Retract those assertions first, or use a tombstone.";
|
|
22075
22125
|
case "pending-delete":
|
|
22076
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.";
|
|
22077
22129
|
case "other":
|
|
22078
22130
|
return "Resolve the conflicting existing state and try again.";
|
|
22079
22131
|
}
|
|
@@ -22097,7 +22149,8 @@ var CONFLICT_SHAPED_CODES = new Set([
|
|
|
22097
22149
|
"ARCHIVED",
|
|
22098
22150
|
"HAS_INBOUND_REFS",
|
|
22099
22151
|
"REPO_PENDING_DELETE",
|
|
22100
|
-
"ALREADY_RETRACTED"
|
|
22152
|
+
"ALREADY_RETRACTED",
|
|
22153
|
+
"LEASE_UNAVAILABLE"
|
|
22101
22154
|
]);
|
|
22102
22155
|
function fromWh(exit, kind, err, hint = err.hint) {
|
|
22103
22156
|
return new CliError(exit, kind, err.message, err, hint, undefined, err.backendCode);
|
|
@@ -22257,6 +22310,11 @@ function generateSuggestions(code, message, context, backendCode) {
|
|
|
22257
22310
|
action: "Wait for the repo delete to finish or cancel it before retrying"
|
|
22258
22311
|
});
|
|
22259
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;
|
|
22260
22318
|
case "other":
|
|
22261
22319
|
suggestions.push({
|
|
22262
22320
|
action: "Resolve the conflicting existing state and retry"
|
|
@@ -22468,6 +22526,21 @@ function safeParseJson(input, label, options) {
|
|
|
22468
22526
|
throw new CliError(2 /* UserInput */, "USER_INPUT", `Invalid JSON for ${label}: ${input.length > 80 ? `${input.slice(0, 77)}...` : input}`, undefined, hint);
|
|
22469
22527
|
}
|
|
22470
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
|
+
}
|
|
22471
22544
|
function parseArgs(argv) {
|
|
22472
22545
|
const positionals = [];
|
|
22473
22546
|
const flags = {};
|
|
@@ -23847,6 +23920,17 @@ function parseOrgRepo(ref, config) {
|
|
|
23847
23920
|
}
|
|
23848
23921
|
throw new CliError(3 /* Config */, "CONFIG", "No repo specified. Use --repo org/repo, set WARMHUB_REPO, or run: wh use org/repo");
|
|
23849
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
|
+
}
|
|
23850
23934
|
|
|
23851
23935
|
// ../../packages/warmhub-cli/src/domain-registry.ts
|
|
23852
23936
|
class DomainRegistry {
|
|
@@ -24264,9 +24348,15 @@ function renderWarningLine(out, c, chars, op) {
|
|
|
24264
24348
|
const moreSuffix = remaining > 0 ? ` ${c.dim}(+${remaining} more)${c.reset}` : "";
|
|
24265
24349
|
out(` ${c.yellow}${chars.warn}${c.reset} ${total} ${noun} not declared in shape${shapeLabel}: ${c.dim}${fieldsList}${c.reset}${moreSuffix}`);
|
|
24266
24350
|
}
|
|
24351
|
+
function renderCommitterEcho(out, c, committer) {
|
|
24352
|
+
if (!committer)
|
|
24353
|
+
return;
|
|
24354
|
+
out(` ${c.dim}committer:${c.reset} ${pinnedWref(c, committer)}`);
|
|
24355
|
+
}
|
|
24267
24356
|
function renderSingleOpSuccess(out, c, chars, op, opts) {
|
|
24268
24357
|
const name = op.name ?? opts.fallbackName;
|
|
24269
24358
|
const suffix = opts.suffix ?? "";
|
|
24359
|
+
renderCommitterEcho(out, c, opts.committer);
|
|
24270
24360
|
out(`${opts.color}${opts.marker}${c.reset} ${displayName(c, name)}${suffix}`);
|
|
24271
24361
|
renderWarningLine(out, c, chars, op);
|
|
24272
24362
|
}
|
|
@@ -24345,6 +24435,10 @@ async function readContentInput(filePath, inline, stdinStream) {
|
|
|
24345
24435
|
}
|
|
24346
24436
|
|
|
24347
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
|
+
}
|
|
24348
24442
|
function usageError2(usage, example) {
|
|
24349
24443
|
throw new CliError(2 /* UserInput */, "USER_INPUT", usage, undefined, `Example: ${example}`);
|
|
24350
24444
|
}
|
|
@@ -24441,6 +24535,10 @@ function renderHead(out, c, chars, result, org, repo, shape, kind) {
|
|
|
24441
24535
|
const truncated = preview.length > 80 ? `${preview.slice(0, 77)}...` : preview;
|
|
24442
24536
|
out(` ${c.dim}${truncated}${c.reset}`);
|
|
24443
24537
|
}
|
|
24538
|
+
const itemMeta = item.metadata;
|
|
24539
|
+
if (itemMeta?.durableId) {
|
|
24540
|
+
out(` ${c.dim}durableId:${c.reset} ${itemMeta.durableId}`);
|
|
24541
|
+
}
|
|
24444
24542
|
}
|
|
24445
24543
|
out(`${c.dim}${items.length} item(s)${c.reset}`);
|
|
24446
24544
|
}
|
|
@@ -24460,6 +24558,19 @@ function renderThing(out, c, result) {
|
|
|
24460
24558
|
if (aboutWref) {
|
|
24461
24559
|
out(` ${c.dim}about:${c.reset} ${String(aboutWref)}`);
|
|
24462
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
|
+
}
|
|
24463
24574
|
const fields = shapeName && result.data ? collectionFields(shapeName, result.data) : null;
|
|
24464
24575
|
if (fields) {
|
|
24465
24576
|
for (const field of fields) {
|
|
@@ -24550,6 +24661,10 @@ function renderHistory(out, c, result) {
|
|
|
24550
24661
|
const wref = result.thing.wref ?? result.thing.name ?? "(unknown)";
|
|
24551
24662
|
out(`${c.bold}History: ${pinnedWref(c, wref)}${c.reset} ${kindLabel(c, result.thing.kind ?? "thing")}`);
|
|
24552
24663
|
}
|
|
24664
|
+
const firstMeta = result.versions?.[0]?.metadata;
|
|
24665
|
+
if (firstMeta?.durableId) {
|
|
24666
|
+
out(` ${c.dim}durableId:${c.reset} ${firstMeta.durableId}`);
|
|
24667
|
+
}
|
|
24553
24668
|
const versions = result.versions ?? [];
|
|
24554
24669
|
const now = Date.now();
|
|
24555
24670
|
for (const ver of versions) {
|
|
@@ -24566,7 +24681,9 @@ function renderHistory(out, c, result) {
|
|
|
24566
24681
|
const wref = ver.wref ?? ver.thingName;
|
|
24567
24682
|
const wrefStr = wref ? pinnedWref(c, wref, ver.version) : "";
|
|
24568
24683
|
const by = ver.committerWref ? ` ${c.dim}by${c.reset} ${pinnedWref(c, ver.committerWref)}` : "";
|
|
24569
|
-
|
|
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}`);
|
|
24570
24687
|
}
|
|
24571
24688
|
}
|
|
24572
24689
|
function renderRefs(out, c, result, wref, direction) {
|
|
@@ -24834,9 +24951,9 @@ async function collectWrefs(opts) {
|
|
|
24834
24951
|
]));
|
|
24835
24952
|
}
|
|
24836
24953
|
async function runSingleView(ctx, wref, flags) {
|
|
24837
|
-
const { org, repo } = parseOrgRepo(getRepoRef(ctx), ctx.config);
|
|
24838
24954
|
const version = flags.version;
|
|
24839
24955
|
const depth = flags.depth;
|
|
24956
|
+
const { org, repo } = looksLikeDurableId(wref) && depth === undefined ? parseOrgRepoOptional(getRepoRef(ctx), ctx.config) : parseOrgRepo(getRepoRef(ctx), ctx.config);
|
|
24840
24957
|
const includeRetracted = flags["include-retracted"] || version !== undefined;
|
|
24841
24958
|
if (depth !== undefined && (depth < 1 || depth > 5)) {
|
|
24842
24959
|
usageError2("Usage: wh thing view <wref> --depth <1-5>", "wh thing view Game/base --depth 2");
|
|
@@ -24880,7 +24997,8 @@ async function runSingleView(ctx, wref, flags) {
|
|
|
24880
24997
|
writeOutput(ctx, result, () => renderThing(ctx.out, ctx.colors, result));
|
|
24881
24998
|
}
|
|
24882
24999
|
async function runBatchView(ctx, wrefs, flags) {
|
|
24883
|
-
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);
|
|
24884
25002
|
const includeRetracted = flags["include-retracted"] || flags.version !== undefined;
|
|
24885
25003
|
const result = await ctx.client.thing.getMany(org, repo, wrefs, flags.version, { includeRetracted });
|
|
24886
25004
|
if (ctx.format === "jsonl") {
|
|
@@ -24932,6 +25050,53 @@ var handleView = async (ctx, { flags, args, terminator }) => {
|
|
|
24932
25050
|
const singleWref = wrefs[0];
|
|
24933
25051
|
return runSingleView(ctx, singleWref, flags);
|
|
24934
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
|
+
};
|
|
24935
25100
|
var graphFlags = {
|
|
24936
25101
|
depth: flag.number({
|
|
24937
25102
|
description: "Resolve embedded graph to this depth (default: 2, max: 5)"
|
|
@@ -24971,7 +25136,7 @@ var historyFlags = {
|
|
|
24971
25136
|
};
|
|
24972
25137
|
var handleHistory = async (ctx, { flags, args }) => {
|
|
24973
25138
|
const wref = args[0];
|
|
24974
|
-
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);
|
|
24975
25140
|
const shape = flags.shape;
|
|
24976
25141
|
const about = flags.about;
|
|
24977
25142
|
const limit = flags.limit;
|
|
@@ -25070,7 +25235,7 @@ var handleResolve = async (ctx, { args }) => {
|
|
|
25070
25235
|
if (!wref) {
|
|
25071
25236
|
usageError2("Usage: wh thing resolve <wref>", "wh thing resolve player");
|
|
25072
25237
|
}
|
|
25073
|
-
const { org, repo } = parseOrgRepo(getRepoRef(ctx), ctx.config);
|
|
25238
|
+
const { org, repo } = looksLikeDurableId(wref) ? parseOrgRepoOptional(getRepoRef(ctx), ctx.config) : parseOrgRepo(getRepoRef(ctx), ctx.config);
|
|
25074
25239
|
const c = ctx.colors;
|
|
25075
25240
|
const result = await ctx.client.thing.resolve(org, repo, wref);
|
|
25076
25241
|
writeOutput(ctx, result, () => {
|
|
@@ -25086,6 +25251,12 @@ var reviseFlags = {
|
|
|
25086
25251
|
message: flag.string({ short: "m", description: "Commit message" }),
|
|
25087
25252
|
committer: flag.string({
|
|
25088
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)"
|
|
25089
25260
|
})
|
|
25090
25261
|
};
|
|
25091
25262
|
var createFlags = {
|
|
@@ -25126,7 +25297,8 @@ var handleCreate = async (ctx, { flags, args }) => {
|
|
|
25126
25297
|
writeOutput(ctx, result, () => renderSingleOpSuccess(ctx.out, c, ctx.chars, result.operations[0] ?? {}, {
|
|
25127
25298
|
marker: "+",
|
|
25128
25299
|
color: c.green,
|
|
25129
|
-
fallbackName: name
|
|
25300
|
+
fallbackName: name,
|
|
25301
|
+
committer
|
|
25130
25302
|
}));
|
|
25131
25303
|
};
|
|
25132
25304
|
var handleRevise = async (ctx, { flags, args }) => {
|
|
@@ -25137,8 +25309,10 @@ var handleRevise = async (ctx, { flags, args }) => {
|
|
|
25137
25309
|
const { org, repo } = parseOrgRepo(getRepoRef(ctx), ctx.config);
|
|
25138
25310
|
const committer = flags.committer;
|
|
25139
25311
|
const message = flags.message;
|
|
25312
|
+
const leaseId = requireLeaseIdFlag(flags["lease-id"]);
|
|
25140
25313
|
const data = flags.data ? safeParseJson(flags.data, "--data") : undefined;
|
|
25141
25314
|
const c = ctx.colors;
|
|
25315
|
+
const expectedVersion = parsePositiveIntFlag(flags["expected-version"], "--expected-version", "wh thing revise Player/alice --data '{...}' --expected-version 3");
|
|
25142
25316
|
if (!data) {
|
|
25143
25317
|
usageError2("--data is required for revise", `wh thing revise Location/player --data '{"x":1}'`);
|
|
25144
25318
|
}
|
|
@@ -25147,13 +25321,16 @@ var handleRevise = async (ctx, { flags, args }) => {
|
|
|
25147
25321
|
operation: "revise",
|
|
25148
25322
|
kind: "thing",
|
|
25149
25323
|
name,
|
|
25150
|
-
data
|
|
25324
|
+
data,
|
|
25325
|
+
...expectedVersion !== undefined ? { expectedVersion } : {},
|
|
25326
|
+
...leaseId ? { leaseId } : {}
|
|
25151
25327
|
}
|
|
25152
25328
|
], { committer });
|
|
25153
25329
|
assertSingleOpSuccess(result);
|
|
25154
25330
|
writeOutput(ctx, result, () => renderSingleOpSuccess(ctx.out, c, ctx.chars, result.operations[0] ?? {}, {
|
|
25155
25331
|
marker: "~",
|
|
25156
|
-
color: c.yellow
|
|
25332
|
+
color: c.yellow,
|
|
25333
|
+
committer
|
|
25157
25334
|
}));
|
|
25158
25335
|
};
|
|
25159
25336
|
var retractFlags = {
|
|
@@ -25164,6 +25341,9 @@ var retractFlags = {
|
|
|
25164
25341
|
message: flag.string({ short: "m", description: "Commit message" }),
|
|
25165
25342
|
committer: flag.string({
|
|
25166
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)"
|
|
25167
25347
|
})
|
|
25168
25348
|
};
|
|
25169
25349
|
var handleThingRetract = async (ctx, { flags, args }) => {
|
|
@@ -25176,18 +25356,21 @@ var handleThingRetract = async (ctx, { flags, args }) => {
|
|
|
25176
25356
|
const message = flags.message;
|
|
25177
25357
|
const kind = flags.kind;
|
|
25178
25358
|
const reason = flags.reason;
|
|
25359
|
+
const leaseId = requireLeaseIdFlag(flags["lease-id"], "wh thing retract Player/alice --lease-id <id>");
|
|
25179
25360
|
const c = ctx.colors;
|
|
25180
25361
|
const result = await ctx.client.commit.apply(org, repo, message ?? `retract ${name}`, [
|
|
25181
25362
|
{
|
|
25182
25363
|
operation: "retract",
|
|
25183
25364
|
name,
|
|
25184
25365
|
...kind ? { kind } : {},
|
|
25185
|
-
...reason ? { reason } : {}
|
|
25366
|
+
...reason ? { reason } : {},
|
|
25367
|
+
...leaseId ? { leaseId } : {}
|
|
25186
25368
|
}
|
|
25187
25369
|
], { committer });
|
|
25188
25370
|
assertSingleOpSuccess(result);
|
|
25189
25371
|
writeOutput(ctx, result, () => {
|
|
25190
25372
|
const op = result.operations[0];
|
|
25373
|
+
renderCommitterEcho(ctx.out, c, committer);
|
|
25191
25374
|
ctx.out(`${c.red}-${c.reset} ${displayName(c, op?.name ?? name)}`);
|
|
25192
25375
|
});
|
|
25193
25376
|
};
|
|
@@ -25530,7 +25713,7 @@ var handleAbout = async (ctx, { flags, args }) => {
|
|
|
25530
25713
|
if (!wref) {
|
|
25531
25714
|
usageError2("Usage: wh thing about <wref> [--shape] [--match] [--limit] [--include-retracted]", "wh thing about Location/cave");
|
|
25532
25715
|
}
|
|
25533
|
-
const { org, repo } = parseOrgRepo(getRepoRef(ctx), ctx.config);
|
|
25716
|
+
const { org, repo } = looksLikeDurableId(wref) ? parseOrgRepoOptional(getRepoRef(ctx), ctx.config) : parseOrgRepo(getRepoRef(ctx), ctx.config);
|
|
25534
25717
|
const includeRetracted = flags["include-retracted"];
|
|
25535
25718
|
const limit = flags.limit;
|
|
25536
25719
|
const cursor = flags.cursor;
|
|
@@ -25650,7 +25833,7 @@ var handleRefs = async (ctx, { flags, args }) => {
|
|
|
25650
25833
|
if (!wref) {
|
|
25651
25834
|
usageError2("Usage: wh thing refs <wref> [--inbound|--outbound] [--field FIELD] [--limit N]", "wh thing refs Loc/player");
|
|
25652
25835
|
}
|
|
25653
|
-
const { org, repo } = parseOrgRepo(getRepoRef(ctx), ctx.config);
|
|
25836
|
+
const { org, repo } = looksLikeDurableId(wref) ? parseOrgRepoOptional(getRepoRef(ctx), ctx.config) : parseOrgRepo(getRepoRef(ctx), ctx.config);
|
|
25654
25837
|
if (flags.inbound && flags.outbound) {
|
|
25655
25838
|
usageError2("Cannot specify both --inbound and --outbound", "wh thing refs Loc/player --outbound");
|
|
25656
25839
|
}
|
|
@@ -25731,6 +25914,25 @@ var THING_DOMAIN = defineDomain({
|
|
|
25731
25914
|
],
|
|
25732
25915
|
handler: handleView
|
|
25733
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
|
+
},
|
|
25734
25936
|
history: {
|
|
25735
25937
|
prime: true,
|
|
25736
25938
|
summary: "Show version history",
|
|
@@ -26044,7 +26246,8 @@ var handleRevise2 = async (ctx, { flags, args }) => {
|
|
|
26044
26246
|
assertSingleOpSuccess(result);
|
|
26045
26247
|
writeOutput(ctx, result, () => renderSingleOpSuccess(ctx.out, c, ctx.chars, result.operations[0] ?? {}, {
|
|
26046
26248
|
marker: "~",
|
|
26047
|
-
color: c.yellow
|
|
26249
|
+
color: c.yellow,
|
|
26250
|
+
committer: flags.committer
|
|
26048
26251
|
}));
|
|
26049
26252
|
};
|
|
26050
26253
|
var retractFlags2 = {
|
|
@@ -26073,6 +26276,7 @@ var handleRetract = async (ctx, { flags, args }) => {
|
|
|
26073
26276
|
assertSingleOpSuccess(result);
|
|
26074
26277
|
writeOutput(ctx, result, () => {
|
|
26075
26278
|
const op = result.operations[0];
|
|
26279
|
+
renderCommitterEcho(ctx.out, ctx.colors, flags.committer);
|
|
26076
26280
|
ctx.out(`${ctx.colors.red}-${ctx.colors.reset} ${displayName(ctx.colors, op?.name ?? name)}`);
|
|
26077
26281
|
});
|
|
26078
26282
|
};
|
|
@@ -26169,7 +26373,8 @@ var handleCreate2 = async (ctx, { flags, args }) => {
|
|
|
26169
26373
|
writeOutput(ctx, result, () => renderSingleOpSuccess(ctx.out, c, ctx.chars, result.operations[0] ?? {}, {
|
|
26170
26374
|
marker: "+",
|
|
26171
26375
|
color: c.green,
|
|
26172
|
-
suffix: ` ${c.dim}(${shape})${c.reset}
|
|
26376
|
+
suffix: ` ${c.dim}(${shape})${c.reset}`,
|
|
26377
|
+
committer
|
|
26173
26378
|
}));
|
|
26174
26379
|
};
|
|
26175
26380
|
var listFlags = {
|
|
@@ -27601,6 +27806,59 @@ import { createReadStream as createReadStream2 } from "node:fs";
|
|
|
27601
27806
|
import { readFile, writeFile } from "node:fs/promises";
|
|
27602
27807
|
import { createInterface as createInterface2 } from "node:readline";
|
|
27603
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
|
+
|
|
27604
27862
|
// ../../packages/warmhub-cli/src/domains/stream-progress.ts
|
|
27605
27863
|
import { createReadStream } from "node:fs";
|
|
27606
27864
|
import { createInterface } from "node:readline";
|
|
@@ -27902,7 +28160,9 @@ async function applyJsonlCommit(ctx, args) {
|
|
|
27902
28160
|
} catch (cause) {
|
|
27903
28161
|
const completed = operationOffset + opCount;
|
|
27904
28162
|
if (opCount > 0 || firstJsonlAppendErrorMayHaveCommitted(cause)) {
|
|
27905
|
-
|
|
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);
|
|
27906
28166
|
}
|
|
27907
28167
|
throw cause;
|
|
27908
28168
|
}
|
|
@@ -27960,6 +28220,24 @@ async function applyJsonlCommit(ctx, args) {
|
|
|
27960
28220
|
continue;
|
|
27961
28221
|
assertWithinStreamOpLimit(parsedOpCount + 1);
|
|
27962
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
|
+
}
|
|
27963
28241
|
parsedOpCount += 1;
|
|
27964
28242
|
chunk.push(withSkipExisting(operation, args.skipExisting === true));
|
|
27965
28243
|
if (chunk.length < chunkSize)
|
|
@@ -28177,7 +28455,7 @@ function buildAddOperations(input) {
|
|
|
28177
28455
|
});
|
|
28178
28456
|
}
|
|
28179
28457
|
function buildRetractOperations(input) {
|
|
28180
|
-
const { retractNames, kinds, reasons } = input;
|
|
28458
|
+
const { retractNames, kinds, reasons, leaseId } = input;
|
|
28181
28459
|
const assertCardinality = (flagName, values) => {
|
|
28182
28460
|
if (values.length === 0)
|
|
28183
28461
|
return;
|
|
@@ -28203,7 +28481,8 @@ function buildRetractOperations(input) {
|
|
|
28203
28481
|
operation: "retract",
|
|
28204
28482
|
name,
|
|
28205
28483
|
...kind ? { kind } : {},
|
|
28206
|
-
...reason ? { reason } : {}
|
|
28484
|
+
...reason ? { reason } : {},
|
|
28485
|
+
...leaseId ? { leaseId } : {}
|
|
28207
28486
|
};
|
|
28208
28487
|
});
|
|
28209
28488
|
}
|
|
@@ -28260,6 +28539,9 @@ var createFlags3 = {
|
|
|
28260
28539
|
"chunk-size": flag.number({
|
|
28261
28540
|
description: `Streamed ops per append chunk for --stream or .jsonl --file (default: ${DEFAULT_STREAM_APPEND_CHUNK_SIZE}, max: ${MAX_STREAM_APPEND_OPERATION_COUNT})`
|
|
28262
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
|
+
}),
|
|
28263
28545
|
"timing-out": flag.string({
|
|
28264
28546
|
description: "Write per-append timing sidecar JSON to this path (debug/bench instrumentation)"
|
|
28265
28547
|
}),
|
|
@@ -28310,6 +28592,12 @@ var createFlags3 = {
|
|
|
28310
28592
|
}),
|
|
28311
28593
|
members: flag.string({
|
|
28312
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)"
|
|
28313
28601
|
})
|
|
28314
28602
|
};
|
|
28315
28603
|
var handleSubmit = async (ctx, { flags, args }) => {
|
|
@@ -28322,6 +28610,7 @@ var handleSubmit = async (ctx, { flags, args }) => {
|
|
|
28322
28610
|
const progressRequested = flags.progress === true;
|
|
28323
28611
|
const skipExisting = flags["skip-existing"] === true;
|
|
28324
28612
|
const chunkSize = flags["chunk-size"];
|
|
28613
|
+
const allowNulBytes = flags["allow-nul-bytes"] === true;
|
|
28325
28614
|
const timingOut = flags["timing-out"];
|
|
28326
28615
|
const resumeStreamId = flags["stream-id"];
|
|
28327
28616
|
const resumeAllocatedTokens = parseAllocatedTokensFlag(flags["allocated-tokens"]);
|
|
@@ -28335,6 +28624,14 @@ var handleSubmit = async (ctx, { flags, args }) => {
|
|
|
28335
28624
|
const abouts = flags.about ?? [];
|
|
28336
28625
|
const reasons = flags.reason ?? [];
|
|
28337
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
|
+
}
|
|
28338
28635
|
const validKinds = [
|
|
28339
28636
|
"thing",
|
|
28340
28637
|
"assertion",
|
|
@@ -28426,7 +28723,8 @@ var handleSubmit = async (ctx, { flags, args }) => {
|
|
|
28426
28723
|
operations = buildRetractOperations({
|
|
28427
28724
|
retractNames,
|
|
28428
28725
|
kinds,
|
|
28429
|
-
reasons
|
|
28726
|
+
reasons,
|
|
28727
|
+
leaseId: leaseIdFlag
|
|
28430
28728
|
});
|
|
28431
28729
|
} else if (reviseName) {
|
|
28432
28730
|
if (dataJsons.length > 1) {
|
|
@@ -28439,13 +28737,30 @@ var handleSubmit = async (ctx, { flags, args }) => {
|
|
|
28439
28737
|
const data = rawData ? safeParseJson(rawData, "--data") : undefined;
|
|
28440
28738
|
const kindFlag = kinds[0];
|
|
28441
28739
|
const kind = kindFlag ?? "thing";
|
|
28442
|
-
operations = [
|
|
28740
|
+
operations = [
|
|
28741
|
+
{
|
|
28742
|
+
operation: "revise",
|
|
28743
|
+
kind,
|
|
28744
|
+
name: reviseName,
|
|
28745
|
+
data,
|
|
28746
|
+
...expectedVersion !== undefined ? { expectedVersion } : {},
|
|
28747
|
+
...leaseIdFlag ? { leaseId: leaseIdFlag } : {}
|
|
28748
|
+
}
|
|
28749
|
+
];
|
|
28443
28750
|
} else {
|
|
28444
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}'`);
|
|
28445
28752
|
}
|
|
28446
28753
|
if (!streamInput && operations.length > 0) {
|
|
28447
28754
|
rejectLegacyLifecycleOperations(operations);
|
|
28448
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
|
+
}
|
|
28449
28764
|
}
|
|
28450
28765
|
const message = streamInput || jsonlFile ? messageFlag : messageFlag ?? synthesizeCommitMessage(operations);
|
|
28451
28766
|
let result;
|
|
@@ -28460,7 +28775,8 @@ var handleSubmit = async (ctx, { flags, args }) => {
|
|
|
28460
28775
|
skipExisting,
|
|
28461
28776
|
streamId: resumeStreamId,
|
|
28462
28777
|
allocatedTokens: resumeAllocatedTokens,
|
|
28463
|
-
operationOffset: resumeOperationOffset
|
|
28778
|
+
operationOffset: resumeOperationOffset,
|
|
28779
|
+
allowNulBytes
|
|
28464
28780
|
}) : jsonlFile ? await applyJsonlFileCommit(ctx, {
|
|
28465
28781
|
org,
|
|
28466
28782
|
repo,
|
|
@@ -28473,7 +28789,8 @@ var handleSubmit = async (ctx, { flags, args }) => {
|
|
|
28473
28789
|
skipExisting,
|
|
28474
28790
|
streamId: resumeStreamId,
|
|
28475
28791
|
allocatedTokens: resumeAllocatedTokens,
|
|
28476
|
-
operationOffset: resumeOperationOffset
|
|
28792
|
+
operationOffset: resumeOperationOffset,
|
|
28793
|
+
allowNulBytes
|
|
28477
28794
|
}) : await ctx.client.commit.apply(org, repo, message, operations, {
|
|
28478
28795
|
committer,
|
|
28479
28796
|
skipExisting
|
|
@@ -28490,6 +28807,7 @@ var handleSubmit = async (ctx, { flags, args }) => {
|
|
|
28490
28807
|
writeOutput(ctx, result, () => {
|
|
28491
28808
|
const failureSuffix = failedCount > 0 ? `, ${failedCount} failed` : "";
|
|
28492
28809
|
ctx.out(`${message ?? "(no message)"} ${c.dim}(${result.operationCount} ops${failureSuffix})${c.reset}`);
|
|
28810
|
+
renderCommitterEcho(ctx.out, c, committer);
|
|
28493
28811
|
for (const op of result.operations) {
|
|
28494
28812
|
const failed = isFailedOpStatus(op.status);
|
|
28495
28813
|
const marker = failed ? "!" : op.operation === "add" ? "+" : op.operation === "revise" ? "~" : "-";
|
|
@@ -30099,6 +30417,17 @@ async function reconcileComponent(client, org, repo, pkg, source, existingInstal
|
|
|
30099
30417
|
};
|
|
30100
30418
|
}
|
|
30101
30419
|
steps.push({ step: "validate", status: "ok" });
|
|
30420
|
+
const partitionedShapes = partitionByProvisioning(manifest.shapes, "Shape");
|
|
30421
|
+
const partitionedCreds = partitionByProvisioning(manifest.credentials, "CredentialSet");
|
|
30422
|
+
const partitionedSubs = partitionByProvisioning(manifest.subscriptions, "Subscription");
|
|
30423
|
+
const setupCreates = [
|
|
30424
|
+
...partitionedShapes.setupRefs,
|
|
30425
|
+
...partitionedCreds.setupRefs,
|
|
30426
|
+
...partitionedSubs.setupRefs
|
|
30427
|
+
];
|
|
30428
|
+
const reconcileShapes = partitionedShapes.manifestEntries;
|
|
30429
|
+
const reconcileCreds = partitionedCreds.manifestEntries;
|
|
30430
|
+
const reconcileSubs = partitionedSubs.manifestEntries;
|
|
30102
30431
|
await ensureSharedInfra(client, org, repo);
|
|
30103
30432
|
steps.push({ step: "ensure-shared-infra", status: "ok" });
|
|
30104
30433
|
const existingData = existingInstall.data;
|
|
@@ -30118,7 +30447,7 @@ async function reconcileComponent(client, org, repo, pkg, source, existingInstal
|
|
|
30118
30447
|
const liveShapeNames = new Set;
|
|
30119
30448
|
const liveShapeDataByName = new Map;
|
|
30120
30449
|
const liveShapeComponentIdByName = new Map;
|
|
30121
|
-
for (const shape of
|
|
30450
|
+
for (const shape of reconcileShapes) {
|
|
30122
30451
|
if (isFailedInstallState || previousState !== "degraded" && !oldShapeNames.has(shape.name)) {
|
|
30123
30452
|
continue;
|
|
30124
30453
|
}
|
|
@@ -30139,7 +30468,7 @@ async function reconcileComponent(client, org, repo, pkg, source, existingInstal
|
|
|
30139
30468
|
} catch {}
|
|
30140
30469
|
}
|
|
30141
30470
|
const liveSubNames = new Set;
|
|
30142
|
-
for (const sub of
|
|
30471
|
+
for (const sub of reconcileSubs) {
|
|
30143
30472
|
if (wasIncomplete || !oldSubNames.has(sub.name))
|
|
30144
30473
|
continue;
|
|
30145
30474
|
try {
|
|
@@ -30148,7 +30477,7 @@ async function reconcileComponent(client, org, repo, pkg, source, existingInstal
|
|
|
30148
30477
|
} catch {}
|
|
30149
30478
|
}
|
|
30150
30479
|
const liveCredNames = new Set;
|
|
30151
|
-
for (const cred of
|
|
30480
|
+
for (const cred of reconcileCreds) {
|
|
30152
30481
|
if (wasIncomplete || !oldCredNames.has(cred.name))
|
|
30153
30482
|
continue;
|
|
30154
30483
|
const credentialSetName = resolveManifestCredentialName(cred.name, {
|
|
@@ -30160,7 +30489,7 @@ async function reconcileComponent(client, org, repo, pkg, source, existingInstal
|
|
|
30160
30489
|
liveCredNames.add(cred.name);
|
|
30161
30490
|
} catch {}
|
|
30162
30491
|
}
|
|
30163
|
-
const newShapes =
|
|
30492
|
+
const newShapes = reconcileShapes.filter((s) => !liveShapeNames.has(s.name));
|
|
30164
30493
|
if (newShapes.length > 0) {
|
|
30165
30494
|
const shapeOps = newShapes.map((shape) => ({
|
|
30166
30495
|
operation: "add",
|
|
@@ -30181,7 +30510,7 @@ async function reconcileComponent(client, org, repo, pkg, source, existingInstal
|
|
|
30181
30510
|
}
|
|
30182
30511
|
}
|
|
30183
30512
|
}
|
|
30184
|
-
const changedShapes =
|
|
30513
|
+
const changedShapes = reconcileShapes.filter((shape) => {
|
|
30185
30514
|
if (!liveShapeNames.has(shape.name))
|
|
30186
30515
|
return false;
|
|
30187
30516
|
const liveData = liveShapeDataByName.get(shape.name);
|
|
@@ -30208,7 +30537,7 @@ async function reconcileComponent(client, org, repo, pkg, source, existingInstal
|
|
|
30208
30537
|
});
|
|
30209
30538
|
}
|
|
30210
30539
|
}
|
|
30211
|
-
const newCreds =
|
|
30540
|
+
const newCreds = reconcileCreds.filter((c) => !oldCredNames.has(c.name) || !liveCredNames.has(c.name));
|
|
30212
30541
|
for (const cred of newCreds) {
|
|
30213
30542
|
const credentialSetName = resolveManifestCredentialName(cred.name, {
|
|
30214
30543
|
orgName: org,
|
|
@@ -30237,7 +30566,7 @@ async function reconcileComponent(client, org, repo, pkg, source, existingInstal
|
|
|
30237
30566
|
}
|
|
30238
30567
|
}
|
|
30239
30568
|
}
|
|
30240
|
-
const newSubs =
|
|
30569
|
+
const newSubs = reconcileSubs.filter((s) => !oldSubNames.has(s.name) || !liveSubNames.has(s.name));
|
|
30241
30570
|
for (const sub of newSubs) {
|
|
30242
30571
|
let compiled;
|
|
30243
30572
|
try {
|
|
@@ -30288,7 +30617,7 @@ async function reconcileComponent(client, org, repo, pkg, source, existingInstal
|
|
|
30288
30617
|
} catch {}
|
|
30289
30618
|
}
|
|
30290
30619
|
}
|
|
30291
|
-
const existingSubs =
|
|
30620
|
+
const existingSubs = reconcileSubs.filter((s) => oldSubNames.has(s.name) && liveSubNames.has(s.name));
|
|
30292
30621
|
for (const sub of existingSubs) {
|
|
30293
30622
|
const stepName = `update-sub-${sub.name}`;
|
|
30294
30623
|
let compiled;
|
|
@@ -30418,7 +30747,7 @@ async function reconcileComponent(client, org, repo, pkg, source, existingInstal
|
|
|
30418
30747
|
state,
|
|
30419
30748
|
steps,
|
|
30420
30749
|
errors,
|
|
30421
|
-
setupCreates
|
|
30750
|
+
setupCreates
|
|
30422
30751
|
};
|
|
30423
30752
|
}
|
|
30424
30753
|
|
|
@@ -31041,12 +31370,28 @@ var updateFlags = {
|
|
|
31041
31370
|
})
|
|
31042
31371
|
};
|
|
31043
31372
|
var validateFlags = {};
|
|
31044
|
-
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
|
+
};
|
|
31045
31382
|
var viewFlags3 = {};
|
|
31046
31383
|
var teardownFlags = {};
|
|
31047
31384
|
var doctorFlags = {};
|
|
31048
31385
|
var initFlags = {};
|
|
31049
|
-
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
|
+
};
|
|
31050
31395
|
var registerFlags = {
|
|
31051
31396
|
org: flag.string({ description: "Owner org for the registered component" }),
|
|
31052
31397
|
"source-url": flag.string({ description: "Source GitHub URL for installs" }),
|
|
@@ -31426,12 +31771,33 @@ function normalizeGithubRemote(remote) {
|
|
|
31426
31771
|
}
|
|
31427
31772
|
return;
|
|
31428
31773
|
}
|
|
31429
|
-
|
|
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 }) => {
|
|
31430
31794
|
const { org, repo } = parseOrgRepo(getRepoRef(ctx), ctx.config);
|
|
31431
|
-
const
|
|
31432
|
-
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
|
+
}
|
|
31433
31800
|
writeOutput(ctx, items, () => {
|
|
31434
|
-
const c = ctx.colors;
|
|
31435
31801
|
if (!items.length) {
|
|
31436
31802
|
ctx.status(`${c.dim}No components installed${c.reset}`);
|
|
31437
31803
|
return;
|
|
@@ -31447,17 +31813,20 @@ var handleList2 = async (ctx) => {
|
|
|
31447
31813
|
}
|
|
31448
31814
|
});
|
|
31449
31815
|
};
|
|
31450
|
-
var handleSearch2 = async (ctx, { args }) => {
|
|
31816
|
+
var handleSearch2 = async (ctx, { flags, args }) => {
|
|
31451
31817
|
const query = args[0]?.trim();
|
|
31452
31818
|
if (!query) {
|
|
31453
31819
|
usageError("Usage: wh component search <query> --repo org/repo", "wh component search research --repo myorg/myrepo");
|
|
31454
31820
|
}
|
|
31455
31821
|
const { org, repo } = parseOrgRepo(getRepoRef(ctx), ctx.config);
|
|
31456
|
-
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 });
|
|
31457
31824
|
const needle = query.toLowerCase();
|
|
31458
|
-
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
|
+
}
|
|
31459
31829
|
writeOutput(ctx, items, () => {
|
|
31460
|
-
const c = ctx.colors;
|
|
31461
31830
|
if (!items.length) {
|
|
31462
31831
|
ctx.status(`${c.dim}No components matching "${query}" in ${org}/${repo}${c.reset}`);
|
|
31463
31832
|
return;
|
|
@@ -33587,7 +33956,7 @@ cat wrefs.txt | wh thing view --format jsonl # one JSON line per *deduped
|
|
|
33587
33956
|
- \`wh thing history [wref] [--shape] [--about] [--include-retracted]\` — Version history
|
|
33588
33957
|
- \`wh thing resolve <wref>\` — Resolve wref
|
|
33589
33958
|
- \`wh thing create <name|Shape/name> --data <json> [--shape] [--message] [--committer]\` — Create
|
|
33590
|
-
- \`wh thing revise <name> [--data] [--message] [--committer]\` — Revise
|
|
33959
|
+
- \`wh thing revise <name> [--data] [--message] [--committer] [--expected-version]\` — Revise (CONFLICT if HEAD≠n)
|
|
33591
33960
|
- \`wh thing retract <wref> -m <message> [--reason] [--kind]\` — Retract
|
|
33592
33961
|
- \`wh thing query [--shape] [--kind] [--about] [--match]\` — Query by filters
|
|
33593
33962
|
- \`wh thing search <query> [--shape] [--kind] [--about] [--mode]\` — Search text
|
|
@@ -33596,7 +33965,7 @@ cat wrefs.txt | wh thing view --format jsonl # one JSON line per *deduped
|
|
|
33596
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
|
|
33597
33966
|
|
|
33598
33967
|
### commit — Write operations
|
|
33599
|
-
- \`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.
|
|
33600
33969
|
- \`wh shape template <shape> [shape2 ...] [--kind] [--operation add|revise|retract] [-o file]\` — Generate sample ops
|
|
33601
33970
|
|
|
33602
33971
|
### assertion — Assertion operations
|
|
@@ -33918,6 +34287,13 @@ var handleCreate5 = async (ctx, { flags, args }) => {
|
|
|
33918
34287
|
var repoListFlags = {
|
|
33919
34288
|
"include-archived": flag.boolean({
|
|
33920
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)"
|
|
33921
34297
|
})
|
|
33922
34298
|
};
|
|
33923
34299
|
var handleList5 = async (ctx, { flags, args }) => {
|
|
@@ -33926,16 +34302,36 @@ var handleList5 = async (ctx, { flags, args }) => {
|
|
|
33926
34302
|
usageError8("Usage: wh repo list <org> (or set WARMHUB_ORG)", "wh repo list myorg");
|
|
33927
34303
|
}
|
|
33928
34304
|
const c = ctx.colors;
|
|
33929
|
-
const
|
|
33930
|
-
|
|
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
|
|
33931
34311
|
});
|
|
33932
|
-
|
|
33933
|
-
|
|
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) {
|
|
33934
34330
|
ctx.status(`${c.dim}No repos in ${orgName}${c.reset}`);
|
|
33935
34331
|
return;
|
|
33936
34332
|
}
|
|
33937
34333
|
ctx.out(`${c.bold}Repos in ${orgName}:${c.reset}`);
|
|
33938
|
-
for (const r of
|
|
34334
|
+
for (const r of items) {
|
|
33939
34335
|
const display = r.displayName && r.displayName !== r.name ? ` ${c.dim}${r.displayName}${c.reset}` : "";
|
|
33940
34336
|
const desc = r.description ? ` ${c.dim}${r.description}${c.reset}` : "";
|
|
33941
34337
|
const archived = r.archivedAt ? ` ${c.yellow}[archived]${c.reset}` : "";
|
|
@@ -34365,6 +34761,8 @@ var handleContentSet = async (ctx, { args, flags }) => {
|
|
|
34365
34761
|
});
|
|
34366
34762
|
break;
|
|
34367
34763
|
}
|
|
34764
|
+
default:
|
|
34765
|
+
throw new CliError(2 /* UserInput */, "USER_INPUT", `--kind ${kind} does not support \`set\`.`);
|
|
34368
34766
|
}
|
|
34369
34767
|
};
|
|
34370
34768
|
var handleContentGenerate = async (ctx, { args, flags }) => {
|
|
@@ -34394,6 +34792,8 @@ var handleContentGenerate = async (ctx, { args, flags }) => {
|
|
|
34394
34792
|
});
|
|
34395
34793
|
break;
|
|
34396
34794
|
}
|
|
34795
|
+
default:
|
|
34796
|
+
throw new CliError(2 /* UserInput */, "USER_INPUT", `--kind ${kind} does not support \`generate\`.`);
|
|
34397
34797
|
}
|
|
34398
34798
|
};
|
|
34399
34799
|
var CONTENT_SUBDOMAIN = defineDomain({
|
|
@@ -34751,6 +35151,7 @@ var handleRetract2 = async (ctx, { flags, args }) => {
|
|
|
34751
35151
|
], { committer: flags.committer });
|
|
34752
35152
|
assertSingleOpSuccess(result);
|
|
34753
35153
|
writeOutput(ctx, result, () => {
|
|
35154
|
+
renderCommitterEcho(ctx.out, c, flags.committer);
|
|
34754
35155
|
ctx.out(`${c.red}Retracted${c.reset} ${c.magenta}${shapeName}${c.reset}`);
|
|
34755
35156
|
});
|
|
34756
35157
|
};
|
|
@@ -37180,7 +37581,7 @@ async function runCli(argv, opts) {
|
|
|
37180
37581
|
return exitCode;
|
|
37181
37582
|
}
|
|
37182
37583
|
if (globalHelpAllRequested) {
|
|
37183
|
-
printDomainHelp(out, { allFlags: true, allDomains: true });
|
|
37584
|
+
await printDomainHelp(out, { allFlags: true, allDomains: true });
|
|
37184
37585
|
exitCode = 0 /* Ok */;
|
|
37185
37586
|
return exitCode;
|
|
37186
37587
|
}
|
|
@@ -37332,7 +37733,7 @@ function resolveLogLevel(flags, env) {
|
|
|
37332
37733
|
// package.json
|
|
37333
37734
|
var package_default3 = {
|
|
37334
37735
|
name: "@warmhub/cli",
|
|
37335
|
-
version: "0.
|
|
37736
|
+
version: "0.49.0",
|
|
37336
37737
|
private: false,
|
|
37337
37738
|
type: "module",
|
|
37338
37739
|
description: "The wh CLI for WarmHub — create repos, commit and query data, and compound knowledge with your AI agents.",
|
|
@@ -37576,7 +37977,10 @@ async function maybeHandleComponentShellBoundary(argv, deps = {}) {
|
|
|
37576
37977
|
pathExists,
|
|
37577
37978
|
runGit,
|
|
37578
37979
|
installFromPath: installFromPathImpl,
|
|
37579
|
-
|
|
37980
|
+
resolveRegisteredInstall: resolveRegisteredInstallImpl,
|
|
37981
|
+
downloadRegisteredSource: downloadRegisteredSourceImpl,
|
|
37982
|
+
materializeComponentArchive: materializeComponentArchiveImpl,
|
|
37983
|
+
callRegisteredSetup: callRegisteredSetupImpl
|
|
37580
37984
|
});
|
|
37581
37985
|
} catch (error) {
|
|
37582
37986
|
return printCliError(toCliError2(error), writeErr, {
|
|
@@ -37649,13 +38053,33 @@ async function handleGithubInstall(args) {
|
|
|
37649
38053
|
}
|
|
37650
38054
|
async function handleRegisteredInstall(args) {
|
|
37651
38055
|
const parsedRepo = parseOrgRepo(args.repoFlag, args.config);
|
|
37652
|
-
|
|
38056
|
+
return performRegisteredInstall({
|
|
38057
|
+
componentRef: args.componentRef,
|
|
38058
|
+
refOverride: args.refOverride,
|
|
38059
|
+
verb: "Installed",
|
|
38060
|
+
client: args.client,
|
|
38061
|
+
parsedRepo,
|
|
38062
|
+
format: args.format,
|
|
38063
|
+
writeOut: args.writeOut,
|
|
38064
|
+
writeErr: args.writeErr,
|
|
38065
|
+
installFromPath: args.installFromPath,
|
|
38066
|
+
resolveRegisteredInstall: args.resolveRegisteredInstall,
|
|
38067
|
+
downloadRegisteredSource: args.downloadRegisteredSource,
|
|
38068
|
+
materializeComponentArchive: args.materializeComponentArchive,
|
|
38069
|
+
callRegisteredSetup: args.callRegisteredSetup
|
|
38070
|
+
});
|
|
38071
|
+
}
|
|
38072
|
+
async function performRegisteredInstall(args) {
|
|
38073
|
+
const installRepo = `${args.parsedRepo.org}/${args.parsedRepo.repo}`;
|
|
37653
38074
|
const resolved = await args.resolveRegisteredInstall({
|
|
37654
38075
|
componentRef: args.componentRef,
|
|
37655
38076
|
installRepo,
|
|
37656
38077
|
client: args.client
|
|
37657
38078
|
});
|
|
37658
|
-
const
|
|
38079
|
+
const persistedInstallId = readPersistedString(args.persistedInstallData, "installId");
|
|
38080
|
+
const persistedRef = readPersistedString(args.persistedInstallData, "sourceRef");
|
|
38081
|
+
const installId = persistedInstallId ?? resolved.installId;
|
|
38082
|
+
const ref = normalizeGitRef(args.refOverride ?? persistedRef ?? resolved.sourceDefaultRef ?? undefined);
|
|
37659
38083
|
const downloaded = await args.downloadRegisteredSource({
|
|
37660
38084
|
componentRef: args.componentRef,
|
|
37661
38085
|
installRepo,
|
|
@@ -37666,16 +38090,16 @@ async function handleRegisteredInstall(args) {
|
|
|
37666
38090
|
try {
|
|
37667
38091
|
const resolvedRef = ref ?? downloaded.sourceRef;
|
|
37668
38092
|
invalidateInstallSnapshotCache(installRepo);
|
|
37669
|
-
const result = await args.installFromPath(args.client, parsedRepo.org, parsedRepo.repo, extracted.componentDir, {
|
|
38093
|
+
const result = await args.installFromPath(args.client, args.parsedRepo.org, args.parsedRepo.repo, extracted.componentDir, {
|
|
37670
38094
|
githubUrl: downloaded.sourceUrl,
|
|
37671
38095
|
ref: resolvedRef,
|
|
37672
38096
|
resolvedSha: downloaded.resolvedSha ?? "",
|
|
37673
|
-
installId
|
|
38097
|
+
installId,
|
|
37674
38098
|
sourceKind: "registered",
|
|
37675
38099
|
registeredComponentRef: args.componentRef
|
|
37676
38100
|
});
|
|
37677
38101
|
if (!result.ok) {
|
|
37678
|
-
await writeInstallResult(args.writeOut, args.writeErr, args.format,
|
|
38102
|
+
await writeInstallResult(args.writeOut, args.writeErr, args.format, args.verb, result, installRepo, args.client);
|
|
37679
38103
|
return 1 /* Runtime */;
|
|
37680
38104
|
}
|
|
37681
38105
|
if (resolved.hasSetup) {
|
|
@@ -37684,7 +38108,7 @@ async function handleRegisteredInstall(args) {
|
|
|
37684
38108
|
setupResult = await args.callRegisteredSetup({
|
|
37685
38109
|
componentRef: args.componentRef,
|
|
37686
38110
|
installRepo,
|
|
37687
|
-
installId
|
|
38111
|
+
installId,
|
|
37688
38112
|
ref: resolvedRef,
|
|
37689
38113
|
resolvedSha: downloaded.resolvedSha,
|
|
37690
38114
|
client: args.client
|
|
@@ -37692,7 +38116,7 @@ async function handleRegisteredInstall(args) {
|
|
|
37692
38116
|
} catch (error) {
|
|
37693
38117
|
if (isMissingManifestPermissionError(error)) {
|
|
37694
38118
|
const backendCode = warmHubErrorBackendCode(error) ?? warmHubErrorKind(error);
|
|
37695
|
-
throw new CliError(2 /* UserInput */, "USER_INPUT", error.message, undefined,
|
|
38119
|
+
throw new CliError(2 /* UserInput */, "USER_INPUT", error.message, undefined, `Ask an org owner/admin to grant the missing permissions on the install repo, then re-run ${args.verb === "Installed" ? "install" : "update"}.`, undefined, backendCode);
|
|
37696
38120
|
}
|
|
37697
38121
|
throw error;
|
|
37698
38122
|
}
|
|
@@ -37700,12 +38124,16 @@ async function handleRegisteredInstall(args) {
|
|
|
37700
38124
|
throw new CliError(1 /* Runtime */, "BACKEND", `Component setup failed with status ${setupResult.status}${setupResult.body ? `: ${setupResult.body}` : ""}`);
|
|
37701
38125
|
}
|
|
37702
38126
|
}
|
|
37703
|
-
await writeInstallResult(args.writeOut, args.writeErr, args.format,
|
|
38127
|
+
await writeInstallResult(args.writeOut, args.writeErr, args.format, args.verb, result, installRepo, args.client);
|
|
37704
38128
|
return result.ok ? 0 /* Ok */ : 1 /* Runtime */;
|
|
37705
38129
|
} finally {
|
|
37706
38130
|
extracted.cleanup();
|
|
37707
38131
|
}
|
|
37708
38132
|
}
|
|
38133
|
+
function readPersistedString(data, key) {
|
|
38134
|
+
const value = data?.[key];
|
|
38135
|
+
return typeof value === "string" && value.length > 0 ? value : undefined;
|
|
38136
|
+
}
|
|
37709
38137
|
function isMissingManifestPermissionError(error) {
|
|
37710
38138
|
return warmHubErrorKind(error) === "FORBIDDEN" && error instanceof Error && error.message.startsWith("Cannot install: caller is missing repo permissions required by the manifest:");
|
|
37711
38139
|
}
|
|
@@ -37749,28 +38177,22 @@ async function handleGithubUpdate(args) {
|
|
|
37749
38177
|
throw new CliError(2 /* UserInput */, "USER_INPUT", `Component '${args.name}' is a bundled system component. Use 'wh component install ${source.componentId} --repo ${installRepo}' to update it.`);
|
|
37750
38178
|
}
|
|
37751
38179
|
if (source.kind === "registered") {
|
|
37752
|
-
|
|
37753
|
-
|
|
37754
|
-
|
|
37755
|
-
|
|
37756
|
-
|
|
38180
|
+
return performRegisteredInstall({
|
|
38181
|
+
componentRef: source.componentRef,
|
|
38182
|
+
refOverride: args.refOverride,
|
|
38183
|
+
persistedInstallData: installData,
|
|
38184
|
+
verb: "Updated",
|
|
38185
|
+
client: args.client,
|
|
38186
|
+
parsedRepo,
|
|
38187
|
+
format: args.format,
|
|
38188
|
+
writeOut: args.writeOut,
|
|
38189
|
+
writeErr: args.writeErr,
|
|
38190
|
+
installFromPath: args.installFromPath,
|
|
38191
|
+
resolveRegisteredInstall: args.resolveRegisteredInstall,
|
|
38192
|
+
downloadRegisteredSource: args.downloadRegisteredSource,
|
|
38193
|
+
materializeComponentArchive: args.materializeComponentArchive,
|
|
38194
|
+
callRegisteredSetup: args.callRegisteredSetup
|
|
37757
38195
|
});
|
|
37758
|
-
const extracted = args.materializeComponentArchive(downloaded.archive, downloaded.componentRef, source.ref ?? downloaded.sourceRef);
|
|
37759
|
-
try {
|
|
37760
|
-
const updateRef2 = source.ref ?? downloaded.sourceRef;
|
|
37761
|
-
invalidateInstallSnapshotCache(installRepo2);
|
|
37762
|
-
const result2 = await args.installFromPath(args.client, parsedRepo.org, parsedRepo.repo, extracted.componentDir, {
|
|
37763
|
-
githubUrl: downloaded.sourceUrl,
|
|
37764
|
-
ref: updateRef2,
|
|
37765
|
-
resolvedSha: downloaded.resolvedSha ?? "",
|
|
37766
|
-
sourceKind: "registered",
|
|
37767
|
-
registeredComponentRef: source.componentRef
|
|
37768
|
-
});
|
|
37769
|
-
await writeInstallResult(args.writeOut, args.writeErr, args.format, "Updated", result2, installRepo2, args.client);
|
|
37770
|
-
return result2.ok ? 0 /* Ok */ : 1 /* Runtime */;
|
|
37771
|
-
} finally {
|
|
37772
|
-
extracted.cleanup();
|
|
37773
|
-
}
|
|
37774
38196
|
}
|
|
37775
38197
|
const componentDir = args.getComponentPath(`${source.owner}--${source.repo}`);
|
|
37776
38198
|
args.ensureCacheDir();
|
|
@@ -38338,4 +38760,4 @@ if (!updateCheckSuppressedByArgv && shouldRunUpdateCheck(updateEligibility)) {
|
|
|
38338
38760
|
var interceptedExitCode = await maybeHandleComponentShellBoundary(dispatchArgv);
|
|
38339
38761
|
process.exitCode = interceptedExitCode === undefined ? await runCli(dispatchArgv, { version: package_default3.version }) : interceptedExitCode;
|
|
38340
38762
|
|
|
38341
|
-
//# debugId=
|
|
38763
|
+
//# debugId=7BEE2CF049FB035564756E2164756E21
|
package/package.json
CHANGED