@warmhub/cli 0.63.0 → 0.65.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 +350 -85
- package/package.json +2 -1
package/dist/wh.js
CHANGED
|
@@ -18731,7 +18731,7 @@ function defaultMatchesCliArgType(type, value) {
|
|
|
18731
18731
|
}
|
|
18732
18732
|
function compileCliArgPattern(pattern) {
|
|
18733
18733
|
try {
|
|
18734
|
-
return new RegExp(pattern);
|
|
18734
|
+
return new RegExp(`^(?:${pattern})$`);
|
|
18735
18735
|
} catch {
|
|
18736
18736
|
return;
|
|
18737
18737
|
}
|
|
@@ -27353,7 +27353,7 @@ function findSystemComponent(componentId) {
|
|
|
27353
27353
|
// ../../packages/sdk-ts/package.json
|
|
27354
27354
|
var package_default = {
|
|
27355
27355
|
name: "@warmhub/sdk-ts",
|
|
27356
|
-
version: "0.
|
|
27356
|
+
version: "0.64.0",
|
|
27357
27357
|
private: false,
|
|
27358
27358
|
type: "module",
|
|
27359
27359
|
description: "The TypeScript SDK for WarmHub — create repos, commit and query data, and compound knowledge with your AI agents.",
|
|
@@ -27403,8 +27403,7 @@ var package_default = {
|
|
|
27403
27403
|
}
|
|
27404
27404
|
},
|
|
27405
27405
|
scripts: {
|
|
27406
|
-
|
|
27407
|
-
build: "tsup && bun run scripts/inject-doc-links.ts",
|
|
27406
|
+
build: "tsc --noEmit && tsup && bun run scripts/inject-doc-links.ts",
|
|
27408
27407
|
"generate:api-contract": "bun run scripts/generate-api-contract.ts",
|
|
27409
27408
|
"generate:backend-types": "bun run scripts/generate-backend-types.ts",
|
|
27410
27409
|
"audit:api-contract": "bun run scripts/audit-api-contract.ts",
|
|
@@ -28352,6 +28351,15 @@ class WarmHubClient {
|
|
|
28352
28351
|
}
|
|
28353
28352
|
}
|
|
28354
28353
|
};
|
|
28354
|
+
homepage = {
|
|
28355
|
+
featuredLists: async () => {
|
|
28356
|
+
try {
|
|
28357
|
+
return await this.trpc.homepage.featuredLists.query();
|
|
28358
|
+
} catch (error) {
|
|
28359
|
+
throw toWarmHubError(error);
|
|
28360
|
+
}
|
|
28361
|
+
}
|
|
28362
|
+
};
|
|
28355
28363
|
access = {
|
|
28356
28364
|
resolve: async (input) => {
|
|
28357
28365
|
try {
|
|
@@ -29194,24 +29202,26 @@ class WarmHubClient {
|
|
|
29194
29202
|
throw toWarmHubError(error);
|
|
29195
29203
|
}
|
|
29196
29204
|
},
|
|
29197
|
-
claimDelivery: async (orgName, repoName,
|
|
29205
|
+
claimDelivery: async (orgName, repoName, target, holderId) => {
|
|
29206
|
+
const deliveryTarget = typeof target === "string" ? { runId: target } : target;
|
|
29198
29207
|
try {
|
|
29199
29208
|
return await this.trpc.action.claimDelivery.mutate({
|
|
29200
29209
|
orgName,
|
|
29201
29210
|
repoName,
|
|
29202
|
-
|
|
29211
|
+
...deliveryTarget,
|
|
29203
29212
|
holderId
|
|
29204
29213
|
});
|
|
29205
29214
|
} catch (error) {
|
|
29206
29215
|
throw toWarmHubError(error);
|
|
29207
29216
|
}
|
|
29208
29217
|
},
|
|
29209
|
-
completeDelivery: async (orgName, repoName,
|
|
29218
|
+
completeDelivery: async (orgName, repoName, target, holderId) => {
|
|
29219
|
+
const deliveryTarget = typeof target === "string" ? { runId: target } : target;
|
|
29210
29220
|
try {
|
|
29211
29221
|
return await this.trpc.action.completeDelivery.mutate({
|
|
29212
29222
|
orgName,
|
|
29213
29223
|
repoName,
|
|
29214
|
-
|
|
29224
|
+
...deliveryTarget,
|
|
29215
29225
|
holderId
|
|
29216
29226
|
});
|
|
29217
29227
|
} catch (error) {
|
|
@@ -30572,11 +30582,25 @@ function safeParseJson(input, label, options) {
|
|
|
30572
30582
|
function parseJsonObject(input, label, options) {
|
|
30573
30583
|
const parsed = safeParseJson(input, label, options);
|
|
30574
30584
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
30575
|
-
const got =
|
|
30585
|
+
const got = describeJsonType(parsed);
|
|
30576
30586
|
throw new CliError(2 /* UserInput */, "USER_INPUT", `${label} must be a JSON object, got ${got}`, undefined, `Pass an object, e.g. '{"key":"value"}'.`);
|
|
30577
30587
|
}
|
|
30578
30588
|
return parsed;
|
|
30579
30589
|
}
|
|
30590
|
+
function parseJsonArray(input, label, options) {
|
|
30591
|
+
const parsed = safeParseJson(input, label, options);
|
|
30592
|
+
if (!Array.isArray(parsed)) {
|
|
30593
|
+
throw new CliError(2 /* UserInput */, "USER_INPUT", `${label} must be a JSON array, got ${describeJsonType(parsed)}`, undefined, `Pass an array of operations, e.g. '[{"operation":"add","kind":"thing","name":"Shape/item","data":{}}]'.`);
|
|
30594
|
+
}
|
|
30595
|
+
return parsed;
|
|
30596
|
+
}
|
|
30597
|
+
function describeJsonType(value) {
|
|
30598
|
+
if (Array.isArray(value))
|
|
30599
|
+
return "array";
|
|
30600
|
+
if (value === null)
|
|
30601
|
+
return "null";
|
|
30602
|
+
return typeof value;
|
|
30603
|
+
}
|
|
30580
30604
|
function parsePositiveIntFlag(value, label, example) {
|
|
30581
30605
|
if (value !== undefined && (!Number.isInteger(value) || value < 1)) {
|
|
30582
30606
|
usageError(`${label} must be a positive integer`, example);
|
|
@@ -32352,7 +32376,7 @@ class DomainRegistry {
|
|
|
32352
32376
|
}
|
|
32353
32377
|
const verbs = {};
|
|
32354
32378
|
for (const [verbName, v] of Object.entries(def.verbs)) {
|
|
32355
|
-
|
|
32379
|
+
const verbSpec = {
|
|
32356
32380
|
status: v.status ?? "live",
|
|
32357
32381
|
prime: v.prime ?? false,
|
|
32358
32382
|
summary: v.summary,
|
|
@@ -32363,6 +32387,13 @@ class DomainRegistry {
|
|
|
32363
32387
|
verbAliases: v.verbAliases,
|
|
32364
32388
|
passthroughFlags: v.passthroughFlags
|
|
32365
32389
|
};
|
|
32390
|
+
if (v.rejectedFlags) {
|
|
32391
|
+
Object.defineProperty(verbSpec, "rejectedFlags", {
|
|
32392
|
+
value: v.rejectedFlags,
|
|
32393
|
+
enumerable: false
|
|
32394
|
+
});
|
|
32395
|
+
}
|
|
32396
|
+
verbs[verbName] = verbSpec;
|
|
32366
32397
|
}
|
|
32367
32398
|
const subdomains = def.subdomains ? Object.fromEntries(Object.entries(def.subdomains).map(([k, sd]) => [
|
|
32368
32399
|
k,
|
|
@@ -32662,20 +32693,88 @@ function extractShapeName(name) {
|
|
|
32662
32693
|
const slash = name.indexOf("/");
|
|
32663
32694
|
return slash > 0 ? name.slice(0, slash) : "";
|
|
32664
32695
|
}
|
|
32696
|
+
var DANGEROUS_TERMINAL_FORMAT_CODEPOINTS = new Set([
|
|
32697
|
+
8203,
|
|
32698
|
+
8204,
|
|
32699
|
+
8205,
|
|
32700
|
+
8288,
|
|
32701
|
+
8294,
|
|
32702
|
+
8295,
|
|
32703
|
+
8296,
|
|
32704
|
+
8297,
|
|
32705
|
+
8234,
|
|
32706
|
+
8235,
|
|
32707
|
+
8236,
|
|
32708
|
+
8237,
|
|
32709
|
+
8238,
|
|
32710
|
+
8232,
|
|
32711
|
+
8233
|
|
32712
|
+
]);
|
|
32713
|
+
function isTerminalControlCodePoint(codePoint) {
|
|
32714
|
+
return codePoint <= 31 || codePoint === 127 || codePoint >= 128 && codePoint <= 159;
|
|
32715
|
+
}
|
|
32716
|
+
function escapeTerminalCodePoint(codePoint) {
|
|
32717
|
+
return codePoint <= 65535 ? `\\u${codePoint.toString(16).padStart(4, "0")}` : `\\u{${codePoint.toString(16)}}`;
|
|
32718
|
+
}
|
|
32719
|
+
function terminalTextNeedsEscape(value) {
|
|
32720
|
+
for (const char of value) {
|
|
32721
|
+
const codePoint = char.codePointAt(0);
|
|
32722
|
+
if (codePoint === undefined)
|
|
32723
|
+
continue;
|
|
32724
|
+
if (isTerminalControlCodePoint(codePoint))
|
|
32725
|
+
return true;
|
|
32726
|
+
if (DANGEROUS_TERMINAL_FORMAT_CODEPOINTS.has(codePoint))
|
|
32727
|
+
return true;
|
|
32728
|
+
}
|
|
32729
|
+
return false;
|
|
32730
|
+
}
|
|
32731
|
+
function escapeTerminalTextForDisplay(value) {
|
|
32732
|
+
if (!terminalTextNeedsEscape(value))
|
|
32733
|
+
return value;
|
|
32734
|
+
const jsonEscaped = JSON.stringify(value).slice(1, -1);
|
|
32735
|
+
let output = "";
|
|
32736
|
+
for (const char of jsonEscaped) {
|
|
32737
|
+
const codePoint = char.codePointAt(0);
|
|
32738
|
+
if (codePoint === undefined)
|
|
32739
|
+
continue;
|
|
32740
|
+
output += isTerminalControlCodePoint(codePoint) || DANGEROUS_TERMINAL_FORMAT_CODEPOINTS.has(codePoint) ? escapeTerminalCodePoint(codePoint) : char;
|
|
32741
|
+
}
|
|
32742
|
+
return output;
|
|
32743
|
+
}
|
|
32665
32744
|
var escapeInlineTerminalText = escapeFieldNameForDisplay;
|
|
32666
32745
|
function renderWarningLine(out, c, chars, op) {
|
|
32667
32746
|
const warnings = op.warnings;
|
|
32668
|
-
if (!warnings
|
|
32747
|
+
if (!warnings)
|
|
32669
32748
|
return;
|
|
32670
|
-
|
|
32671
|
-
|
|
32749
|
+
renderUndeclaredFieldsWarning(out, c, chars, op.name, warnings);
|
|
32750
|
+
renderCoalescedWrefsWarning(out, c, chars, warnings);
|
|
32751
|
+
}
|
|
32752
|
+
function renderUndeclaredFieldsWarning(out, c, chars, opName, warnings) {
|
|
32753
|
+
const undeclaredFields = warnings.undeclaredFields;
|
|
32754
|
+
if (!undeclaredFields || undeclaredFields.length === 0)
|
|
32755
|
+
return;
|
|
32756
|
+
const shapeName = extractShapeName(opName);
|
|
32757
|
+
const total = warnings.totalUndeclared ?? undeclaredFields.length;
|
|
32672
32758
|
const noun = total === 1 ? "field" : "fields";
|
|
32673
32759
|
const shapeLabel = shapeName ? ` ${shapeName}` : "";
|
|
32674
|
-
const remaining = warnings.undeclaredFieldsTruncated ? total -
|
|
32675
|
-
const fieldsList =
|
|
32760
|
+
const remaining = warnings.undeclaredFieldsTruncated ? total - undeclaredFields.length : 0;
|
|
32761
|
+
const fieldsList = undeclaredFields.map(escapeInlineTerminalText).join(", ");
|
|
32676
32762
|
const moreSuffix = remaining > 0 ? ` ${c.dim}(+${remaining} more)${c.reset}` : "";
|
|
32677
32763
|
out(` ${c.yellow}${chars.warn}${c.reset} ${total} ${noun} not declared in shape${shapeLabel}: ${c.dim}${fieldsList}${c.reset}${moreSuffix}`);
|
|
32678
32764
|
}
|
|
32765
|
+
function renderCoalescedWrefsWarning(out, c, chars, warnings) {
|
|
32766
|
+
const coalescedWrefs = warnings.coalescedWrefs;
|
|
32767
|
+
if (!coalescedWrefs || coalescedWrefs.length === 0)
|
|
32768
|
+
return;
|
|
32769
|
+
for (const entry of coalescedWrefs) {
|
|
32770
|
+
out(` ${c.yellow}${chars.warn}${c.reset} coalesced wref ${escapeInlineTerminalText(entry.fieldPath)}: ${c.dim}${escapeInlineTerminalText(entry.wref)}${c.reset} (${escapeInlineTerminalText(entry.reason)})`);
|
|
32771
|
+
}
|
|
32772
|
+
const total = warnings.totalCoalescedWrefs ?? coalescedWrefs.length;
|
|
32773
|
+
const remaining = warnings.coalescedWrefsTruncated ? total - coalescedWrefs.length : 0;
|
|
32774
|
+
if (remaining > 0) {
|
|
32775
|
+
out(` ${c.dim}(+${remaining} more coalesced wrefs)${c.reset}`);
|
|
32776
|
+
}
|
|
32777
|
+
}
|
|
32679
32778
|
function renderCommitterEcho(out, c, committer) {
|
|
32680
32779
|
if (!committer)
|
|
32681
32780
|
return;
|
|
@@ -34269,10 +34368,10 @@ var searchFlags = {
|
|
|
34269
34368
|
cursor: flag.string({ description: "Opaque pagination cursor (text mode)" }),
|
|
34270
34369
|
all: flag.boolean({ description: "Fetch all pages (text mode)" }),
|
|
34271
34370
|
component: flag.string({
|
|
34272
|
-
description: "Filter to things owned by this component (Org/Name ref)"
|
|
34371
|
+
description: "Filter to things owned by this component (Org/Name ref, text mode)"
|
|
34273
34372
|
}),
|
|
34274
34373
|
"exclude-components": flag.boolean({
|
|
34275
|
-
description: "Exclude component-owned things from results"
|
|
34374
|
+
description: "Exclude component-owned things from results (text mode)"
|
|
34276
34375
|
})
|
|
34277
34376
|
};
|
|
34278
34377
|
var handleSearch = async (ctx, { flags, args }) => {
|
|
@@ -34306,10 +34405,14 @@ var handleSearch = async (ctx, { flags, args }) => {
|
|
|
34306
34405
|
const pageLimit = all ? Math.min(limit ?? AUTO_PAGE_LIMIT, MAX_PAGE_LIMIT) : boundedTextLimit;
|
|
34307
34406
|
const resolveCollections = mode !== "hybrid" ? flags["resolve-collections"] : undefined;
|
|
34308
34407
|
const supportsComponentFilters = !mode || mode === "text";
|
|
34309
|
-
const componentRef = supportsComponentFilters ? flags.component : undefined;
|
|
34310
34408
|
const hasShape = !!flags.shape;
|
|
34311
|
-
const
|
|
34312
|
-
|
|
34409
|
+
const hasComponentFilter = flags.component !== undefined;
|
|
34410
|
+
const strictExclude = !!flags["exclude-components"];
|
|
34411
|
+
validateComponentFilters(flags.component, strictExclude, 'wh thing search "policy" --component acme/veritas');
|
|
34412
|
+
if (!supportsComponentFilters && (hasComponentFilter || strictExclude)) {
|
|
34413
|
+
usageError("--component/--exclude-components are only supported with text search mode.", 'wh thing search "policy" --mode text --component acme/veritas');
|
|
34414
|
+
}
|
|
34415
|
+
const componentRef = supportsComponentFilters ? flags.component : undefined;
|
|
34313
34416
|
const excludeComponents = supportsComponentFilters && strictExclude ? true : undefined;
|
|
34314
34417
|
const excludeInfraShapes = supportsComponentFilters && !strictExclude && !hasShape ? true : undefined;
|
|
34315
34418
|
const rawResult = all ? await fetchAllSearchPages(ctx, org, repo, queryText, {
|
|
@@ -36060,7 +36163,7 @@ var HEADER_DELIMITER = `\r
|
|
|
36060
36163
|
`;
|
|
36061
36164
|
var CONTENT_LENGTH_RE = /^Content-Length:\s*(\d+)$/im;
|
|
36062
36165
|
var MAX_MESSAGE_BYTES = 64 * 1024 * 1024;
|
|
36063
|
-
function parseFramedMessage(buffer, maxContentLength = MAX_MESSAGE_BYTES) {
|
|
36166
|
+
function parseFramedMessage(buffer, maxContentLength = MAX_MESSAGE_BYTES, bufferByteLength) {
|
|
36064
36167
|
const headerEnd = buffer.indexOf(HEADER_DELIMITER);
|
|
36065
36168
|
if (headerEnd === -1)
|
|
36066
36169
|
return null;
|
|
@@ -36073,11 +36176,36 @@ function parseFramedMessage(buffer, maxContentLength = MAX_MESSAGE_BYTES) {
|
|
|
36073
36176
|
throw new RangeError(`Content-Length ${contentLength} exceeds the maximum allowed ${maxContentLength} bytes`);
|
|
36074
36177
|
}
|
|
36075
36178
|
const bodyStart = headerEnd + HEADER_DELIMITER.length;
|
|
36076
|
-
const
|
|
36077
|
-
|
|
36179
|
+
const bodyStartBytes = Buffer.byteLength(buffer.slice(0, bodyStart), "utf8");
|
|
36180
|
+
const totalBytes = bufferByteLength ?? Buffer.byteLength(buffer, "utf8");
|
|
36181
|
+
if (totalBytes - bodyStartBytes < contentLength)
|
|
36078
36182
|
return null;
|
|
36079
|
-
const
|
|
36080
|
-
|
|
36183
|
+
const bodyEnd = findUtf8ByteBoundary(buffer, bodyStart, contentLength);
|
|
36184
|
+
if (bodyEnd === null)
|
|
36185
|
+
return null;
|
|
36186
|
+
const body = buffer.slice(bodyStart, bodyEnd);
|
|
36187
|
+
return { message: JSON.parse(body), consumed: bodyEnd };
|
|
36188
|
+
}
|
|
36189
|
+
function findUtf8ByteBoundary(value, start, targetBytes) {
|
|
36190
|
+
let bytes = 0;
|
|
36191
|
+
let index = start;
|
|
36192
|
+
while (index < value.length && bytes < targetBytes) {
|
|
36193
|
+
const codePoint = value.codePointAt(index);
|
|
36194
|
+
if (codePoint === undefined)
|
|
36195
|
+
return null;
|
|
36196
|
+
bytes += utf8CodePointByteLength(codePoint);
|
|
36197
|
+
index += codePoint > 65535 ? 2 : 1;
|
|
36198
|
+
}
|
|
36199
|
+
return bytes === targetBytes ? index : null;
|
|
36200
|
+
}
|
|
36201
|
+
function utf8CodePointByteLength(codePoint) {
|
|
36202
|
+
if (codePoint <= 127)
|
|
36203
|
+
return 1;
|
|
36204
|
+
if (codePoint <= 2047)
|
|
36205
|
+
return 2;
|
|
36206
|
+
if (codePoint <= 65535)
|
|
36207
|
+
return 3;
|
|
36208
|
+
return 4;
|
|
36081
36209
|
}
|
|
36082
36210
|
function parseNdjsonMessage(buffer) {
|
|
36083
36211
|
const newlineIdx = buffer.indexOf(`
|
|
@@ -36125,7 +36253,7 @@ function createMessageReader(input, onMessage, onError = () => {}, maxMessageByt
|
|
|
36125
36253
|
}
|
|
36126
36254
|
let result;
|
|
36127
36255
|
try {
|
|
36128
|
-
result = mode === "ndjson" ? parseNdjsonMessage(buffer) : parseFramedMessage(buffer, maxMessageBytes);
|
|
36256
|
+
result = mode === "ndjson" ? parseNdjsonMessage(buffer) : parseFramedMessage(buffer, maxMessageBytes, bufferBytes);
|
|
36129
36257
|
} catch (err) {
|
|
36130
36258
|
if (err instanceof RangeError) {
|
|
36131
36259
|
onError(err);
|
|
@@ -36187,27 +36315,47 @@ function createMessageReader(input, onMessage, onError = () => {}, maxMessageByt
|
|
|
36187
36315
|
var MCP_PROTOCOL_VERSION2 = "2025-11-25";
|
|
36188
36316
|
function createChannelServer(opts) {
|
|
36189
36317
|
let reader = null;
|
|
36318
|
+
let removeInputCloseListeners = () => {};
|
|
36190
36319
|
let resolveReady;
|
|
36191
36320
|
let rejectReady;
|
|
36192
36321
|
let readySettled = false;
|
|
36322
|
+
let resolveClosed;
|
|
36323
|
+
let closedSettled = false;
|
|
36193
36324
|
const onReady = new Promise((resolve, reject) => {
|
|
36194
36325
|
resolveReady = resolve;
|
|
36195
36326
|
rejectReady = reject;
|
|
36196
36327
|
});
|
|
36328
|
+
const onClosed = new Promise((resolve) => {
|
|
36329
|
+
resolveClosed = resolve;
|
|
36330
|
+
});
|
|
36197
36331
|
function settleReady() {
|
|
36198
36332
|
if (readySettled)
|
|
36199
36333
|
return;
|
|
36200
36334
|
readySettled = true;
|
|
36201
36335
|
resolveReady();
|
|
36202
36336
|
}
|
|
36203
|
-
function
|
|
36204
|
-
if (
|
|
36337
|
+
function settleClosed() {
|
|
36338
|
+
if (closedSettled)
|
|
36205
36339
|
return;
|
|
36206
|
-
|
|
36340
|
+
closedSettled = true;
|
|
36341
|
+
removeInputCloseListeners();
|
|
36207
36342
|
reader?.close();
|
|
36208
|
-
|
|
36343
|
+
resolveClosed();
|
|
36344
|
+
}
|
|
36345
|
+
function closeServer() {
|
|
36346
|
+
settleClosed();
|
|
36347
|
+
settleReady();
|
|
36348
|
+
}
|
|
36349
|
+
function failReady(error) {
|
|
36350
|
+
if (!readySettled) {
|
|
36351
|
+
readySettled = true;
|
|
36352
|
+
rejectReady(error);
|
|
36353
|
+
}
|
|
36354
|
+
settleClosed();
|
|
36209
36355
|
}
|
|
36210
36356
|
function send(msg) {
|
|
36357
|
+
if (closedSettled)
|
|
36358
|
+
return;
|
|
36211
36359
|
opts.output.write(ndjsonMessage(msg));
|
|
36212
36360
|
}
|
|
36213
36361
|
function handleMessage(msg) {
|
|
@@ -36246,6 +36394,13 @@ function createChannelServer(opts) {
|
|
|
36246
36394
|
}
|
|
36247
36395
|
return {
|
|
36248
36396
|
start() {
|
|
36397
|
+
const handleInputClose = () => closeServer();
|
|
36398
|
+
opts.input.on("end", handleInputClose);
|
|
36399
|
+
opts.input.on("close", handleInputClose);
|
|
36400
|
+
removeInputCloseListeners = () => {
|
|
36401
|
+
opts.input.removeListener("end", handleInputClose);
|
|
36402
|
+
opts.input.removeListener("close", handleInputClose);
|
|
36403
|
+
};
|
|
36249
36404
|
reader = createMessageReader(opts.input, handleMessage, failReady);
|
|
36250
36405
|
},
|
|
36251
36406
|
notify(content, meta) {
|
|
@@ -36256,14 +36411,15 @@ function createChannelServer(opts) {
|
|
|
36256
36411
|
});
|
|
36257
36412
|
},
|
|
36258
36413
|
onReady,
|
|
36414
|
+
onClosed,
|
|
36259
36415
|
close() {
|
|
36260
|
-
|
|
36261
|
-
settleReady();
|
|
36416
|
+
closeServer();
|
|
36262
36417
|
}
|
|
36263
36418
|
};
|
|
36264
36419
|
}
|
|
36265
36420
|
|
|
36266
36421
|
// ../../packages/warmhub-cli/src/domains/channel.ts
|
|
36422
|
+
var RECONNECT_DELAY_MS = 2000;
|
|
36267
36423
|
function formatChannelEvent(org, repo, event) {
|
|
36268
36424
|
const things = event.affectedThings.join(", ");
|
|
36269
36425
|
const shapes = event.affectedShapes.join(",");
|
|
@@ -36280,6 +36436,22 @@ function formatChannelEvent(org, repo, event) {
|
|
|
36280
36436
|
};
|
|
36281
36437
|
}
|
|
36282
36438
|
async function subscribeLoop(client, org, repo, signal, server) {
|
|
36439
|
+
const pauseBeforeReconnect = () => new Promise((resolve) => {
|
|
36440
|
+
if (signal.aborted) {
|
|
36441
|
+
resolve();
|
|
36442
|
+
return;
|
|
36443
|
+
}
|
|
36444
|
+
let timeout;
|
|
36445
|
+
const onAbort = () => {
|
|
36446
|
+
clearTimeout(timeout);
|
|
36447
|
+
resolve();
|
|
36448
|
+
};
|
|
36449
|
+
timeout = setTimeout(() => {
|
|
36450
|
+
signal.removeEventListener("abort", onAbort);
|
|
36451
|
+
resolve();
|
|
36452
|
+
}, RECONNECT_DELAY_MS);
|
|
36453
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
36454
|
+
});
|
|
36283
36455
|
while (!signal.aborted) {
|
|
36284
36456
|
try {
|
|
36285
36457
|
const handle = await client.live.subscribe(org, repo, { signal }, (event) => {
|
|
@@ -36287,6 +36459,8 @@ async function subscribeLoop(client, org, repo, signal, server) {
|
|
|
36287
36459
|
server.notify(content, meta);
|
|
36288
36460
|
});
|
|
36289
36461
|
await handle.closed;
|
|
36462
|
+
if (!signal.aborted)
|
|
36463
|
+
await pauseBeforeReconnect();
|
|
36290
36464
|
} catch (err) {
|
|
36291
36465
|
if (signal.aborted)
|
|
36292
36466
|
break;
|
|
@@ -36294,7 +36468,7 @@ async function subscribeLoop(client, org, repo, signal, server) {
|
|
|
36294
36468
|
if (msg.includes("401") || msg.includes("403") || msg.includes("404") || msg.includes("AUTH") || msg.includes("not found") || msg.includes("Session expired")) {
|
|
36295
36469
|
throw new Error(`${org}/${repo}: ${msg}`);
|
|
36296
36470
|
}
|
|
36297
|
-
await
|
|
36471
|
+
await pauseBeforeReconnect();
|
|
36298
36472
|
}
|
|
36299
36473
|
}
|
|
36300
36474
|
}
|
|
@@ -36313,7 +36487,6 @@ var handleChannel = async (ctx) => {
|
|
|
36313
36487
|
input: process.stdin,
|
|
36314
36488
|
output: process.stdout
|
|
36315
36489
|
});
|
|
36316
|
-
server.start();
|
|
36317
36490
|
const signal = ctx.signal ?? new AbortController().signal;
|
|
36318
36491
|
const aborted = new Promise((resolve) => {
|
|
36319
36492
|
if (signal.aborted)
|
|
@@ -36323,15 +36496,19 @@ var handleChannel = async (ctx) => {
|
|
|
36323
36496
|
});
|
|
36324
36497
|
let ready;
|
|
36325
36498
|
try {
|
|
36326
|
-
|
|
36327
|
-
|
|
36328
|
-
|
|
36499
|
+
const startup = Promise.race([
|
|
36500
|
+
server.onClosed.then(() => "closed"),
|
|
36501
|
+
server.onReady.then(() => "ready"),
|
|
36502
|
+
aborted
|
|
36503
|
+
]);
|
|
36504
|
+
server.start();
|
|
36505
|
+
ready = await startup;
|
|
36329
36506
|
} catch (err) {
|
|
36330
36507
|
server.close();
|
|
36331
36508
|
const msg = err instanceof Error ? err.message : String(err);
|
|
36332
36509
|
throw new CliError(4 /* Backend */, "BACKEND", `channel startup failed: ${msg}`);
|
|
36333
36510
|
}
|
|
36334
|
-
if (ready
|
|
36511
|
+
if (ready !== "ready") {
|
|
36335
36512
|
server.close();
|
|
36336
36513
|
return;
|
|
36337
36514
|
}
|
|
@@ -36342,7 +36519,11 @@ var handleChannel = async (ctx) => {
|
|
|
36342
36519
|
signal.addEventListener("abort", () => controller.abort(), { once: true });
|
|
36343
36520
|
let fatal;
|
|
36344
36521
|
try {
|
|
36345
|
-
|
|
36522
|
+
const subscriptions = Promise.all(repos.map(({ org, repo }) => subscribeLoop(ctx.client, org, repo, controller.signal, server)));
|
|
36523
|
+
const closed = server.onClosed.then(() => {
|
|
36524
|
+
controller.abort();
|
|
36525
|
+
});
|
|
36526
|
+
await Promise.race([subscriptions, closed]);
|
|
36346
36527
|
} catch (err) {
|
|
36347
36528
|
controller.abort();
|
|
36348
36529
|
fatal = err;
|
|
@@ -36373,7 +36554,7 @@ var CHANNEL_DOMAIN = defineDomain({
|
|
|
36373
36554
|
// ../../packages/warmhub-cli/src/domains/commit-submit-flags.ts
|
|
36374
36555
|
var createFlags3 = {
|
|
36375
36556
|
ops: flag.string({
|
|
36376
|
-
description: "Operations JSON (inline). For ops from a file, use -f/--file <path> instead; --ops accepts inline JSON only."
|
|
36557
|
+
description: "Operations JSON array (inline). For ops from a file, use -f/--file <path> instead; --ops accepts an inline JSON array only."
|
|
36377
36558
|
}),
|
|
36378
36559
|
file: flag.string({
|
|
36379
36560
|
short: "f",
|
|
@@ -37461,7 +37642,7 @@ var handleSubmit = async (ctx, { flags, args }) => {
|
|
|
37461
37642
|
}
|
|
37462
37643
|
];
|
|
37463
37644
|
} else if (opsJson) {
|
|
37464
|
-
operations =
|
|
37645
|
+
operations = parseJsonArray(opsJson, "--ops", {
|
|
37465
37646
|
fileFlagSibling: "-f/--file"
|
|
37466
37647
|
});
|
|
37467
37648
|
} else if (opsFile) {
|
|
@@ -37474,7 +37655,7 @@ var handleSubmit = async (ctx, { flags, args }) => {
|
|
|
37474
37655
|
} catch (e) {
|
|
37475
37656
|
throw new CliError(2 /* UserInput */, "USER_INPUT", `Cannot read file '${opsFile}': ${e instanceof Error ? e.message : String(e)}`, undefined, "Check that the file path is correct and the file exists.");
|
|
37476
37657
|
}
|
|
37477
|
-
operations =
|
|
37658
|
+
operations = parseJsonArray(file, "--file contents");
|
|
37478
37659
|
}
|
|
37479
37660
|
} else if (addNames.length > 0) {
|
|
37480
37661
|
operations = buildAddOperations({
|
|
@@ -37721,6 +37902,24 @@ function isInstallSnapshotCacheShape(value) {
|
|
|
37721
37902
|
if (!Array.isArray(component.methods))
|
|
37722
37903
|
return false;
|
|
37723
37904
|
}
|
|
37905
|
+
if (!isPlainObject2(value.installs))
|
|
37906
|
+
return false;
|
|
37907
|
+
const installs = value.installs;
|
|
37908
|
+
for (const entry of Object.values(installs)) {
|
|
37909
|
+
if (!isPlainObject2(entry))
|
|
37910
|
+
return false;
|
|
37911
|
+
const install = entry;
|
|
37912
|
+
if (typeof install.ref !== "string")
|
|
37913
|
+
return false;
|
|
37914
|
+
if (typeof install.version !== "string")
|
|
37915
|
+
return false;
|
|
37916
|
+
if (install.latestVersion !== undefined && typeof install.latestVersion !== "string") {
|
|
37917
|
+
return false;
|
|
37918
|
+
}
|
|
37919
|
+
if (install.updateAvailable !== undefined && typeof install.updateAvailable !== "boolean") {
|
|
37920
|
+
return false;
|
|
37921
|
+
}
|
|
37922
|
+
}
|
|
37724
37923
|
return true;
|
|
37725
37924
|
}
|
|
37726
37925
|
|
|
@@ -37794,6 +37993,7 @@ async function refreshInstallSnapshotCache(repoSlug, client, opts) {
|
|
|
37794
37993
|
}
|
|
37795
37994
|
async function refreshFromSummaries(repoSlug, parsed, activeItems, client, now, previousCache) {
|
|
37796
37995
|
const components = {};
|
|
37996
|
+
const installs = {};
|
|
37797
37997
|
let detailReadFailures = 0;
|
|
37798
37998
|
for (const item of activeItems) {
|
|
37799
37999
|
if (!item.ref)
|
|
@@ -37813,6 +38013,12 @@ async function refreshFromSummaries(repoSlug, parsed, activeItems, client, now,
|
|
|
37813
38013
|
const manifest = extractInstalledManifest(detail.install.data);
|
|
37814
38014
|
if (!manifest)
|
|
37815
38015
|
continue;
|
|
38016
|
+
installs[item.componentName] = {
|
|
38017
|
+
ref: itemRef,
|
|
38018
|
+
version: manifest.component.version ?? item.version ?? "",
|
|
38019
|
+
latestVersion: item.latestVersion,
|
|
38020
|
+
updateAvailable: item.updateAvailable
|
|
38021
|
+
};
|
|
37816
38022
|
const methods = manifest.cli?.methods ?? [];
|
|
37817
38023
|
if (methods.length === 0)
|
|
37818
38024
|
continue;
|
|
@@ -37826,7 +38032,9 @@ async function refreshFromSummaries(repoSlug, parsed, activeItems, client, now,
|
|
|
37826
38032
|
version: manifest.component.version ?? item.version ?? "",
|
|
37827
38033
|
description: manifest.cli?.description,
|
|
37828
38034
|
manifestHash: item.manifestHash ?? "",
|
|
37829
|
-
methods
|
|
38035
|
+
methods,
|
|
38036
|
+
latestVersion: item.latestVersion,
|
|
38037
|
+
updateAvailable: item.updateAvailable
|
|
37830
38038
|
};
|
|
37831
38039
|
}
|
|
37832
38040
|
if (activeItems.length > 0 && detailReadFailures === activeItems.length) {
|
|
@@ -37838,7 +38046,8 @@ async function refreshFromSummaries(repoSlug, parsed, activeItems, client, now,
|
|
|
37838
38046
|
const cache = {
|
|
37839
38047
|
cachedAt: now,
|
|
37840
38048
|
repoSlug,
|
|
37841
|
-
components
|
|
38049
|
+
components,
|
|
38050
|
+
installs
|
|
37842
38051
|
};
|
|
37843
38052
|
writeInstallSnapshotCache(repoSlug, cache);
|
|
37844
38053
|
return cache;
|
|
@@ -38112,7 +38321,7 @@ function coerceArg(arg, value) {
|
|
|
38112
38321
|
if (arg.pattern) {
|
|
38113
38322
|
let re;
|
|
38114
38323
|
try {
|
|
38115
|
-
re = new RegExp(arg.pattern);
|
|
38324
|
+
re = new RegExp(`^(?:${arg.pattern})$`);
|
|
38116
38325
|
} catch {
|
|
38117
38326
|
throw new CliError(2 /* UserInput */, "USER_INPUT", `invalid regex pattern for --${arg.name}: /${arg.pattern}/`);
|
|
38118
38327
|
}
|
|
@@ -38204,6 +38413,13 @@ var handleComponentExec = async (ctx, { args, terminator }) => {
|
|
|
38204
38413
|
const cache = await ensureFreshInstallSnapshotCache(installRepo, ctx.client);
|
|
38205
38414
|
const entry = cache.components[componentName];
|
|
38206
38415
|
if (!entry) {
|
|
38416
|
+
const install = cache.installs[componentName];
|
|
38417
|
+
if (install?.updateAvailable && install.latestVersion) {
|
|
38418
|
+
throw new CliError(2 /* UserInput */, "USER_INPUT", `Component '${componentName}' is installed at ${install.version || "an older version"} in ${installRepo}, which exposes no CLI method${methodName ? ` '${methodName}'` : "s"}.`, undefined, `Version ${install.latestVersion} is available — run 'wh component update ${install.ref} --repo ${installRepo}', then 'wh component exec ${componentName} --help' to see its methods.`);
|
|
38419
|
+
}
|
|
38420
|
+
if (install) {
|
|
38421
|
+
throw new CliError(2 /* UserInput */, "USER_INPUT", `Component '${componentName}' is installed in ${installRepo} but exposes no CLI methods.`);
|
|
38422
|
+
}
|
|
38207
38423
|
throw new CliError(2 /* UserInput */, "USER_INPUT", `Component '${componentName}' is not installed in ${installRepo}.`, undefined, `Run 'wh component install <ref> --repo ${installRepo}' first.`);
|
|
38208
38424
|
}
|
|
38209
38425
|
if (!methodName) {
|
|
@@ -38215,7 +38431,9 @@ var handleComponentExec = async (ctx, { args, terminator }) => {
|
|
|
38215
38431
|
}
|
|
38216
38432
|
const method = entry.methods.find((m) => m.name === methodName);
|
|
38217
38433
|
if (!method) {
|
|
38218
|
-
|
|
38434
|
+
const available = entry.methods.map((m) => m.name).join(", ");
|
|
38435
|
+
const updateHint = entry.updateAvailable && entry.latestVersion ? `Version ${entry.latestVersion} is available — run wh component update ${entry.ref} --repo ${installRepo} for newer methods.` : `Run wh component update ${entry.ref} --repo ${installRepo} if you expect a newer method.`;
|
|
38436
|
+
throw new CliError(2 /* UserInput */, "USER_INPUT", `Method '${methodName}' not found on component '${componentName}'.`, undefined, `Available: ${available}. ${updateHint}`);
|
|
38219
38437
|
}
|
|
38220
38438
|
if (helpRequested) {
|
|
38221
38439
|
renderMethodHelp(ctx, componentName, method);
|
|
@@ -38864,7 +39082,8 @@ var handleView3 = async (ctx, { args }) => {
|
|
|
38864
39082
|
writeOutput(ctx, viewData, () => {
|
|
38865
39083
|
const c = ctx.colors;
|
|
38866
39084
|
ctx.out(`${c.bold}Component:${c.reset} ${c.cyan}${viewData.ref ?? ref}${c.reset}`);
|
|
38867
|
-
|
|
39085
|
+
const update = viewData.updateAvailable && viewData.latestVersion ? ` ${c.yellow}(${viewData.latestVersion} available — run wh component update ${viewData.ref ?? ref} --repo ${org}/${repo})${c.reset}` : "";
|
|
39086
|
+
ctx.out(`${c.bold}Version:${c.reset} ${viewData.version ?? "unknown"}${update}`);
|
|
38868
39087
|
ctx.out(`${c.bold}State:${c.reset} ${viewData.state ?? "-"}`);
|
|
38869
39088
|
ctx.out(`${c.bold}Source:${c.reset} ${viewData.source ?? "-"}`);
|
|
38870
39089
|
if (viewData.ownedShapes.length > 0) {
|
|
@@ -39121,6 +39340,22 @@ async function doctorComponent(client, org, repo, componentId) {
|
|
|
39121
39340
|
});
|
|
39122
39341
|
}
|
|
39123
39342
|
}
|
|
39343
|
+
try {
|
|
39344
|
+
const detail = await client.component.get(org, repo, registeredComponentRef);
|
|
39345
|
+
if (detail.updateAvailable === true && detail.latestVersion) {
|
|
39346
|
+
findings.push({
|
|
39347
|
+
resource: "version",
|
|
39348
|
+
status: "warning",
|
|
39349
|
+
message: `Installed ${detail.version ?? "version"}; ${detail.latestVersion} available — run wh component update ${registeredComponentRef} --repo ${org}/${repo}`
|
|
39350
|
+
});
|
|
39351
|
+
} else if (detail.updateAvailable === false && detail.version) {
|
|
39352
|
+
findings.push({
|
|
39353
|
+
resource: "version",
|
|
39354
|
+
status: "ok",
|
|
39355
|
+
message: `Up to date (${detail.version})`
|
|
39356
|
+
});
|
|
39357
|
+
}
|
|
39358
|
+
} catch {}
|
|
39124
39359
|
const hasMissing = findings.some((f) => f.status === "missing");
|
|
39125
39360
|
const hasInactive = findings.some((f) => f.status === "inactive" && !f.resource.startsWith("sub:"));
|
|
39126
39361
|
const hasShapeDrift = findings.some((f) => f.resource.startsWith("shape:") && f.status === "warning" && f.message.includes("differs from installed manifest"));
|
|
@@ -39133,21 +39368,23 @@ async function doctorComponent(client, org, repo, componentId) {
|
|
|
39133
39368
|
} else {
|
|
39134
39369
|
state = "ready";
|
|
39135
39370
|
}
|
|
39136
|
-
|
|
39137
|
-
|
|
39138
|
-
{
|
|
39139
|
-
|
|
39140
|
-
|
|
39141
|
-
|
|
39142
|
-
|
|
39143
|
-
|
|
39144
|
-
|
|
39145
|
-
|
|
39146
|
-
|
|
39147
|
-
|
|
39148
|
-
|
|
39149
|
-
|
|
39150
|
-
|
|
39371
|
+
if (state !== existingState) {
|
|
39372
|
+
try {
|
|
39373
|
+
await client.commit.apply(org, repo, `Doctor: update ${componentName} state to ${state}`, [
|
|
39374
|
+
{
|
|
39375
|
+
operation: "revise",
|
|
39376
|
+
kind: "thing",
|
|
39377
|
+
name: `ComponentInstall/${componentId}`,
|
|
39378
|
+
data: { ...installData, state }
|
|
39379
|
+
}
|
|
39380
|
+
], { componentRef: SYSTEM_REGISTERED_COMPONENT_REF });
|
|
39381
|
+
} catch {
|
|
39382
|
+
findings.push({
|
|
39383
|
+
resource: "state-update",
|
|
39384
|
+
status: "warning",
|
|
39385
|
+
message: "Failed to persist computed state"
|
|
39386
|
+
});
|
|
39387
|
+
}
|
|
39151
39388
|
}
|
|
39152
39389
|
return { componentId, componentName, state, findings };
|
|
39153
39390
|
}
|
|
@@ -39265,7 +39502,8 @@ var handleList2 = async (ctx, { flags }) => {
|
|
|
39265
39502
|
const state = item.state ?? "unknown";
|
|
39266
39503
|
const source = item.source ?? "-";
|
|
39267
39504
|
const stateColor = stateToColor2(c, state);
|
|
39268
|
-
|
|
39505
|
+
const update = item.updateAvailable && item.latestVersion ? ` ${c.yellow}(${item.latestVersion} available)${c.reset}` : "";
|
|
39506
|
+
ctx.out(` ${c.cyan}${item.ref ?? item.componentName}${c.reset} ${stateColor}${state}${c.reset} ${c.dim}v${version}${c.reset}${update} ${source}`);
|
|
39269
39507
|
}
|
|
39270
39508
|
});
|
|
39271
39509
|
};
|
|
@@ -40666,8 +40904,9 @@ function renderActionNotifications(out, statusOut, c, notifications) {
|
|
|
40666
40904
|
const subscriptionName = notification.subscriptionName ? `${c.cyan}${notification.subscriptionName}${c.reset}` : `${c.dim}(unknown subscription)${c.reset}`;
|
|
40667
40905
|
out(` ${status} ${c.dim}${time}${c.reset} ${subscriptionName} attempt #${notification.attempt} ${c.dim}${notification.channel}${c.reset}`);
|
|
40668
40906
|
if (notification.errorMessage) {
|
|
40669
|
-
const code = notification.errorCode ? `${notification.errorCode}: ` : "";
|
|
40670
|
-
|
|
40907
|
+
const code = notification.errorCode ? `${escapeTerminalTextForDisplay(notification.errorCode)}: ` : "";
|
|
40908
|
+
const message = escapeTerminalTextForDisplay(notification.errorMessage);
|
|
40909
|
+
out(` ${c.red}${code}${message}${c.reset}`);
|
|
40671
40910
|
}
|
|
40672
40911
|
}
|
|
40673
40912
|
}
|
|
@@ -42244,7 +42483,7 @@ var handleDescribe = async (ctx, { args, flags }) => {
|
|
|
42244
42483
|
const data = version?.data;
|
|
42245
42484
|
const shapeDesc = data?.description;
|
|
42246
42485
|
if (typeof shapeDesc === "string" && shapeDesc) {
|
|
42247
|
-
ctx.out(` ${c.dim}${shapeDesc}${c.reset}`);
|
|
42486
|
+
ctx.out(` ${c.dim}${escapeTerminalTextForDisplay(shapeDesc)}${c.reset}`);
|
|
42248
42487
|
}
|
|
42249
42488
|
const fields = data?.fields;
|
|
42250
42489
|
if (fields) {
|
|
@@ -42256,9 +42495,10 @@ var handleDescribe = async (ctx, { args, flags }) => {
|
|
|
42256
42495
|
return Math.max(m, ts.length);
|
|
42257
42496
|
}, 0);
|
|
42258
42497
|
for (const [fieldName, fieldType] of entries) {
|
|
42498
|
+
const safeFieldName = escapeFieldNameForDisplay(fieldName);
|
|
42259
42499
|
const typeStr = displayFieldType(fieldType);
|
|
42260
42500
|
const fieldDesc = fieldDescriptionFromSpec(fieldType);
|
|
42261
|
-
const line = fieldDesc ? ` ${c.cyan}${
|
|
42501
|
+
const line = fieldDesc ? ` ${c.cyan}${safeFieldName.padEnd(maxName)}${c.reset} ${c.dim}${typeStr.padEnd(maxType)}${c.reset} ${escapeTerminalTextForDisplay(fieldDesc)}` : ` ${c.cyan}${safeFieldName.padEnd(maxName)}${c.reset} ${c.dim}${typeStr}${c.reset}`;
|
|
42262
42502
|
ctx.out(line);
|
|
42263
42503
|
}
|
|
42264
42504
|
}
|
|
@@ -42647,7 +42887,7 @@ var handleList6 = async (ctx, { flags }) => {
|
|
|
42647
42887
|
const shapeData = shape.version?.data;
|
|
42648
42888
|
const shapeDescription = shapeData?.description;
|
|
42649
42889
|
if (typeof shapeDescription === "string" && shapeDescription) {
|
|
42650
|
-
ctx.out(` ${c.dim}${shapeDescription}${c.reset}`);
|
|
42890
|
+
ctx.out(` ${c.dim}${escapeTerminalTextForDisplay(shapeDescription)}${c.reset}`);
|
|
42651
42891
|
}
|
|
42652
42892
|
const fields = shapeData?.fields;
|
|
42653
42893
|
if (fields) {
|
|
@@ -42662,7 +42902,7 @@ var handleList6 = async (ctx, { flags }) => {
|
|
|
42662
42902
|
const typeStr = displayFieldType(fieldType);
|
|
42663
42903
|
const padded = fieldName.padEnd(maxLen);
|
|
42664
42904
|
const fieldDesc = fieldDescriptionFromSpec(fieldType);
|
|
42665
|
-
const descSuffix = fieldDesc ? ` ${typeStr.padEnd(maxTypeLen)} ${fieldDesc}` : ` ${typeStr}`;
|
|
42905
|
+
const descSuffix = fieldDesc ? ` ${typeStr.padEnd(maxTypeLen)} ${escapeTerminalTextForDisplay(fieldDesc)}` : ` ${typeStr}`;
|
|
42666
42906
|
ctx.out(` ${c.cyan}${padded}${c.reset} ${c.dim}${descSuffix}${c.reset}`);
|
|
42667
42907
|
}
|
|
42668
42908
|
}
|
|
@@ -42694,7 +42934,7 @@ var handleView7 = async (ctx, { flags, args }) => {
|
|
|
42694
42934
|
const shapeData = shapeVersion?.data;
|
|
42695
42935
|
const shapeDescription = shapeData?.description;
|
|
42696
42936
|
if (typeof shapeDescription === "string" && shapeDescription) {
|
|
42697
|
-
ctx.out(` ${c.dim}${shapeDescription}${c.reset}`);
|
|
42937
|
+
ctx.out(` ${c.dim}${escapeTerminalTextForDisplay(shapeDescription)}${c.reset}`);
|
|
42698
42938
|
}
|
|
42699
42939
|
const componentRef = result.componentRef;
|
|
42700
42940
|
if (componentRef) {
|
|
@@ -42706,7 +42946,7 @@ var handleView7 = async (ctx, { flags, args }) => {
|
|
|
42706
42946
|
for (const [fieldName, fieldType] of Object.entries(fields)) {
|
|
42707
42947
|
const typeStr = displayFieldType(fieldType);
|
|
42708
42948
|
const fieldDesc = fieldDescriptionFromSpec(fieldType);
|
|
42709
|
-
const descSuffix = fieldDesc ? ` ${c.dim}${fieldDesc}${c.reset}` : "";
|
|
42949
|
+
const descSuffix = fieldDesc ? ` ${c.dim}${escapeTerminalTextForDisplay(fieldDesc)}${c.reset}` : "";
|
|
42710
42950
|
const safeFieldName = escapeFieldNameForDisplay(fieldName);
|
|
42711
42951
|
ctx.out(` ${c.cyan}${safeFieldName}${c.reset}: ${c.dim}${typeStr}${c.reset}${descSuffix}`);
|
|
42712
42952
|
}
|
|
@@ -42807,8 +43047,10 @@ var handleShapeRename = async (ctx, { args }) => {
|
|
|
42807
43047
|
}
|
|
42808
43048
|
const { org, repo } = parseOrgRepo(getRepoRef(ctx), ctx.config);
|
|
42809
43049
|
const c = ctx.colors;
|
|
42810
|
-
await ctx.client.shape.rename(org, repo, oldName, newName);
|
|
42811
|
-
ctx
|
|
43050
|
+
const result = await ctx.client.shape.rename(org, repo, oldName, newName);
|
|
43051
|
+
writeOutput(ctx, { ...result, oldName, newName }, () => {
|
|
43052
|
+
ctx.out(`${c.green}Renamed shape${c.reset} ${c.magenta}${oldName}${c.reset} → ${c.magenta}${newName}${c.reset}`);
|
|
43053
|
+
});
|
|
42812
43054
|
};
|
|
42813
43055
|
|
|
42814
43056
|
// ../../packages/warmhub-cli/src/domains/shape.ts
|
|
@@ -43265,6 +43507,11 @@ function renderResponseSnippet(out, c, snippet, baseIndent) {
|
|
|
43265
43507
|
out(`${baseIndent} ${c.dim}${line}${c.reset}`);
|
|
43266
43508
|
}
|
|
43267
43509
|
}
|
|
43510
|
+
function renderErrorMessageLine(out, c, code, message, baseIndent) {
|
|
43511
|
+
const safeCode = code ? `${escapeTerminalTextForDisplay(code)}: ` : "";
|
|
43512
|
+
const safeMessage = escapeTerminalTextForDisplay(message);
|
|
43513
|
+
out(`${baseIndent}${c.red}${safeCode}${safeMessage}${c.reset}`);
|
|
43514
|
+
}
|
|
43268
43515
|
function statusColor(c, status) {
|
|
43269
43516
|
switch (status) {
|
|
43270
43517
|
case "completed":
|
|
@@ -43305,11 +43552,10 @@ function renderSubscriptionLog(out, statusOut, c, subscriptionName, result) {
|
|
|
43305
43552
|
const sourceLabel = (item.matchedOperationIndexes?.length ?? 0) > 0 ? `${c.cyan}write${c.reset}` : `${c.magenta}cron tick${c.reset}`;
|
|
43306
43553
|
const matched = (item.matchedOperationIndexes ?? []).join(",") || "-";
|
|
43307
43554
|
const attemptSuffix = item.attemptCount != null && item.maxAttempts != null ? ` ${c.dim}${item.attemptCount}/${item.maxAttempts}${c.reset}` : "";
|
|
43308
|
-
const
|
|
43309
|
-
out(` ${status}${attemptSuffix} ${c.dim}${time}${c.reset}${
|
|
43555
|
+
const idSuffix = item.runId ? ` ${c.dim}run ${item.runId}${c.reset}` : item.deliveryId ? ` ${c.dim}delivery ${item.deliveryId}${c.reset}` : "";
|
|
43556
|
+
out(` ${status}${attemptSuffix} ${c.dim}${time}${c.reset}${idSuffix} ${sourceLabel} ops[${matched}]`);
|
|
43310
43557
|
if ((displayStatus === "failed_terminal" || displayStatus === "dead_letter") && item.lastErrorMessage) {
|
|
43311
|
-
|
|
43312
|
-
out(` ${c.red}${code}${item.lastErrorMessage}${c.reset}`);
|
|
43558
|
+
renderErrorMessageLine(out, c, item.lastErrorCode, item.lastErrorMessage, " ");
|
|
43313
43559
|
}
|
|
43314
43560
|
if ((displayStatus === "failed_terminal" || displayStatus === "dead_letter") && item.lastResponseSnippet) {
|
|
43315
43561
|
renderResponseSnippet(out, c, item.lastResponseSnippet, " ");
|
|
@@ -43420,7 +43666,12 @@ var handleLog = async (ctx, { flags, args }) => {
|
|
|
43420
43666
|
if (!name) {
|
|
43421
43667
|
usageError("Usage: wh sub log <name> [--repo org/repo]", "wh sub log my-sub");
|
|
43422
43668
|
}
|
|
43423
|
-
const
|
|
43669
|
+
const scope = resolveSubScope(ctx, flags);
|
|
43670
|
+
if (!scope.repoName) {
|
|
43671
|
+
usageError("Usage: wh sub log <name> [--repo org/repo]", "wh sub log my-sub --repo myorg/myrepo");
|
|
43672
|
+
}
|
|
43673
|
+
const org = scope.orgName;
|
|
43674
|
+
const repo = scope.repoName;
|
|
43424
43675
|
if (ctx.liveMode) {
|
|
43425
43676
|
await runLive({
|
|
43426
43677
|
apiUrl: ctx.config.apiUrl,
|
|
@@ -43464,8 +43715,7 @@ var handleAttempts = async (ctx, { args }) => {
|
|
|
43464
43715
|
const http = attempt.httpStatus ? ` ${c.dim}HTTP ${attempt.httpStatus}${c.reset}` : "";
|
|
43465
43716
|
ctx.out(` #${attempt.attempt} ${sc}${attempt.status}${c.reset}${dur}${http}`);
|
|
43466
43717
|
if (attempt.errorMessage) {
|
|
43467
|
-
|
|
43468
|
-
ctx.out(` ${c.red}${code}${attempt.errorMessage}${c.reset}`);
|
|
43718
|
+
renderErrorMessageLine(ctx.out, c, attempt.errorCode, attempt.errorMessage, " ");
|
|
43469
43719
|
}
|
|
43470
43720
|
if (attempt.status === "failed" && attempt.responseSnippet) {
|
|
43471
43721
|
renderResponseSnippet(ctx.out, c, attempt.responseSnippet, " ");
|
|
@@ -43558,6 +43808,9 @@ var SUB_DOMAIN = defineDomain({
|
|
|
43558
43808
|
summary: "Tail subscription delivery feed with failed response snippets",
|
|
43559
43809
|
args: "<name>",
|
|
43560
43810
|
flags: logFlags,
|
|
43811
|
+
rejectedFlags: {
|
|
43812
|
+
org: "Use repo-scoped delivery logs: wh sub log my-sub --repo myorg/myrepo"
|
|
43813
|
+
},
|
|
43561
43814
|
examples: [
|
|
43562
43815
|
"# Show recent deliveries",
|
|
43563
43816
|
" $ wh sub log signal-hook --repo org/repo",
|
|
@@ -43566,7 +43819,10 @@ var SUB_DOMAIN = defineDomain({
|
|
|
43566
43819
|
" $ wh sub log daily-digest --repo org/repo",
|
|
43567
43820
|
"",
|
|
43568
43821
|
"# Follow deliveries in live mode",
|
|
43569
|
-
" $ wh sub log signal-hook --repo org/repo --live"
|
|
43822
|
+
" $ wh sub log signal-hook --repo org/repo --live",
|
|
43823
|
+
"",
|
|
43824
|
+
"# Delivery logs currently require a repo-scoped subscription",
|
|
43825
|
+
" $ wh sub log signal-hook --repo org/repo"
|
|
43570
43826
|
],
|
|
43571
43827
|
handler: handleLog
|
|
43572
43828
|
},
|
|
@@ -44523,9 +44779,9 @@ function extractFlagsForVerb(flags, verbSpec) {
|
|
|
44523
44779
|
}
|
|
44524
44780
|
return flags;
|
|
44525
44781
|
}
|
|
44526
|
-
return extractFlags(flags, verbSpec.flags);
|
|
44782
|
+
return extractFlags(flags, verbSpec.flags, verbSpec.rejectedFlags);
|
|
44527
44783
|
}
|
|
44528
|
-
function extractFlags(flags, specs) {
|
|
44784
|
+
function extractFlags(flags, specs, rejectedFlags = {}) {
|
|
44529
44785
|
const normalized = { ...flags };
|
|
44530
44786
|
const result = {};
|
|
44531
44787
|
const specLongs = specs.map((s) => s.long);
|
|
@@ -44560,11 +44816,19 @@ function extractFlags(flags, specs) {
|
|
|
44560
44816
|
}
|
|
44561
44817
|
for (const key of Object.keys(normalized)) {
|
|
44562
44818
|
if (key.length === 1) {
|
|
44819
|
+
const rejectedHint2 = rejectedFlags[key];
|
|
44820
|
+
if (rejectedHint2) {
|
|
44821
|
+
throw new CliError(2 /* UserInput */, "USER_INPUT", `Unknown flag: -${key}`, undefined, rejectedHint2);
|
|
44822
|
+
}
|
|
44563
44823
|
if (!allowedShorts.has(key) && !isGlobalFlag(key)) {
|
|
44564
44824
|
throw new CliError(2 /* UserInput */, "USER_INPUT", `Unknown flag: -${key}`);
|
|
44565
44825
|
}
|
|
44566
44826
|
continue;
|
|
44567
44827
|
}
|
|
44828
|
+
const rejectedHint = rejectedFlags[key];
|
|
44829
|
+
if (rejectedHint) {
|
|
44830
|
+
throw new CliError(2 /* UserInput */, "USER_INPUT", `Unknown flag: --${key}`, undefined, rejectedHint);
|
|
44831
|
+
}
|
|
44568
44832
|
if (!allowedLongs.has(key) && !isGlobalFlag(key)) {
|
|
44569
44833
|
const hint = findClosest(key, [...allowedLongs]);
|
|
44570
44834
|
throw new CliError(2 /* UserInput */, "USER_INPUT", `Unknown flag: --${key}`, undefined, hint ? `Did you mean '--${hint}'?` : undefined);
|
|
@@ -45574,7 +45838,7 @@ function resolveLogLevel(flags, env) {
|
|
|
45574
45838
|
// package.json
|
|
45575
45839
|
var package_default3 = {
|
|
45576
45840
|
name: "@warmhub/cli",
|
|
45577
|
-
version: "0.
|
|
45841
|
+
version: "0.65.0",
|
|
45578
45842
|
private: false,
|
|
45579
45843
|
type: "module",
|
|
45580
45844
|
description: "The wh CLI for WarmHub — create repos, commit and query data, and compound knowledge with your AI agents.",
|
|
@@ -45615,6 +45879,7 @@ var package_default3 = {
|
|
|
45615
45879
|
},
|
|
45616
45880
|
scripts: {
|
|
45617
45881
|
build: "bun run scripts/build.ts",
|
|
45882
|
+
prepack: "bun run build",
|
|
45618
45883
|
"check:boundary": "node ../../scripts/lint/boundary-imports.mjs bin src scripts",
|
|
45619
45884
|
"audit:bundle": "bun run scripts/audit-bundle.ts",
|
|
45620
45885
|
"audit:pack": "bun run scripts/audit-pack.ts",
|
|
@@ -46228,4 +46493,4 @@ if (!updateCheckSuppressedByArgv && shouldRunUpdateCheck(updateEligibility)) {
|
|
|
46228
46493
|
var interceptedExitCode = await maybeHandleComponentShellBoundary(dispatchArgv);
|
|
46229
46494
|
process.exitCode = interceptedExitCode === undefined ? await runCli(dispatchArgv, { version: package_default3.version }) : interceptedExitCode;
|
|
46230
46495
|
|
|
46231
|
-
//# debugId=
|
|
46496
|
+
//# debugId=B70D5B946B8CF0E364756E2164756E21
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@warmhub/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.65.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "The wh CLI for WarmHub — create repos, commit and query data, and compound knowledge with your AI agents.",
|
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
},
|
|
42
42
|
"scripts": {
|
|
43
43
|
"build": "bun run scripts/build.ts",
|
|
44
|
+
"prepack": "bun run build",
|
|
44
45
|
"check:boundary": "node ../../scripts/lint/boundary-imports.mjs bin src scripts",
|
|
45
46
|
"audit:bundle": "bun run scripts/audit-bundle.ts",
|
|
46
47
|
"audit:pack": "bun run scripts/audit-pack.ts",
|