@ainyc/canonry 4.13.3 → 4.15.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/assets/assets/{index-C3thP3DI.js → index-B6Mi9Fd1.js} +1 -1
- package/assets/index.html +1 -1
- package/dist/{chunk-5NYG5EC7.js → chunk-C32VL5BB.js} +1 -0
- package/dist/{chunk-FRDVC2XF.js → chunk-DLSQXNUN.js} +311 -83
- package/dist/cli.js +191 -113
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -2
- package/dist/mcp.js +1 -1
- package/package.json +7 -7
package/dist/cli.js
CHANGED
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
coerceAgentProvider,
|
|
4
4
|
computeCompetitorOverlap,
|
|
5
5
|
createServer,
|
|
6
|
+
detectAndTrackUpgrade,
|
|
6
7
|
determineCitationState,
|
|
7
8
|
extractRecommendedCompetitors,
|
|
8
9
|
formatAuditFactorScore,
|
|
@@ -16,9 +17,10 @@ import {
|
|
|
16
17
|
reparseStoredResult3,
|
|
17
18
|
reparseStoredResult4,
|
|
18
19
|
setGoogleAuthConfig,
|
|
20
|
+
setTelemetrySource,
|
|
19
21
|
showFirstRunNotice,
|
|
20
22
|
trackEvent
|
|
21
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-DLSQXNUN.js";
|
|
22
24
|
import {
|
|
23
25
|
CliError,
|
|
24
26
|
EXIT_SYSTEM_ERROR,
|
|
@@ -29,11 +31,12 @@ import {
|
|
|
29
31
|
getConfigPath,
|
|
30
32
|
isEndpointMissing,
|
|
31
33
|
loadConfig,
|
|
34
|
+
loadConfigRaw,
|
|
32
35
|
printCliError,
|
|
33
36
|
saveConfig,
|
|
34
37
|
saveConfigPatch,
|
|
35
38
|
usageError
|
|
36
|
-
} from "./chunk-
|
|
39
|
+
} from "./chunk-C32VL5BB.js";
|
|
37
40
|
import {
|
|
38
41
|
apiKeys,
|
|
39
42
|
competitors,
|
|
@@ -43,6 +46,7 @@ import {
|
|
|
43
46
|
migrate,
|
|
44
47
|
parseJsonColumn,
|
|
45
48
|
projects,
|
|
49
|
+
queries,
|
|
46
50
|
querySnapshots,
|
|
47
51
|
runs
|
|
48
52
|
} from "./chunk-7HBZCGRL.js";
|
|
@@ -69,6 +73,42 @@ import {
|
|
|
69
73
|
// src/cli.ts
|
|
70
74
|
import { pathToFileURL } from "url";
|
|
71
75
|
|
|
76
|
+
// src/setup-state.ts
|
|
77
|
+
import fs from "fs";
|
|
78
|
+
function buildSetupState() {
|
|
79
|
+
if (!configExists()) return void 0;
|
|
80
|
+
let provider_count = 0;
|
|
81
|
+
let has_keywords = false;
|
|
82
|
+
let project_count = 0;
|
|
83
|
+
let is_first_run = true;
|
|
84
|
+
let dbPath;
|
|
85
|
+
try {
|
|
86
|
+
const raw = loadConfigRaw();
|
|
87
|
+
if (raw) {
|
|
88
|
+
is_first_run = !raw.anonymousId;
|
|
89
|
+
if (raw.providers) {
|
|
90
|
+
provider_count = Object.values(raw.providers).filter(
|
|
91
|
+
(p) => Boolean(p?.apiKey) || Boolean(p?.baseUrl)
|
|
92
|
+
).length;
|
|
93
|
+
}
|
|
94
|
+
if (typeof raw.database === "string" && raw.database.length > 0) {
|
|
95
|
+
dbPath = raw.database;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
} catch {
|
|
99
|
+
}
|
|
100
|
+
if (dbPath && fs.existsSync(dbPath)) {
|
|
101
|
+
try {
|
|
102
|
+
const db = createClient(dbPath);
|
|
103
|
+
project_count = db.select({ id: projects.id }).from(projects).all().length;
|
|
104
|
+
const firstQuery = db.select({ id: queries.id }).from(queries).limit(1).all();
|
|
105
|
+
has_keywords = firstQuery.length > 0;
|
|
106
|
+
} catch {
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return { provider_count, has_keywords, project_count, is_first_run };
|
|
110
|
+
}
|
|
111
|
+
|
|
72
112
|
// src/cli-dispatch.ts
|
|
73
113
|
import { parseArgs } from "util";
|
|
74
114
|
function commandId(spec) {
|
|
@@ -2018,9 +2058,9 @@ async function gaConnect(project, opts) {
|
|
|
2018
2058
|
propertyId: opts.propertyId
|
|
2019
2059
|
};
|
|
2020
2060
|
if (opts.keyFile) {
|
|
2021
|
-
const
|
|
2061
|
+
const fs13 = await import("fs");
|
|
2022
2062
|
try {
|
|
2023
|
-
const content =
|
|
2063
|
+
const content = fs13.readFileSync(opts.keyFile, "utf-8");
|
|
2024
2064
|
JSON.parse(content);
|
|
2025
2065
|
body.keyJson = content;
|
|
2026
2066
|
} catch (e) {
|
|
@@ -2698,10 +2738,10 @@ async function trafficConnectCloudRun(project, opts) {
|
|
|
2698
2738
|
details: { project }
|
|
2699
2739
|
});
|
|
2700
2740
|
}
|
|
2701
|
-
const
|
|
2741
|
+
const fs13 = await import("fs");
|
|
2702
2742
|
let keyJson;
|
|
2703
2743
|
try {
|
|
2704
|
-
keyJson =
|
|
2744
|
+
keyJson = fs13.readFileSync(opts.serviceAccountKey, "utf-8");
|
|
2705
2745
|
JSON.parse(keyJson);
|
|
2706
2746
|
} catch (e) {
|
|
2707
2747
|
const msg = e instanceof Error ? e.message : String(e);
|
|
@@ -3837,7 +3877,7 @@ var GOOGLE_CLI_COMMANDS = [
|
|
|
3837
3877
|
];
|
|
3838
3878
|
|
|
3839
3879
|
// src/commands/keyword.ts
|
|
3840
|
-
import
|
|
3880
|
+
import fs2 from "fs";
|
|
3841
3881
|
function getClient8() {
|
|
3842
3882
|
return createApiClient();
|
|
3843
3883
|
}
|
|
@@ -3902,7 +3942,7 @@ async function listKeywords(project, format) {
|
|
|
3902
3942
|
}
|
|
3903
3943
|
}
|
|
3904
3944
|
async function importKeywords(project, filePath, format) {
|
|
3905
|
-
if (!
|
|
3945
|
+
if (!fs2.existsSync(filePath)) {
|
|
3906
3946
|
throw new CliError({
|
|
3907
3947
|
code: "KEYWORD_IMPORT_FILE_NOT_FOUND",
|
|
3908
3948
|
message: `File not found: ${filePath}`,
|
|
@@ -3913,7 +3953,7 @@ async function importKeywords(project, filePath, format) {
|
|
|
3913
3953
|
}
|
|
3914
3954
|
});
|
|
3915
3955
|
}
|
|
3916
|
-
const content =
|
|
3956
|
+
const content = fs2.readFileSync(filePath, "utf-8");
|
|
3917
3957
|
const keywords = content.split("\n").map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
|
|
3918
3958
|
if (keywords.length === 0) {
|
|
3919
3959
|
if (format === "json") {
|
|
@@ -4114,46 +4154,46 @@ var KEYWORD_CLI_COMMANDS = [
|
|
|
4114
4154
|
];
|
|
4115
4155
|
|
|
4116
4156
|
// src/commands/query.ts
|
|
4117
|
-
import
|
|
4157
|
+
import fs3 from "fs";
|
|
4118
4158
|
function getClient9() {
|
|
4119
4159
|
return createApiClient();
|
|
4120
4160
|
}
|
|
4121
|
-
async function addQueries(project,
|
|
4161
|
+
async function addQueries(project, queries2, format) {
|
|
4122
4162
|
const client = getClient9();
|
|
4123
|
-
await client.appendQueries(project,
|
|
4163
|
+
await client.appendQueries(project, queries2);
|
|
4124
4164
|
if (format === "json") {
|
|
4125
4165
|
console.log(JSON.stringify({
|
|
4126
4166
|
project,
|
|
4127
|
-
queries,
|
|
4128
|
-
addedCount:
|
|
4167
|
+
queries: queries2,
|
|
4168
|
+
addedCount: queries2.length
|
|
4129
4169
|
}, null, 2));
|
|
4130
4170
|
return;
|
|
4131
4171
|
}
|
|
4132
|
-
console.log(`Added ${
|
|
4172
|
+
console.log(`Added ${queries2.length} ${queries2.length === 1 ? "query" : "queries"} to "${project}".`);
|
|
4133
4173
|
}
|
|
4134
|
-
async function replaceQueries(project,
|
|
4174
|
+
async function replaceQueries(project, queries2, format) {
|
|
4135
4175
|
const client = getClient9();
|
|
4136
|
-
await client.putQueries(project,
|
|
4176
|
+
await client.putQueries(project, queries2);
|
|
4137
4177
|
if (format === "json") {
|
|
4138
4178
|
console.log(JSON.stringify({
|
|
4139
4179
|
project,
|
|
4140
|
-
queries,
|
|
4141
|
-
replacedCount:
|
|
4180
|
+
queries: queries2,
|
|
4181
|
+
replacedCount: queries2.length
|
|
4142
4182
|
}, null, 2));
|
|
4143
4183
|
return;
|
|
4144
4184
|
}
|
|
4145
|
-
console.log(`Set ${
|
|
4185
|
+
console.log(`Set ${queries2.length} ${queries2.length === 1 ? "query" : "queries"} for "${project}".`);
|
|
4146
4186
|
}
|
|
4147
|
-
async function removeQueries(project,
|
|
4187
|
+
async function removeQueries(project, queries2, format) {
|
|
4148
4188
|
const client = getClient9();
|
|
4149
4189
|
const existing = await client.listQueries(project);
|
|
4150
4190
|
const existingSet = new Set(existing.map((q) => q.query));
|
|
4151
|
-
const removedQueries =
|
|
4152
|
-
await client.deleteQueries(project,
|
|
4191
|
+
const removedQueries = queries2.filter((q) => existingSet.has(q));
|
|
4192
|
+
await client.deleteQueries(project, queries2);
|
|
4153
4193
|
if (format === "json") {
|
|
4154
4194
|
console.log(JSON.stringify({
|
|
4155
4195
|
project,
|
|
4156
|
-
queries,
|
|
4196
|
+
queries: queries2,
|
|
4157
4197
|
removedQueries,
|
|
4158
4198
|
removedCount: removedQueries.length
|
|
4159
4199
|
}, null, 2));
|
|
@@ -4179,7 +4219,7 @@ async function listQueries(project, format) {
|
|
|
4179
4219
|
}
|
|
4180
4220
|
}
|
|
4181
4221
|
async function importQueries(project, filePath, format) {
|
|
4182
|
-
if (!
|
|
4222
|
+
if (!fs3.existsSync(filePath)) {
|
|
4183
4223
|
throw new CliError({
|
|
4184
4224
|
code: "QUERY_IMPORT_FILE_NOT_FOUND",
|
|
4185
4225
|
message: `File not found: ${filePath}`,
|
|
@@ -4190,9 +4230,9 @@ async function importQueries(project, filePath, format) {
|
|
|
4190
4230
|
}
|
|
4191
4231
|
});
|
|
4192
4232
|
}
|
|
4193
|
-
const content =
|
|
4194
|
-
const
|
|
4195
|
-
if (
|
|
4233
|
+
const content = fs3.readFileSync(filePath, "utf-8");
|
|
4234
|
+
const queries2 = content.split("\n").map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
|
|
4235
|
+
if (queries2.length === 0) {
|
|
4196
4236
|
if (format === "json") {
|
|
4197
4237
|
console.log(JSON.stringify({
|
|
4198
4238
|
project,
|
|
@@ -4206,17 +4246,17 @@ async function importQueries(project, filePath, format) {
|
|
|
4206
4246
|
return;
|
|
4207
4247
|
}
|
|
4208
4248
|
const client = getClient9();
|
|
4209
|
-
await client.appendQueries(project,
|
|
4249
|
+
await client.appendQueries(project, queries2);
|
|
4210
4250
|
if (format === "json") {
|
|
4211
4251
|
console.log(JSON.stringify({
|
|
4212
4252
|
project,
|
|
4213
4253
|
filePath,
|
|
4214
|
-
queries,
|
|
4215
|
-
importedCount:
|
|
4254
|
+
queries: queries2,
|
|
4255
|
+
importedCount: queries2.length
|
|
4216
4256
|
}, null, 2));
|
|
4217
4257
|
return;
|
|
4218
4258
|
}
|
|
4219
|
-
console.log(`Imported ${
|
|
4259
|
+
console.log(`Imported ${queries2.length} ${queries2.length === 1 ? "query" : "queries"} to "${project}".`);
|
|
4220
4260
|
}
|
|
4221
4261
|
async function generateQueries(project, provider, opts) {
|
|
4222
4262
|
const client = getClient9();
|
|
@@ -4259,8 +4299,8 @@ var QUERY_CLI_COMMANDS = [
|
|
|
4259
4299
|
usage: "canonry query add <project> <query...> [--format json]",
|
|
4260
4300
|
run: async (input) => {
|
|
4261
4301
|
const project = requireProject(input, "query.add", "canonry query add <project> <query...> [--format json]");
|
|
4262
|
-
const
|
|
4263
|
-
if (
|
|
4302
|
+
const queries2 = input.positionals.slice(1);
|
|
4303
|
+
if (queries2.length === 0) {
|
|
4264
4304
|
throw usageError("Error: project name and at least one query required\nUsage: canonry query add <project> <query...> [--format json]", {
|
|
4265
4305
|
message: "project name and at least one query required",
|
|
4266
4306
|
details: {
|
|
@@ -4269,7 +4309,7 @@ var QUERY_CLI_COMMANDS = [
|
|
|
4269
4309
|
}
|
|
4270
4310
|
});
|
|
4271
4311
|
}
|
|
4272
|
-
await addQueries(project,
|
|
4312
|
+
await addQueries(project, queries2, input.format);
|
|
4273
4313
|
}
|
|
4274
4314
|
},
|
|
4275
4315
|
{
|
|
@@ -4277,8 +4317,8 @@ var QUERY_CLI_COMMANDS = [
|
|
|
4277
4317
|
usage: "canonry query replace <project> <query...> [--format json]",
|
|
4278
4318
|
run: async (input) => {
|
|
4279
4319
|
const project = requireProject(input, "query.replace", "canonry query replace <project> <query...> [--format json]");
|
|
4280
|
-
const
|
|
4281
|
-
if (
|
|
4320
|
+
const queries2 = input.positionals.slice(1);
|
|
4321
|
+
if (queries2.length === 0) {
|
|
4282
4322
|
throw usageError("Error: project name and at least one query required\nUsage: canonry query replace <project> <query...> [--format json]", {
|
|
4283
4323
|
message: "project name and at least one query required",
|
|
4284
4324
|
details: {
|
|
@@ -4287,7 +4327,7 @@ var QUERY_CLI_COMMANDS = [
|
|
|
4287
4327
|
}
|
|
4288
4328
|
});
|
|
4289
4329
|
}
|
|
4290
|
-
await replaceQueries(project,
|
|
4330
|
+
await replaceQueries(project, queries2, input.format);
|
|
4291
4331
|
}
|
|
4292
4332
|
},
|
|
4293
4333
|
{
|
|
@@ -4295,8 +4335,8 @@ var QUERY_CLI_COMMANDS = [
|
|
|
4295
4335
|
usage: "canonry query remove <project> <query...> [--format json]",
|
|
4296
4336
|
run: async (input) => {
|
|
4297
4337
|
const project = requireProject(input, "query.remove", "canonry query remove <project> <query...> [--format json]");
|
|
4298
|
-
const
|
|
4299
|
-
if (
|
|
4338
|
+
const queries2 = input.positionals.slice(1);
|
|
4339
|
+
if (queries2.length === 0) {
|
|
4300
4340
|
throw usageError("Error: project name and at least one query required\nUsage: canonry query remove <project> <query...> [--format json]", {
|
|
4301
4341
|
message: "project name and at least one query required",
|
|
4302
4342
|
details: {
|
|
@@ -4305,7 +4345,7 @@ var QUERY_CLI_COMMANDS = [
|
|
|
4305
4345
|
}
|
|
4306
4346
|
});
|
|
4307
4347
|
}
|
|
4308
|
-
await removeQueries(project,
|
|
4348
|
+
await removeQueries(project, queries2, input.format);
|
|
4309
4349
|
}
|
|
4310
4350
|
},
|
|
4311
4351
|
{
|
|
@@ -4313,8 +4353,8 @@ var QUERY_CLI_COMMANDS = [
|
|
|
4313
4353
|
usage: "canonry query delete <project> <query...> [--format json]",
|
|
4314
4354
|
run: async (input) => {
|
|
4315
4355
|
const project = requireProject(input, "query.delete", "canonry query delete <project> <query...> [--format json]");
|
|
4316
|
-
const
|
|
4317
|
-
if (
|
|
4356
|
+
const queries2 = input.positionals.slice(1);
|
|
4357
|
+
if (queries2.length === 0) {
|
|
4318
4358
|
throw usageError("Error: project name and at least one query required\nUsage: canonry query delete <project> <query...> [--format json]", {
|
|
4319
4359
|
message: "project name and at least one query required",
|
|
4320
4360
|
details: {
|
|
@@ -4323,7 +4363,7 @@ var QUERY_CLI_COMMANDS = [
|
|
|
4323
4363
|
}
|
|
4324
4364
|
});
|
|
4325
4365
|
}
|
|
4326
|
-
await removeQueries(project,
|
|
4366
|
+
await removeQueries(project, queries2, input.format);
|
|
4327
4367
|
}
|
|
4328
4368
|
},
|
|
4329
4369
|
{
|
|
@@ -4391,7 +4431,7 @@ var QUERY_CLI_COMMANDS = [
|
|
|
4391
4431
|
];
|
|
4392
4432
|
|
|
4393
4433
|
// src/commands/mcp.ts
|
|
4394
|
-
import
|
|
4434
|
+
import fs4 from "fs";
|
|
4395
4435
|
import path2 from "path";
|
|
4396
4436
|
import { createRequire } from "module";
|
|
4397
4437
|
|
|
@@ -4497,8 +4537,8 @@ function renderClientSnippet(client, serverName, entry) {
|
|
|
4497
4537
|
return renderJsonSnippet(serverName, entry, client.format);
|
|
4498
4538
|
}
|
|
4499
4539
|
function readJsonConfig(configPath) {
|
|
4500
|
-
if (!
|
|
4501
|
-
const raw =
|
|
4540
|
+
if (!fs4.existsSync(configPath)) return {};
|
|
4541
|
+
const raw = fs4.readFileSync(configPath, "utf-8").trim();
|
|
4502
4542
|
if (!raw) return {};
|
|
4503
4543
|
try {
|
|
4504
4544
|
const parsed = JSON.parse(raw);
|
|
@@ -4516,14 +4556,14 @@ function readJsonConfig(configPath) {
|
|
|
4516
4556
|
}
|
|
4517
4557
|
}
|
|
4518
4558
|
function writeJsonConfig(configPath, value) {
|
|
4519
|
-
|
|
4520
|
-
|
|
4559
|
+
fs4.mkdirSync(path2.dirname(configPath), { recursive: true });
|
|
4560
|
+
fs4.writeFileSync(configPath, `${JSON.stringify(value, null, 2)}
|
|
4521
4561
|
`, "utf-8");
|
|
4522
4562
|
}
|
|
4523
4563
|
function backupConfigIfPresent(configPath) {
|
|
4524
|
-
if (!
|
|
4564
|
+
if (!fs4.existsSync(configPath)) return void 0;
|
|
4525
4565
|
const backupPath = `${configPath}.canonry.bak`;
|
|
4526
|
-
|
|
4566
|
+
fs4.copyFileSync(configPath, backupPath);
|
|
4527
4567
|
return backupPath;
|
|
4528
4568
|
}
|
|
4529
4569
|
function findClientOrThrow(id) {
|
|
@@ -4870,13 +4910,13 @@ var NOTIFY_CLI_COMMANDS = [
|
|
|
4870
4910
|
];
|
|
4871
4911
|
|
|
4872
4912
|
// src/commands/apply.ts
|
|
4873
|
-
import
|
|
4913
|
+
import fs5 from "fs";
|
|
4874
4914
|
import { parseAllDocuments } from "yaml";
|
|
4875
4915
|
async function applyConfigFile(filePath) {
|
|
4876
|
-
if (!
|
|
4916
|
+
if (!fs5.existsSync(filePath)) {
|
|
4877
4917
|
throw new Error(`File not found: ${filePath}`);
|
|
4878
4918
|
}
|
|
4879
|
-
const content =
|
|
4919
|
+
const content = fs5.readFileSync(filePath, "utf-8");
|
|
4880
4920
|
const docs = parseAllDocuments(content);
|
|
4881
4921
|
const client = createApiClient();
|
|
4882
4922
|
const errors = [];
|
|
@@ -5620,7 +5660,7 @@ var PROJECT_CLI_COMMANDS = [
|
|
|
5620
5660
|
];
|
|
5621
5661
|
|
|
5622
5662
|
// src/commands/report.ts
|
|
5623
|
-
import
|
|
5663
|
+
import fs6 from "fs";
|
|
5624
5664
|
import path3 from "path";
|
|
5625
5665
|
function defaultOutputPath(project, audience) {
|
|
5626
5666
|
const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
@@ -5637,10 +5677,10 @@ async function runReportCommand(project, opts = {}) {
|
|
|
5637
5677
|
const html = renderReportHtml(report, { audience });
|
|
5638
5678
|
const targetPath = opts.output ? path3.resolve(opts.output) : defaultOutputPath(project, audience);
|
|
5639
5679
|
const dir = path3.dirname(targetPath);
|
|
5640
|
-
if (!
|
|
5641
|
-
|
|
5680
|
+
if (!fs6.existsSync(dir)) {
|
|
5681
|
+
fs6.mkdirSync(dir, { recursive: true });
|
|
5642
5682
|
}
|
|
5643
|
-
|
|
5683
|
+
fs6.writeFileSync(targetPath, html, "utf-8");
|
|
5644
5684
|
console.log(`Report written to ${targetPath}`);
|
|
5645
5685
|
}
|
|
5646
5686
|
|
|
@@ -6381,7 +6421,7 @@ Usage: canonry settings provider ${name} --api-key <key> [--model <model>] [--ma
|
|
|
6381
6421
|
];
|
|
6382
6422
|
|
|
6383
6423
|
// src/commands/skills.ts
|
|
6384
|
-
import
|
|
6424
|
+
import fs7 from "fs";
|
|
6385
6425
|
import path4 from "path";
|
|
6386
6426
|
import { fileURLToPath } from "url";
|
|
6387
6427
|
var BUNDLED_SKILL_NAMES = ["canonry-setup", "aero"];
|
|
@@ -6393,7 +6433,7 @@ function resolveBundledSkillsRoot(pkgDir) {
|
|
|
6393
6433
|
path4.join(here, "../../../../skills")
|
|
6394
6434
|
];
|
|
6395
6435
|
for (const candidate of candidates) {
|
|
6396
|
-
if (BUNDLED_SKILL_NAMES.every((name) =>
|
|
6436
|
+
if (BUNDLED_SKILL_NAMES.every((name) => fs7.existsSync(path4.join(candidate, name, "SKILL.md")))) {
|
|
6397
6437
|
return candidate;
|
|
6398
6438
|
}
|
|
6399
6439
|
}
|
|
@@ -6416,13 +6456,13 @@ function getBundledSkills(pkgDir) {
|
|
|
6416
6456
|
return BUNDLED_SKILL_NAMES.map((name) => {
|
|
6417
6457
|
const skillDir = path4.join(root, name);
|
|
6418
6458
|
const skillFile = path4.join(skillDir, "SKILL.md");
|
|
6419
|
-
const content =
|
|
6459
|
+
const content = fs7.readFileSync(skillFile, "utf-8");
|
|
6420
6460
|
return { name, description: parseDescription(content), bundledPath: skillDir };
|
|
6421
6461
|
});
|
|
6422
6462
|
}
|
|
6423
6463
|
function walkRelative(dir, prefix = "") {
|
|
6424
6464
|
const out = [];
|
|
6425
|
-
for (const entry of
|
|
6465
|
+
for (const entry of fs7.readdirSync(dir, { withFileTypes: true })) {
|
|
6426
6466
|
const rel = prefix ? path4.join(prefix, entry.name) : entry.name;
|
|
6427
6467
|
const full = path4.join(dir, entry.name);
|
|
6428
6468
|
if (entry.isDirectory()) {
|
|
@@ -6434,28 +6474,28 @@ function walkRelative(dir, prefix = "") {
|
|
|
6434
6474
|
return out.sort();
|
|
6435
6475
|
}
|
|
6436
6476
|
function compareDirContent(srcDir, destDir) {
|
|
6437
|
-
if (!
|
|
6438
|
-
if (!
|
|
6477
|
+
if (!fs7.existsSync(destDir)) return "missing";
|
|
6478
|
+
if (!fs7.statSync(destDir).isDirectory()) return "different";
|
|
6439
6479
|
const srcFiles = walkRelative(srcDir);
|
|
6440
6480
|
const destFiles = walkRelative(destDir);
|
|
6441
6481
|
if (srcFiles.length !== destFiles.length) return "different";
|
|
6442
6482
|
for (let i = 0; i < srcFiles.length; i++) {
|
|
6443
6483
|
if (srcFiles[i] !== destFiles[i]) return "different";
|
|
6444
|
-
const srcBytes =
|
|
6445
|
-
const destBytes =
|
|
6484
|
+
const srcBytes = fs7.readFileSync(path4.join(srcDir, srcFiles[i]));
|
|
6485
|
+
const destBytes = fs7.readFileSync(path4.join(destDir, destFiles[i]));
|
|
6446
6486
|
if (!srcBytes.equals(destBytes)) return "different";
|
|
6447
6487
|
}
|
|
6448
6488
|
return "match";
|
|
6449
6489
|
}
|
|
6450
6490
|
function copyDirRecursive(src, dest) {
|
|
6451
|
-
|
|
6452
|
-
for (const entry of
|
|
6491
|
+
fs7.mkdirSync(dest, { recursive: true });
|
|
6492
|
+
for (const entry of fs7.readdirSync(src, { withFileTypes: true })) {
|
|
6453
6493
|
const srcPath = path4.join(src, entry.name);
|
|
6454
6494
|
const destPath = path4.join(dest, entry.name);
|
|
6455
6495
|
if (entry.isDirectory()) {
|
|
6456
6496
|
copyDirRecursive(srcPath, destPath);
|
|
6457
6497
|
} else if (entry.isFile()) {
|
|
6458
|
-
|
|
6498
|
+
fs7.copyFileSync(srcPath, destPath);
|
|
6459
6499
|
}
|
|
6460
6500
|
}
|
|
6461
6501
|
}
|
|
@@ -6480,7 +6520,7 @@ function installClaudeSkill(skill, targetDir, force) {
|
|
|
6480
6520
|
});
|
|
6481
6521
|
}
|
|
6482
6522
|
if (compare === "different") {
|
|
6483
|
-
|
|
6523
|
+
fs7.rmSync(targetPath, { recursive: true, force: true });
|
|
6484
6524
|
}
|
|
6485
6525
|
copyDirRecursive(skill.bundledPath, targetPath);
|
|
6486
6526
|
return {
|
|
@@ -6495,15 +6535,15 @@ function installCodexSymlink(skill, targetDir, force) {
|
|
|
6495
6535
|
const codexPath = path4.join(targetDir, ".codex", "skills", skill.name);
|
|
6496
6536
|
const claudePath = path4.join(targetDir, ".claude", "skills", skill.name);
|
|
6497
6537
|
const linkTarget = path4.relative(path4.dirname(codexPath), claudePath);
|
|
6498
|
-
|
|
6538
|
+
fs7.mkdirSync(path4.dirname(codexPath), { recursive: true });
|
|
6499
6539
|
let stat;
|
|
6500
6540
|
try {
|
|
6501
|
-
stat =
|
|
6541
|
+
stat = fs7.lstatSync(codexPath);
|
|
6502
6542
|
} catch {
|
|
6503
6543
|
stat = void 0;
|
|
6504
6544
|
}
|
|
6505
6545
|
if (stat?.isSymbolicLink()) {
|
|
6506
|
-
const existing =
|
|
6546
|
+
const existing = fs7.readlinkSync(codexPath);
|
|
6507
6547
|
if (existing === linkTarget) {
|
|
6508
6548
|
return {
|
|
6509
6549
|
skill: skill.name,
|
|
@@ -6521,8 +6561,8 @@ function installCodexSymlink(skill, targetDir, force) {
|
|
|
6521
6561
|
exitCode: 1
|
|
6522
6562
|
});
|
|
6523
6563
|
}
|
|
6524
|
-
|
|
6525
|
-
|
|
6564
|
+
fs7.unlinkSync(codexPath);
|
|
6565
|
+
fs7.symlinkSync(linkTarget, codexPath);
|
|
6526
6566
|
return {
|
|
6527
6567
|
skill: skill.name,
|
|
6528
6568
|
client: CodingAgents.codex,
|
|
@@ -6540,9 +6580,9 @@ function installCodexSymlink(skill, targetDir, force) {
|
|
|
6540
6580
|
exitCode: 1
|
|
6541
6581
|
});
|
|
6542
6582
|
}
|
|
6543
|
-
|
|
6583
|
+
fs7.rmSync(codexPath, { recursive: true, force: true });
|
|
6544
6584
|
}
|
|
6545
|
-
|
|
6585
|
+
fs7.symlinkSync(linkTarget, codexPath);
|
|
6546
6586
|
return {
|
|
6547
6587
|
skill: skill.name,
|
|
6548
6588
|
client: CodingAgents.codex,
|
|
@@ -6574,7 +6614,7 @@ async function installSkills(opts = {}) {
|
|
|
6574
6614
|
});
|
|
6575
6615
|
}
|
|
6576
6616
|
const skillsToInstall = allSkills.filter((s) => requestedNames.includes(s.name));
|
|
6577
|
-
|
|
6617
|
+
fs7.mkdirSync(targetDir, { recursive: true });
|
|
6578
6618
|
const results = [];
|
|
6579
6619
|
for (const skill of skillsToInstall) {
|
|
6580
6620
|
results.push(installClaudeSkill(skill, targetDir, force));
|
|
@@ -6675,11 +6715,11 @@ var SKILLS_CLI_COMMANDS = [
|
|
|
6675
6715
|
];
|
|
6676
6716
|
|
|
6677
6717
|
// src/commands/snapshot.ts
|
|
6678
|
-
import
|
|
6718
|
+
import fs9 from "fs";
|
|
6679
6719
|
import path6 from "path";
|
|
6680
6720
|
|
|
6681
6721
|
// src/snapshot-pdf.ts
|
|
6682
|
-
import
|
|
6722
|
+
import fs8 from "fs";
|
|
6683
6723
|
import path5 from "path";
|
|
6684
6724
|
import { PDFDocument, StandardFonts, rgb } from "pdf-lib";
|
|
6685
6725
|
var PAGE_WIDTH = 612;
|
|
@@ -6890,8 +6930,8 @@ async function writeSnapshotPdf(report, outputPath) {
|
|
|
6890
6930
|
renderQueries(pdf, report);
|
|
6891
6931
|
const bytes = await doc.save();
|
|
6892
6932
|
const resolvedPath = path5.resolve(outputPath);
|
|
6893
|
-
|
|
6894
|
-
|
|
6933
|
+
fs8.mkdirSync(path5.dirname(resolvedPath), { recursive: true });
|
|
6934
|
+
fs8.writeFileSync(resolvedPath, bytes);
|
|
6895
6935
|
return resolvedPath;
|
|
6896
6936
|
}
|
|
6897
6937
|
function renderCover(pdf, report) {
|
|
@@ -7050,8 +7090,8 @@ PDF saved: ${savedPdfPath}`);
|
|
|
7050
7090
|
}
|
|
7051
7091
|
function writeSnapshotMarkdown(report, outputPath) {
|
|
7052
7092
|
const resolvedPath = path6.resolve(outputPath);
|
|
7053
|
-
|
|
7054
|
-
|
|
7093
|
+
fs9.mkdirSync(path6.dirname(resolvedPath), { recursive: true });
|
|
7094
|
+
fs9.writeFileSync(resolvedPath, formatSnapshotMarkdown(report), "utf-8");
|
|
7055
7095
|
return resolvedPath;
|
|
7056
7096
|
}
|
|
7057
7097
|
function formatSnapshotMarkdown(report) {
|
|
@@ -7993,7 +8033,7 @@ async function bootstrapCommand(_opts) {
|
|
|
7993
8033
|
|
|
7994
8034
|
// src/commands/daemon.ts
|
|
7995
8035
|
import { spawn } from "child_process";
|
|
7996
|
-
import
|
|
8036
|
+
import fs10 from "fs";
|
|
7997
8037
|
import path8 from "path";
|
|
7998
8038
|
function getPidPath() {
|
|
7999
8039
|
return path8.join(getConfigDir(), "canonry.pid");
|
|
@@ -8023,8 +8063,8 @@ async function waitForReady(host, port, maxMs = 1e4) {
|
|
|
8023
8063
|
async function startDaemon(opts) {
|
|
8024
8064
|
const pidPath = getPidPath();
|
|
8025
8065
|
const format = opts.format ?? "text";
|
|
8026
|
-
if (
|
|
8027
|
-
const existingPid = parseInt(
|
|
8066
|
+
if (fs10.existsSync(pidPath)) {
|
|
8067
|
+
const existingPid = parseInt(fs10.readFileSync(pidPath, "utf-8").trim(), 10);
|
|
8028
8068
|
if (!isNaN(existingPid) && isProcessAlive(existingPid)) {
|
|
8029
8069
|
throw new CliError({
|
|
8030
8070
|
code: "DAEMON_ALREADY_RUNNING",
|
|
@@ -8035,7 +8075,7 @@ async function startDaemon(opts) {
|
|
|
8035
8075
|
}
|
|
8036
8076
|
});
|
|
8037
8077
|
}
|
|
8038
|
-
|
|
8078
|
+
fs10.unlinkSync(pidPath);
|
|
8039
8079
|
}
|
|
8040
8080
|
const cliPath = path8.resolve(new URL(import.meta.url).pathname);
|
|
8041
8081
|
const inSourceMode = new URL(import.meta.url).pathname.endsWith(".ts");
|
|
@@ -8056,10 +8096,10 @@ async function startDaemon(opts) {
|
|
|
8056
8096
|
});
|
|
8057
8097
|
}
|
|
8058
8098
|
const configDir = getConfigDir();
|
|
8059
|
-
if (!
|
|
8060
|
-
|
|
8099
|
+
if (!fs10.existsSync(configDir)) {
|
|
8100
|
+
fs10.mkdirSync(configDir, { recursive: true });
|
|
8061
8101
|
}
|
|
8062
|
-
|
|
8102
|
+
fs10.writeFileSync(pidPath, String(child.pid), "utf-8");
|
|
8063
8103
|
const port = opts.port ?? "4100";
|
|
8064
8104
|
const host = opts.host ?? "127.0.0.1";
|
|
8065
8105
|
if (format !== "json") {
|
|
@@ -8068,7 +8108,7 @@ async function startDaemon(opts) {
|
|
|
8068
8108
|
const ready = await waitForReady(host, port);
|
|
8069
8109
|
if (!ready) {
|
|
8070
8110
|
try {
|
|
8071
|
-
|
|
8111
|
+
fs10.unlinkSync(pidPath);
|
|
8072
8112
|
} catch {
|
|
8073
8113
|
}
|
|
8074
8114
|
throw new CliError({
|
|
@@ -8100,7 +8140,7 @@ async function startDaemon(opts) {
|
|
|
8100
8140
|
}
|
|
8101
8141
|
function stopDaemon(format = "text") {
|
|
8102
8142
|
const pidPath = getPidPath();
|
|
8103
|
-
if (!
|
|
8143
|
+
if (!fs10.existsSync(pidPath)) {
|
|
8104
8144
|
if (format === "json") {
|
|
8105
8145
|
console.log(JSON.stringify({
|
|
8106
8146
|
stopped: false,
|
|
@@ -8111,7 +8151,7 @@ function stopDaemon(format = "text") {
|
|
|
8111
8151
|
console.log("Canonry is not running (no PID file found)");
|
|
8112
8152
|
return;
|
|
8113
8153
|
}
|
|
8114
|
-
const pid = parseInt(
|
|
8154
|
+
const pid = parseInt(fs10.readFileSync(pidPath, "utf-8").trim(), 10);
|
|
8115
8155
|
if (isNaN(pid)) {
|
|
8116
8156
|
if (format === "json") {
|
|
8117
8157
|
console.log(JSON.stringify({
|
|
@@ -8122,7 +8162,7 @@ function stopDaemon(format = "text") {
|
|
|
8122
8162
|
} else {
|
|
8123
8163
|
console.error("Invalid PID file. Removing it.");
|
|
8124
8164
|
}
|
|
8125
|
-
|
|
8165
|
+
fs10.unlinkSync(pidPath);
|
|
8126
8166
|
return;
|
|
8127
8167
|
}
|
|
8128
8168
|
if (!isProcessAlive(pid)) {
|
|
@@ -8136,12 +8176,12 @@ function stopDaemon(format = "text") {
|
|
|
8136
8176
|
} else {
|
|
8137
8177
|
console.log(`Canonry is not running (stale PID: ${pid}). Cleaning up.`);
|
|
8138
8178
|
}
|
|
8139
|
-
|
|
8179
|
+
fs10.unlinkSync(pidPath);
|
|
8140
8180
|
return;
|
|
8141
8181
|
}
|
|
8142
8182
|
try {
|
|
8143
8183
|
process.kill(pid, "SIGTERM");
|
|
8144
|
-
|
|
8184
|
+
fs10.unlinkSync(pidPath);
|
|
8145
8185
|
if (format === "json") {
|
|
8146
8186
|
console.log(JSON.stringify({
|
|
8147
8187
|
stopped: true,
|
|
@@ -8165,7 +8205,7 @@ function stopDaemon(format = "text") {
|
|
|
8165
8205
|
|
|
8166
8206
|
// src/commands/init.ts
|
|
8167
8207
|
import crypto2 from "crypto";
|
|
8168
|
-
import
|
|
8208
|
+
import fs11 from "fs";
|
|
8169
8209
|
import readline from "readline";
|
|
8170
8210
|
import path9 from "path";
|
|
8171
8211
|
function prompt(question) {
|
|
@@ -8189,7 +8229,7 @@ var PROJECT_MARKERS = [".git", "canonry.yaml", "canonry.yml", "package.json"];
|
|
|
8189
8229
|
function cwdLooksLikeProject(dir) {
|
|
8190
8230
|
const home = process.env.HOME ?? "";
|
|
8191
8231
|
if (home && path9.resolve(dir) === path9.resolve(home)) return false;
|
|
8192
|
-
return PROJECT_MARKERS.some((marker) =>
|
|
8232
|
+
return PROJECT_MARKERS.some((marker) => fs11.existsSync(path9.join(dir, marker)));
|
|
8193
8233
|
}
|
|
8194
8234
|
var DEFAULT_AGENT_MODELS = {
|
|
8195
8235
|
anthropic: "anthropic/claude-sonnet-4-6",
|
|
@@ -8219,8 +8259,8 @@ async function initCommand(opts) {
|
|
|
8219
8259
|
return void 0;
|
|
8220
8260
|
}
|
|
8221
8261
|
const configDir = getConfigDir();
|
|
8222
|
-
if (!
|
|
8223
|
-
|
|
8262
|
+
if (!fs11.existsSync(configDir)) {
|
|
8263
|
+
fs11.mkdirSync(configDir, { recursive: true });
|
|
8224
8264
|
}
|
|
8225
8265
|
const bootstrapEnv = getBootstrapEnv(process.env, {
|
|
8226
8266
|
GEMINI_API_KEY: opts?.geminiKey,
|
|
@@ -8368,6 +8408,7 @@ async function initCommand(opts) {
|
|
|
8368
8408
|
skillsTip = 'Run "canonry skills install" in a project directory to add the canonry + Aero playbook to .claude/skills/ and .codex/skills/.';
|
|
8369
8409
|
}
|
|
8370
8410
|
}
|
|
8411
|
+
const nextSteps = buildNextSteps();
|
|
8371
8412
|
if (format === "json") {
|
|
8372
8413
|
console.log(JSON.stringify({
|
|
8373
8414
|
initialized: true,
|
|
@@ -8378,7 +8419,8 @@ async function initCommand(opts) {
|
|
|
8378
8419
|
providers: providerNames,
|
|
8379
8420
|
googleConfigured: !!google,
|
|
8380
8421
|
skills: skillsSummary,
|
|
8381
|
-
skillsTip
|
|
8422
|
+
skillsTip,
|
|
8423
|
+
nextSteps
|
|
8382
8424
|
}, null, 2));
|
|
8383
8425
|
} else {
|
|
8384
8426
|
console.log(`
|
|
@@ -8419,14 +8461,44 @@ ${skillsTip}`);
|
|
|
8419
8461
|
}
|
|
8420
8462
|
if (format !== "json") {
|
|
8421
8463
|
showFirstRunNotice();
|
|
8422
|
-
console.log(
|
|
8464
|
+
console.log("\nNext steps:");
|
|
8465
|
+
for (const line of nextSteps) {
|
|
8466
|
+
console.log(` ${line}`);
|
|
8467
|
+
}
|
|
8423
8468
|
}
|
|
8424
8469
|
trackEvent("cli.init", {
|
|
8425
8470
|
providerCount: providerNames.length,
|
|
8426
|
-
providers: providerNames
|
|
8471
|
+
providers: providerNames,
|
|
8472
|
+
setupState: encodeSetupState({
|
|
8473
|
+
hasProvider: !!hasProvider,
|
|
8474
|
+
hasGoogle: !!google,
|
|
8475
|
+
hasAgent: !!agentLLM
|
|
8476
|
+
}),
|
|
8477
|
+
skillsInstalled: !!skillsSummary
|
|
8427
8478
|
});
|
|
8428
8479
|
return agentLLM;
|
|
8429
8480
|
}
|
|
8481
|
+
function buildNextSteps() {
|
|
8482
|
+
return [
|
|
8483
|
+
"1. Create a project for the domain you want to track:",
|
|
8484
|
+
" canonry project create my-site --domain example.com --country US --language en",
|
|
8485
|
+
"",
|
|
8486
|
+
"2. Add the questions your customers ask AI assistants:",
|
|
8487
|
+
' canonry query add my-site "best <category> for <use case>"',
|
|
8488
|
+
"",
|
|
8489
|
+
"3. Run your first sweep:",
|
|
8490
|
+
" canonry run my-site",
|
|
8491
|
+
"",
|
|
8492
|
+
'Tip: "canonry doctor" verifies your setup. "canonry serve" opens the dashboard.'
|
|
8493
|
+
];
|
|
8494
|
+
}
|
|
8495
|
+
function encodeSetupState(state) {
|
|
8496
|
+
const flags = [];
|
|
8497
|
+
if (state.hasProvider) flags.push("provider");
|
|
8498
|
+
if (state.hasGoogle) flags.push("google");
|
|
8499
|
+
if (state.hasAgent) flags.push("agent");
|
|
8500
|
+
return flags.length > 0 ? flags.sort().join("|") : "none";
|
|
8501
|
+
}
|
|
8430
8502
|
|
|
8431
8503
|
// src/commands/serve.ts
|
|
8432
8504
|
function resolveServePort(envPort, configPort) {
|
|
@@ -8498,6 +8570,7 @@ Received ${signal}, stopping server...`);
|
|
|
8498
8570
|
Canonry server running at ${url}`);
|
|
8499
8571
|
console.log("Press Ctrl+C to stop.\n");
|
|
8500
8572
|
}
|
|
8573
|
+
setTelemetrySource("cli-server");
|
|
8501
8574
|
const providerNames = Object.keys(config.providers ?? {}).filter(
|
|
8502
8575
|
(k) => config.providers?.[k]?.apiKey || config.providers?.[k]?.baseUrl
|
|
8503
8576
|
);
|
|
@@ -8783,7 +8856,7 @@ var SYSTEM_CLI_COMMANDS = [
|
|
|
8783
8856
|
];
|
|
8784
8857
|
|
|
8785
8858
|
// src/cli-commands/wordpress.ts
|
|
8786
|
-
import
|
|
8859
|
+
import fs12 from "fs";
|
|
8787
8860
|
|
|
8788
8861
|
// src/commands/wordpress.ts
|
|
8789
8862
|
function getClient20() {
|
|
@@ -9019,12 +9092,12 @@ async function wordpressSetMeta(project, body) {
|
|
|
9019
9092
|
printPageDetail(result);
|
|
9020
9093
|
}
|
|
9021
9094
|
async function wordpressBulkSetMeta(project, opts) {
|
|
9022
|
-
const
|
|
9095
|
+
const fs13 = await import("fs/promises");
|
|
9023
9096
|
const path10 = await import("path");
|
|
9024
9097
|
const filePath = path10.resolve(opts.from);
|
|
9025
9098
|
let raw;
|
|
9026
9099
|
try {
|
|
9027
|
-
raw = await
|
|
9100
|
+
raw = await fs13.readFile(filePath, "utf8");
|
|
9028
9101
|
} catch {
|
|
9029
9102
|
throw new CliError({
|
|
9030
9103
|
code: "FILE_READ_ERROR",
|
|
@@ -9121,13 +9194,13 @@ async function wordpressSetSchema(project, body) {
|
|
|
9121
9194
|
printManualAssist(`Schema update for "${body.slug}"`, result);
|
|
9122
9195
|
}
|
|
9123
9196
|
async function wordpressSchemaDeploy(project, opts) {
|
|
9124
|
-
const
|
|
9197
|
+
const fs13 = await import("fs/promises");
|
|
9125
9198
|
const path10 = await import("path");
|
|
9126
9199
|
const yaml = await import("yaml").catch(() => null);
|
|
9127
9200
|
const filePath = path10.resolve(opts.profile);
|
|
9128
9201
|
let raw;
|
|
9129
9202
|
try {
|
|
9130
|
-
raw = await
|
|
9203
|
+
raw = await fs13.readFile(filePath, "utf8");
|
|
9131
9204
|
} catch {
|
|
9132
9205
|
throw new CliError({
|
|
9133
9206
|
code: "FILE_READ_ERROR",
|
|
@@ -9232,13 +9305,13 @@ async function wordpressOnboard(project, opts) {
|
|
|
9232
9305
|
}
|
|
9233
9306
|
let profileData;
|
|
9234
9307
|
if (opts.profile) {
|
|
9235
|
-
const
|
|
9308
|
+
const fs13 = await import("fs/promises");
|
|
9236
9309
|
const path10 = await import("path");
|
|
9237
9310
|
const yaml = await import("yaml").catch(() => null);
|
|
9238
9311
|
const filePath = path10.resolve(opts.profile);
|
|
9239
9312
|
let raw;
|
|
9240
9313
|
try {
|
|
9241
|
-
raw = await
|
|
9314
|
+
raw = await fs13.readFile(filePath, "utf8");
|
|
9242
9315
|
} catch {
|
|
9243
9316
|
throw new CliError({
|
|
9244
9317
|
code: "FILE_READ_ERROR",
|
|
@@ -9387,7 +9460,7 @@ function resolveContent(input, command, usage, options) {
|
|
|
9387
9460
|
}
|
|
9388
9461
|
if (contentFile) {
|
|
9389
9462
|
try {
|
|
9390
|
-
return
|
|
9463
|
+
return fs12.readFileSync(contentFile, "utf-8");
|
|
9391
9464
|
} catch (error) {
|
|
9392
9465
|
const message = error instanceof Error ? error.message : String(error);
|
|
9393
9466
|
throw usageError(`Error: could not read --content-file "${contentFile}": ${message}`, {
|
|
@@ -10433,7 +10506,12 @@ async function runCli(args = process.argv.slice(2)) {
|
|
|
10433
10506
|
resolvedCommand = command;
|
|
10434
10507
|
}
|
|
10435
10508
|
if (!isHelpRequest && command !== "telemetry") {
|
|
10436
|
-
|
|
10509
|
+
detectAndTrackUpgrade();
|
|
10510
|
+
const setupState = buildSetupState();
|
|
10511
|
+
trackEvent("cli.command", {
|
|
10512
|
+
command: resolvedCommand,
|
|
10513
|
+
...setupState ? { setup_state: setupState } : {}
|
|
10514
|
+
});
|
|
10437
10515
|
}
|
|
10438
10516
|
try {
|
|
10439
10517
|
if (await dispatchRegisteredCommand(args, format, REGISTERED_CLI_COMMANDS)) {
|