@warmhub/cli 0.63.0 → 0.64.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 +248 -60
- 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.63.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,6 +32693,54 @@ 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;
|
|
@@ -34269,10 +34348,10 @@ var searchFlags = {
|
|
|
34269
34348
|
cursor: flag.string({ description: "Opaque pagination cursor (text mode)" }),
|
|
34270
34349
|
all: flag.boolean({ description: "Fetch all pages (text mode)" }),
|
|
34271
34350
|
component: flag.string({
|
|
34272
|
-
description: "Filter to things owned by this component (Org/Name ref)"
|
|
34351
|
+
description: "Filter to things owned by this component (Org/Name ref, text mode)"
|
|
34273
34352
|
}),
|
|
34274
34353
|
"exclude-components": flag.boolean({
|
|
34275
|
-
description: "Exclude component-owned things from results"
|
|
34354
|
+
description: "Exclude component-owned things from results (text mode)"
|
|
34276
34355
|
})
|
|
34277
34356
|
};
|
|
34278
34357
|
var handleSearch = async (ctx, { flags, args }) => {
|
|
@@ -34306,10 +34385,14 @@ var handleSearch = async (ctx, { flags, args }) => {
|
|
|
34306
34385
|
const pageLimit = all ? Math.min(limit ?? AUTO_PAGE_LIMIT, MAX_PAGE_LIMIT) : boundedTextLimit;
|
|
34307
34386
|
const resolveCollections = mode !== "hybrid" ? flags["resolve-collections"] : undefined;
|
|
34308
34387
|
const supportsComponentFilters = !mode || mode === "text";
|
|
34309
|
-
const componentRef = supportsComponentFilters ? flags.component : undefined;
|
|
34310
34388
|
const hasShape = !!flags.shape;
|
|
34311
|
-
const
|
|
34312
|
-
|
|
34389
|
+
const hasComponentFilter = flags.component !== undefined;
|
|
34390
|
+
const strictExclude = !!flags["exclude-components"];
|
|
34391
|
+
validateComponentFilters(flags.component, strictExclude, 'wh thing search "policy" --component acme/veritas');
|
|
34392
|
+
if (!supportsComponentFilters && (hasComponentFilter || strictExclude)) {
|
|
34393
|
+
usageError("--component/--exclude-components are only supported with text search mode.", 'wh thing search "policy" --mode text --component acme/veritas');
|
|
34394
|
+
}
|
|
34395
|
+
const componentRef = supportsComponentFilters ? flags.component : undefined;
|
|
34313
34396
|
const excludeComponents = supportsComponentFilters && strictExclude ? true : undefined;
|
|
34314
34397
|
const excludeInfraShapes = supportsComponentFilters && !strictExclude && !hasShape ? true : undefined;
|
|
34315
34398
|
const rawResult = all ? await fetchAllSearchPages(ctx, org, repo, queryText, {
|
|
@@ -36060,7 +36143,7 @@ var HEADER_DELIMITER = `\r
|
|
|
36060
36143
|
`;
|
|
36061
36144
|
var CONTENT_LENGTH_RE = /^Content-Length:\s*(\d+)$/im;
|
|
36062
36145
|
var MAX_MESSAGE_BYTES = 64 * 1024 * 1024;
|
|
36063
|
-
function parseFramedMessage(buffer, maxContentLength = MAX_MESSAGE_BYTES) {
|
|
36146
|
+
function parseFramedMessage(buffer, maxContentLength = MAX_MESSAGE_BYTES, bufferByteLength) {
|
|
36064
36147
|
const headerEnd = buffer.indexOf(HEADER_DELIMITER);
|
|
36065
36148
|
if (headerEnd === -1)
|
|
36066
36149
|
return null;
|
|
@@ -36073,11 +36156,36 @@ function parseFramedMessage(buffer, maxContentLength = MAX_MESSAGE_BYTES) {
|
|
|
36073
36156
|
throw new RangeError(`Content-Length ${contentLength} exceeds the maximum allowed ${maxContentLength} bytes`);
|
|
36074
36157
|
}
|
|
36075
36158
|
const bodyStart = headerEnd + HEADER_DELIMITER.length;
|
|
36076
|
-
const
|
|
36077
|
-
|
|
36159
|
+
const bodyStartBytes = Buffer.byteLength(buffer.slice(0, bodyStart), "utf8");
|
|
36160
|
+
const totalBytes = bufferByteLength ?? Buffer.byteLength(buffer, "utf8");
|
|
36161
|
+
if (totalBytes - bodyStartBytes < contentLength)
|
|
36162
|
+
return null;
|
|
36163
|
+
const bodyEnd = findUtf8ByteBoundary(buffer, bodyStart, contentLength);
|
|
36164
|
+
if (bodyEnd === null)
|
|
36078
36165
|
return null;
|
|
36079
|
-
const body =
|
|
36080
|
-
return { message: JSON.parse(body), consumed:
|
|
36166
|
+
const body = buffer.slice(bodyStart, bodyEnd);
|
|
36167
|
+
return { message: JSON.parse(body), consumed: bodyEnd };
|
|
36168
|
+
}
|
|
36169
|
+
function findUtf8ByteBoundary(value, start, targetBytes) {
|
|
36170
|
+
let bytes = 0;
|
|
36171
|
+
let index = start;
|
|
36172
|
+
while (index < value.length && bytes < targetBytes) {
|
|
36173
|
+
const codePoint = value.codePointAt(index);
|
|
36174
|
+
if (codePoint === undefined)
|
|
36175
|
+
return null;
|
|
36176
|
+
bytes += utf8CodePointByteLength(codePoint);
|
|
36177
|
+
index += codePoint > 65535 ? 2 : 1;
|
|
36178
|
+
}
|
|
36179
|
+
return bytes === targetBytes ? index : null;
|
|
36180
|
+
}
|
|
36181
|
+
function utf8CodePointByteLength(codePoint) {
|
|
36182
|
+
if (codePoint <= 127)
|
|
36183
|
+
return 1;
|
|
36184
|
+
if (codePoint <= 2047)
|
|
36185
|
+
return 2;
|
|
36186
|
+
if (codePoint <= 65535)
|
|
36187
|
+
return 3;
|
|
36188
|
+
return 4;
|
|
36081
36189
|
}
|
|
36082
36190
|
function parseNdjsonMessage(buffer) {
|
|
36083
36191
|
const newlineIdx = buffer.indexOf(`
|
|
@@ -36125,7 +36233,7 @@ function createMessageReader(input, onMessage, onError = () => {}, maxMessageByt
|
|
|
36125
36233
|
}
|
|
36126
36234
|
let result;
|
|
36127
36235
|
try {
|
|
36128
|
-
result = mode === "ndjson" ? parseNdjsonMessage(buffer) : parseFramedMessage(buffer, maxMessageBytes);
|
|
36236
|
+
result = mode === "ndjson" ? parseNdjsonMessage(buffer) : parseFramedMessage(buffer, maxMessageBytes, bufferBytes);
|
|
36129
36237
|
} catch (err) {
|
|
36130
36238
|
if (err instanceof RangeError) {
|
|
36131
36239
|
onError(err);
|
|
@@ -36187,27 +36295,47 @@ function createMessageReader(input, onMessage, onError = () => {}, maxMessageByt
|
|
|
36187
36295
|
var MCP_PROTOCOL_VERSION2 = "2025-11-25";
|
|
36188
36296
|
function createChannelServer(opts) {
|
|
36189
36297
|
let reader = null;
|
|
36298
|
+
let removeInputCloseListeners = () => {};
|
|
36190
36299
|
let resolveReady;
|
|
36191
36300
|
let rejectReady;
|
|
36192
36301
|
let readySettled = false;
|
|
36302
|
+
let resolveClosed;
|
|
36303
|
+
let closedSettled = false;
|
|
36193
36304
|
const onReady = new Promise((resolve, reject) => {
|
|
36194
36305
|
resolveReady = resolve;
|
|
36195
36306
|
rejectReady = reject;
|
|
36196
36307
|
});
|
|
36308
|
+
const onClosed = new Promise((resolve) => {
|
|
36309
|
+
resolveClosed = resolve;
|
|
36310
|
+
});
|
|
36197
36311
|
function settleReady() {
|
|
36198
36312
|
if (readySettled)
|
|
36199
36313
|
return;
|
|
36200
36314
|
readySettled = true;
|
|
36201
36315
|
resolveReady();
|
|
36202
36316
|
}
|
|
36203
|
-
function
|
|
36204
|
-
if (
|
|
36317
|
+
function settleClosed() {
|
|
36318
|
+
if (closedSettled)
|
|
36205
36319
|
return;
|
|
36206
|
-
|
|
36320
|
+
closedSettled = true;
|
|
36321
|
+
removeInputCloseListeners();
|
|
36207
36322
|
reader?.close();
|
|
36208
|
-
|
|
36323
|
+
resolveClosed();
|
|
36324
|
+
}
|
|
36325
|
+
function closeServer() {
|
|
36326
|
+
settleClosed();
|
|
36327
|
+
settleReady();
|
|
36328
|
+
}
|
|
36329
|
+
function failReady(error) {
|
|
36330
|
+
if (!readySettled) {
|
|
36331
|
+
readySettled = true;
|
|
36332
|
+
rejectReady(error);
|
|
36333
|
+
}
|
|
36334
|
+
settleClosed();
|
|
36209
36335
|
}
|
|
36210
36336
|
function send(msg) {
|
|
36337
|
+
if (closedSettled)
|
|
36338
|
+
return;
|
|
36211
36339
|
opts.output.write(ndjsonMessage(msg));
|
|
36212
36340
|
}
|
|
36213
36341
|
function handleMessage(msg) {
|
|
@@ -36246,6 +36374,13 @@ function createChannelServer(opts) {
|
|
|
36246
36374
|
}
|
|
36247
36375
|
return {
|
|
36248
36376
|
start() {
|
|
36377
|
+
const handleInputClose = () => closeServer();
|
|
36378
|
+
opts.input.on("end", handleInputClose);
|
|
36379
|
+
opts.input.on("close", handleInputClose);
|
|
36380
|
+
removeInputCloseListeners = () => {
|
|
36381
|
+
opts.input.removeListener("end", handleInputClose);
|
|
36382
|
+
opts.input.removeListener("close", handleInputClose);
|
|
36383
|
+
};
|
|
36249
36384
|
reader = createMessageReader(opts.input, handleMessage, failReady);
|
|
36250
36385
|
},
|
|
36251
36386
|
notify(content, meta) {
|
|
@@ -36256,14 +36391,15 @@ function createChannelServer(opts) {
|
|
|
36256
36391
|
});
|
|
36257
36392
|
},
|
|
36258
36393
|
onReady,
|
|
36394
|
+
onClosed,
|
|
36259
36395
|
close() {
|
|
36260
|
-
|
|
36261
|
-
settleReady();
|
|
36396
|
+
closeServer();
|
|
36262
36397
|
}
|
|
36263
36398
|
};
|
|
36264
36399
|
}
|
|
36265
36400
|
|
|
36266
36401
|
// ../../packages/warmhub-cli/src/domains/channel.ts
|
|
36402
|
+
var RECONNECT_DELAY_MS = 2000;
|
|
36267
36403
|
function formatChannelEvent(org, repo, event) {
|
|
36268
36404
|
const things = event.affectedThings.join(", ");
|
|
36269
36405
|
const shapes = event.affectedShapes.join(",");
|
|
@@ -36280,6 +36416,22 @@ function formatChannelEvent(org, repo, event) {
|
|
|
36280
36416
|
};
|
|
36281
36417
|
}
|
|
36282
36418
|
async function subscribeLoop(client, org, repo, signal, server) {
|
|
36419
|
+
const pauseBeforeReconnect = () => new Promise((resolve) => {
|
|
36420
|
+
if (signal.aborted) {
|
|
36421
|
+
resolve();
|
|
36422
|
+
return;
|
|
36423
|
+
}
|
|
36424
|
+
let timeout;
|
|
36425
|
+
const onAbort = () => {
|
|
36426
|
+
clearTimeout(timeout);
|
|
36427
|
+
resolve();
|
|
36428
|
+
};
|
|
36429
|
+
timeout = setTimeout(() => {
|
|
36430
|
+
signal.removeEventListener("abort", onAbort);
|
|
36431
|
+
resolve();
|
|
36432
|
+
}, RECONNECT_DELAY_MS);
|
|
36433
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
36434
|
+
});
|
|
36283
36435
|
while (!signal.aborted) {
|
|
36284
36436
|
try {
|
|
36285
36437
|
const handle = await client.live.subscribe(org, repo, { signal }, (event) => {
|
|
@@ -36287,6 +36439,8 @@ async function subscribeLoop(client, org, repo, signal, server) {
|
|
|
36287
36439
|
server.notify(content, meta);
|
|
36288
36440
|
});
|
|
36289
36441
|
await handle.closed;
|
|
36442
|
+
if (!signal.aborted)
|
|
36443
|
+
await pauseBeforeReconnect();
|
|
36290
36444
|
} catch (err) {
|
|
36291
36445
|
if (signal.aborted)
|
|
36292
36446
|
break;
|
|
@@ -36294,7 +36448,7 @@ async function subscribeLoop(client, org, repo, signal, server) {
|
|
|
36294
36448
|
if (msg.includes("401") || msg.includes("403") || msg.includes("404") || msg.includes("AUTH") || msg.includes("not found") || msg.includes("Session expired")) {
|
|
36295
36449
|
throw new Error(`${org}/${repo}: ${msg}`);
|
|
36296
36450
|
}
|
|
36297
|
-
await
|
|
36451
|
+
await pauseBeforeReconnect();
|
|
36298
36452
|
}
|
|
36299
36453
|
}
|
|
36300
36454
|
}
|
|
@@ -36313,7 +36467,6 @@ var handleChannel = async (ctx) => {
|
|
|
36313
36467
|
input: process.stdin,
|
|
36314
36468
|
output: process.stdout
|
|
36315
36469
|
});
|
|
36316
|
-
server.start();
|
|
36317
36470
|
const signal = ctx.signal ?? new AbortController().signal;
|
|
36318
36471
|
const aborted = new Promise((resolve) => {
|
|
36319
36472
|
if (signal.aborted)
|
|
@@ -36323,15 +36476,19 @@ var handleChannel = async (ctx) => {
|
|
|
36323
36476
|
});
|
|
36324
36477
|
let ready;
|
|
36325
36478
|
try {
|
|
36326
|
-
|
|
36327
|
-
|
|
36328
|
-
|
|
36479
|
+
const startup = Promise.race([
|
|
36480
|
+
server.onClosed.then(() => "closed"),
|
|
36481
|
+
server.onReady.then(() => "ready"),
|
|
36482
|
+
aborted
|
|
36483
|
+
]);
|
|
36484
|
+
server.start();
|
|
36485
|
+
ready = await startup;
|
|
36329
36486
|
} catch (err) {
|
|
36330
36487
|
server.close();
|
|
36331
36488
|
const msg = err instanceof Error ? err.message : String(err);
|
|
36332
36489
|
throw new CliError(4 /* Backend */, "BACKEND", `channel startup failed: ${msg}`);
|
|
36333
36490
|
}
|
|
36334
|
-
if (ready
|
|
36491
|
+
if (ready !== "ready") {
|
|
36335
36492
|
server.close();
|
|
36336
36493
|
return;
|
|
36337
36494
|
}
|
|
@@ -36342,7 +36499,11 @@ var handleChannel = async (ctx) => {
|
|
|
36342
36499
|
signal.addEventListener("abort", () => controller.abort(), { once: true });
|
|
36343
36500
|
let fatal;
|
|
36344
36501
|
try {
|
|
36345
|
-
|
|
36502
|
+
const subscriptions = Promise.all(repos.map(({ org, repo }) => subscribeLoop(ctx.client, org, repo, controller.signal, server)));
|
|
36503
|
+
const closed = server.onClosed.then(() => {
|
|
36504
|
+
controller.abort();
|
|
36505
|
+
});
|
|
36506
|
+
await Promise.race([subscriptions, closed]);
|
|
36346
36507
|
} catch (err) {
|
|
36347
36508
|
controller.abort();
|
|
36348
36509
|
fatal = err;
|
|
@@ -36373,7 +36534,7 @@ var CHANNEL_DOMAIN = defineDomain({
|
|
|
36373
36534
|
// ../../packages/warmhub-cli/src/domains/commit-submit-flags.ts
|
|
36374
36535
|
var createFlags3 = {
|
|
36375
36536
|
ops: flag.string({
|
|
36376
|
-
description: "Operations JSON (inline). For ops from a file, use -f/--file <path> instead; --ops accepts inline JSON only."
|
|
36537
|
+
description: "Operations JSON array (inline). For ops from a file, use -f/--file <path> instead; --ops accepts an inline JSON array only."
|
|
36377
36538
|
}),
|
|
36378
36539
|
file: flag.string({
|
|
36379
36540
|
short: "f",
|
|
@@ -37461,7 +37622,7 @@ var handleSubmit = async (ctx, { flags, args }) => {
|
|
|
37461
37622
|
}
|
|
37462
37623
|
];
|
|
37463
37624
|
} else if (opsJson) {
|
|
37464
|
-
operations =
|
|
37625
|
+
operations = parseJsonArray(opsJson, "--ops", {
|
|
37465
37626
|
fileFlagSibling: "-f/--file"
|
|
37466
37627
|
});
|
|
37467
37628
|
} else if (opsFile) {
|
|
@@ -37474,7 +37635,7 @@ var handleSubmit = async (ctx, { flags, args }) => {
|
|
|
37474
37635
|
} catch (e) {
|
|
37475
37636
|
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
37637
|
}
|
|
37477
|
-
operations =
|
|
37638
|
+
operations = parseJsonArray(file, "--file contents");
|
|
37478
37639
|
}
|
|
37479
37640
|
} else if (addNames.length > 0) {
|
|
37480
37641
|
operations = buildAddOperations({
|
|
@@ -38112,7 +38273,7 @@ function coerceArg(arg, value) {
|
|
|
38112
38273
|
if (arg.pattern) {
|
|
38113
38274
|
let re;
|
|
38114
38275
|
try {
|
|
38115
|
-
re = new RegExp(arg.pattern);
|
|
38276
|
+
re = new RegExp(`^(?:${arg.pattern})$`);
|
|
38116
38277
|
} catch {
|
|
38117
38278
|
throw new CliError(2 /* UserInput */, "USER_INPUT", `invalid regex pattern for --${arg.name}: /${arg.pattern}/`);
|
|
38118
38279
|
}
|
|
@@ -40666,8 +40827,9 @@ function renderActionNotifications(out, statusOut, c, notifications) {
|
|
|
40666
40827
|
const subscriptionName = notification.subscriptionName ? `${c.cyan}${notification.subscriptionName}${c.reset}` : `${c.dim}(unknown subscription)${c.reset}`;
|
|
40667
40828
|
out(` ${status} ${c.dim}${time}${c.reset} ${subscriptionName} attempt #${notification.attempt} ${c.dim}${notification.channel}${c.reset}`);
|
|
40668
40829
|
if (notification.errorMessage) {
|
|
40669
|
-
const code = notification.errorCode ? `${notification.errorCode}: ` : "";
|
|
40670
|
-
|
|
40830
|
+
const code = notification.errorCode ? `${escapeTerminalTextForDisplay(notification.errorCode)}: ` : "";
|
|
40831
|
+
const message = escapeTerminalTextForDisplay(notification.errorMessage);
|
|
40832
|
+
out(` ${c.red}${code}${message}${c.reset}`);
|
|
40671
40833
|
}
|
|
40672
40834
|
}
|
|
40673
40835
|
}
|
|
@@ -42244,7 +42406,7 @@ var handleDescribe = async (ctx, { args, flags }) => {
|
|
|
42244
42406
|
const data = version?.data;
|
|
42245
42407
|
const shapeDesc = data?.description;
|
|
42246
42408
|
if (typeof shapeDesc === "string" && shapeDesc) {
|
|
42247
|
-
ctx.out(` ${c.dim}${shapeDesc}${c.reset}`);
|
|
42409
|
+
ctx.out(` ${c.dim}${escapeTerminalTextForDisplay(shapeDesc)}${c.reset}`);
|
|
42248
42410
|
}
|
|
42249
42411
|
const fields = data?.fields;
|
|
42250
42412
|
if (fields) {
|
|
@@ -42256,9 +42418,10 @@ var handleDescribe = async (ctx, { args, flags }) => {
|
|
|
42256
42418
|
return Math.max(m, ts.length);
|
|
42257
42419
|
}, 0);
|
|
42258
42420
|
for (const [fieldName, fieldType] of entries) {
|
|
42421
|
+
const safeFieldName = escapeFieldNameForDisplay(fieldName);
|
|
42259
42422
|
const typeStr = displayFieldType(fieldType);
|
|
42260
42423
|
const fieldDesc = fieldDescriptionFromSpec(fieldType);
|
|
42261
|
-
const line = fieldDesc ? ` ${c.cyan}${
|
|
42424
|
+
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
42425
|
ctx.out(line);
|
|
42263
42426
|
}
|
|
42264
42427
|
}
|
|
@@ -42647,7 +42810,7 @@ var handleList6 = async (ctx, { flags }) => {
|
|
|
42647
42810
|
const shapeData = shape.version?.data;
|
|
42648
42811
|
const shapeDescription = shapeData?.description;
|
|
42649
42812
|
if (typeof shapeDescription === "string" && shapeDescription) {
|
|
42650
|
-
ctx.out(` ${c.dim}${shapeDescription}${c.reset}`);
|
|
42813
|
+
ctx.out(` ${c.dim}${escapeTerminalTextForDisplay(shapeDescription)}${c.reset}`);
|
|
42651
42814
|
}
|
|
42652
42815
|
const fields = shapeData?.fields;
|
|
42653
42816
|
if (fields) {
|
|
@@ -42662,7 +42825,7 @@ var handleList6 = async (ctx, { flags }) => {
|
|
|
42662
42825
|
const typeStr = displayFieldType(fieldType);
|
|
42663
42826
|
const padded = fieldName.padEnd(maxLen);
|
|
42664
42827
|
const fieldDesc = fieldDescriptionFromSpec(fieldType);
|
|
42665
|
-
const descSuffix = fieldDesc ? ` ${typeStr.padEnd(maxTypeLen)} ${fieldDesc}` : ` ${typeStr}`;
|
|
42828
|
+
const descSuffix = fieldDesc ? ` ${typeStr.padEnd(maxTypeLen)} ${escapeTerminalTextForDisplay(fieldDesc)}` : ` ${typeStr}`;
|
|
42666
42829
|
ctx.out(` ${c.cyan}${padded}${c.reset} ${c.dim}${descSuffix}${c.reset}`);
|
|
42667
42830
|
}
|
|
42668
42831
|
}
|
|
@@ -42694,7 +42857,7 @@ var handleView7 = async (ctx, { flags, args }) => {
|
|
|
42694
42857
|
const shapeData = shapeVersion?.data;
|
|
42695
42858
|
const shapeDescription = shapeData?.description;
|
|
42696
42859
|
if (typeof shapeDescription === "string" && shapeDescription) {
|
|
42697
|
-
ctx.out(` ${c.dim}${shapeDescription}${c.reset}`);
|
|
42860
|
+
ctx.out(` ${c.dim}${escapeTerminalTextForDisplay(shapeDescription)}${c.reset}`);
|
|
42698
42861
|
}
|
|
42699
42862
|
const componentRef = result.componentRef;
|
|
42700
42863
|
if (componentRef) {
|
|
@@ -42706,7 +42869,7 @@ var handleView7 = async (ctx, { flags, args }) => {
|
|
|
42706
42869
|
for (const [fieldName, fieldType] of Object.entries(fields)) {
|
|
42707
42870
|
const typeStr = displayFieldType(fieldType);
|
|
42708
42871
|
const fieldDesc = fieldDescriptionFromSpec(fieldType);
|
|
42709
|
-
const descSuffix = fieldDesc ? ` ${c.dim}${fieldDesc}${c.reset}` : "";
|
|
42872
|
+
const descSuffix = fieldDesc ? ` ${c.dim}${escapeTerminalTextForDisplay(fieldDesc)}${c.reset}` : "";
|
|
42710
42873
|
const safeFieldName = escapeFieldNameForDisplay(fieldName);
|
|
42711
42874
|
ctx.out(` ${c.cyan}${safeFieldName}${c.reset}: ${c.dim}${typeStr}${c.reset}${descSuffix}`);
|
|
42712
42875
|
}
|
|
@@ -42807,8 +42970,10 @@ var handleShapeRename = async (ctx, { args }) => {
|
|
|
42807
42970
|
}
|
|
42808
42971
|
const { org, repo } = parseOrgRepo(getRepoRef(ctx), ctx.config);
|
|
42809
42972
|
const c = ctx.colors;
|
|
42810
|
-
await ctx.client.shape.rename(org, repo, oldName, newName);
|
|
42811
|
-
ctx
|
|
42973
|
+
const result = await ctx.client.shape.rename(org, repo, oldName, newName);
|
|
42974
|
+
writeOutput(ctx, { ...result, oldName, newName }, () => {
|
|
42975
|
+
ctx.out(`${c.green}Renamed shape${c.reset} ${c.magenta}${oldName}${c.reset} → ${c.magenta}${newName}${c.reset}`);
|
|
42976
|
+
});
|
|
42812
42977
|
};
|
|
42813
42978
|
|
|
42814
42979
|
// ../../packages/warmhub-cli/src/domains/shape.ts
|
|
@@ -43265,6 +43430,11 @@ function renderResponseSnippet(out, c, snippet, baseIndent) {
|
|
|
43265
43430
|
out(`${baseIndent} ${c.dim}${line}${c.reset}`);
|
|
43266
43431
|
}
|
|
43267
43432
|
}
|
|
43433
|
+
function renderErrorMessageLine(out, c, code, message, baseIndent) {
|
|
43434
|
+
const safeCode = code ? `${escapeTerminalTextForDisplay(code)}: ` : "";
|
|
43435
|
+
const safeMessage = escapeTerminalTextForDisplay(message);
|
|
43436
|
+
out(`${baseIndent}${c.red}${safeCode}${safeMessage}${c.reset}`);
|
|
43437
|
+
}
|
|
43268
43438
|
function statusColor(c, status) {
|
|
43269
43439
|
switch (status) {
|
|
43270
43440
|
case "completed":
|
|
@@ -43305,11 +43475,10 @@ function renderSubscriptionLog(out, statusOut, c, subscriptionName, result) {
|
|
|
43305
43475
|
const sourceLabel = (item.matchedOperationIndexes?.length ?? 0) > 0 ? `${c.cyan}write${c.reset}` : `${c.magenta}cron tick${c.reset}`;
|
|
43306
43476
|
const matched = (item.matchedOperationIndexes ?? []).join(",") || "-";
|
|
43307
43477
|
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}${
|
|
43478
|
+
const idSuffix = item.runId ? ` ${c.dim}run ${item.runId}${c.reset}` : item.deliveryId ? ` ${c.dim}delivery ${item.deliveryId}${c.reset}` : "";
|
|
43479
|
+
out(` ${status}${attemptSuffix} ${c.dim}${time}${c.reset}${idSuffix} ${sourceLabel} ops[${matched}]`);
|
|
43310
43480
|
if ((displayStatus === "failed_terminal" || displayStatus === "dead_letter") && item.lastErrorMessage) {
|
|
43311
|
-
|
|
43312
|
-
out(` ${c.red}${code}${item.lastErrorMessage}${c.reset}`);
|
|
43481
|
+
renderErrorMessageLine(out, c, item.lastErrorCode, item.lastErrorMessage, " ");
|
|
43313
43482
|
}
|
|
43314
43483
|
if ((displayStatus === "failed_terminal" || displayStatus === "dead_letter") && item.lastResponseSnippet) {
|
|
43315
43484
|
renderResponseSnippet(out, c, item.lastResponseSnippet, " ");
|
|
@@ -43420,7 +43589,12 @@ var handleLog = async (ctx, { flags, args }) => {
|
|
|
43420
43589
|
if (!name) {
|
|
43421
43590
|
usageError("Usage: wh sub log <name> [--repo org/repo]", "wh sub log my-sub");
|
|
43422
43591
|
}
|
|
43423
|
-
const
|
|
43592
|
+
const scope = resolveSubScope(ctx, flags);
|
|
43593
|
+
if (!scope.repoName) {
|
|
43594
|
+
usageError("Usage: wh sub log <name> [--repo org/repo]", "wh sub log my-sub --repo myorg/myrepo");
|
|
43595
|
+
}
|
|
43596
|
+
const org = scope.orgName;
|
|
43597
|
+
const repo = scope.repoName;
|
|
43424
43598
|
if (ctx.liveMode) {
|
|
43425
43599
|
await runLive({
|
|
43426
43600
|
apiUrl: ctx.config.apiUrl,
|
|
@@ -43464,8 +43638,7 @@ var handleAttempts = async (ctx, { args }) => {
|
|
|
43464
43638
|
const http = attempt.httpStatus ? ` ${c.dim}HTTP ${attempt.httpStatus}${c.reset}` : "";
|
|
43465
43639
|
ctx.out(` #${attempt.attempt} ${sc}${attempt.status}${c.reset}${dur}${http}`);
|
|
43466
43640
|
if (attempt.errorMessage) {
|
|
43467
|
-
|
|
43468
|
-
ctx.out(` ${c.red}${code}${attempt.errorMessage}${c.reset}`);
|
|
43641
|
+
renderErrorMessageLine(ctx.out, c, attempt.errorCode, attempt.errorMessage, " ");
|
|
43469
43642
|
}
|
|
43470
43643
|
if (attempt.status === "failed" && attempt.responseSnippet) {
|
|
43471
43644
|
renderResponseSnippet(ctx.out, c, attempt.responseSnippet, " ");
|
|
@@ -43558,6 +43731,9 @@ var SUB_DOMAIN = defineDomain({
|
|
|
43558
43731
|
summary: "Tail subscription delivery feed with failed response snippets",
|
|
43559
43732
|
args: "<name>",
|
|
43560
43733
|
flags: logFlags,
|
|
43734
|
+
rejectedFlags: {
|
|
43735
|
+
org: "Use repo-scoped delivery logs: wh sub log my-sub --repo myorg/myrepo"
|
|
43736
|
+
},
|
|
43561
43737
|
examples: [
|
|
43562
43738
|
"# Show recent deliveries",
|
|
43563
43739
|
" $ wh sub log signal-hook --repo org/repo",
|
|
@@ -43566,7 +43742,10 @@ var SUB_DOMAIN = defineDomain({
|
|
|
43566
43742
|
" $ wh sub log daily-digest --repo org/repo",
|
|
43567
43743
|
"",
|
|
43568
43744
|
"# Follow deliveries in live mode",
|
|
43569
|
-
" $ wh sub log signal-hook --repo org/repo --live"
|
|
43745
|
+
" $ wh sub log signal-hook --repo org/repo --live",
|
|
43746
|
+
"",
|
|
43747
|
+
"# Delivery logs currently require a repo-scoped subscription",
|
|
43748
|
+
" $ wh sub log signal-hook --repo org/repo"
|
|
43570
43749
|
],
|
|
43571
43750
|
handler: handleLog
|
|
43572
43751
|
},
|
|
@@ -44523,9 +44702,9 @@ function extractFlagsForVerb(flags, verbSpec) {
|
|
|
44523
44702
|
}
|
|
44524
44703
|
return flags;
|
|
44525
44704
|
}
|
|
44526
|
-
return extractFlags(flags, verbSpec.flags);
|
|
44705
|
+
return extractFlags(flags, verbSpec.flags, verbSpec.rejectedFlags);
|
|
44527
44706
|
}
|
|
44528
|
-
function extractFlags(flags, specs) {
|
|
44707
|
+
function extractFlags(flags, specs, rejectedFlags = {}) {
|
|
44529
44708
|
const normalized = { ...flags };
|
|
44530
44709
|
const result = {};
|
|
44531
44710
|
const specLongs = specs.map((s) => s.long);
|
|
@@ -44560,11 +44739,19 @@ function extractFlags(flags, specs) {
|
|
|
44560
44739
|
}
|
|
44561
44740
|
for (const key of Object.keys(normalized)) {
|
|
44562
44741
|
if (key.length === 1) {
|
|
44742
|
+
const rejectedHint2 = rejectedFlags[key];
|
|
44743
|
+
if (rejectedHint2) {
|
|
44744
|
+
throw new CliError(2 /* UserInput */, "USER_INPUT", `Unknown flag: -${key}`, undefined, rejectedHint2);
|
|
44745
|
+
}
|
|
44563
44746
|
if (!allowedShorts.has(key) && !isGlobalFlag(key)) {
|
|
44564
44747
|
throw new CliError(2 /* UserInput */, "USER_INPUT", `Unknown flag: -${key}`);
|
|
44565
44748
|
}
|
|
44566
44749
|
continue;
|
|
44567
44750
|
}
|
|
44751
|
+
const rejectedHint = rejectedFlags[key];
|
|
44752
|
+
if (rejectedHint) {
|
|
44753
|
+
throw new CliError(2 /* UserInput */, "USER_INPUT", `Unknown flag: --${key}`, undefined, rejectedHint);
|
|
44754
|
+
}
|
|
44568
44755
|
if (!allowedLongs.has(key) && !isGlobalFlag(key)) {
|
|
44569
44756
|
const hint = findClosest(key, [...allowedLongs]);
|
|
44570
44757
|
throw new CliError(2 /* UserInput */, "USER_INPUT", `Unknown flag: --${key}`, undefined, hint ? `Did you mean '--${hint}'?` : undefined);
|
|
@@ -45574,7 +45761,7 @@ function resolveLogLevel(flags, env) {
|
|
|
45574
45761
|
// package.json
|
|
45575
45762
|
var package_default3 = {
|
|
45576
45763
|
name: "@warmhub/cli",
|
|
45577
|
-
version: "0.
|
|
45764
|
+
version: "0.64.0",
|
|
45578
45765
|
private: false,
|
|
45579
45766
|
type: "module",
|
|
45580
45767
|
description: "The wh CLI for WarmHub — create repos, commit and query data, and compound knowledge with your AI agents.",
|
|
@@ -45615,6 +45802,7 @@ var package_default3 = {
|
|
|
45615
45802
|
},
|
|
45616
45803
|
scripts: {
|
|
45617
45804
|
build: "bun run scripts/build.ts",
|
|
45805
|
+
prepack: "bun run build",
|
|
45618
45806
|
"check:boundary": "node ../../scripts/lint/boundary-imports.mjs bin src scripts",
|
|
45619
45807
|
"audit:bundle": "bun run scripts/audit-bundle.ts",
|
|
45620
45808
|
"audit:pack": "bun run scripts/audit-pack.ts",
|
|
@@ -46228,4 +46416,4 @@ if (!updateCheckSuppressedByArgv && shouldRunUpdateCheck(updateEligibility)) {
|
|
|
46228
46416
|
var interceptedExitCode = await maybeHandleComponentShellBoundary(dispatchArgv);
|
|
46229
46417
|
process.exitCode = interceptedExitCode === undefined ? await runCli(dispatchArgv, { version: package_default3.version }) : interceptedExitCode;
|
|
46230
46418
|
|
|
46231
|
-
//# debugId=
|
|
46419
|
+
//# debugId=7FF3388CDD4F972C64756E2164756E21
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@warmhub/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.64.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",
|