@warmhub/cli 0.52.1 → 0.53.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 +311 -233
- package/package.json +1 -1
package/dist/wh.js
CHANGED
|
@@ -18914,6 +18914,10 @@ var RUNTIME_ACCESS_BUILTINS = new Set([
|
|
|
18914
18914
|
"ComponentConfig",
|
|
18915
18915
|
...BUILTIN_SHAPE_NAMES
|
|
18916
18916
|
]);
|
|
18917
|
+
var SUBSCRIPTION_TRIGGER_BUILTINS = new Set([
|
|
18918
|
+
"ComponentInstall",
|
|
18919
|
+
"ComponentConfig"
|
|
18920
|
+
]);
|
|
18917
18921
|
function validateProvisioning(obj, path, errors) {
|
|
18918
18922
|
if (!("provisioning" in obj))
|
|
18919
18923
|
return;
|
|
@@ -19206,8 +19210,19 @@ function validateManifestSemantics(manifest) {
|
|
|
19206
19210
|
}
|
|
19207
19211
|
const shapeNames = new Set(manifest.shapes.map((s) => s.name));
|
|
19208
19212
|
const credentialNames = new Set(manifest.credentials.map((c) => c.name));
|
|
19209
|
-
const
|
|
19213
|
+
const knownSubscriptionTriggerShapes = new Set([
|
|
19214
|
+
...shapeNames,
|
|
19215
|
+
...SUBSCRIPTION_TRIGGER_BUILTINS
|
|
19216
|
+
]);
|
|
19217
|
+
const knownSeedShapes = new Set([...shapeNames, "ComponentConfig"]);
|
|
19210
19218
|
for (const sub of manifest.subscriptions) {
|
|
19219
|
+
if (sub.trigger.kind === "event" && !knownSubscriptionTriggerShapes.has(sub.trigger.shape)) {
|
|
19220
|
+
findings.push({
|
|
19221
|
+
level: "error",
|
|
19222
|
+
code: "MISSING_SUBSCRIPTION_TRIGGER_SHAPE_REF",
|
|
19223
|
+
message: `subscription "${sub.name}" trigger references shape "${sub.trigger.shape}" which is not declared and is not a supported subscription trigger built-in`
|
|
19224
|
+
});
|
|
19225
|
+
}
|
|
19211
19226
|
if (sub.credentials) {
|
|
19212
19227
|
if (sub.credentials.length > 1) {
|
|
19213
19228
|
findings.push({
|
|
@@ -19236,7 +19251,7 @@ function validateManifestSemantics(manifest) {
|
|
|
19236
19251
|
}
|
|
19237
19252
|
}
|
|
19238
19253
|
for (const seed of manifest.seeds) {
|
|
19239
|
-
if (!
|
|
19254
|
+
if (!knownSeedShapes.has(seed.shape)) {
|
|
19240
19255
|
findings.push({
|
|
19241
19256
|
level: "error",
|
|
19242
19257
|
code: "MISSING_SHAPE_REF",
|
|
@@ -19381,6 +19396,11 @@ function joinFieldIdentityPath(...segments) {
|
|
|
19381
19396
|
function joinFieldPathWithEscaper(escapeSegment, segments) {
|
|
19382
19397
|
return segments.map((segment) => typeof segment === "number" ? `[${segment}]` : escapeSegment(segment)).join(".").replace(/\.\[/g, "[");
|
|
19383
19398
|
}
|
|
19399
|
+
// ../../packages/rules/src/permission-scopes.ts
|
|
19400
|
+
var PUBLIC_ORG_PERMISSIONS = new Set([
|
|
19401
|
+
"org:read",
|
|
19402
|
+
"components:read"
|
|
19403
|
+
]);
|
|
19384
19404
|
// ../../packages/rules/src/platform-status.ts
|
|
19385
19405
|
var PLATFORM_STATUS_CATALOG_SHAPE = "PlatformStatusCatalog";
|
|
19386
19406
|
var PLATFORM_STATUS_CATALOG_NAME = "main";
|
|
@@ -21213,6 +21233,7 @@ function nestedObjectFields(typeDef) {
|
|
|
21213
21233
|
}
|
|
21214
21234
|
// ../../packages/rules/src/system-components/system.ts
|
|
21215
21235
|
var SYSTEM_COMPONENT_ID = "com.warmhub.system";
|
|
21236
|
+
var SYSTEM_REGISTERED_COMPONENT_REF = "warmhub/system";
|
|
21216
21237
|
var COMPONENT_INSTALL_FIELDS = {
|
|
21217
21238
|
componentId: "string",
|
|
21218
21239
|
name: "string",
|
|
@@ -21273,7 +21294,7 @@ function findSystemComponent(componentId) {
|
|
|
21273
21294
|
// ../../packages/sdk-ts/package.json
|
|
21274
21295
|
var package_default = {
|
|
21275
21296
|
name: "@warmhub/sdk-ts",
|
|
21276
|
-
version: "0.52.
|
|
21297
|
+
version: "0.52.1",
|
|
21277
21298
|
private: false,
|
|
21278
21299
|
type: "module",
|
|
21279
21300
|
description: "The TypeScript SDK for WarmHub — create repos, commit and query data, and compound knowledge with your AI agents.",
|
|
@@ -21601,7 +21622,7 @@ async function submitOperationsViaStream(client, args) {
|
|
|
21601
21622
|
orgName: args.orgName,
|
|
21602
21623
|
repoName: args.repoName,
|
|
21603
21624
|
streamId,
|
|
21604
|
-
|
|
21625
|
+
componentRef: args.componentRef,
|
|
21605
21626
|
committer: args.committer,
|
|
21606
21627
|
message: args.message,
|
|
21607
21628
|
operations: chunk
|
|
@@ -22107,23 +22128,9 @@ class WarmHubClient {
|
|
|
22107
22128
|
}
|
|
22108
22129
|
};
|
|
22109
22130
|
access = {
|
|
22110
|
-
|
|
22131
|
+
resolve: async (input) => {
|
|
22111
22132
|
try {
|
|
22112
|
-
return await this.trpc.access.
|
|
22113
|
-
orgName,
|
|
22114
|
-
repoName,
|
|
22115
|
-
permission
|
|
22116
|
-
});
|
|
22117
|
-
} catch (error) {
|
|
22118
|
-
throw toWarmHubError(error);
|
|
22119
|
-
}
|
|
22120
|
-
},
|
|
22121
|
-
checkOrgPermission: async (orgName, permission) => {
|
|
22122
|
-
try {
|
|
22123
|
-
return await this.trpc.access.checkOrgPermission.query({
|
|
22124
|
-
orgName,
|
|
22125
|
-
permission
|
|
22126
|
-
});
|
|
22133
|
+
return await this.trpc.access.resolve.query(input);
|
|
22127
22134
|
} catch (error) {
|
|
22128
22135
|
throw toWarmHubError(error);
|
|
22129
22136
|
}
|
|
@@ -22177,12 +22184,12 @@ class WarmHubClient {
|
|
|
22177
22184
|
throw toWarmHubError(error);
|
|
22178
22185
|
}
|
|
22179
22186
|
},
|
|
22180
|
-
get: async (orgName, repoName,
|
|
22187
|
+
get: async (orgName, repoName, componentRef) => {
|
|
22181
22188
|
try {
|
|
22182
22189
|
return await this.trpc.component.get.query({
|
|
22183
22190
|
orgName,
|
|
22184
22191
|
repoName,
|
|
22185
|
-
|
|
22192
|
+
componentRef
|
|
22186
22193
|
});
|
|
22187
22194
|
} catch (error) {
|
|
22188
22195
|
throw toWarmHubError(error);
|
|
@@ -22277,7 +22284,7 @@ class WarmHubClient {
|
|
|
22277
22284
|
repoName,
|
|
22278
22285
|
committer: opts?.committer,
|
|
22279
22286
|
message,
|
|
22280
|
-
|
|
22287
|
+
componentRef: opts?.componentRef,
|
|
22281
22288
|
chunkSize: opts?.chunkSize,
|
|
22282
22289
|
skipExisting: opts?.skipExisting,
|
|
22283
22290
|
streamId: opts?.streamId,
|
|
@@ -22715,7 +22722,7 @@ class WarmHubClient {
|
|
|
22715
22722
|
orgName,
|
|
22716
22723
|
repoName,
|
|
22717
22724
|
match: opts?.match,
|
|
22718
|
-
|
|
22725
|
+
componentRef: opts?.componentRef,
|
|
22719
22726
|
excludeComponents: opts?.excludeComponents,
|
|
22720
22727
|
includeRetracted: opts?.includeRetracted
|
|
22721
22728
|
});
|
|
@@ -23061,7 +23068,7 @@ class WarmHubClient {
|
|
|
23061
23068
|
includeRetracted: opts?.includeRetracted,
|
|
23062
23069
|
limit: opts?.limit,
|
|
23063
23070
|
cursor: opts?.cursor,
|
|
23064
|
-
|
|
23071
|
+
componentRef: opts?.componentRef,
|
|
23065
23072
|
excludeComponents: opts?.excludeComponents,
|
|
23066
23073
|
excludeInfraShapes: opts?.excludeInfraShapes,
|
|
23067
23074
|
where: opts?.where
|
|
@@ -23282,7 +23289,7 @@ class WarmHubClient {
|
|
|
23282
23289
|
resolveCollections: opts?.resolveCollections,
|
|
23283
23290
|
limit: opts?.limit,
|
|
23284
23291
|
cursor: opts?.cursor,
|
|
23285
|
-
|
|
23292
|
+
componentRef: opts?.componentRef,
|
|
23286
23293
|
excludeComponents: opts?.excludeComponents,
|
|
23287
23294
|
excludeInfraShapes: opts?.excludeInfraShapes,
|
|
23288
23295
|
where: opts?.where
|
|
@@ -23313,7 +23320,7 @@ class WarmHubClient {
|
|
|
23313
23320
|
resolveCollections: opts?.resolveCollections,
|
|
23314
23321
|
limit: opts?.limit,
|
|
23315
23322
|
cursor: opts?.cursor,
|
|
23316
|
-
|
|
23323
|
+
componentRef: opts?.componentRef,
|
|
23317
23324
|
excludeComponents: opts?.excludeComponents,
|
|
23318
23325
|
excludeInfraShapes: opts?.excludeInfraShapes,
|
|
23319
23326
|
mode: opts?.mode
|
|
@@ -23334,7 +23341,7 @@ class WarmHubClient {
|
|
|
23334
23341
|
match: opts?.match,
|
|
23335
23342
|
includeRetracted: opts?.includeRetracted,
|
|
23336
23343
|
resolveCollections: opts?.resolveCollections,
|
|
23337
|
-
|
|
23344
|
+
componentRef: opts?.componentRef,
|
|
23338
23345
|
excludeComponents: opts?.excludeComponents,
|
|
23339
23346
|
excludeInfraShapes: opts?.excludeInfraShapes,
|
|
23340
23347
|
where: opts?.where
|
|
@@ -25176,7 +25183,7 @@ function loadProfileStore(path) {
|
|
|
25176
25183
|
} catch (cause) {
|
|
25177
25184
|
throw corruptedAuthError(p, cause);
|
|
25178
25185
|
}
|
|
25179
|
-
if (parsed === null || typeof parsed !== "object" || parsed.version !== 1 || parsed.profiles === null || typeof parsed.profiles !== "object") {
|
|
25186
|
+
if (parsed === null || typeof parsed !== "object" || parsed.version !== 1 || parsed.profiles === null || typeof parsed.profiles !== "object" || Array.isArray(parsed.profiles)) {
|
|
25180
25187
|
throw corruptedAuthError(p);
|
|
25181
25188
|
}
|
|
25182
25189
|
return parsed;
|
|
@@ -25481,20 +25488,34 @@ function recordBenchmarkResponse(response, benchmarkId) {
|
|
|
25481
25488
|
benchmarkTelemetry.requestDbQueryCountSum += requestDbQueryCount;
|
|
25482
25489
|
}
|
|
25483
25490
|
}
|
|
25484
|
-
function createBenchmarkAwareFetch(benchmarkId) {
|
|
25485
|
-
if (!benchmarkId)
|
|
25491
|
+
function createBenchmarkAwareFetch(benchmarkId, signal) {
|
|
25492
|
+
if (!benchmarkId && !signal)
|
|
25486
25493
|
return;
|
|
25487
25494
|
return async (input, init) => {
|
|
25488
25495
|
const headers = new Headers(init?.headers);
|
|
25489
|
-
|
|
25496
|
+
if (benchmarkId)
|
|
25497
|
+
headers.set(BENCHMARK_HEADER, benchmarkId);
|
|
25490
25498
|
const response = await fetch(input, {
|
|
25491
25499
|
...init,
|
|
25492
|
-
headers
|
|
25500
|
+
headers,
|
|
25501
|
+
signal: mergeAbortSignals(init?.signal, signal)
|
|
25493
25502
|
});
|
|
25494
|
-
|
|
25503
|
+
if (benchmarkId)
|
|
25504
|
+
recordBenchmarkResponse(response, benchmarkId);
|
|
25495
25505
|
return response;
|
|
25496
25506
|
};
|
|
25497
25507
|
}
|
|
25508
|
+
function mergeAbortSignals(requestSignal, liveSignal) {
|
|
25509
|
+
if (!requestSignal)
|
|
25510
|
+
return liveSignal;
|
|
25511
|
+
if (!liveSignal)
|
|
25512
|
+
return requestSignal;
|
|
25513
|
+
if (requestSignal.aborted)
|
|
25514
|
+
return requestSignal;
|
|
25515
|
+
if (liveSignal.aborted)
|
|
25516
|
+
return liveSignal;
|
|
25517
|
+
return AbortSignal.any([requestSignal, liveSignal]);
|
|
25518
|
+
}
|
|
25498
25519
|
function resetBenchmarkTelemetry() {
|
|
25499
25520
|
benchmarkTelemetry = emptyBenchmarkTelemetry();
|
|
25500
25521
|
}
|
|
@@ -25522,18 +25543,34 @@ function createClient(config, opts = {}) {
|
|
|
25522
25543
|
function wantsStructuredLiveOutput(format) {
|
|
25523
25544
|
return format === "json" || format === "jsonl";
|
|
25524
25545
|
}
|
|
25546
|
+
var LIVE_ABORTED = Symbol("live-aborted");
|
|
25547
|
+
function pollUntilAbort(poll, signal) {
|
|
25548
|
+
if (signal.aborted)
|
|
25549
|
+
return Promise.resolve(LIVE_ABORTED);
|
|
25550
|
+
return new Promise((resolve, reject) => {
|
|
25551
|
+
const onAbort = () => resolve(LIVE_ABORTED);
|
|
25552
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
25553
|
+
poll.then((result) => {
|
|
25554
|
+
signal.removeEventListener("abort", onAbort);
|
|
25555
|
+
resolve(result);
|
|
25556
|
+
}, (error) => {
|
|
25557
|
+
signal.removeEventListener("abort", onAbort);
|
|
25558
|
+
reject(error);
|
|
25559
|
+
});
|
|
25560
|
+
});
|
|
25561
|
+
}
|
|
25525
25562
|
async function runLive(opts) {
|
|
25526
25563
|
const auth = opts.auth ?? {
|
|
25527
25564
|
getToken: async () => await getValidToken(opts.profile) ?? undefined
|
|
25528
25565
|
};
|
|
25529
25566
|
const benchmarkId = process.env.WH_BENCHMARK_ID?.trim();
|
|
25567
|
+
const controller = new AbortController;
|
|
25530
25568
|
const client = new WarmHubClient({
|
|
25531
25569
|
apiUrl: opts.apiUrl,
|
|
25532
25570
|
auth,
|
|
25533
|
-
fetch: createBenchmarkAwareFetch(benchmarkId),
|
|
25571
|
+
fetch: createBenchmarkAwareFetch(benchmarkId, controller.signal),
|
|
25534
25572
|
functionLogs: opts.functionLogs
|
|
25535
25573
|
});
|
|
25536
|
-
const controller = new AbortController;
|
|
25537
25574
|
if (opts.signal) {
|
|
25538
25575
|
if (opts.signal.aborted)
|
|
25539
25576
|
controller.abort();
|
|
@@ -25557,7 +25594,12 @@ async function runLive(opts) {
|
|
|
25557
25594
|
startTimer = setTimeout(() => controller.abort(), opts.startTimeoutMs);
|
|
25558
25595
|
}
|
|
25559
25596
|
while (!controller.signal.aborted) {
|
|
25560
|
-
const
|
|
25597
|
+
const poll = opts.poll(client, controller.signal);
|
|
25598
|
+
const result = await pollUntilAbort(poll, controller.signal);
|
|
25599
|
+
if (result === LIVE_ABORTED) {
|
|
25600
|
+
poll.catch(() => {});
|
|
25601
|
+
break;
|
|
25602
|
+
}
|
|
25561
25603
|
updates += 1;
|
|
25562
25604
|
if (startTimer) {
|
|
25563
25605
|
clearTimeout(startTimer);
|
|
@@ -26570,14 +26612,14 @@ function renderBatchView(out, c, result, wrefs, flagsVersion) {
|
|
|
26570
26612
|
// ../../packages/warmhub-cli/src/domains/thing/graph.ts
|
|
26571
26613
|
var graphFlags = {
|
|
26572
26614
|
depth: flag.number({
|
|
26573
|
-
description: "Resolve
|
|
26615
|
+
description: "Resolve outbound wref fields, assertion backlinks, and assertion about targets to this depth (default: 2, max: 5)"
|
|
26574
26616
|
}),
|
|
26575
26617
|
version: flag.number({ description: "Specific version number" })
|
|
26576
26618
|
};
|
|
26577
26619
|
var handleThingGraph = async (ctx, { flags, args }) => {
|
|
26578
26620
|
const wref = args[0];
|
|
26579
26621
|
if (!wref) {
|
|
26580
|
-
usageError("Usage: wh thing graph <wref> [--depth N]", "wh thing graph Game/base");
|
|
26622
|
+
usageError("Usage: wh thing graph <wref> [--depth N]", "wh thing graph Game/base", "wh thing refs Game/base --inbound");
|
|
26581
26623
|
}
|
|
26582
26624
|
const depth = flags.depth;
|
|
26583
26625
|
if (depth !== undefined && (depth < 1 || depth > 5)) {
|
|
@@ -26758,8 +26800,8 @@ function validateKind(value, flagName = "--kind") {
|
|
|
26758
26800
|
function resolveRepoContext(ctx) {
|
|
26759
26801
|
return parseOrgRepo(getRepoRef(ctx), ctx.config);
|
|
26760
26802
|
}
|
|
26761
|
-
function validateComponentFilters(
|
|
26762
|
-
if (
|
|
26803
|
+
function validateComponentFilters(componentRef, excludeComponents, ...examples) {
|
|
26804
|
+
if (componentRef && excludeComponents) {
|
|
26763
26805
|
usageError("Cannot combine --component with --exclude-components.", ...examples);
|
|
26764
26806
|
}
|
|
26765
26807
|
}
|
|
@@ -26835,7 +26877,7 @@ var headFlags = {
|
|
|
26835
26877
|
description: "Include retracted things"
|
|
26836
26878
|
}),
|
|
26837
26879
|
component: flag.string({
|
|
26838
|
-
description: "Filter to things owned by this component
|
|
26880
|
+
description: "Filter to things owned by this component (Org/Name ref)"
|
|
26839
26881
|
}),
|
|
26840
26882
|
"exclude-components": flag.boolean({
|
|
26841
26883
|
description: "Exclude component-owned things from results"
|
|
@@ -26861,15 +26903,15 @@ var handleHead = async (ctx, { flags, args }) => {
|
|
|
26861
26903
|
if (cursor || all || limit || ctx.liveMode) {
|
|
26862
26904
|
usageError("Usage: wh thing list --count [--shape SHAPE] [--kind KIND] [--match PATTERN]", "wh thing list --shape Player --count");
|
|
26863
26905
|
}
|
|
26864
|
-
const
|
|
26906
|
+
const componentRef2 = flags.component;
|
|
26865
26907
|
const strictExclude2 = !!flags["exclude-components"];
|
|
26866
|
-
validateComponentFilters(
|
|
26908
|
+
validateComponentFilters(componentRef2, strictExclude2, "wh thing list --component acme/veritas");
|
|
26867
26909
|
return handleCount(ctx, org, repo, {
|
|
26868
26910
|
shape,
|
|
26869
26911
|
kind,
|
|
26870
26912
|
match,
|
|
26871
26913
|
includeRetracted,
|
|
26872
|
-
|
|
26914
|
+
componentRef: componentRef2,
|
|
26873
26915
|
excludeComponents: strictExclude2,
|
|
26874
26916
|
excludeInfraShapes: !strictExclude2 && !shape,
|
|
26875
26917
|
where: where.length > 0 ? where : undefined
|
|
@@ -26883,10 +26925,10 @@ var handleHead = async (ctx, { flags, args }) => {
|
|
|
26883
26925
|
}
|
|
26884
26926
|
const boundedLimit = Math.min(limit ?? DEFAULT_PAGE_LIMIT, MAX_PAGE_LIMIT);
|
|
26885
26927
|
const pageLimit = all ? Math.min(limit ?? AUTO_PAGE_LIMIT, MAX_PAGE_LIMIT) : boundedLimit;
|
|
26886
|
-
const
|
|
26928
|
+
const componentRef = flags.component;
|
|
26887
26929
|
const hasShape = !!shape;
|
|
26888
26930
|
const strictExclude = !!flags["exclude-components"];
|
|
26889
|
-
validateComponentFilters(
|
|
26931
|
+
validateComponentFilters(componentRef, strictExclude, "wh thing list --component acme/veritas");
|
|
26890
26932
|
const excludeComponents = strictExclude;
|
|
26891
26933
|
const excludeInfraShapes = !strictExclude && !hasShape;
|
|
26892
26934
|
const headOpts = {
|
|
@@ -26896,7 +26938,7 @@ var handleHead = async (ctx, { flags, args }) => {
|
|
|
26896
26938
|
includeRetracted,
|
|
26897
26939
|
limit: pageLimit,
|
|
26898
26940
|
cursor,
|
|
26899
|
-
|
|
26941
|
+
componentRef,
|
|
26900
26942
|
excludeComponents,
|
|
26901
26943
|
excludeInfraShapes,
|
|
26902
26944
|
where: where.length > 0 ? where : undefined
|
|
@@ -26928,7 +26970,7 @@ var handleHead = async (ctx, { flags, args }) => {
|
|
|
26928
26970
|
includeRetracted,
|
|
26929
26971
|
limit: pageLimit,
|
|
26930
26972
|
cursor,
|
|
26931
|
-
|
|
26973
|
+
componentRef,
|
|
26932
26974
|
excludeComponents,
|
|
26933
26975
|
excludeInfraShapes,
|
|
26934
26976
|
where: where.length > 0 ? where : undefined
|
|
@@ -26939,7 +26981,7 @@ var handleHead = async (ctx, { flags, args }) => {
|
|
|
26939
26981
|
includeRetracted,
|
|
26940
26982
|
limit: boundedLimit,
|
|
26941
26983
|
cursor,
|
|
26942
|
-
|
|
26984
|
+
componentRef,
|
|
26943
26985
|
excludeComponents,
|
|
26944
26986
|
excludeInfraShapes,
|
|
26945
26987
|
where: where.length > 0 ? where : undefined
|
|
@@ -26960,7 +27002,7 @@ async function fetchAllHeadPages(ctx, org, repo, opts) {
|
|
|
26960
27002
|
includeRetracted: opts.includeRetracted,
|
|
26961
27003
|
limit: opts.limit,
|
|
26962
27004
|
cursor,
|
|
26963
|
-
|
|
27005
|
+
componentRef: opts.componentRef,
|
|
26964
27006
|
excludeComponents: opts.excludeComponents,
|
|
26965
27007
|
excludeInfraShapes: opts.excludeInfraShapes,
|
|
26966
27008
|
where: opts.where
|
|
@@ -26992,7 +27034,7 @@ var queryFlags = {
|
|
|
26992
27034
|
description: "Include assertions about collections (Pair/Triple/Set/List) containing the target. Only applies with --about."
|
|
26993
27035
|
}),
|
|
26994
27036
|
component: flag.string({
|
|
26995
|
-
description: "Filter to things owned by this component
|
|
27037
|
+
description: "Filter to things owned by this component (Org/Name ref)"
|
|
26996
27038
|
}),
|
|
26997
27039
|
"exclude-components": flag.boolean({
|
|
26998
27040
|
description: "Exclude component-owned things from results"
|
|
@@ -27014,10 +27056,10 @@ var handleQuery = async (ctx, { flags }) => {
|
|
|
27014
27056
|
const count = flags.count;
|
|
27015
27057
|
const includeRetracted = flags["include-retracted"];
|
|
27016
27058
|
const resolveCollections = flags["resolve-collections"];
|
|
27017
|
-
const
|
|
27059
|
+
const componentRef = flags.component;
|
|
27018
27060
|
const hasShape = !!shape;
|
|
27019
27061
|
const strictExclude = !!flags["exclude-components"];
|
|
27020
|
-
validateComponentFilters(
|
|
27062
|
+
validateComponentFilters(componentRef, strictExclude, "wh thing query --component acme/veritas");
|
|
27021
27063
|
const excludeComponents = strictExclude;
|
|
27022
27064
|
const excludeInfraShapes = !strictExclude && !hasShape;
|
|
27023
27065
|
const c = ctx.colors;
|
|
@@ -27034,7 +27076,7 @@ var handleQuery = async (ctx, { flags }) => {
|
|
|
27034
27076
|
about,
|
|
27035
27077
|
includeRetracted,
|
|
27036
27078
|
resolveCollections,
|
|
27037
|
-
|
|
27079
|
+
componentRef,
|
|
27038
27080
|
excludeComponents,
|
|
27039
27081
|
excludeInfraShapes,
|
|
27040
27082
|
where: where.length > 0 ? where : undefined
|
|
@@ -27057,7 +27099,7 @@ var handleQuery = async (ctx, { flags }) => {
|
|
|
27057
27099
|
resolveCollections,
|
|
27058
27100
|
limit: pageLimit,
|
|
27059
27101
|
cursor,
|
|
27060
|
-
|
|
27102
|
+
componentRef,
|
|
27061
27103
|
excludeComponents,
|
|
27062
27104
|
excludeInfraShapes,
|
|
27063
27105
|
where: where.length > 0 ? where : undefined
|
|
@@ -27091,7 +27133,7 @@ var handleQuery = async (ctx, { flags }) => {
|
|
|
27091
27133
|
resolveCollections,
|
|
27092
27134
|
limit: pageLimit,
|
|
27093
27135
|
cursor,
|
|
27094
|
-
|
|
27136
|
+
componentRef,
|
|
27095
27137
|
excludeComponents,
|
|
27096
27138
|
excludeInfraShapes,
|
|
27097
27139
|
where: where.length > 0 ? where : undefined
|
|
@@ -27104,7 +27146,7 @@ var handleQuery = async (ctx, { flags }) => {
|
|
|
27104
27146
|
resolveCollections,
|
|
27105
27147
|
limit: boundedLimit,
|
|
27106
27148
|
cursor,
|
|
27107
|
-
|
|
27149
|
+
componentRef,
|
|
27108
27150
|
excludeComponents,
|
|
27109
27151
|
excludeInfraShapes,
|
|
27110
27152
|
where: where.length > 0 ? where : undefined
|
|
@@ -27127,7 +27169,7 @@ async function fetchAllQueryPages(ctx, org, repo, opts) {
|
|
|
27127
27169
|
resolveCollections: opts.resolveCollections,
|
|
27128
27170
|
limit: opts.limit,
|
|
27129
27171
|
cursor,
|
|
27130
|
-
|
|
27172
|
+
componentRef: opts.componentRef,
|
|
27131
27173
|
excludeComponents: opts.excludeComponents,
|
|
27132
27174
|
excludeInfraShapes: opts.excludeInfraShapes,
|
|
27133
27175
|
where: opts.where
|
|
@@ -27405,7 +27447,7 @@ var searchFlags = {
|
|
|
27405
27447
|
cursor: flag.string({ description: "Opaque pagination cursor (text mode)" }),
|
|
27406
27448
|
all: flag.boolean({ description: "Fetch all pages (text mode)" }),
|
|
27407
27449
|
component: flag.string({
|
|
27408
|
-
description: "Filter to things owned by this component
|
|
27450
|
+
description: "Filter to things owned by this component (Org/Name ref)"
|
|
27409
27451
|
}),
|
|
27410
27452
|
"exclude-components": flag.boolean({
|
|
27411
27453
|
description: "Exclude component-owned things from results"
|
|
@@ -27442,10 +27484,10 @@ var handleSearch = async (ctx, { flags, args }) => {
|
|
|
27442
27484
|
const pageLimit = all ? Math.min(limit ?? AUTO_PAGE_LIMIT, MAX_PAGE_LIMIT) : boundedTextLimit;
|
|
27443
27485
|
const resolveCollections = mode !== "hybrid" ? flags["resolve-collections"] : undefined;
|
|
27444
27486
|
const supportsComponentFilters = !mode || mode === "text";
|
|
27445
|
-
const
|
|
27487
|
+
const componentRef = supportsComponentFilters ? flags.component : undefined;
|
|
27446
27488
|
const hasShape = !!flags.shape;
|
|
27447
27489
|
const strictExclude = supportsComponentFilters ? !!flags["exclude-components"] : false;
|
|
27448
|
-
validateComponentFilters(
|
|
27490
|
+
validateComponentFilters(componentRef, strictExclude, 'wh thing search "policy" --component acme/veritas');
|
|
27449
27491
|
const excludeComponents = supportsComponentFilters && strictExclude ? true : undefined;
|
|
27450
27492
|
const excludeInfraShapes = supportsComponentFilters && !strictExclude && !hasShape ? true : undefined;
|
|
27451
27493
|
const rawResult = all ? await fetchAllSearchPages(ctx, org, repo, queryText, {
|
|
@@ -27456,7 +27498,7 @@ var handleSearch = async (ctx, { flags, args }) => {
|
|
|
27456
27498
|
resolveCollections,
|
|
27457
27499
|
limit: pageLimit,
|
|
27458
27500
|
cursor,
|
|
27459
|
-
|
|
27501
|
+
componentRef,
|
|
27460
27502
|
excludeComponents,
|
|
27461
27503
|
excludeInfraShapes
|
|
27462
27504
|
}) : await ctx.client.thing.search(org, repo, queryText, {
|
|
@@ -27468,7 +27510,7 @@ var handleSearch = async (ctx, { flags, args }) => {
|
|
|
27468
27510
|
limit: boundedTextLimit,
|
|
27469
27511
|
cursor,
|
|
27470
27512
|
mode,
|
|
27471
|
-
|
|
27513
|
+
componentRef,
|
|
27472
27514
|
excludeComponents,
|
|
27473
27515
|
excludeInfraShapes
|
|
27474
27516
|
});
|
|
@@ -27494,7 +27536,7 @@ async function fetchAllSearchPages(ctx, org, repo, queryText, opts) {
|
|
|
27494
27536
|
limit: opts.limit,
|
|
27495
27537
|
cursor,
|
|
27496
27538
|
mode: "text",
|
|
27497
|
-
|
|
27539
|
+
componentRef: opts.componentRef,
|
|
27498
27540
|
excludeComponents: opts.excludeComponents,
|
|
27499
27541
|
excludeInfraShapes: opts.excludeInfraShapes
|
|
27500
27542
|
});
|
|
@@ -27847,13 +27889,16 @@ var THING_DOMAIN = defineDomain({
|
|
|
27847
27889
|
},
|
|
27848
27890
|
graph: {
|
|
27849
27891
|
prime: true,
|
|
27850
|
-
summary: "Fetch a thing's graph (
|
|
27892
|
+
summary: "Fetch a thing's graph (outbound wref fields, assertion backlinks, and assertion about targets)",
|
|
27851
27893
|
args: "<wref>",
|
|
27852
27894
|
flags: graphFlags,
|
|
27853
27895
|
examples: [
|
|
27854
27896
|
"wh thing graph Game/base",
|
|
27855
27897
|
"wh thing graph Game/base --depth 2"
|
|
27856
27898
|
],
|
|
27899
|
+
notes: [
|
|
27900
|
+
"`graph` does not traverse inbound wref-field references; use `wh thing refs <wref> --inbound` to find things whose fields point at this thing."
|
|
27901
|
+
],
|
|
27857
27902
|
handler: handleThingGraph
|
|
27858
27903
|
}
|
|
27859
27904
|
}
|
|
@@ -29417,7 +29462,7 @@ function ndjsonMessage(msg) {
|
|
|
29417
29462
|
return `${JSON.stringify(msg)}
|
|
29418
29463
|
`;
|
|
29419
29464
|
}
|
|
29420
|
-
function createMessageReader(input, onMessage) {
|
|
29465
|
+
function createMessageReader(input, onMessage, onError = () => {}) {
|
|
29421
29466
|
let buffer = "";
|
|
29422
29467
|
let mode = null;
|
|
29423
29468
|
function drain() {
|
|
@@ -29440,9 +29485,12 @@ function createMessageReader(input, onMessage) {
|
|
|
29440
29485
|
continue;
|
|
29441
29486
|
}
|
|
29442
29487
|
} else {
|
|
29443
|
-
const
|
|
29444
|
-
if (
|
|
29445
|
-
|
|
29488
|
+
const headerEnd = buffer.indexOf(HEADER_DELIMITER);
|
|
29489
|
+
if (headerEnd !== -1) {
|
|
29490
|
+
const resyncFrom = headerEnd + HEADER_DELIMITER.length;
|
|
29491
|
+
const nextHeaderMatch = /Content-Length:/i.exec(buffer.slice(resyncFrom));
|
|
29492
|
+
const nextHeader = nextHeaderMatch === null ? -1 : resyncFrom + nextHeaderMatch.index;
|
|
29493
|
+
buffer = nextHeader === -1 ? "" : buffer.slice(nextHeader);
|
|
29446
29494
|
continue;
|
|
29447
29495
|
}
|
|
29448
29496
|
}
|
|
@@ -29462,12 +29510,14 @@ function createMessageReader(input, onMessage) {
|
|
|
29462
29510
|
};
|
|
29463
29511
|
input.setEncoding("utf8");
|
|
29464
29512
|
input.on("data", onData);
|
|
29513
|
+
input.on("error", onError);
|
|
29465
29514
|
if ("resume" in input && typeof input.resume === "function") {
|
|
29466
29515
|
input.resume();
|
|
29467
29516
|
}
|
|
29468
29517
|
return {
|
|
29469
29518
|
close() {
|
|
29470
29519
|
input.removeListener("data", onData);
|
|
29520
|
+
input.removeListener("error", onError);
|
|
29471
29521
|
}
|
|
29472
29522
|
};
|
|
29473
29523
|
}
|
|
@@ -29477,9 +29527,25 @@ var MCP_PROTOCOL_VERSION2 = "2025-11-25";
|
|
|
29477
29527
|
function createChannelServer(opts) {
|
|
29478
29528
|
let reader = null;
|
|
29479
29529
|
let resolveReady;
|
|
29480
|
-
|
|
29530
|
+
let rejectReady;
|
|
29531
|
+
let readySettled = false;
|
|
29532
|
+
const onReady = new Promise((resolve, reject) => {
|
|
29481
29533
|
resolveReady = resolve;
|
|
29534
|
+
rejectReady = reject;
|
|
29482
29535
|
});
|
|
29536
|
+
function settleReady() {
|
|
29537
|
+
if (readySettled)
|
|
29538
|
+
return;
|
|
29539
|
+
readySettled = true;
|
|
29540
|
+
resolveReady();
|
|
29541
|
+
}
|
|
29542
|
+
function failReady(error) {
|
|
29543
|
+
if (readySettled)
|
|
29544
|
+
return;
|
|
29545
|
+
readySettled = true;
|
|
29546
|
+
reader?.close();
|
|
29547
|
+
rejectReady(error);
|
|
29548
|
+
}
|
|
29483
29549
|
function send(msg) {
|
|
29484
29550
|
opts.output.write(ndjsonMessage(msg));
|
|
29485
29551
|
}
|
|
@@ -29502,7 +29568,7 @@ function createChannelServer(opts) {
|
|
|
29502
29568
|
return;
|
|
29503
29569
|
}
|
|
29504
29570
|
if (method === "notifications/initialized") {
|
|
29505
|
-
|
|
29571
|
+
settleReady();
|
|
29506
29572
|
return;
|
|
29507
29573
|
}
|
|
29508
29574
|
if (method === "ping") {
|
|
@@ -29519,7 +29585,7 @@ function createChannelServer(opts) {
|
|
|
29519
29585
|
}
|
|
29520
29586
|
return {
|
|
29521
29587
|
start() {
|
|
29522
|
-
reader = createMessageReader(opts.input, handleMessage);
|
|
29588
|
+
reader = createMessageReader(opts.input, handleMessage, failReady);
|
|
29523
29589
|
},
|
|
29524
29590
|
notify(content, meta) {
|
|
29525
29591
|
send({
|
|
@@ -29531,6 +29597,7 @@ function createChannelServer(opts) {
|
|
|
29531
29597
|
onReady,
|
|
29532
29598
|
close() {
|
|
29533
29599
|
reader?.close();
|
|
29600
|
+
settleReady();
|
|
29534
29601
|
}
|
|
29535
29602
|
};
|
|
29536
29603
|
}
|
|
@@ -29593,7 +29660,16 @@ var handleChannel = async (ctx) => {
|
|
|
29593
29660
|
else
|
|
29594
29661
|
signal.addEventListener("abort", () => resolve("aborted"), { once: true });
|
|
29595
29662
|
});
|
|
29596
|
-
|
|
29663
|
+
let ready;
|
|
29664
|
+
try {
|
|
29665
|
+
ready = await Promise.race([server.onReady.then(() => {
|
|
29666
|
+
return;
|
|
29667
|
+
}), aborted]);
|
|
29668
|
+
} catch (err) {
|
|
29669
|
+
server.close();
|
|
29670
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
29671
|
+
throw new CliError(4 /* Backend */, "BACKEND", `channel startup failed: ${msg}`);
|
|
29672
|
+
}
|
|
29597
29673
|
if (ready === "aborted") {
|
|
29598
29674
|
server.close();
|
|
29599
29675
|
return;
|
|
@@ -30969,13 +31045,16 @@ async function refreshFromSummaries(repoSlug, parsed, activeItems, client, now,
|
|
|
30969
31045
|
const components = {};
|
|
30970
31046
|
let detailReadFailures = 0;
|
|
30971
31047
|
for (const item of activeItems) {
|
|
31048
|
+
if (!item.ref)
|
|
31049
|
+
continue;
|
|
31050
|
+
const itemRef = item.ref;
|
|
30972
31051
|
let detail;
|
|
30973
31052
|
try {
|
|
30974
|
-
detail = await client.component.get(parsed.org, parsed.repo,
|
|
31053
|
+
detail = await client.component.get(parsed.org, parsed.repo, itemRef);
|
|
30975
31054
|
} catch {
|
|
30976
31055
|
detailReadFailures++;
|
|
30977
31056
|
const previousEntry = previousCache?.components[item.componentName];
|
|
30978
|
-
if (previousEntry?.
|
|
31057
|
+
if (previousEntry?.ref === itemRef) {
|
|
30979
31058
|
components[item.componentName] = previousEntry;
|
|
30980
31059
|
}
|
|
30981
31060
|
continue;
|
|
@@ -30990,7 +31069,7 @@ async function refreshFromSummaries(repoSlug, parsed, activeItems, client, now,
|
|
|
30990
31069
|
if (!ref)
|
|
30991
31070
|
continue;
|
|
30992
31071
|
components[item.componentName] = {
|
|
30993
|
-
|
|
31072
|
+
ref: itemRef,
|
|
30994
31073
|
ownerOrgName: ref.ownerOrgName,
|
|
30995
31074
|
registeredComponentName: ref.registeredComponentName,
|
|
30996
31075
|
version: manifest.component.version ?? item.version ?? "",
|
|
@@ -31350,7 +31429,7 @@ var handleComponentExec = async (ctx, { args, terminator }) => {
|
|
|
31350
31429
|
}
|
|
31351
31430
|
const method = entry.methods.find((m) => m.name === methodName);
|
|
31352
31431
|
if (!method) {
|
|
31353
|
-
throw new CliError(2 /* UserInput */, "USER_INPUT", `Method '${methodName}' not found on component '${componentName}'.`, undefined, `Available: ${entry.methods.map((m) => m.name).join(", ")}. Run wh component update ${
|
|
31432
|
+
throw new CliError(2 /* UserInput */, "USER_INPUT", `Method '${methodName}' not found on component '${componentName}'.`, undefined, `Available: ${entry.methods.map((m) => m.name).join(", ")}. Run wh component update ${entry.ref} --repo ${installRepo} if you expect a newer method.`);
|
|
31354
31433
|
}
|
|
31355
31434
|
if (helpRequested) {
|
|
31356
31435
|
renderMethodHelp(ctx, componentName, method);
|
|
@@ -31459,7 +31538,7 @@ async function ensureSharedInfra(client, org, repo) {
|
|
|
31459
31538
|
name: shape.name,
|
|
31460
31539
|
data: { fields: shape.fields }
|
|
31461
31540
|
}
|
|
31462
|
-
], {
|
|
31541
|
+
], { componentRef: SYSTEM_REGISTERED_COMPONENT_REF });
|
|
31463
31542
|
} catch (err) {
|
|
31464
31543
|
if (!isAlreadyExistsError(err)) {
|
|
31465
31544
|
throw err;
|
|
@@ -31472,7 +31551,7 @@ async function ensureSharedInfra(client, org, repo) {
|
|
|
31472
31551
|
name: shape.name,
|
|
31473
31552
|
data: { fields: shape.fields }
|
|
31474
31553
|
}
|
|
31475
|
-
], {
|
|
31554
|
+
], { componentRef: SYSTEM_REGISTERED_COMPONENT_REF });
|
|
31476
31555
|
} catch {}
|
|
31477
31556
|
}
|
|
31478
31557
|
}
|
|
@@ -31505,6 +31584,15 @@ async function doctorComponent(client, org, repo, componentId) {
|
|
|
31505
31584
|
};
|
|
31506
31585
|
}
|
|
31507
31586
|
const componentName = typeof installData.name === "string" ? installData.name : componentId;
|
|
31587
|
+
const registeredComponentRef = typeof installData.registeredComponentRef === "string" && installData.registeredComponentRef.length > 0 ? installData.registeredComponentRef : undefined;
|
|
31588
|
+
if (!registeredComponentRef) {
|
|
31589
|
+
findings.push({
|
|
31590
|
+
resource: "ComponentInstall",
|
|
31591
|
+
status: "error",
|
|
31592
|
+
message: "Install record is missing registeredComponentRef"
|
|
31593
|
+
});
|
|
31594
|
+
return { componentId, componentName, state: "error", findings };
|
|
31595
|
+
}
|
|
31508
31596
|
const existingState = typeof installData.state === "string" ? installData.state : undefined;
|
|
31509
31597
|
if (existingState === "error") {
|
|
31510
31598
|
findings.push({
|
|
@@ -31543,12 +31631,12 @@ async function doctorComponent(client, org, repo, componentId) {
|
|
|
31543
31631
|
message: `Shape "${shape.name}" exists but is inactive`
|
|
31544
31632
|
});
|
|
31545
31633
|
} else {
|
|
31546
|
-
const
|
|
31547
|
-
if (
|
|
31634
|
+
const shapeComponentRef = s && typeof s === "object" && "componentRef" in s ? s.componentRef : undefined;
|
|
31635
|
+
if (shapeComponentRef !== undefined && shapeComponentRef !== registeredComponentRef) {
|
|
31548
31636
|
findings.push({
|
|
31549
31637
|
resource: `shape:${shape.name}`,
|
|
31550
31638
|
status: "warning",
|
|
31551
|
-
message: `Shape "${shape.name}" exists but is owned by "${
|
|
31639
|
+
message: `Shape "${shape.name}" exists but is owned by "${shapeComponentRef}"`
|
|
31552
31640
|
});
|
|
31553
31641
|
} else {
|
|
31554
31642
|
const expectedShapeData = manifestShapeData(shape);
|
|
@@ -31582,19 +31670,19 @@ async function doctorComponent(client, org, repo, componentId) {
|
|
|
31582
31670
|
hasSubs = true;
|
|
31583
31671
|
try {
|
|
31584
31672
|
const s = await client.subscription.get(org, repo, sub.name);
|
|
31585
|
-
const
|
|
31586
|
-
if (
|
|
31673
|
+
const subComponentRef = s && typeof s === "object" && "componentRef" in s ? s.componentRef : undefined;
|
|
31674
|
+
if (subComponentRef !== undefined && subComponentRef !== registeredComponentRef) {
|
|
31675
|
+
allSubsPaused = false;
|
|
31587
31676
|
findings.push({
|
|
31588
31677
|
resource: `sub:${sub.name}`,
|
|
31589
|
-
status: "
|
|
31590
|
-
message: `Subscription "${sub.name}" is
|
|
31678
|
+
status: "warning",
|
|
31679
|
+
message: `Subscription "${sub.name}" is owned by "${subComponentRef}"`
|
|
31591
31680
|
});
|
|
31592
|
-
} else if (
|
|
31593
|
-
allSubsPaused = false;
|
|
31681
|
+
} else if (!s.active) {
|
|
31594
31682
|
findings.push({
|
|
31595
31683
|
resource: `sub:${sub.name}`,
|
|
31596
|
-
status: "
|
|
31597
|
-
message: `Subscription "${sub.name}" is
|
|
31684
|
+
status: "inactive",
|
|
31685
|
+
message: `Subscription "${sub.name}" is paused`
|
|
31598
31686
|
});
|
|
31599
31687
|
} else {
|
|
31600
31688
|
allSubsPaused = false;
|
|
@@ -31664,10 +31752,11 @@ async function doctorComponent(client, org, repo, componentId) {
|
|
|
31664
31752
|
const hasMissing = findings.some((f) => f.status === "missing");
|
|
31665
31753
|
const hasInactive = findings.some((f) => f.status === "inactive" && !f.resource.startsWith("sub:"));
|
|
31666
31754
|
const hasShapeDrift = findings.some((f) => f.resource.startsWith("shape:") && f.status === "warning" && f.message.includes("differs from installed manifest"));
|
|
31755
|
+
const hasOwnershipConflict = findings.some((f) => (f.resource.startsWith("shape:") || f.resource.startsWith("sub:")) && f.status === "warning" && f.message.includes("owned by"));
|
|
31667
31756
|
let state;
|
|
31668
|
-
if (hasSubs && allSubsPaused && !hasMissing && !hasInactive && !hasShapeDrift) {
|
|
31757
|
+
if (hasSubs && allSubsPaused && !hasMissing && !hasInactive && !hasShapeDrift && !hasOwnershipConflict) {
|
|
31669
31758
|
state = "paused";
|
|
31670
|
-
} else if (hasMissing || hasInactive || hasShapeDrift) {
|
|
31759
|
+
} else if (hasMissing || hasInactive || hasShapeDrift || hasOwnershipConflict) {
|
|
31671
31760
|
state = "degraded";
|
|
31672
31761
|
} else {
|
|
31673
31762
|
state = "ready";
|
|
@@ -31680,7 +31769,7 @@ async function doctorComponent(client, org, repo, componentId) {
|
|
|
31680
31769
|
name: `ComponentInstall/${componentId}`,
|
|
31681
31770
|
data: { ...installData, state, checkedAt: new Date().toISOString() }
|
|
31682
31771
|
}
|
|
31683
|
-
], {
|
|
31772
|
+
], { componentRef: SYSTEM_REGISTERED_COMPONENT_REF });
|
|
31684
31773
|
} catch {
|
|
31685
31774
|
findings.push({
|
|
31686
31775
|
resource: "state-update",
|
|
@@ -31774,6 +31863,22 @@ async function teardownComponent(client, org, repo, componentId) {
|
|
|
31774
31863
|
};
|
|
31775
31864
|
}
|
|
31776
31865
|
const componentName = typeof installData.name === "string" ? installData.name : componentId;
|
|
31866
|
+
const registeredComponentRef = typeof installData.registeredComponentRef === "string" && installData.registeredComponentRef.length > 0 ? installData.registeredComponentRef : undefined;
|
|
31867
|
+
if (!registeredComponentRef) {
|
|
31868
|
+
return {
|
|
31869
|
+
componentId,
|
|
31870
|
+
componentName,
|
|
31871
|
+
state: "error",
|
|
31872
|
+
steps: [
|
|
31873
|
+
{
|
|
31874
|
+
step: "load-install",
|
|
31875
|
+
status: "error",
|
|
31876
|
+
message: "Install record is missing registeredComponentRef"
|
|
31877
|
+
}
|
|
31878
|
+
],
|
|
31879
|
+
errors: ["Install record is missing registeredComponentRef"]
|
|
31880
|
+
};
|
|
31881
|
+
}
|
|
31777
31882
|
let subscriptionNames = [];
|
|
31778
31883
|
let teardownPolicy = {};
|
|
31779
31884
|
try {
|
|
@@ -31796,9 +31901,9 @@ async function teardownComponent(client, org, repo, componentId) {
|
|
|
31796
31901
|
for (const subName of subscriptionNames) {
|
|
31797
31902
|
try {
|
|
31798
31903
|
const sub = await client.subscription.get(org, repo, subName);
|
|
31799
|
-
const
|
|
31800
|
-
if (typeof
|
|
31801
|
-
const msg = `Subscription "${subName}" is owned by "${
|
|
31904
|
+
const ownerComponentRef = sub && typeof sub === "object" && "componentRef" in sub ? sub.componentRef : undefined;
|
|
31905
|
+
if (typeof ownerComponentRef === "string" && ownerComponentRef !== registeredComponentRef) {
|
|
31906
|
+
const msg = `Subscription "${subName}" is owned by "${ownerComponentRef}", not "${registeredComponentRef}"`;
|
|
31802
31907
|
errors.push(msg);
|
|
31803
31908
|
steps.push({
|
|
31804
31909
|
step: `pause-${subName}`,
|
|
@@ -31847,7 +31952,7 @@ async function teardownComponent(client, org, repo, componentId) {
|
|
|
31847
31952
|
updatedAt: new Date().toISOString()
|
|
31848
31953
|
}
|
|
31849
31954
|
}
|
|
31850
|
-
], {
|
|
31955
|
+
], { componentRef: SYSTEM_REGISTERED_COMPONENT_REF });
|
|
31851
31956
|
steps.push({ step: "update-state", status: "ok" });
|
|
31852
31957
|
} catch (err) {
|
|
31853
31958
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -32069,38 +32174,11 @@ function componentInstallCanonicalId(item) {
|
|
|
32069
32174
|
const data = asRecord(item.data);
|
|
32070
32175
|
return componentInstallIdFromWref(item.wref) ?? readString(data, "id") ?? readString(data, "componentId") ?? item.name;
|
|
32071
32176
|
}
|
|
32072
|
-
function
|
|
32073
|
-
return
|
|
32074
|
-
}
|
|
32075
|
-
function componentInstallIdentityIds(item) {
|
|
32076
|
-
const data = asRecord(item.data);
|
|
32077
|
-
return uniqueStrings([
|
|
32078
|
-
componentInstallCanonicalId(item),
|
|
32079
|
-
readString(data, "id"),
|
|
32080
|
-
readString(data, "componentId"),
|
|
32081
|
-
item.name
|
|
32082
|
-
]);
|
|
32083
|
-
}
|
|
32084
|
-
function componentInstallHasExactId(item, name) {
|
|
32085
|
-
return componentInstallIdentityIds(item).includes(name);
|
|
32177
|
+
function componentInstallHasRegisteredRef(item, ref) {
|
|
32178
|
+
return readString(asRecord(item.data), "registeredComponentRef") === ref;
|
|
32086
32179
|
}
|
|
32087
|
-
function
|
|
32088
|
-
return readString(asRecord(item.data), "name") === name;
|
|
32089
|
-
}
|
|
32090
|
-
function formatComponentInstallAmbiguity(name, matches) {
|
|
32091
|
-
const componentIds = uniqueStrings(matches.map((item) => componentInstallCanonicalId(item)));
|
|
32092
|
-
const listedIds = componentIds.map((id) => `- ${id}`).join(`
|
|
32093
|
-
`);
|
|
32094
|
-
const exampleId = componentIds[0] ?? name;
|
|
32095
|
-
return {
|
|
32096
|
-
message: `Component name "${name}" is ambiguous. It matches multiple installed components:
|
|
32097
|
-
${listedIds}`,
|
|
32098
|
-
hint: `Use a component id instead, for example: wh component doctor ${exampleId}`
|
|
32099
|
-
};
|
|
32100
|
-
}
|
|
32101
|
-
async function resolveComponentDoctorId(client, org, repo, name) {
|
|
32180
|
+
async function resolveInstalledComponentRefId(client, org, repo, ref) {
|
|
32102
32181
|
let cursor;
|
|
32103
|
-
const displayNameMatches = [];
|
|
32104
32182
|
do {
|
|
32105
32183
|
const result = await client.thing.head(org, repo, {
|
|
32106
32184
|
shape: "ComponentInstall",
|
|
@@ -32109,35 +32187,27 @@ async function resolveComponentDoctorId(client, org, repo, name) {
|
|
|
32109
32187
|
cursor
|
|
32110
32188
|
});
|
|
32111
32189
|
const items = result.items ?? [];
|
|
32112
|
-
const exactMatch = items.find((item) =>
|
|
32190
|
+
const exactMatch = items.find((item) => componentInstallHasRegisteredRef(item, ref));
|
|
32113
32191
|
const resolved = exactMatch ? componentInstallCanonicalId(exactMatch) : undefined;
|
|
32114
32192
|
if (resolved) {
|
|
32115
32193
|
return resolved;
|
|
32116
32194
|
}
|
|
32117
|
-
displayNameMatches.push(...items.filter((item) => componentInstallHasDisplayName(item, name)));
|
|
32118
32195
|
cursor = result.nextCursor;
|
|
32119
32196
|
} while (cursor);
|
|
32120
|
-
|
|
32121
|
-
return componentInstallCanonicalId(displayNameMatches[0]) ?? name;
|
|
32122
|
-
}
|
|
32123
|
-
if (displayNameMatches.length > 1) {
|
|
32124
|
-
const { message, hint } = formatComponentInstallAmbiguity(name, displayNameMatches);
|
|
32125
|
-
throw new CliError(2 /* UserInput */, "USER_INPUT", message, undefined, hint);
|
|
32126
|
-
}
|
|
32127
|
-
return name;
|
|
32197
|
+
throw new CliError(2 /* UserInput */, "USER_INPUT", `Component '${ref}' is not installed. Run 'wh component install <org>/<name>' first.`);
|
|
32128
32198
|
}
|
|
32129
32199
|
var handleUpdate = async (ctx, { args }) => {
|
|
32130
|
-
const
|
|
32131
|
-
|
|
32132
|
-
|
|
32200
|
+
const ref = args[0];
|
|
32201
|
+
const usage = "Usage: wh component update <org/name> --repo org/repo";
|
|
32202
|
+
const example = "wh component update warmhub/research-knowledge --repo org/repo";
|
|
32203
|
+
if (!ref) {
|
|
32204
|
+
usageError(usage, example);
|
|
32133
32205
|
}
|
|
32134
|
-
|
|
32135
|
-
|
|
32136
|
-
|
|
32137
|
-
} catch {
|
|
32138
|
-
throw new CliError(2 /* UserInput */, "USER_INPUT", `Component '${name}' is not installed. Run 'wh component install <org>/<name>' first.`);
|
|
32206
|
+
resolveRegisteredComponentRef(ref, usage, example);
|
|
32207
|
+
if (ctx.liveMode === false) {
|
|
32208
|
+
usageError("Dry-run is not supported for component update.", "wh component update warmhub/research-knowledge --repo org/repo");
|
|
32139
32209
|
}
|
|
32140
|
-
throw new CliError(2 /* UserInput */, "USER_INPUT", `Component '${
|
|
32210
|
+
throw new CliError(2 /* UserInput */, "USER_INPUT", `Component '${ref}' could not be updated through the component shell boundary.`, undefined, "Run `wh component update <org/name> --repo org/repo` without --dry-run.");
|
|
32141
32211
|
};
|
|
32142
32212
|
var handleRegister = async (ctx, { flags, args }) => {
|
|
32143
32213
|
const componentName = args[0];
|
|
@@ -32230,8 +32300,7 @@ var handleRegistryUpdate = async (ctx, { flags, args }) => {
|
|
|
32230
32300
|
};
|
|
32231
32301
|
var handleInstall = async (ctx, { args }) => {
|
|
32232
32302
|
const source = args[0];
|
|
32233
|
-
const usage =
|
|
32234
|
-
source: <org>/<name> (registered component)`;
|
|
32303
|
+
const usage = "Usage: wh component install <org/name> --repo org/repo";
|
|
32235
32304
|
const example = "wh component install warmhub/veritas --repo myorg/myrepo";
|
|
32236
32305
|
if (!source) {
|
|
32237
32306
|
usageError(usage, example);
|
|
@@ -32276,7 +32345,7 @@ var handleList2 = async (ctx, { flags }) => {
|
|
|
32276
32345
|
const state = item.state ?? "unknown";
|
|
32277
32346
|
const source = item.source ?? "-";
|
|
32278
32347
|
const stateColor = stateToColor(c, state);
|
|
32279
|
-
ctx.out(` ${c.cyan}${item.
|
|
32348
|
+
ctx.out(` ${c.cyan}${item.ref ?? item.componentName}${c.reset} ${stateColor}${state}${c.reset} ${c.dim}v${version}${c.reset} ${source}`);
|
|
32280
32349
|
}
|
|
32281
32350
|
});
|
|
32282
32351
|
};
|
|
@@ -32289,7 +32358,7 @@ var handleSearch2 = async (ctx, { flags, args }) => {
|
|
|
32289
32358
|
const c = ctx.colors;
|
|
32290
32359
|
const { items: allItems, nextCursor } = await fetchComponentPages(ctx.client, org, repo, { all: flags.all, limit: flags.limit, cursor: flags.cursor });
|
|
32291
32360
|
const needle = query.toLowerCase();
|
|
32292
|
-
const items = allItems.filter((item) => [item.
|
|
32361
|
+
const items = allItems.filter((item) => [item.ref, item.componentName, item.source].filter((value) => typeof value === "string").some((value) => value.toLowerCase().includes(needle)));
|
|
32293
32362
|
if (!flags.all && nextCursor) {
|
|
32294
32363
|
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.`);
|
|
32295
32364
|
}
|
|
@@ -32305,22 +32374,22 @@ var handleSearch2 = async (ctx, { flags, args }) => {
|
|
|
32305
32374
|
const state = item.state ?? "unknown";
|
|
32306
32375
|
const source = item.source ?? "-";
|
|
32307
32376
|
const stateColor = stateToColor(c, state);
|
|
32308
|
-
ctx.out(` ${c.cyan}${item.
|
|
32377
|
+
ctx.out(` ${c.cyan}${item.ref ?? item.componentName}${c.reset} ${stateColor}${state}${c.reset} ${c.dim}v${version}${c.reset} ${source}`);
|
|
32309
32378
|
}
|
|
32310
32379
|
});
|
|
32311
32380
|
};
|
|
32312
32381
|
var handleView3 = async (ctx, { args }) => {
|
|
32313
|
-
const
|
|
32314
|
-
const usage = "Usage: wh component view <name> --repo org/repo";
|
|
32315
|
-
const example = "wh component view research-knowledge --repo myorg/myrepo";
|
|
32316
|
-
if (!
|
|
32382
|
+
const ref = args[0];
|
|
32383
|
+
const usage = "Usage: wh component view <org/name> --repo org/repo";
|
|
32384
|
+
const example = "wh component view myorg/research-knowledge --repo myorg/myrepo";
|
|
32385
|
+
if (!ref) {
|
|
32317
32386
|
usageError(usage, example);
|
|
32318
32387
|
}
|
|
32319
32388
|
const { org, repo } = parseOrgRepo(getRepoRef(ctx), ctx.config);
|
|
32320
|
-
const viewData = await ctx.client.component.get(org, repo,
|
|
32389
|
+
const viewData = await ctx.client.component.get(org, repo, ref);
|
|
32321
32390
|
writeOutput(ctx, viewData, () => {
|
|
32322
32391
|
const c = ctx.colors;
|
|
32323
|
-
ctx.out(`${c.bold}Component:${c.reset} ${c.cyan}${
|
|
32392
|
+
ctx.out(`${c.bold}Component:${c.reset} ${c.cyan}${viewData.ref ?? ref}${c.reset}`);
|
|
32324
32393
|
ctx.out(`${c.bold}Version:${c.reset} ${viewData.version ?? "unknown"}`);
|
|
32325
32394
|
ctx.out(`${c.bold}State:${c.reset} ${viewData.state ?? "-"}`);
|
|
32326
32395
|
ctx.out(`${c.bold}Source:${c.reset} ${viewData.source ?? "-"}`);
|
|
@@ -32396,23 +32465,24 @@ function renderValidationResult(ctx, result) {
|
|
|
32396
32465
|
var handleDoctor = async (ctx, { args }) => {
|
|
32397
32466
|
const name = args[0];
|
|
32398
32467
|
if (!name) {
|
|
32399
|
-
usageError("Usage: wh component doctor <name> --repo org/repo", "wh component doctor research-knowledge --repo myorg/myrepo");
|
|
32468
|
+
usageError("Usage: wh component doctor <org/name> --repo org/repo", "wh component doctor warmhub/research-knowledge --repo myorg/myrepo");
|
|
32400
32469
|
}
|
|
32401
32470
|
const { org, repo } = parseOrgRepo(getRepoRef(ctx), ctx.config);
|
|
32402
|
-
const componentId = await
|
|
32471
|
+
const componentId = await resolveInstalledComponentRefId(ctx.client, org, repo, name);
|
|
32403
32472
|
const result = await doctorComponent(ctx.client, org, repo, componentId);
|
|
32404
32473
|
writeOutput(ctx, result, () => renderDoctorResult(ctx, result));
|
|
32405
32474
|
};
|
|
32406
32475
|
var handleTeardown = async (ctx, { args }) => {
|
|
32407
32476
|
const name = args[0];
|
|
32408
32477
|
if (!name) {
|
|
32409
|
-
usageError("Usage: wh component teardown <name> --repo org/repo", "wh component teardown research-knowledge --repo myorg/myrepo");
|
|
32478
|
+
usageError("Usage: wh component teardown <org/name> --repo org/repo", "wh component teardown warmhub/research-knowledge --repo myorg/myrepo");
|
|
32410
32479
|
}
|
|
32411
32480
|
const { org, repo } = parseOrgRepo(getRepoRef(ctx), ctx.config);
|
|
32412
32481
|
const repoSlug = `${org}/${repo}`;
|
|
32482
|
+
const componentId = await resolveInstalledComponentRefId(ctx.client, org, repo, name);
|
|
32413
32483
|
let result;
|
|
32414
32484
|
try {
|
|
32415
|
-
result = await teardownComponent(ctx.client, org, repo,
|
|
32485
|
+
result = await teardownComponent(ctx.client, org, repo, componentId);
|
|
32416
32486
|
} catch (error) {
|
|
32417
32487
|
invalidateInstallSnapshotCache(repoSlug);
|
|
32418
32488
|
throw error;
|
|
@@ -32543,7 +32613,7 @@ var COMPONENT_DOMAIN = defineDomain({
|
|
|
32543
32613
|
install: {
|
|
32544
32614
|
prime: true,
|
|
32545
32615
|
summary: "Install a registered component by its <org>/<name> ref",
|
|
32546
|
-
args: "<
|
|
32616
|
+
args: "<org/name>",
|
|
32547
32617
|
flags: installFlags,
|
|
32548
32618
|
examples: [
|
|
32549
32619
|
"wh component install warmhub/identity --repo org/repo",
|
|
@@ -32553,9 +32623,9 @@ var COMPONENT_DOMAIN = defineDomain({
|
|
|
32553
32623
|
},
|
|
32554
32624
|
update: {
|
|
32555
32625
|
summary: "Update an installed registered component to the latest manifest",
|
|
32556
|
-
args: "<name>",
|
|
32626
|
+
args: "<org/name>",
|
|
32557
32627
|
flags: updateFlags,
|
|
32558
|
-
examples: ["wh component update
|
|
32628
|
+
examples: ["wh component update warmhub/identity --repo org/repo"],
|
|
32559
32629
|
handler: handleUpdate
|
|
32560
32630
|
},
|
|
32561
32631
|
list: {
|
|
@@ -32569,25 +32639,25 @@ var COMPONENT_DOMAIN = defineDomain({
|
|
|
32569
32639
|
view: {
|
|
32570
32640
|
prime: true,
|
|
32571
32641
|
summary: "Show component details",
|
|
32572
|
-
args: "<name>",
|
|
32642
|
+
args: "<org/name>",
|
|
32573
32643
|
flags: viewFlags3,
|
|
32574
|
-
examples: ["wh component view
|
|
32644
|
+
examples: ["wh component view warmhub/identity --repo org/repo"],
|
|
32575
32645
|
handler: handleView3
|
|
32576
32646
|
},
|
|
32577
32647
|
teardown: {
|
|
32578
32648
|
prime: true,
|
|
32579
32649
|
summary: "Pause component subscriptions",
|
|
32580
|
-
args: "<name>",
|
|
32650
|
+
args: "<org/name>",
|
|
32581
32651
|
flags: teardownFlags,
|
|
32582
|
-
examples: ["wh component teardown
|
|
32652
|
+
examples: ["wh component teardown warmhub/identity --repo org/repo"],
|
|
32583
32653
|
handler: handleTeardown
|
|
32584
32654
|
},
|
|
32585
32655
|
doctor: {
|
|
32586
32656
|
prime: true,
|
|
32587
32657
|
summary: "Run component health checks",
|
|
32588
|
-
args: "<name>",
|
|
32658
|
+
args: "<org/name>",
|
|
32589
32659
|
flags: doctorFlags,
|
|
32590
|
-
examples: ["wh component doctor
|
|
32660
|
+
examples: ["wh component doctor warmhub/identity --repo org/repo"],
|
|
32591
32661
|
handler: handleDoctor
|
|
32592
32662
|
},
|
|
32593
32663
|
init: {
|
|
@@ -33035,7 +33105,7 @@ import { basename } from "node:path";
|
|
|
33035
33105
|
// ../../packages/warmhub-cli/src/harness.ts
|
|
33036
33106
|
import { mkdir, readFile as readFile2, writeFile as writeFile2 } from "node:fs/promises";
|
|
33037
33107
|
import { homedir as homedir4 } from "node:os";
|
|
33038
|
-
import { dirname as dirname6, join as
|
|
33108
|
+
import { dirname as dirname6, join as join5 } from "node:path";
|
|
33039
33109
|
var AGENTS_BEGIN_MARKER = "<!-- BEGIN WARMHUB CLI INTEGRATION -->";
|
|
33040
33110
|
var AGENTS_END_MARKER = "<!-- END WARMHUB CLI INTEGRATION -->";
|
|
33041
33111
|
var PRIME_COMMAND = "wh prime";
|
|
@@ -33055,10 +33125,10 @@ function getHarnessPaths(opts) {
|
|
|
33055
33125
|
const userHome = opts?.homeDir ?? homedir4();
|
|
33056
33126
|
return {
|
|
33057
33127
|
repoDir,
|
|
33058
|
-
agentsPath:
|
|
33059
|
-
projectSettingsPath:
|
|
33060
|
-
projectLocalSettingsPath:
|
|
33061
|
-
globalSettingsPath:
|
|
33128
|
+
agentsPath: join5(repoDir, "AGENTS.md"),
|
|
33129
|
+
projectSettingsPath: join5(repoDir, ".claude", "settings.json"),
|
|
33130
|
+
projectLocalSettingsPath: join5(repoDir, ".claude", "settings.local.json"),
|
|
33131
|
+
globalSettingsPath: join5(userHome, ".claude", "settings.json")
|
|
33062
33132
|
};
|
|
33063
33133
|
}
|
|
33064
33134
|
async function readJsonFile(path2) {
|
|
@@ -34459,17 +34529,18 @@ cat wrefs.txt | wh thing view --format jsonl # one JSON line per *deduped
|
|
|
34459
34529
|
- \`wh credential revoke <setName> [--repo org/repo | --org org] [--reason]\` — Revoke a credential set (blocks new binds and strips auth from existing webhook deliveries)
|
|
34460
34530
|
|
|
34461
34531
|
### component — Component management
|
|
34462
|
-
- \`wh component validate <path>\` — Validate
|
|
34463
|
-
- \`wh component install <
|
|
34464
|
-
- \`wh component register <name> --org <org> --manifest <path> [flags]\` — Register
|
|
34532
|
+
- \`wh component validate <path>\` — Validate package
|
|
34533
|
+
- \`wh component install <org/name>\` — Install a registered component
|
|
34534
|
+
- \`wh component register <name> --org <org> --manifest <path> [flags]\` — Register component identity
|
|
34465
34535
|
- \`wh component unregister <org/name>\` — Remove a registered component identity
|
|
34466
34536
|
- \`wh component registry list --org <org>\` — List registered components
|
|
34467
34537
|
- \`wh component registry view <org/name>\` — View a registered component
|
|
34468
34538
|
- \`wh component registry update <org/name> [flags]\` — Update a registered component
|
|
34469
34539
|
- \`wh component list\` — List installed components
|
|
34470
|
-
- \`wh component
|
|
34471
|
-
- \`wh component
|
|
34472
|
-
- \`wh component
|
|
34540
|
+
- \`wh component update <org/name>\` — Update installed component
|
|
34541
|
+
- \`wh component view <org/name>\` — Show component details (alias: show)
|
|
34542
|
+
- \`wh component doctor <org/name>\` — Run component health checks
|
|
34543
|
+
- \`wh component teardown <org/name>\` — Pause component subscriptions
|
|
34473
34544
|
|
|
34474
34545
|
### Getting More Info
|
|
34475
34546
|
- \`wh help\` — full help overview
|
|
@@ -35481,7 +35552,7 @@ var FIELD_CONSTRAINTS_NOTES = [
|
|
|
35481
35552
|
var listFlags4 = {
|
|
35482
35553
|
match: flag.string({ description: "Filter by name glob pattern" }),
|
|
35483
35554
|
component: flag.string({
|
|
35484
|
-
description: "Filter to shapes owned by this component
|
|
35555
|
+
description: "Filter to shapes owned by this component (Org/Name ref)"
|
|
35485
35556
|
}),
|
|
35486
35557
|
"exclude-components": flag.boolean({
|
|
35487
35558
|
description: "Exclude component-owned shapes from results"
|
|
@@ -35494,13 +35565,13 @@ var handleList6 = async (ctx, { flags }) => {
|
|
|
35494
35565
|
const { org, repo } = parseOrgRepo(getRepoRef(ctx), ctx.config);
|
|
35495
35566
|
const c = ctx.colors;
|
|
35496
35567
|
const match = flags.match;
|
|
35497
|
-
const
|
|
35568
|
+
const componentRef = flags.component;
|
|
35498
35569
|
const excludeComponents = !!flags["exclude-components"];
|
|
35499
35570
|
const includeRetracted = flags["include-retracted"];
|
|
35500
|
-
validateComponentFilters(
|
|
35571
|
+
validateComponentFilters(componentRef, excludeComponents, "wh shape list --component acme/veritas", "wh shape list --exclude-components");
|
|
35501
35572
|
const result = await ctx.client.shape.list(org, repo, {
|
|
35502
35573
|
match,
|
|
35503
|
-
|
|
35574
|
+
componentRef,
|
|
35504
35575
|
excludeComponents,
|
|
35505
35576
|
includeRetracted
|
|
35506
35577
|
});
|
|
@@ -35567,9 +35638,9 @@ var handleView7 = async (ctx, { flags, args }) => {
|
|
|
35567
35638
|
if (typeof shapeDescription === "string" && shapeDescription) {
|
|
35568
35639
|
ctx.out(` ${c.dim}${shapeDescription}${c.reset}`);
|
|
35569
35640
|
}
|
|
35570
|
-
const
|
|
35571
|
-
if (
|
|
35572
|
-
ctx.out(` ${c.dim}owner:${c.reset} ${c.yellow}${
|
|
35641
|
+
const componentRef = result.componentRef;
|
|
35642
|
+
if (componentRef) {
|
|
35643
|
+
ctx.out(` ${c.dim}owner:${c.reset} ${c.yellow}${componentRef}${c.reset}`);
|
|
35573
35644
|
}
|
|
35574
35645
|
const fields = shapeData?.fields;
|
|
35575
35646
|
if (fields) {
|
|
@@ -37869,10 +37940,6 @@ async function dispatch(ctx) {
|
|
|
37869
37940
|
const { command } = ctx.invocation;
|
|
37870
37941
|
if (!command || command === "help") {
|
|
37871
37942
|
const helpTarget = command === "help" ? ctx.invocation.positional[0] : undefined;
|
|
37872
|
-
if (ctx.format === "json") {
|
|
37873
|
-
printJson(ctx.out, buildCliSpec());
|
|
37874
|
-
return;
|
|
37875
|
-
}
|
|
37876
37943
|
if (helpTarget) {
|
|
37877
37944
|
const domain = registry.getDomain(helpTarget);
|
|
37878
37945
|
if (domain) {
|
|
@@ -37881,6 +37948,10 @@ async function dispatch(ctx) {
|
|
|
37881
37948
|
throw new CliError(2 /* UserInput */, "USER_INPUT", `Unknown command: ${helpTarget}`, undefined, "Run 'wh help' for available commands.");
|
|
37882
37949
|
}
|
|
37883
37950
|
} else {
|
|
37951
|
+
if (ctx.format === "json") {
|
|
37952
|
+
printJson(ctx.out, buildCliSpec());
|
|
37953
|
+
return;
|
|
37954
|
+
}
|
|
37884
37955
|
let repoSlug;
|
|
37885
37956
|
try {
|
|
37886
37957
|
const { org, repo } = parseOrgRepo(getRepoRef(ctx), ctx.config);
|
|
@@ -37932,6 +38003,7 @@ async function reconcileComponent(client, org, repo, pkg, source, existingInstal
|
|
|
37932
38003
|
const errors = [];
|
|
37933
38004
|
const { meta, manifest } = pkg;
|
|
37934
38005
|
const componentId = meta.id;
|
|
38006
|
+
const componentRef = source.registeredComponentRef;
|
|
37935
38007
|
const validation = validateComponentPackage(pkg);
|
|
37936
38008
|
if (!validation.valid) {
|
|
37937
38009
|
const validationErrors = validation.findings.filter((f) => f.level === "error").map((f) => f.message);
|
|
@@ -37982,7 +38054,7 @@ async function reconcileComponent(client, org, repo, pkg, source, existingInstal
|
|
|
37982
38054
|
const oldCredNames = wasIncomplete ? new Set : new Set(oldManifest?.credentials?.map((c) => c.name) ?? []);
|
|
37983
38055
|
const liveShapeNames = new Set;
|
|
37984
38056
|
const liveShapeDataByName = new Map;
|
|
37985
|
-
const
|
|
38057
|
+
const liveShapeComponentRefByName = new Map;
|
|
37986
38058
|
for (const shape of reconcileShapes) {
|
|
37987
38059
|
if (isFailedInstallState || previousState !== "degraded" && !oldShapeNames.has(shape.name)) {
|
|
37988
38060
|
continue;
|
|
@@ -37999,7 +38071,7 @@ async function reconcileComponent(client, org, repo, pkg, source, existingInstal
|
|
|
37999
38071
|
includeRetracted: true
|
|
38000
38072
|
});
|
|
38001
38073
|
liveShapeDataByName.set(shape.name, liveShape.version?.data);
|
|
38002
|
-
|
|
38074
|
+
liveShapeComponentRefByName.set(shape.name, liveShape.componentRef);
|
|
38003
38075
|
} catch {}
|
|
38004
38076
|
} catch {}
|
|
38005
38077
|
}
|
|
@@ -38034,7 +38106,7 @@ async function reconcileComponent(client, org, repo, pkg, source, existingInstal
|
|
|
38034
38106
|
data: manifestShapeData(shape)
|
|
38035
38107
|
}));
|
|
38036
38108
|
try {
|
|
38037
|
-
await client.commit.apply(org, repo, `Add new shapes for ${meta.name}`, shapeOps, {
|
|
38109
|
+
await client.commit.apply(org, repo, `Add new shapes for ${meta.name}`, shapeOps, { componentRef });
|
|
38038
38110
|
steps.push({ step: "add-new-shapes", status: "ok" });
|
|
38039
38111
|
} catch (err) {
|
|
38040
38112
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -38050,8 +38122,8 @@ async function reconcileComponent(client, org, repo, pkg, source, existingInstal
|
|
|
38050
38122
|
if (!liveShapeNames.has(shape.name))
|
|
38051
38123
|
return false;
|
|
38052
38124
|
const liveData = liveShapeDataByName.get(shape.name);
|
|
38053
|
-
const
|
|
38054
|
-
return
|
|
38125
|
+
const liveComponentRef = liveShapeComponentRefByName.get(shape.name);
|
|
38126
|
+
return liveComponentRef !== componentRef || !shapeDataEquals(manifestShapeData(shape), liveData);
|
|
38055
38127
|
});
|
|
38056
38128
|
if (changedShapes.length > 0) {
|
|
38057
38129
|
const shapeOps = changedShapes.map((shape) => ({
|
|
@@ -38061,7 +38133,7 @@ async function reconcileComponent(client, org, repo, pkg, source, existingInstal
|
|
|
38061
38133
|
data: manifestShapeData(shape)
|
|
38062
38134
|
}));
|
|
38063
38135
|
try {
|
|
38064
|
-
await client.commit.apply(org, repo, `Reconcile shapes for ${meta.name}`, shapeOps, {
|
|
38136
|
+
await client.commit.apply(org, repo, `Reconcile shapes for ${meta.name}`, shapeOps, { componentRef });
|
|
38065
38137
|
steps.push({ step: "claim-existing-shapes", status: "ok" });
|
|
38066
38138
|
} catch (err) {
|
|
38067
38139
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -38127,7 +38199,7 @@ async function reconcileComponent(client, org, repo, pkg, source, existingInstal
|
|
|
38127
38199
|
filterJson: compiled.filterJson,
|
|
38128
38200
|
webhookUrl: compiled.webhookUrl,
|
|
38129
38201
|
fallbackWebhookUrl: compiled.fallbackWebhookUrl,
|
|
38130
|
-
|
|
38202
|
+
componentRef
|
|
38131
38203
|
});
|
|
38132
38204
|
steps.push({ step: `add-sub-${sub.name}`, status: "ok" });
|
|
38133
38205
|
} catch (err) {
|
|
@@ -38166,8 +38238,8 @@ async function reconcileComponent(client, org, repo, pkg, source, existingInstal
|
|
|
38166
38238
|
}
|
|
38167
38239
|
try {
|
|
38168
38240
|
const liveSub = await client.subscription.get(org, repo, sub.name);
|
|
38169
|
-
if (liveSub.
|
|
38170
|
-
const msg = `Subscription "${sub.name}" is owned by component "${liveSub.
|
|
38241
|
+
if (liveSub.componentRef && liveSub.componentRef !== componentRef) {
|
|
38242
|
+
const msg = `Subscription "${sub.name}" is owned by component "${liveSub.componentRef}"`;
|
|
38171
38243
|
errors.push(msg);
|
|
38172
38244
|
steps.push({ step: stepName, status: "error", message: msg });
|
|
38173
38245
|
continue;
|
|
@@ -38185,7 +38257,7 @@ async function reconcileComponent(client, org, repo, pkg, source, existingInstal
|
|
|
38185
38257
|
filterJson: compiled.filterJson,
|
|
38186
38258
|
webhookUrl: compiled.webhookUrl,
|
|
38187
38259
|
fallbackWebhookUrl: compiled.fallbackWebhookUrl,
|
|
38188
|
-
|
|
38260
|
+
componentRef
|
|
38189
38261
|
});
|
|
38190
38262
|
} catch (createErr) {
|
|
38191
38263
|
const createMsg = createErr instanceof Error ? createErr.message : String(createErr);
|
|
@@ -38242,7 +38314,7 @@ async function reconcileComponent(client, org, repo, pkg, source, existingInstal
|
|
|
38242
38314
|
name: `${seed.shape}/${seed.name}`,
|
|
38243
38315
|
data: seed.data
|
|
38244
38316
|
}
|
|
38245
|
-
], {
|
|
38317
|
+
], { componentRef });
|
|
38246
38318
|
} catch (reviseErr) {
|
|
38247
38319
|
const reviseMsg = reviseErr instanceof Error ? reviseErr.message : String(reviseErr);
|
|
38248
38320
|
const reviseLooksMissing = reviseMsg.includes("not found") || reviseMsg.includes("NOT_FOUND");
|
|
@@ -38258,7 +38330,7 @@ async function reconcileComponent(client, org, repo, pkg, source, existingInstal
|
|
|
38258
38330
|
name: `${seed.shape}/${seed.name}`,
|
|
38259
38331
|
data: seed.data
|
|
38260
38332
|
}
|
|
38261
|
-
], {
|
|
38333
|
+
], { componentRef });
|
|
38262
38334
|
} catch (addErr) {
|
|
38263
38335
|
const msg = addErr instanceof Error ? addErr.message : String(addErr);
|
|
38264
38336
|
if (!isAlreadyExistsError(addErr)) {
|
|
@@ -38283,8 +38355,8 @@ async function reconcileComponent(client, org, repo, pkg, source, existingInstal
|
|
|
38283
38355
|
componentId,
|
|
38284
38356
|
name: meta.name,
|
|
38285
38357
|
version: meta.version,
|
|
38286
|
-
source:
|
|
38287
|
-
sourceKind:
|
|
38358
|
+
source: "registry",
|
|
38359
|
+
sourceKind: "registered",
|
|
38288
38360
|
sourceRef: source.ref ?? "",
|
|
38289
38361
|
resolvedSha: source.resolvedSha ?? "",
|
|
38290
38362
|
...source.registeredComponentRef ? { registeredComponentRef: source.registeredComponentRef } : {},
|
|
@@ -38296,7 +38368,7 @@ async function reconcileComponent(client, org, repo, pkg, source, existingInstal
|
|
|
38296
38368
|
...source.installId ?? persistedInstallId ? { installId: source.installId ?? persistedInstallId } : {}
|
|
38297
38369
|
}
|
|
38298
38370
|
}
|
|
38299
|
-
], {
|
|
38371
|
+
], { componentRef: SYSTEM_REGISTERED_COMPONENT_REF });
|
|
38300
38372
|
steps.push({ step: "update-install-record", status: "ok" });
|
|
38301
38373
|
} catch (err) {
|
|
38302
38374
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -38411,8 +38483,8 @@ async function installComponent(client, org, repo, pkg, source) {
|
|
|
38411
38483
|
componentId,
|
|
38412
38484
|
name: meta.name,
|
|
38413
38485
|
version: meta.version,
|
|
38414
|
-
source:
|
|
38415
|
-
sourceKind:
|
|
38486
|
+
source: "registry",
|
|
38487
|
+
sourceKind: "registered",
|
|
38416
38488
|
sourceRef: source.ref ?? "",
|
|
38417
38489
|
resolvedSha: source.resolvedSha ?? "",
|
|
38418
38490
|
...source.registeredComponentRef ? { registeredComponentRef: source.registeredComponentRef } : {},
|
|
@@ -38423,7 +38495,7 @@ async function installComponent(client, org, repo, pkg, source) {
|
|
|
38423
38495
|
...source.installId ? { installId: source.installId } : {}
|
|
38424
38496
|
}
|
|
38425
38497
|
}
|
|
38426
|
-
], {
|
|
38498
|
+
], { componentRef: SYSTEM_REGISTERED_COMPONENT_REF });
|
|
38427
38499
|
steps.push({ step: "create-install-record", status: "ok" });
|
|
38428
38500
|
} catch (err) {
|
|
38429
38501
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -38439,13 +38511,13 @@ async function installComponent(client, org, repo, pkg, source) {
|
|
|
38439
38511
|
data: manifestShapeData(shape)
|
|
38440
38512
|
}));
|
|
38441
38513
|
try {
|
|
38442
|
-
await client.commit.apply(org, repo, `Add shapes for ${meta.name}`, shapeOps, {
|
|
38514
|
+
await client.commit.apply(org, repo, `Add shapes for ${meta.name}`, shapeOps, { componentRef: source.registeredComponentRef });
|
|
38443
38515
|
steps.push({ step: "create-shapes", status: "ok" });
|
|
38444
38516
|
} catch (err) {
|
|
38445
38517
|
const msg = err instanceof Error ? err.message : String(err);
|
|
38446
38518
|
if (isAlreadyExistsError(err)) {
|
|
38447
38519
|
try {
|
|
38448
|
-
await reconcileShapesAfterCreateConflict(client, org, repo, pkg);
|
|
38520
|
+
await reconcileShapesAfterCreateConflict(client, org, repo, pkg, source);
|
|
38449
38521
|
steps.push({
|
|
38450
38522
|
step: "create-shapes",
|
|
38451
38523
|
status: "ok",
|
|
@@ -38522,7 +38594,7 @@ async function installComponent(client, org, repo, pkg, source) {
|
|
|
38522
38594
|
filterJson: compiled.filterJson,
|
|
38523
38595
|
webhookUrl: compiled.webhookUrl,
|
|
38524
38596
|
fallbackWebhookUrl: compiled.fallbackWebhookUrl,
|
|
38525
|
-
|
|
38597
|
+
componentRef: source.registeredComponentRef
|
|
38526
38598
|
});
|
|
38527
38599
|
steps.push({ step: `create-sub-${sub.name}`, status: "ok" });
|
|
38528
38600
|
} catch (err) {
|
|
@@ -38561,7 +38633,7 @@ async function installComponent(client, org, repo, pkg, source) {
|
|
|
38561
38633
|
name: seedName,
|
|
38562
38634
|
data: seed.data
|
|
38563
38635
|
}
|
|
38564
|
-
], {
|
|
38636
|
+
], { componentRef: source.registeredComponentRef });
|
|
38565
38637
|
steps.push({ step: `seed-${seedName}`, status: "ok" });
|
|
38566
38638
|
} catch (err) {
|
|
38567
38639
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -38588,8 +38660,8 @@ async function installComponent(client, org, repo, pkg, source) {
|
|
|
38588
38660
|
componentId,
|
|
38589
38661
|
name: meta.name,
|
|
38590
38662
|
version: meta.version,
|
|
38591
|
-
source:
|
|
38592
|
-
sourceKind:
|
|
38663
|
+
source: "registry",
|
|
38664
|
+
sourceKind: "registered",
|
|
38593
38665
|
sourceRef: source.ref ?? "",
|
|
38594
38666
|
resolvedSha: source.resolvedSha ?? "",
|
|
38595
38667
|
...source.registeredComponentRef ? { registeredComponentRef: source.registeredComponentRef } : {},
|
|
@@ -38601,7 +38673,7 @@ async function installComponent(client, org, repo, pkg, source) {
|
|
|
38601
38673
|
...source.installId ? { installId: source.installId } : {}
|
|
38602
38674
|
}
|
|
38603
38675
|
}
|
|
38604
|
-
], {
|
|
38676
|
+
], { componentRef: SYSTEM_REGISTERED_COMPONENT_REF });
|
|
38605
38677
|
steps.push({ step: "finalize", status: "ok" });
|
|
38606
38678
|
} catch (err) {
|
|
38607
38679
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -38619,12 +38691,12 @@ function assertCliMethodsAllowedForSource(pkg, source) {
|
|
|
38619
38691
|
const hasCliMethods = (pkg.manifest.cli?.methods?.length ?? 0) > 0;
|
|
38620
38692
|
if (!hasCliMethods)
|
|
38621
38693
|
return;
|
|
38622
|
-
if (
|
|
38694
|
+
if (typeof source.registeredComponentRef === "string" && source.registeredComponentRef.length > 0) {
|
|
38623
38695
|
return;
|
|
38624
38696
|
}
|
|
38625
38697
|
throw new CliError(2 /* UserInput */, "USER_INPUT", "Components that declare manifest.cli.methods must be installed from the registry.", undefined, "Register the component, then install it as <org>/<name>. Local path and GitHub URL installs cannot expose CLI methods.");
|
|
38626
38698
|
}
|
|
38627
|
-
async function reconcileShapesAfterCreateConflict(client, org, repo, pkg) {
|
|
38699
|
+
async function reconcileShapesAfterCreateConflict(client, org, repo, pkg, source) {
|
|
38628
38700
|
const { meta, manifest } = pkg;
|
|
38629
38701
|
const existingShapes = new Map;
|
|
38630
38702
|
for (const shape of manifest.shapes) {
|
|
@@ -38632,8 +38704,8 @@ async function reconcileShapesAfterCreateConflict(client, org, repo, pkg) {
|
|
|
38632
38704
|
const existingShape = await client.shape.get(org, repo, shape.name, {
|
|
38633
38705
|
includeRetracted: true
|
|
38634
38706
|
});
|
|
38635
|
-
if (existingShape.
|
|
38636
|
-
const owner = existingShape.
|
|
38707
|
+
if (existingShape.componentRef !== source.registeredComponentRef) {
|
|
38708
|
+
const owner = existingShape.componentRef ? `owned by component "${existingShape.componentRef}"` : "not owned by this component";
|
|
38637
38709
|
throw new Error(`Shape "${shape.name}" already exists and is ${owner}; cannot reconcile during fresh install`);
|
|
38638
38710
|
}
|
|
38639
38711
|
existingShapes.set(shape.name, existingShape);
|
|
@@ -38655,7 +38727,7 @@ async function reconcileShapesAfterCreateConflict(client, org, repo, pkg) {
|
|
|
38655
38727
|
name: shape.name,
|
|
38656
38728
|
data
|
|
38657
38729
|
}
|
|
38658
|
-
], {
|
|
38730
|
+
], { componentRef: source.registeredComponentRef });
|
|
38659
38731
|
continue;
|
|
38660
38732
|
}
|
|
38661
38733
|
try {
|
|
@@ -38666,7 +38738,7 @@ async function reconcileShapesAfterCreateConflict(client, org, repo, pkg) {
|
|
|
38666
38738
|
name: shape.name,
|
|
38667
38739
|
data
|
|
38668
38740
|
}
|
|
38669
|
-
], {
|
|
38741
|
+
], { componentRef: source.registeredComponentRef });
|
|
38670
38742
|
} catch (err) {
|
|
38671
38743
|
if (isAlreadyExistsError(err)) {
|
|
38672
38744
|
throw new Error(`Shape "${shape.name}" already exists but ownership could not be verified; cannot reconcile during fresh install`);
|
|
@@ -39081,7 +39153,7 @@ function resolveLogLevel(flags, env) {
|
|
|
39081
39153
|
// package.json
|
|
39082
39154
|
var package_default3 = {
|
|
39083
39155
|
name: "@warmhub/cli",
|
|
39084
|
-
version: "0.
|
|
39156
|
+
version: "0.53.0",
|
|
39085
39157
|
private: false,
|
|
39086
39158
|
type: "module",
|
|
39087
39159
|
description: "The wh CLI for WarmHub — create repos, commit and query data, and compound knowledge with your AI agents.",
|
|
@@ -39228,14 +39300,17 @@ async function maybeHandleComponentShellBoundary(argv, deps = {}) {
|
|
|
39228
39300
|
callRegisteredSetup: callRegisteredSetupImpl
|
|
39229
39301
|
});
|
|
39230
39302
|
}
|
|
39231
|
-
const
|
|
39232
|
-
if (!
|
|
39303
|
+
const componentRef = invocation.positional[1];
|
|
39304
|
+
if (!componentRef) {
|
|
39233
39305
|
return;
|
|
39234
39306
|
}
|
|
39307
|
+
if (!isRegisteredComponentSource(componentRef)) {
|
|
39308
|
+
throw new CliError(2 /* UserInput */, "USER_INPUT", `Invalid component reference '${componentRef}'. Expected '<org>/<name>' with no extra slashes and no empty parts.`, undefined, "Usage: wh component update <org/name> --repo org/repo");
|
|
39309
|
+
}
|
|
39235
39310
|
const repoFlag = getStringFlag(invocation.flags, "repo") ?? config.defaultRepo;
|
|
39236
39311
|
const refOverride = getStringFlag(invocation.flags, "ref");
|
|
39237
39312
|
return await handleComponentUpdate({
|
|
39238
|
-
|
|
39313
|
+
componentRef,
|
|
39239
39314
|
repoFlag,
|
|
39240
39315
|
refOverride,
|
|
39241
39316
|
client,
|
|
@@ -39306,7 +39381,6 @@ async function performRegisteredInstall(args) {
|
|
|
39306
39381
|
invalidateInstallSnapshotCache(installRepo);
|
|
39307
39382
|
const result = await args.installFromManifest(args.client, args.parsedRepo.org, args.parsedRepo.repo, resolved.manifest, {
|
|
39308
39383
|
installId,
|
|
39309
|
-
sourceKind: "registered",
|
|
39310
39384
|
registeredComponentRef: args.componentRef
|
|
39311
39385
|
});
|
|
39312
39386
|
if (!result.ok) {
|
|
@@ -39371,11 +39445,15 @@ function warmHubErrorBackendCode(error) {
|
|
|
39371
39445
|
async function handleComponentUpdate(args) {
|
|
39372
39446
|
const parsedRepo = parseOrgRepo(args.repoFlag, args.config);
|
|
39373
39447
|
const installRepo = `${parsedRepo.org}/${parsedRepo.repo}`;
|
|
39374
|
-
const
|
|
39448
|
+
const componentId = await resolveInstalledComponentRefId(args.client, parsedRepo.org, parsedRepo.repo, args.componentRef);
|
|
39449
|
+
const installThing = await args.client.thing.get(parsedRepo.org, parsedRepo.repo, `ComponentInstall/${componentId}`);
|
|
39375
39450
|
const installData = installThing.data && typeof installThing.data === "object" ? installThing.data : {};
|
|
39376
39451
|
const source = resolveComponentUpdateSource(installData);
|
|
39377
39452
|
if (source.kind === "registered") {
|
|
39378
39453
|
rejectRefForRegistered(source.componentRef, args.refOverride);
|
|
39454
|
+
if (source.componentRef !== args.componentRef) {
|
|
39455
|
+
throw new CliError(2 /* UserInput */, "USER_INPUT", `Component '${args.componentRef}' resolved to an install for '${source.componentRef}', which is inconsistent with the install record.`);
|
|
39456
|
+
}
|
|
39379
39457
|
return performRegisteredInstall({
|
|
39380
39458
|
componentRef: source.componentRef,
|
|
39381
39459
|
persistedInstallData: installData,
|
|
@@ -39391,9 +39469,9 @@ async function handleComponentUpdate(args) {
|
|
|
39391
39469
|
});
|
|
39392
39470
|
}
|
|
39393
39471
|
if (source.kind === "system") {
|
|
39394
|
-
throw new CliError(2 /* UserInput */, "USER_INPUT", `Component '${args.
|
|
39472
|
+
throw new CliError(2 /* UserInput */, "USER_INPUT", `Component '${args.componentRef}' is a platform-managed system install and cannot be updated via the CLI; it is reconciled automatically by the WarmHub backend.`);
|
|
39395
39473
|
}
|
|
39396
|
-
throw new CliError(2 /* UserInput */, "USER_INPUT", `Component '${args.
|
|
39474
|
+
throw new CliError(2 /* UserInput */, "USER_INPUT", `Component '${args.componentRef}' was not installed from a registered component and can no longer be updated in place.`, undefined, "Register the component (`wh component register <name> --org <org> --manifest <path>`) and reinstall it with `wh component install <org>/<name>`.");
|
|
39397
39475
|
}
|
|
39398
39476
|
async function writeInstallResult(writeOut, writeErr, format, verb, result, installRepo, client) {
|
|
39399
39477
|
if (result.ok) {
|
|
@@ -39866,4 +39944,4 @@ if (!updateCheckSuppressedByArgv && shouldRunUpdateCheck(updateEligibility)) {
|
|
|
39866
39944
|
var interceptedExitCode = await maybeHandleComponentShellBoundary(dispatchArgv);
|
|
39867
39945
|
process.exitCode = interceptedExitCode === undefined ? await runCli(dispatchArgv, { version: package_default3.version }) : interceptedExitCode;
|
|
39868
39946
|
|
|
39869
|
-
//# debugId=
|
|
39947
|
+
//# debugId=E69740B781D6D4C864756E2164756E21
|