@ainyc/canonry 4.142.0 → 4.144.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/agent-workspace/skills/canonry/references/canonry-cli.md +33 -0
- package/assets/assets/{AuditHistoryPanel-CfaF5B_e.js → AuditHistoryPanel-DxRP9WsD.js} +1 -1
- package/assets/assets/{BacklinksPage-BIytWBpL.js → BacklinksPage-yiEbyV67.js} +1 -1
- package/assets/assets/{ChartPrimitives-0tQT6GE7.js → ChartPrimitives-D2hRlMHn.js} +1 -1
- package/assets/assets/{HistoryPage-Bn6IH8WV.js → HistoryPage-CW6MJ-dR.js} +1 -1
- package/assets/assets/ProjectPage-Bnr7I5qu.js +9 -0
- package/assets/assets/{RunRow-RHd8Bd52.js → RunRow-Dr607W0P.js} +1 -1
- package/assets/assets/{RunsPage-BsDqqQFX.js → RunsPage-CtF3P7CA.js} +1 -1
- package/assets/assets/SettingsPage-3-uzs2lp.js +1 -0
- package/assets/assets/{TrafficPage-I19b7i9m.js → TrafficPage-Bww4KUn8.js} +1 -1
- package/assets/assets/{TrafficSourceDetailPage-DOLEAPsc.js → TrafficSourceDetailPage-DiHxUH2H.js} +1 -1
- package/assets/assets/{arrow-left-BG9o86__.js → arrow-left-D-PcVbQ4.js} +1 -1
- package/assets/assets/{extract-error-message-D0cgM2XG.js → extract-error-message-BRq0yLWg.js} +1 -1
- package/assets/assets/index-ANFzZ3nU.css +1 -0
- package/assets/assets/index-b5M4QpB0.js +213 -0
- package/assets/assets/{trash-2-C_THWxO_.js → trash-2-B6aJTnJl.js} +1 -1
- package/assets/index.html +2 -2
- package/dist/{chunk-UFPP5CSN.js → chunk-3NYTF3YC.js} +346 -97
- package/dist/{chunk-NR6OGEV3.js → chunk-7D2GZU6O.js} +8174 -1431
- package/dist/{chunk-LS6SEZVF.js → chunk-WADGZMWT.js} +5457 -3192
- package/dist/{chunk-D7NJUGNQ.js → chunk-Z672VQ7G.js} +363 -2
- package/dist/cli.js +534 -164
- package/dist/index.js +4 -4
- package/dist/{intelligence-service-EOUP37XN.js → intelligence-service-OLIGR6HE.js} +2 -2
- package/dist/mcp.js +2 -2
- package/package.json +7 -7
- package/assets/assets/ProjectPage-DsQic9wX.js +0 -8
- package/assets/assets/SettingsPage-CX2LkFDB.js +0 -1
- package/assets/assets/index-BDo9nl4O.css +0 -1
- package/assets/assets/index-CYGBt2f0.js +0 -213
package/dist/cli.js
CHANGED
|
@@ -30,7 +30,7 @@ import {
|
|
|
30
30
|
showFirstRunNotice,
|
|
31
31
|
trackCliCommandFinished,
|
|
32
32
|
trackEvent
|
|
33
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-3NYTF3YC.js";
|
|
34
34
|
import {
|
|
35
35
|
CliError,
|
|
36
36
|
EXIT_SYSTEM_ERROR,
|
|
@@ -47,7 +47,7 @@ import {
|
|
|
47
47
|
saveConfig,
|
|
48
48
|
saveConfigPatch,
|
|
49
49
|
usageError
|
|
50
|
-
} from "./chunk-
|
|
50
|
+
} from "./chunk-Z672VQ7G.js";
|
|
51
51
|
import {
|
|
52
52
|
apiKeys,
|
|
53
53
|
createClient,
|
|
@@ -55,7 +55,7 @@ import {
|
|
|
55
55
|
projects,
|
|
56
56
|
queries,
|
|
57
57
|
renderReportHtml
|
|
58
|
-
} from "./chunk-
|
|
58
|
+
} from "./chunk-7D2GZU6O.js";
|
|
59
59
|
import {
|
|
60
60
|
AdsDeliverySnapshotStatuses,
|
|
61
61
|
AdsHistoricalCampaignRollupStatuses,
|
|
@@ -74,6 +74,8 @@ import {
|
|
|
74
74
|
RunStatuses,
|
|
75
75
|
TrafficEventKinds,
|
|
76
76
|
TrafficSeriesGranularities,
|
|
77
|
+
USER_PASSWORD_MIN_LENGTH,
|
|
78
|
+
UserRoles,
|
|
77
79
|
adsActivateTreeRequestSchema,
|
|
78
80
|
adsActivationGrantCreateRequestSchema,
|
|
79
81
|
adsAdCreateRequestSchema,
|
|
@@ -96,12 +98,15 @@ import {
|
|
|
96
98
|
formatMicros,
|
|
97
99
|
formatRatio,
|
|
98
100
|
formatRunErrorOneLine,
|
|
101
|
+
measurementDiscoveryRequestSchema,
|
|
102
|
+
measurementDiscoveryRuleSchema,
|
|
103
|
+
measurementPlanInputSchema,
|
|
99
104
|
normalizeProjectAliases,
|
|
100
105
|
notificationEventSchema,
|
|
101
106
|
providerQuotaPolicySchema,
|
|
102
107
|
resolveProviderInput,
|
|
103
108
|
winnabilityClassSchema
|
|
104
|
-
} from "./chunk-
|
|
109
|
+
} from "./chunk-WADGZMWT.js";
|
|
105
110
|
|
|
106
111
|
// src/cli.ts
|
|
107
112
|
import { pathToFileURL } from "url";
|
|
@@ -3847,9 +3852,9 @@ async function gaConnect(project, opts) {
|
|
|
3847
3852
|
propertyId: opts.propertyId
|
|
3848
3853
|
};
|
|
3849
3854
|
if (opts.keyFile) {
|
|
3850
|
-
const
|
|
3855
|
+
const fs17 = await import("fs");
|
|
3851
3856
|
try {
|
|
3852
|
-
const content =
|
|
3857
|
+
const content = fs17.readFileSync(opts.keyFile, "utf-8");
|
|
3853
3858
|
JSON.parse(content);
|
|
3854
3859
|
body.keyJson = content;
|
|
3855
3860
|
} catch (e) {
|
|
@@ -5298,9 +5303,9 @@ async function trafficConnectWordpress(project, opts) {
|
|
|
5298
5303
|
}
|
|
5299
5304
|
let applicationPassword = opts.appPassword?.trim() ?? "";
|
|
5300
5305
|
if (!applicationPassword && opts.appPasswordFile) {
|
|
5301
|
-
const
|
|
5306
|
+
const fs17 = await import("fs");
|
|
5302
5307
|
try {
|
|
5303
|
-
applicationPassword =
|
|
5308
|
+
applicationPassword = fs17.readFileSync(opts.appPasswordFile, "utf-8").trim();
|
|
5304
5309
|
} catch (e) {
|
|
5305
5310
|
const msg = e instanceof Error ? e.message : String(e);
|
|
5306
5311
|
throw new CliError({
|
|
@@ -5356,10 +5361,10 @@ async function trafficConnectCloudRun(project, opts) {
|
|
|
5356
5361
|
details: { project }
|
|
5357
5362
|
});
|
|
5358
5363
|
}
|
|
5359
|
-
const
|
|
5364
|
+
const fs17 = await import("fs");
|
|
5360
5365
|
let keyJson;
|
|
5361
5366
|
try {
|
|
5362
|
-
keyJson =
|
|
5367
|
+
keyJson = fs17.readFileSync(opts.serviceAccountKey, "utf-8");
|
|
5363
5368
|
JSON.parse(keyJson);
|
|
5364
5369
|
} catch (e) {
|
|
5365
5370
|
const msg = e instanceof Error ? e.message : String(e);
|
|
@@ -5419,9 +5424,9 @@ async function trafficConnectVercel(project, opts) {
|
|
|
5419
5424
|
}
|
|
5420
5425
|
let token = opts.token?.trim() ?? "";
|
|
5421
5426
|
if (!token && opts.tokenFile) {
|
|
5422
|
-
const
|
|
5427
|
+
const fs17 = await import("fs");
|
|
5423
5428
|
try {
|
|
5424
|
-
token =
|
|
5429
|
+
token = fs17.readFileSync(opts.tokenFile, "utf-8").trim();
|
|
5425
5430
|
} catch (e) {
|
|
5426
5431
|
const msg = e instanceof Error ? e.message : String(e);
|
|
5427
5432
|
throw new CliError({
|
|
@@ -7546,13 +7551,224 @@ var KEYS_CLI_COMMANDS = [
|
|
|
7546
7551
|
}
|
|
7547
7552
|
];
|
|
7548
7553
|
|
|
7554
|
+
// src/cli-prompt.ts
|
|
7555
|
+
import readline from "readline";
|
|
7556
|
+
async function promptHiddenInput(question) {
|
|
7557
|
+
const input = process.stdin;
|
|
7558
|
+
const output = process.stdout;
|
|
7559
|
+
if (!input.isTTY) {
|
|
7560
|
+
const rl2 = readline.createInterface({ input, output });
|
|
7561
|
+
try {
|
|
7562
|
+
return await new Promise((resolve) => {
|
|
7563
|
+
rl2.question(question, resolve);
|
|
7564
|
+
});
|
|
7565
|
+
} finally {
|
|
7566
|
+
rl2.close();
|
|
7567
|
+
}
|
|
7568
|
+
}
|
|
7569
|
+
const rl = readline.createInterface({ input, output, terminal: true });
|
|
7570
|
+
const mutable = rl;
|
|
7571
|
+
const originalWrite = mutable._writeToOutput?.bind(rl);
|
|
7572
|
+
let muted = false;
|
|
7573
|
+
mutable._writeToOutput = (chunk) => {
|
|
7574
|
+
if (muted) {
|
|
7575
|
+
output.write("");
|
|
7576
|
+
return;
|
|
7577
|
+
}
|
|
7578
|
+
originalWrite?.(chunk);
|
|
7579
|
+
};
|
|
7580
|
+
try {
|
|
7581
|
+
return await new Promise((resolve) => {
|
|
7582
|
+
rl.question(question, (answer) => {
|
|
7583
|
+
output.write("\n");
|
|
7584
|
+
resolve(answer);
|
|
7585
|
+
});
|
|
7586
|
+
muted = true;
|
|
7587
|
+
});
|
|
7588
|
+
} finally {
|
|
7589
|
+
muted = false;
|
|
7590
|
+
if (originalWrite) mutable._writeToOutput = originalWrite;
|
|
7591
|
+
rl.close();
|
|
7592
|
+
}
|
|
7593
|
+
}
|
|
7594
|
+
async function readAllStdin() {
|
|
7595
|
+
const chunks = [];
|
|
7596
|
+
for await (const chunk of process.stdin) {
|
|
7597
|
+
chunks.push(Buffer.from(chunk));
|
|
7598
|
+
}
|
|
7599
|
+
return Buffer.concat(chunks).toString("utf8");
|
|
7600
|
+
}
|
|
7601
|
+
|
|
7602
|
+
// src/commands/users.ts
|
|
7603
|
+
function getClient13() {
|
|
7604
|
+
return createApiClient();
|
|
7605
|
+
}
|
|
7606
|
+
var ROLE_NAMES = Object.values(UserRoles);
|
|
7607
|
+
function parseRole(role) {
|
|
7608
|
+
const normalized = role.trim().toLowerCase();
|
|
7609
|
+
if (ROLE_NAMES.includes(normalized)) return normalized;
|
|
7610
|
+
throw new CliError({
|
|
7611
|
+
code: "CLI_USAGE_ERROR",
|
|
7612
|
+
message: `Unknown role "${role}" \u2014 choose ${ROLE_NAMES.join(" or ")}`,
|
|
7613
|
+
displayMessage: `Error: unknown role "${role}". Choose ${ROLE_NAMES.join(" or ")}.`
|
|
7614
|
+
});
|
|
7615
|
+
}
|
|
7616
|
+
async function listUsers(format) {
|
|
7617
|
+
const client = getClient13();
|
|
7618
|
+
const { users } = await client.listUsers();
|
|
7619
|
+
if (format === "json") {
|
|
7620
|
+
console.log(JSON.stringify({ users }, null, 2));
|
|
7621
|
+
return;
|
|
7622
|
+
} else if (format === "jsonl") {
|
|
7623
|
+
emitJsonl(users);
|
|
7624
|
+
return;
|
|
7625
|
+
}
|
|
7626
|
+
if (users.length === 0) {
|
|
7627
|
+
console.log("No accounts yet \u2014 the dashboard opens without a sign-in.");
|
|
7628
|
+
console.log("Create the first one with: canonry user create --name <name> --role admin");
|
|
7629
|
+
return;
|
|
7630
|
+
}
|
|
7631
|
+
console.log(`${"NAME".padEnd(24)} ${"ROLE".padEnd(8)} ${"CREATED".padEnd(12)} LAST SIGN-IN`);
|
|
7632
|
+
for (const user of users) {
|
|
7633
|
+
const lastLogin = user.lastLoginAt ? formatIsoDate(user.lastLoginAt) : "never";
|
|
7634
|
+
console.log(
|
|
7635
|
+
`${user.name.padEnd(24)} ${user.role.padEnd(8)} ${formatIsoDate(user.createdAt).padEnd(12)} ${lastLogin}`
|
|
7636
|
+
);
|
|
7637
|
+
}
|
|
7638
|
+
}
|
|
7639
|
+
async function createUser(opts) {
|
|
7640
|
+
const role = parseRole(opts.role);
|
|
7641
|
+
const password = opts.passwordStdin ? (await (opts.readStdin ?? readAllStdin)()).replace(/\r?\n$/, "") : await askForPassword();
|
|
7642
|
+
if (password.length < USER_PASSWORD_MIN_LENGTH) {
|
|
7643
|
+
throw new CliError({
|
|
7644
|
+
code: "CLI_USAGE_ERROR",
|
|
7645
|
+
message: "Password too short",
|
|
7646
|
+
displayMessage: `Error: the password must be at least ${USER_PASSWORD_MIN_LENGTH} characters.`
|
|
7647
|
+
});
|
|
7648
|
+
}
|
|
7649
|
+
const client = getClient13();
|
|
7650
|
+
const wasFirst = await isFirstAccount(client);
|
|
7651
|
+
const created = await client.createUser({ name: opts.name, role, password });
|
|
7652
|
+
if (isMachineFormat(opts.format)) {
|
|
7653
|
+
console.log(JSON.stringify(created, null, 2));
|
|
7654
|
+
return;
|
|
7655
|
+
}
|
|
7656
|
+
printCreated(created, wasFirst);
|
|
7657
|
+
}
|
|
7658
|
+
async function askForPassword() {
|
|
7659
|
+
const first = await promptHiddenInput("Password: ");
|
|
7660
|
+
const second = await promptHiddenInput("Confirm password: ");
|
|
7661
|
+
if (first !== second) {
|
|
7662
|
+
throw new CliError({
|
|
7663
|
+
code: "CLI_USAGE_ERROR",
|
|
7664
|
+
message: "Passwords do not match",
|
|
7665
|
+
displayMessage: "Error: the two passwords do not match. Nothing was created."
|
|
7666
|
+
});
|
|
7667
|
+
}
|
|
7668
|
+
return first;
|
|
7669
|
+
}
|
|
7670
|
+
async function isFirstAccount(client) {
|
|
7671
|
+
try {
|
|
7672
|
+
const { users } = await client.listUsers();
|
|
7673
|
+
return users.length === 0;
|
|
7674
|
+
} catch {
|
|
7675
|
+
return false;
|
|
7676
|
+
}
|
|
7677
|
+
}
|
|
7678
|
+
function printCreated(created, wasFirst) {
|
|
7679
|
+
console.log(`Account "${created.name}" created with ${created.role} access.
|
|
7680
|
+
`);
|
|
7681
|
+
if (wasFirst) {
|
|
7682
|
+
console.log("This is the first account on this install, so the dashboard now asks");
|
|
7683
|
+
console.log("everyone to sign in. API keys are unaffected and keep working as before.\n");
|
|
7684
|
+
}
|
|
7685
|
+
if (created.role === UserRoles.viewer) {
|
|
7686
|
+
console.log("A viewer can read everything and change nothing.");
|
|
7687
|
+
} else {
|
|
7688
|
+
console.log("An administrator can do everything the install could already do.");
|
|
7689
|
+
}
|
|
7690
|
+
}
|
|
7691
|
+
async function deleteUser(name, format) {
|
|
7692
|
+
const client = getClient13();
|
|
7693
|
+
const result = await client.deleteUser(name);
|
|
7694
|
+
if (isMachineFormat(format)) {
|
|
7695
|
+
console.log(JSON.stringify(result, null, 2));
|
|
7696
|
+
return;
|
|
7697
|
+
}
|
|
7698
|
+
console.log(`Account "${result.name}" deleted. Any browser signed in as them is signed out now.`);
|
|
7699
|
+
}
|
|
7700
|
+
|
|
7701
|
+
// src/cli-commands/users.ts
|
|
7702
|
+
var CREATE_USAGE = "canonry user create --name <name> --role <admin|viewer> [--password-stdin] [--format json]";
|
|
7703
|
+
var USERS_CLI_COMMANDS = [
|
|
7704
|
+
{
|
|
7705
|
+
path: ["user", "list"],
|
|
7706
|
+
usage: "canonry user list [--format json|jsonl]",
|
|
7707
|
+
run: async (input) => {
|
|
7708
|
+
await listUsers(input.format);
|
|
7709
|
+
}
|
|
7710
|
+
},
|
|
7711
|
+
{
|
|
7712
|
+
path: ["user", "create"],
|
|
7713
|
+
usage: CREATE_USAGE,
|
|
7714
|
+
options: {
|
|
7715
|
+
name: stringOption(),
|
|
7716
|
+
role: stringOption(),
|
|
7717
|
+
// There is deliberately no `--password` flag: a password given on the
|
|
7718
|
+
// command line lands in the shell history and the process list.
|
|
7719
|
+
"password-stdin": { type: "boolean" }
|
|
7720
|
+
},
|
|
7721
|
+
run: async (input) => {
|
|
7722
|
+
const name = requireStringOption(input, "name", {
|
|
7723
|
+
command: "user.create",
|
|
7724
|
+
usage: CREATE_USAGE,
|
|
7725
|
+
message: "--name is required"
|
|
7726
|
+
});
|
|
7727
|
+
const role = requireStringOption(input, "role", {
|
|
7728
|
+
command: "user.create",
|
|
7729
|
+
usage: CREATE_USAGE,
|
|
7730
|
+
message: "--role is required (admin or viewer)"
|
|
7731
|
+
});
|
|
7732
|
+
await createUser({
|
|
7733
|
+
name,
|
|
7734
|
+
role,
|
|
7735
|
+
passwordStdin: getBoolean(input.values, "password-stdin"),
|
|
7736
|
+
format: input.format
|
|
7737
|
+
});
|
|
7738
|
+
}
|
|
7739
|
+
},
|
|
7740
|
+
{
|
|
7741
|
+
path: ["user", "delete"],
|
|
7742
|
+
usage: "canonry user delete <name> [--format json]",
|
|
7743
|
+
run: async (input) => {
|
|
7744
|
+
const name = requirePositional(input, 0, {
|
|
7745
|
+
command: "user.delete",
|
|
7746
|
+
usage: "canonry user delete <name> [--format json]",
|
|
7747
|
+
message: "Account name is required"
|
|
7748
|
+
});
|
|
7749
|
+
await deleteUser(name, input.format);
|
|
7750
|
+
}
|
|
7751
|
+
},
|
|
7752
|
+
{
|
|
7753
|
+
path: ["user"],
|
|
7754
|
+
usage: "canonry user <list|create|delete>",
|
|
7755
|
+
run: async (input) => {
|
|
7756
|
+
unknownSubcommand(input.positionals[0], {
|
|
7757
|
+
command: "user",
|
|
7758
|
+
usage: "canonry user <list|create|delete>",
|
|
7759
|
+
available: ["list", "create", "delete"]
|
|
7760
|
+
});
|
|
7761
|
+
}
|
|
7762
|
+
}
|
|
7763
|
+
];
|
|
7764
|
+
|
|
7549
7765
|
// src/commands/keyword.ts
|
|
7550
7766
|
import fs4 from "fs";
|
|
7551
|
-
function
|
|
7767
|
+
function getClient14() {
|
|
7552
7768
|
return createApiClient();
|
|
7553
7769
|
}
|
|
7554
7770
|
async function addKeywords(project, keywords, format) {
|
|
7555
|
-
const client =
|
|
7771
|
+
const client = getClient14();
|
|
7556
7772
|
await client.appendKeywords(project, keywords);
|
|
7557
7773
|
if (isMachineFormat(format)) {
|
|
7558
7774
|
console.log(JSON.stringify({
|
|
@@ -7565,7 +7781,7 @@ async function addKeywords(project, keywords, format) {
|
|
|
7565
7781
|
console.log(`Added ${keywords.length} key phrase(s) to "${project}".`);
|
|
7566
7782
|
}
|
|
7567
7783
|
async function replaceKeywords(project, keywords, format) {
|
|
7568
|
-
const client =
|
|
7784
|
+
const client = getClient14();
|
|
7569
7785
|
await client.putKeywords(project, keywords);
|
|
7570
7786
|
if (isMachineFormat(format)) {
|
|
7571
7787
|
console.log(JSON.stringify({
|
|
@@ -7578,7 +7794,7 @@ async function replaceKeywords(project, keywords, format) {
|
|
|
7578
7794
|
console.log(`Set ${keywords.length} key phrase(s) for "${project}".`);
|
|
7579
7795
|
}
|
|
7580
7796
|
async function removeKeywords(project, keywords, format) {
|
|
7581
|
-
const client =
|
|
7797
|
+
const client = getClient14();
|
|
7582
7798
|
const existing = await client.listKeywords(project);
|
|
7583
7799
|
const existingSet = new Set(existing.map((k) => k.keyword));
|
|
7584
7800
|
const removedKeywords = keywords.filter((k) => existingSet.has(k));
|
|
@@ -7595,7 +7811,7 @@ async function removeKeywords(project, keywords, format) {
|
|
|
7595
7811
|
console.log(`Removed ${removedKeywords.length} key phrase(s) from "${project}".`);
|
|
7596
7812
|
}
|
|
7597
7813
|
async function listKeywords(project, format) {
|
|
7598
|
-
const client =
|
|
7814
|
+
const client = getClient14();
|
|
7599
7815
|
const kws = await client.listKeywords(project);
|
|
7600
7816
|
if (format === "json") {
|
|
7601
7817
|
console.log(JSON.stringify(kws, null, 2));
|
|
@@ -7641,7 +7857,7 @@ async function importKeywords(project, filePath, format) {
|
|
|
7641
7857
|
console.log("No key phrases found in file.");
|
|
7642
7858
|
return;
|
|
7643
7859
|
}
|
|
7644
|
-
const client =
|
|
7860
|
+
const client = getClient14();
|
|
7645
7861
|
await client.appendKeywords(project, keywords);
|
|
7646
7862
|
if (isMachineFormat(format)) {
|
|
7647
7863
|
console.log(JSON.stringify({
|
|
@@ -7655,7 +7871,7 @@ async function importKeywords(project, filePath, format) {
|
|
|
7655
7871
|
console.log(`Imported ${keywords.length} key phrase(s) to "${project}".`);
|
|
7656
7872
|
}
|
|
7657
7873
|
async function generateKeywords(project, provider, opts) {
|
|
7658
|
-
const client =
|
|
7874
|
+
const client = getClient14();
|
|
7659
7875
|
const result = await client.generateKeywords(project, provider, opts.count);
|
|
7660
7876
|
const saved = Boolean(opts.save && result.keywords.length > 0);
|
|
7661
7877
|
if (!isMachineFormat(opts.format)) {
|
|
@@ -7828,11 +8044,11 @@ var KEYWORD_CLI_COMMANDS = [
|
|
|
7828
8044
|
|
|
7829
8045
|
// src/commands/query.ts
|
|
7830
8046
|
import fs5 from "fs";
|
|
7831
|
-
function
|
|
8047
|
+
function getClient15() {
|
|
7832
8048
|
return createApiClient();
|
|
7833
8049
|
}
|
|
7834
8050
|
async function addQueries(project, queries2, format) {
|
|
7835
|
-
const client =
|
|
8051
|
+
const client = getClient15();
|
|
7836
8052
|
await client.appendQueries(project, queries2);
|
|
7837
8053
|
if (isMachineFormat(format)) {
|
|
7838
8054
|
console.log(JSON.stringify({
|
|
@@ -7845,7 +8061,7 @@ async function addQueries(project, queries2, format) {
|
|
|
7845
8061
|
console.log(`Added ${queries2.length} ${queries2.length === 1 ? "query" : "queries"} to "${project}".`);
|
|
7846
8062
|
}
|
|
7847
8063
|
async function replaceQueries(project, queries2, opts) {
|
|
7848
|
-
const client =
|
|
8064
|
+
const client = getClient15();
|
|
7849
8065
|
const isJson = isMachineFormat(opts?.format);
|
|
7850
8066
|
if (opts?.dryRun) {
|
|
7851
8067
|
const preview = await client.previewReplaceQueries(project, queries2);
|
|
@@ -7881,7 +8097,7 @@ async function replaceQueries(project, queries2, opts) {
|
|
|
7881
8097
|
console.log(`Set ${queries2.length} ${queries2.length === 1 ? "query" : "queries"} for "${project}".`);
|
|
7882
8098
|
}
|
|
7883
8099
|
async function removeQueries(project, queries2, format) {
|
|
7884
|
-
const client =
|
|
8100
|
+
const client = getClient15();
|
|
7885
8101
|
const existing = await client.listQueries(project);
|
|
7886
8102
|
const existingSet = new Set(existing.map((q) => q.query));
|
|
7887
8103
|
const removedQueries = queries2.filter((q) => existingSet.has(q));
|
|
@@ -7898,7 +8114,7 @@ async function removeQueries(project, queries2, format) {
|
|
|
7898
8114
|
console.log(`Removed ${removedQueries.length} ${removedQueries.length === 1 ? "query" : "queries"} from "${project}".`);
|
|
7899
8115
|
}
|
|
7900
8116
|
async function listQueries(project, format) {
|
|
7901
|
-
const client =
|
|
8117
|
+
const client = getClient15();
|
|
7902
8118
|
const qs = await client.listQueries(project);
|
|
7903
8119
|
if (format === "json") {
|
|
7904
8120
|
console.log(JSON.stringify(qs, null, 2));
|
|
@@ -7944,7 +8160,7 @@ async function importQueries(project, filePath, format) {
|
|
|
7944
8160
|
console.log("No queries found in file.");
|
|
7945
8161
|
return;
|
|
7946
8162
|
}
|
|
7947
|
-
const client =
|
|
8163
|
+
const client = getClient15();
|
|
7948
8164
|
await client.appendQueries(project, queries2);
|
|
7949
8165
|
if (isMachineFormat(format)) {
|
|
7950
8166
|
console.log(JSON.stringify({
|
|
@@ -7958,7 +8174,7 @@ async function importQueries(project, filePath, format) {
|
|
|
7958
8174
|
console.log(`Imported ${queries2.length} ${queries2.length === 1 ? "query" : "queries"} to "${project}".`);
|
|
7959
8175
|
}
|
|
7960
8176
|
async function generateQueries(project, provider, opts) {
|
|
7961
|
-
const client =
|
|
8177
|
+
const client = getClient15();
|
|
7962
8178
|
const result = await client.generateQueries(project, provider, opts.count);
|
|
7963
8179
|
const saved = Boolean(opts.save && result.queries.length > 0);
|
|
7964
8180
|
if (!isMachineFormat(opts.format)) {
|
|
@@ -8453,11 +8669,11 @@ var MCP_CLI_COMMANDS = [
|
|
|
8453
8669
|
];
|
|
8454
8670
|
|
|
8455
8671
|
// src/commands/notify.ts
|
|
8456
|
-
function
|
|
8672
|
+
function getClient16() {
|
|
8457
8673
|
return createApiClient();
|
|
8458
8674
|
}
|
|
8459
8675
|
async function addNotification(project, opts) {
|
|
8460
|
-
const client =
|
|
8676
|
+
const client = getClient16();
|
|
8461
8677
|
const result = await client.createNotification(project, {
|
|
8462
8678
|
channel: "webhook",
|
|
8463
8679
|
url: opts.webhook,
|
|
@@ -8471,7 +8687,7 @@ async function addNotification(project, opts) {
|
|
|
8471
8687
|
printNotification(result);
|
|
8472
8688
|
}
|
|
8473
8689
|
async function listNotifications(project, format) {
|
|
8474
|
-
const client =
|
|
8690
|
+
const client = getClient16();
|
|
8475
8691
|
const results = await client.listNotifications(project);
|
|
8476
8692
|
if (format === "json") {
|
|
8477
8693
|
console.log(JSON.stringify(results, null, 2));
|
|
@@ -8492,7 +8708,7 @@ async function listNotifications(project, format) {
|
|
|
8492
8708
|
}
|
|
8493
8709
|
}
|
|
8494
8710
|
async function removeNotification(project, id, format) {
|
|
8495
|
-
const client =
|
|
8711
|
+
const client = getClient16();
|
|
8496
8712
|
await client.deleteNotification(project, id);
|
|
8497
8713
|
if (isMachineFormat(format)) {
|
|
8498
8714
|
console.log(JSON.stringify({ project, id, removed: true }, null, 2));
|
|
@@ -8501,7 +8717,7 @@ async function removeNotification(project, id, format) {
|
|
|
8501
8717
|
console.log(`Notification ${id} removed from "${project}"`);
|
|
8502
8718
|
}
|
|
8503
8719
|
async function testNotification(project, id, format) {
|
|
8504
|
-
const client =
|
|
8720
|
+
const client = getClient16();
|
|
8505
8721
|
const result = await client.testNotification(project, id);
|
|
8506
8722
|
if (isMachineFormat(format)) {
|
|
8507
8723
|
console.log(JSON.stringify({ project, id, ...result }, null, 2));
|
|
@@ -8698,11 +8914,11 @@ async function applyConfigs(filePaths, format) {
|
|
|
8698
8914
|
}
|
|
8699
8915
|
|
|
8700
8916
|
// src/commands/analytics.ts
|
|
8701
|
-
function
|
|
8917
|
+
function getClient17() {
|
|
8702
8918
|
return createApiClient();
|
|
8703
8919
|
}
|
|
8704
8920
|
async function showAnalytics(project, options) {
|
|
8705
|
-
const client =
|
|
8921
|
+
const client = getClient17();
|
|
8706
8922
|
const features = options.feature ? [options.feature] : ["metrics", "gaps", "sources"];
|
|
8707
8923
|
const results = {};
|
|
8708
8924
|
for (const feature of features) {
|
|
@@ -8905,7 +9121,7 @@ Source Origin Breakdown`);
|
|
|
8905
9121
|
}
|
|
8906
9122
|
|
|
8907
9123
|
// src/commands/sources.ts
|
|
8908
|
-
function
|
|
9124
|
+
function getClient18() {
|
|
8909
9125
|
return createApiClient();
|
|
8910
9126
|
}
|
|
8911
9127
|
var pct = (n) => `${(n * 100).toFixed(1)}%`;
|
|
@@ -8916,7 +9132,7 @@ async function showSources(project, options) {
|
|
|
8916
9132
|
details: { command: "sources", option: "limit", value: options.limit }
|
|
8917
9133
|
});
|
|
8918
9134
|
}
|
|
8919
|
-
const client =
|
|
9135
|
+
const client = getClient18();
|
|
8920
9136
|
const data = await client.getAnalyticsSources(project, { window: options.window, limit: options.limit });
|
|
8921
9137
|
if (options.format === "jsonl") {
|
|
8922
9138
|
emitJsonl(data.ranked.entries.map((e) => ({ project, ...e })));
|
|
@@ -8967,11 +9183,11 @@ function printRankedEntries(list, indent = "") {
|
|
|
8967
9183
|
}
|
|
8968
9184
|
|
|
8969
9185
|
// src/commands/evidence.ts
|
|
8970
|
-
function
|
|
9186
|
+
function getClient19() {
|
|
8971
9187
|
return createApiClient();
|
|
8972
9188
|
}
|
|
8973
9189
|
async function showEvidence(project, format) {
|
|
8974
|
-
const client =
|
|
9190
|
+
const client = getClient19();
|
|
8975
9191
|
const timeline = await client.getTimeline(project);
|
|
8976
9192
|
if (format === "json") {
|
|
8977
9193
|
const enriched = timeline.map((entry) => ({
|
|
@@ -9054,7 +9270,7 @@ async function exportResults(project, opts) {
|
|
|
9054
9270
|
}
|
|
9055
9271
|
|
|
9056
9272
|
// src/commands/history.ts
|
|
9057
|
-
function
|
|
9273
|
+
function getClient20() {
|
|
9058
9274
|
return createApiClient();
|
|
9059
9275
|
}
|
|
9060
9276
|
function originLabel(entry) {
|
|
@@ -9065,7 +9281,7 @@ function originLabel(entry) {
|
|
|
9065
9281
|
return entry.actor;
|
|
9066
9282
|
}
|
|
9067
9283
|
async function showHistory(project, format, opts = {}) {
|
|
9068
|
-
const client =
|
|
9284
|
+
const client = getClient20();
|
|
9069
9285
|
try {
|
|
9070
9286
|
const entries = project ? await client.getHistory(project, opts) : await client.getGlobalHistory(opts);
|
|
9071
9287
|
if (format === "json") {
|
|
@@ -9106,11 +9322,11 @@ async function showHistory(project, format, opts = {}) {
|
|
|
9106
9322
|
}
|
|
9107
9323
|
|
|
9108
9324
|
// src/commands/status.ts
|
|
9109
|
-
function
|
|
9325
|
+
function getClient21() {
|
|
9110
9326
|
return createApiClient();
|
|
9111
9327
|
}
|
|
9112
9328
|
async function showStatus(project, format) {
|
|
9113
|
-
const client =
|
|
9329
|
+
const client = getClient21();
|
|
9114
9330
|
const projectData = await client.getProject(project);
|
|
9115
9331
|
const latest = await getLatestRunSummary(client, project);
|
|
9116
9332
|
if (isMachineFormat(format)) {
|
|
@@ -9309,11 +9525,11 @@ var OPERATOR_CLI_COMMANDS = [
|
|
|
9309
9525
|
];
|
|
9310
9526
|
|
|
9311
9527
|
// src/commands/project.ts
|
|
9312
|
-
function
|
|
9528
|
+
function getClient22() {
|
|
9313
9529
|
return createApiClient();
|
|
9314
9530
|
}
|
|
9315
9531
|
async function createProject(name, opts) {
|
|
9316
|
-
const client =
|
|
9532
|
+
const client = getClient22();
|
|
9317
9533
|
const result = await client.putProject(name, {
|
|
9318
9534
|
displayName: opts.displayName,
|
|
9319
9535
|
canonicalDomain: opts.domain,
|
|
@@ -9331,7 +9547,7 @@ async function createProject(name, opts) {
|
|
|
9331
9547
|
console.log(`Project created: ${result.name} (${result.id})`);
|
|
9332
9548
|
}
|
|
9333
9549
|
async function listProjects(format) {
|
|
9334
|
-
const client =
|
|
9550
|
+
const client = getClient22();
|
|
9335
9551
|
const projects2 = await client.listProjects();
|
|
9336
9552
|
if (format === "json") {
|
|
9337
9553
|
console.log(JSON.stringify(projects2, null, 2));
|
|
@@ -9363,7 +9579,7 @@ async function listProjects(format) {
|
|
|
9363
9579
|
}
|
|
9364
9580
|
}
|
|
9365
9581
|
async function showProject(name, format) {
|
|
9366
|
-
const client =
|
|
9582
|
+
const client = getClient22();
|
|
9367
9583
|
const project = await client.getProject(name);
|
|
9368
9584
|
if (isMachineFormat(format)) {
|
|
9369
9585
|
console.log(JSON.stringify(project, null, 2));
|
|
@@ -9395,7 +9611,7 @@ async function showProject(name, format) {
|
|
|
9395
9611
|
if (project.updatedAt) console.log(` Updated: ${project.updatedAt}`);
|
|
9396
9612
|
}
|
|
9397
9613
|
async function updateProjectSettings(name, opts) {
|
|
9398
|
-
const client =
|
|
9614
|
+
const client = getClient22();
|
|
9399
9615
|
const project = await client.getProject(name);
|
|
9400
9616
|
let ownedDomains = opts.ownedDomains ?? project.ownedDomains ?? [];
|
|
9401
9617
|
if (opts.addOwnedDomain) {
|
|
@@ -9458,7 +9674,7 @@ async function updateProjectSettings(name, opts) {
|
|
|
9458
9674
|
}
|
|
9459
9675
|
}
|
|
9460
9676
|
async function deleteProject(name, opts) {
|
|
9461
|
-
const client =
|
|
9677
|
+
const client = getClient22();
|
|
9462
9678
|
const isJson = isMachineFormat(opts?.format);
|
|
9463
9679
|
if (opts?.dryRun) {
|
|
9464
9680
|
const preview = await client.previewProjectDelete(name);
|
|
@@ -9488,7 +9704,7 @@ async function deleteProject(name, opts) {
|
|
|
9488
9704
|
console.log(`Project deleted: ${name}`);
|
|
9489
9705
|
}
|
|
9490
9706
|
async function addLocation(project, opts) {
|
|
9491
|
-
const client =
|
|
9707
|
+
const client = getClient22();
|
|
9492
9708
|
const location = await client.addLocation(project, {
|
|
9493
9709
|
label: opts.label,
|
|
9494
9710
|
city: opts.city,
|
|
@@ -9503,7 +9719,7 @@ async function addLocation(project, opts) {
|
|
|
9503
9719
|
console.log(`Location added: ${opts.label} (${opts.city}, ${opts.region}, ${opts.country})`);
|
|
9504
9720
|
}
|
|
9505
9721
|
async function listLocations(project, format) {
|
|
9506
|
-
const client =
|
|
9722
|
+
const client = getClient22();
|
|
9507
9723
|
const result = await client.listLocations(project);
|
|
9508
9724
|
if (format === "json") {
|
|
9509
9725
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -9537,7 +9753,7 @@ async function listLocations(project, format) {
|
|
|
9537
9753
|
}
|
|
9538
9754
|
}
|
|
9539
9755
|
async function removeLocation(project, label, format) {
|
|
9540
|
-
const client =
|
|
9756
|
+
const client = getClient22();
|
|
9541
9757
|
await client.removeLocation(project, label);
|
|
9542
9758
|
if (isMachineFormat(format)) {
|
|
9543
9759
|
console.log(JSON.stringify({ project, label, removed: true }, null, 2));
|
|
@@ -9546,7 +9762,7 @@ async function removeLocation(project, label, format) {
|
|
|
9546
9762
|
console.log(`Location removed: ${label}`);
|
|
9547
9763
|
}
|
|
9548
9764
|
async function setDefaultLocation(project, label, format) {
|
|
9549
|
-
const client =
|
|
9765
|
+
const client = getClient22();
|
|
9550
9766
|
const result = await client.setDefaultLocation(project, label);
|
|
9551
9767
|
if (isMachineFormat(format)) {
|
|
9552
9768
|
console.log(JSON.stringify({ project, ...result }, null, 2));
|
|
@@ -9894,12 +10110,12 @@ var ORGANIC_EVIDENCE_CLI_COMMANDS = [
|
|
|
9894
10110
|
];
|
|
9895
10111
|
|
|
9896
10112
|
// src/commands/run.ts
|
|
9897
|
-
function
|
|
10113
|
+
function getClient23() {
|
|
9898
10114
|
return createApiClient();
|
|
9899
10115
|
}
|
|
9900
10116
|
var TERMINAL_STATUSES = /* @__PURE__ */ new Set(["completed", "partial", "failed", "cancelled"]);
|
|
9901
10117
|
async function triggerRun(project, opts) {
|
|
9902
|
-
const client =
|
|
10118
|
+
const client = getClient23();
|
|
9903
10119
|
const body = {};
|
|
9904
10120
|
if (opts?.provider) {
|
|
9905
10121
|
const providerInputs = opts.provider.split(",").map((s) => s.trim()).filter(Boolean);
|
|
@@ -9909,6 +10125,12 @@ async function triggerRun(project, opts) {
|
|
|
9909
10125
|
if (opts?.queries?.length) {
|
|
9910
10126
|
body.queries = opts.queries;
|
|
9911
10127
|
}
|
|
10128
|
+
if (opts?.groups?.length || opts?.targets?.length) {
|
|
10129
|
+
body.measurementScope = {
|
|
10130
|
+
...opts.groups?.length ? { groups: opts.groups } : {},
|
|
10131
|
+
...opts.targets?.length ? { targets: opts.targets } : {}
|
|
10132
|
+
};
|
|
10133
|
+
}
|
|
9912
10134
|
if (opts?.location) {
|
|
9913
10135
|
body.location = opts.location;
|
|
9914
10136
|
}
|
|
@@ -10001,7 +10223,7 @@ async function triggerRun(project, opts) {
|
|
|
10001
10223
|
}
|
|
10002
10224
|
}
|
|
10003
10225
|
async function triggerRunAll(opts) {
|
|
10004
|
-
const client =
|
|
10226
|
+
const client = getClient23();
|
|
10005
10227
|
const projects2 = await client.listProjects();
|
|
10006
10228
|
if (projects2.length === 0) {
|
|
10007
10229
|
if (isMachineFormat(opts?.format)) {
|
|
@@ -10084,7 +10306,7 @@ async function triggerRunAll(opts) {
|
|
|
10084
10306
|
}
|
|
10085
10307
|
}
|
|
10086
10308
|
async function cancelRun(project, runId, format) {
|
|
10087
|
-
const client =
|
|
10309
|
+
const client = getClient23();
|
|
10088
10310
|
let targetId = runId;
|
|
10089
10311
|
if (!targetId) {
|
|
10090
10312
|
const runs = await client.listRuns(project);
|
|
@@ -10116,7 +10338,7 @@ To cancel by ID : canonry run cancel ${project} <run-id>`,
|
|
|
10116
10338
|
console.log(`Run ${result.id} cancelled.`);
|
|
10117
10339
|
}
|
|
10118
10340
|
async function showRun(id, format) {
|
|
10119
|
-
const client =
|
|
10341
|
+
const client = getClient23();
|
|
10120
10342
|
const run = await client.getRun(id);
|
|
10121
10343
|
if (isMachineFormat(format)) {
|
|
10122
10344
|
console.log(JSON.stringify(run, null, 2));
|
|
@@ -10125,7 +10347,7 @@ async function showRun(id, format) {
|
|
|
10125
10347
|
printRunDetail(run);
|
|
10126
10348
|
}
|
|
10127
10349
|
async function listRuns(project, opts) {
|
|
10128
|
-
const client =
|
|
10350
|
+
const client = getClient23();
|
|
10129
10351
|
const runs = await client.listRuns(project, opts?.limit, opts?.kind);
|
|
10130
10352
|
if (opts?.format === "json") {
|
|
10131
10353
|
console.log(JSON.stringify(runs, null, 2));
|
|
@@ -10192,6 +10414,90 @@ function printRunDetail(run) {
|
|
|
10192
10414
|
}
|
|
10193
10415
|
|
|
10194
10416
|
// src/cli-commands/run.ts
|
|
10417
|
+
var RUN_TRIGGER_USAGE = "canonry run trigger <project> [--group <key>]... [--target <key>]... [--provider <name>] [--query <q>...] [--location <label>] [--all-locations] [--no-location] [--probe] [--wait] [--format json]";
|
|
10418
|
+
var RUN_USAGE2 = "canonry run <project|--all> [--group <key>]... [--target <key>]... [--provider <name>] [--query <q>...] [--location <label>] [--all-locations] [--no-location] [--probe] [--wait] [--format json]";
|
|
10419
|
+
var RUN_TRIGGER_OPTIONS = {
|
|
10420
|
+
provider: stringOption(),
|
|
10421
|
+
query: multiStringOption(),
|
|
10422
|
+
// Measure one slice of the project's published measurement plan. A group
|
|
10423
|
+
// stands for its member targets; repeat either flag to widen the slice.
|
|
10424
|
+
group: multiStringOption(),
|
|
10425
|
+
target: multiStringOption(),
|
|
10426
|
+
wait: { type: "boolean", default: false },
|
|
10427
|
+
all: { type: "boolean", default: false },
|
|
10428
|
+
location: stringOption(),
|
|
10429
|
+
"all-locations": { type: "boolean", default: false },
|
|
10430
|
+
"no-location": { type: "boolean", default: false },
|
|
10431
|
+
// Probe runs are operator/agent test runs — they write a snapshot
|
|
10432
|
+
// for inspection but are excluded from dashboard / analytics /
|
|
10433
|
+
// intelligence / notifications. Use when you want to verify a
|
|
10434
|
+
// provider works without polluting the project's metrics.
|
|
10435
|
+
probe: { type: "boolean", default: false }
|
|
10436
|
+
};
|
|
10437
|
+
async function triggerRunCommand(input, command) {
|
|
10438
|
+
const groups = getStringArray(input.values, "group") ?? [];
|
|
10439
|
+
const targets = getStringArray(input.values, "target") ?? [];
|
|
10440
|
+
const queries2 = getStringArray(input.values, "query") ?? [];
|
|
10441
|
+
const usage = command === "run" ? RUN_USAGE2 : RUN_TRIGGER_USAGE;
|
|
10442
|
+
if (getBoolean(input.values, "all")) {
|
|
10443
|
+
if (input.positionals.length > 0) {
|
|
10444
|
+
throw usageError("Error: --all cannot be combined with a project name", {
|
|
10445
|
+
message: "--all cannot be combined with a project name",
|
|
10446
|
+
details: {
|
|
10447
|
+
command,
|
|
10448
|
+
usage: "canonry run --all [--provider <name>] [--wait] [--format json]"
|
|
10449
|
+
}
|
|
10450
|
+
});
|
|
10451
|
+
}
|
|
10452
|
+
if (queries2.length) {
|
|
10453
|
+
throw usageError("Error: --query cannot be combined with --all (query scope is project-specific)", {
|
|
10454
|
+
message: "--query cannot be combined with --all (query scope is project-specific)",
|
|
10455
|
+
details: {
|
|
10456
|
+
command,
|
|
10457
|
+
usage: "canonry run <project> --query <q>... [--provider <name>] [--wait] [--format json]"
|
|
10458
|
+
}
|
|
10459
|
+
});
|
|
10460
|
+
}
|
|
10461
|
+
if (groups.length || targets.length) {
|
|
10462
|
+
throw usageError("Error: --group and --target cannot be combined with --all (a plan slice belongs to one project)", {
|
|
10463
|
+
message: "--group and --target cannot be combined with --all (a plan slice belongs to one project)",
|
|
10464
|
+
details: { command, usage }
|
|
10465
|
+
});
|
|
10466
|
+
}
|
|
10467
|
+
await triggerRunAll({
|
|
10468
|
+
provider: getString(input.values, "provider"),
|
|
10469
|
+
wait: getBoolean(input.values, "wait"),
|
|
10470
|
+
allLocations: getBoolean(input.values, "all-locations"),
|
|
10471
|
+
noLocation: getBoolean(input.values, "no-location"),
|
|
10472
|
+
format: input.format
|
|
10473
|
+
});
|
|
10474
|
+
return;
|
|
10475
|
+
}
|
|
10476
|
+
if (queries2.length && (groups.length || targets.length)) {
|
|
10477
|
+
throw usageError("Error: --query cannot be combined with --group or --target (pick questions, or pick a slice of the plan)", {
|
|
10478
|
+
message: "--query cannot be combined with --group or --target (pick questions, or pick a slice of the plan)",
|
|
10479
|
+
details: { command, usage }
|
|
10480
|
+
});
|
|
10481
|
+
}
|
|
10482
|
+
const project = requireProject(
|
|
10483
|
+
input,
|
|
10484
|
+
command,
|
|
10485
|
+
usage,
|
|
10486
|
+
command === "run" ? "project name is required (or use --all)" : "project name is required"
|
|
10487
|
+
);
|
|
10488
|
+
await triggerRun(project, {
|
|
10489
|
+
provider: getString(input.values, "provider"),
|
|
10490
|
+
queries: queries2.length ? queries2 : void 0,
|
|
10491
|
+
groups: groups.length ? groups : void 0,
|
|
10492
|
+
targets: targets.length ? targets : void 0,
|
|
10493
|
+
wait: getBoolean(input.values, "wait"),
|
|
10494
|
+
location: getString(input.values, "location"),
|
|
10495
|
+
allLocations: getBoolean(input.values, "all-locations"),
|
|
10496
|
+
noLocation: getBoolean(input.values, "no-location"),
|
|
10497
|
+
probe: getBoolean(input.values, "probe"),
|
|
10498
|
+
format: input.format
|
|
10499
|
+
});
|
|
10500
|
+
}
|
|
10195
10501
|
var RUN_CLI_COMMANDS = [
|
|
10196
10502
|
{
|
|
10197
10503
|
path: ["run", "show"],
|
|
@@ -10213,69 +10519,25 @@ var RUN_CLI_COMMANDS = [
|
|
|
10213
10519
|
await cancelRun(project, input.positionals[1], input.format);
|
|
10214
10520
|
}
|
|
10215
10521
|
},
|
|
10522
|
+
{
|
|
10523
|
+
path: ["run", "trigger"],
|
|
10524
|
+
usage: RUN_TRIGGER_USAGE,
|
|
10525
|
+
options: RUN_TRIGGER_OPTIONS,
|
|
10526
|
+
run: (input) => triggerRunCommand(
|
|
10527
|
+
// `canonry run trigger` with nothing after it is ambiguous: the
|
|
10528
|
+
// subcommand with no project, or the older form naming a project called
|
|
10529
|
+
// "trigger". Nobody types the subcommand without a project, and a project
|
|
10530
|
+
// whose name collides with a keyword still has to be runnable, so the
|
|
10531
|
+
// project wins and the word is handed back as the positional.
|
|
10532
|
+
input.positionals.length === 0 && !getBoolean(input.values, "all") ? { ...input, positionals: ["trigger"] } : input,
|
|
10533
|
+
"run.trigger"
|
|
10534
|
+
)
|
|
10535
|
+
},
|
|
10216
10536
|
{
|
|
10217
10537
|
path: ["run"],
|
|
10218
|
-
usage:
|
|
10219
|
-
options:
|
|
10220
|
-
|
|
10221
|
-
query: multiStringOption(),
|
|
10222
|
-
wait: { type: "boolean", default: false },
|
|
10223
|
-
all: { type: "boolean", default: false },
|
|
10224
|
-
location: stringOption(),
|
|
10225
|
-
"all-locations": { type: "boolean", default: false },
|
|
10226
|
-
"no-location": { type: "boolean", default: false },
|
|
10227
|
-
// Probe runs are operator/agent test runs — they write a snapshot
|
|
10228
|
-
// for inspection but are excluded from dashboard / analytics /
|
|
10229
|
-
// intelligence / notifications. Use when you want to verify a
|
|
10230
|
-
// provider works without polluting the project's metrics.
|
|
10231
|
-
probe: { type: "boolean", default: false }
|
|
10232
|
-
},
|
|
10233
|
-
run: async (input) => {
|
|
10234
|
-
if (getBoolean(input.values, "all")) {
|
|
10235
|
-
if (input.positionals.length > 0) {
|
|
10236
|
-
throw usageError("Error: --all cannot be combined with a project name", {
|
|
10237
|
-
message: "--all cannot be combined with a project name",
|
|
10238
|
-
details: {
|
|
10239
|
-
command: "run",
|
|
10240
|
-
usage: "canonry run --all [--provider <name>] [--wait] [--format json]"
|
|
10241
|
-
}
|
|
10242
|
-
});
|
|
10243
|
-
}
|
|
10244
|
-
if (getStringArray(input.values, "query")?.length) {
|
|
10245
|
-
throw usageError("Error: --query cannot be combined with --all (query scope is project-specific)", {
|
|
10246
|
-
message: "--query cannot be combined with --all (query scope is project-specific)",
|
|
10247
|
-
details: {
|
|
10248
|
-
command: "run",
|
|
10249
|
-
usage: "canonry run <project> --query <q>... [--provider <name>] [--wait] [--format json]"
|
|
10250
|
-
}
|
|
10251
|
-
});
|
|
10252
|
-
}
|
|
10253
|
-
await triggerRunAll({
|
|
10254
|
-
provider: getString(input.values, "provider"),
|
|
10255
|
-
wait: getBoolean(input.values, "wait"),
|
|
10256
|
-
allLocations: getBoolean(input.values, "all-locations"),
|
|
10257
|
-
noLocation: getBoolean(input.values, "no-location"),
|
|
10258
|
-
format: input.format
|
|
10259
|
-
});
|
|
10260
|
-
return;
|
|
10261
|
-
}
|
|
10262
|
-
const project = requireProject(
|
|
10263
|
-
input,
|
|
10264
|
-
"run",
|
|
10265
|
-
"canonry run <project> [--provider <name>] [--query <q>...] [--wait] [--format json]",
|
|
10266
|
-
"project name is required (or use --all)"
|
|
10267
|
-
);
|
|
10268
|
-
await triggerRun(project, {
|
|
10269
|
-
provider: getString(input.values, "provider"),
|
|
10270
|
-
queries: getStringArray(input.values, "query"),
|
|
10271
|
-
wait: getBoolean(input.values, "wait"),
|
|
10272
|
-
location: getString(input.values, "location"),
|
|
10273
|
-
allLocations: getBoolean(input.values, "all-locations"),
|
|
10274
|
-
noLocation: getBoolean(input.values, "no-location"),
|
|
10275
|
-
probe: getBoolean(input.values, "probe"),
|
|
10276
|
-
format: input.format
|
|
10277
|
-
});
|
|
10278
|
-
}
|
|
10538
|
+
usage: RUN_USAGE2,
|
|
10539
|
+
options: RUN_TRIGGER_OPTIONS,
|
|
10540
|
+
run: (input) => triggerRunCommand(input, "run")
|
|
10279
10541
|
},
|
|
10280
10542
|
{
|
|
10281
10543
|
path: ["runs"],
|
|
@@ -10300,11 +10562,11 @@ var RUN_CLI_COMMANDS = [
|
|
|
10300
10562
|
];
|
|
10301
10563
|
|
|
10302
10564
|
// src/commands/schedule.ts
|
|
10303
|
-
function
|
|
10565
|
+
function getClient24() {
|
|
10304
10566
|
return createApiClient();
|
|
10305
10567
|
}
|
|
10306
10568
|
async function setSchedule(project, opts) {
|
|
10307
|
-
const client =
|
|
10569
|
+
const client = getClient24();
|
|
10308
10570
|
const body = {};
|
|
10309
10571
|
if (opts.kind) body.kind = opts.kind;
|
|
10310
10572
|
if (opts.sourceId) body.sourceId = opts.sourceId;
|
|
@@ -10321,7 +10583,7 @@ async function setSchedule(project, opts) {
|
|
|
10321
10583
|
printSchedule(result);
|
|
10322
10584
|
}
|
|
10323
10585
|
async function showSchedule(project, format, kind) {
|
|
10324
|
-
const client =
|
|
10586
|
+
const client = getClient24();
|
|
10325
10587
|
const result = await client.getSchedule(project, kind);
|
|
10326
10588
|
if (isMachineFormat(format)) {
|
|
10327
10589
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -10330,7 +10592,7 @@ async function showSchedule(project, format, kind) {
|
|
|
10330
10592
|
printSchedule(result);
|
|
10331
10593
|
}
|
|
10332
10594
|
async function enableSchedule(project, format, kind) {
|
|
10333
|
-
const client =
|
|
10595
|
+
const client = getClient24();
|
|
10334
10596
|
const current = await client.getSchedule(project, kind);
|
|
10335
10597
|
const body = { kind: current.kind, timezone: current.timezone, enabled: true };
|
|
10336
10598
|
if (current.preset) body.preset = current.preset;
|
|
@@ -10345,7 +10607,7 @@ async function enableSchedule(project, format, kind) {
|
|
|
10345
10607
|
console.log(`Schedule enabled for "${project}" (kind: ${result.kind})`);
|
|
10346
10608
|
}
|
|
10347
10609
|
async function disableSchedule(project, format, kind) {
|
|
10348
|
-
const client =
|
|
10610
|
+
const client = getClient24();
|
|
10349
10611
|
const current = await client.getSchedule(project, kind);
|
|
10350
10612
|
const body = { kind: current.kind, timezone: current.timezone, enabled: false };
|
|
10351
10613
|
if (current.preset) body.preset = current.preset;
|
|
@@ -10360,7 +10622,7 @@ async function disableSchedule(project, format, kind) {
|
|
|
10360
10622
|
console.log(`Schedule disabled for "${project}" (kind: ${result.kind})`);
|
|
10361
10623
|
}
|
|
10362
10624
|
async function removeSchedule(project, format, kind) {
|
|
10363
|
-
const client =
|
|
10625
|
+
const client = getClient24();
|
|
10364
10626
|
await client.deleteSchedule(project, kind);
|
|
10365
10627
|
const resolvedKind = kind ?? "answer-visibility";
|
|
10366
10628
|
if (isMachineFormat(format)) {
|
|
@@ -10478,11 +10740,11 @@ var SCHEDULE_CLI_COMMANDS = [
|
|
|
10478
10740
|
];
|
|
10479
10741
|
|
|
10480
10742
|
// src/commands/settings.ts
|
|
10481
|
-
function
|
|
10743
|
+
function getClient25() {
|
|
10482
10744
|
return createApiClient();
|
|
10483
10745
|
}
|
|
10484
10746
|
async function setProvider(name, opts) {
|
|
10485
|
-
const client =
|
|
10747
|
+
const client = getClient25();
|
|
10486
10748
|
const { format, ...payload } = opts;
|
|
10487
10749
|
const result = await client.updateProvider(name, payload);
|
|
10488
10750
|
if (isMachineFormat(format)) {
|
|
@@ -10498,7 +10760,7 @@ async function setProvider(name, opts) {
|
|
|
10498
10760
|
}
|
|
10499
10761
|
}
|
|
10500
10762
|
async function showSettings(format) {
|
|
10501
|
-
const client =
|
|
10763
|
+
const client = getClient25();
|
|
10502
10764
|
const config = loadConfig();
|
|
10503
10765
|
const settings = await client.getSettings();
|
|
10504
10766
|
if (isMachineFormat(format)) {
|
|
@@ -11048,7 +11310,7 @@ function wrapText(font, text, size, maxWidth) {
|
|
|
11048
11310
|
}
|
|
11049
11311
|
|
|
11050
11312
|
// src/commands/snapshot.ts
|
|
11051
|
-
function
|
|
11313
|
+
function getClient26() {
|
|
11052
11314
|
return createApiClient();
|
|
11053
11315
|
}
|
|
11054
11316
|
function slugify(value) {
|
|
@@ -11059,7 +11321,7 @@ function autoOutputPath(companyName, ext) {
|
|
|
11059
11321
|
return `${slugify(companyName)}-snapshot-${date}.${ext}`;
|
|
11060
11322
|
}
|
|
11061
11323
|
async function createSnapshotReport(companyName, opts) {
|
|
11062
|
-
const client =
|
|
11324
|
+
const client = getClient26();
|
|
11063
11325
|
const report = await client.createSnapshot({
|
|
11064
11326
|
companyName,
|
|
11065
11327
|
domain: opts.domain,
|
|
@@ -12505,7 +12767,7 @@ function stopDaemon(format = "text") {
|
|
|
12505
12767
|
// src/commands/init.ts
|
|
12506
12768
|
import crypto2 from "crypto";
|
|
12507
12769
|
import fs13 from "fs";
|
|
12508
|
-
import
|
|
12770
|
+
import readline2 from "readline";
|
|
12509
12771
|
import path10 from "path";
|
|
12510
12772
|
var pendingServeHandoff = false;
|
|
12511
12773
|
function consumePendingServeHandoff() {
|
|
@@ -12522,7 +12784,7 @@ async function promptProviderApiKey(label, envVar, promptFn = prompt, env = proc
|
|
|
12522
12784
|
return promptFn(`${label} API key (press Enter to skip): `);
|
|
12523
12785
|
}
|
|
12524
12786
|
function prompt(question) {
|
|
12525
|
-
const rl =
|
|
12787
|
+
const rl = readline2.createInterface({
|
|
12526
12788
|
input: process.stdin,
|
|
12527
12789
|
output: process.stdout
|
|
12528
12790
|
});
|
|
@@ -13435,11 +13697,11 @@ var SYSTEM_CLI_COMMANDS = [
|
|
|
13435
13697
|
];
|
|
13436
13698
|
|
|
13437
13699
|
// src/commands/technical-aeo.ts
|
|
13438
|
-
function
|
|
13700
|
+
function getClient27() {
|
|
13439
13701
|
return createApiClient();
|
|
13440
13702
|
}
|
|
13441
13703
|
async function technicalAeoScore(project, opts) {
|
|
13442
|
-
const client =
|
|
13704
|
+
const client = getClient27();
|
|
13443
13705
|
const score = await client.getTechnicalAeoScore(project, { runId: opts.runId });
|
|
13444
13706
|
if (isMachineFormat(opts.format)) {
|
|
13445
13707
|
console.log(JSON.stringify(score, null, 2));
|
|
@@ -13475,7 +13737,7 @@ async function technicalAeoScore(project, opts) {
|
|
|
13475
13737
|
console.log(lines.join("\n"));
|
|
13476
13738
|
}
|
|
13477
13739
|
async function technicalAeoPages(project, opts) {
|
|
13478
|
-
const client =
|
|
13740
|
+
const client = getClient27();
|
|
13479
13741
|
const status = opts.status === "success" || opts.status === "error" ? opts.status : void 0;
|
|
13480
13742
|
const res = await client.getTechnicalAeoPages(project, { runId: opts.runId, status, sort: opts.sort, limit: opts.limit });
|
|
13481
13743
|
if (opts.format === "jsonl") {
|
|
@@ -13501,7 +13763,7 @@ async function technicalAeoPages(project, opts) {
|
|
|
13501
13763
|
console.log(lines.join("\n"));
|
|
13502
13764
|
}
|
|
13503
13765
|
async function technicalAeoTrend(project, opts) {
|
|
13504
|
-
const client =
|
|
13766
|
+
const client = getClient27();
|
|
13505
13767
|
const res = await client.getTechnicalAeoTrend(project, { limit: opts.limit });
|
|
13506
13768
|
if (opts.format === "jsonl") {
|
|
13507
13769
|
emitJsonl(res.points.map((p) => ({ project, ...p })));
|
|
@@ -13523,7 +13785,7 @@ async function technicalAeoTrend(project, opts) {
|
|
|
13523
13785
|
console.log(lines.join("\n"));
|
|
13524
13786
|
}
|
|
13525
13787
|
async function technicalAeoRun(project, opts) {
|
|
13526
|
-
const client =
|
|
13788
|
+
const client = getClient27();
|
|
13527
13789
|
const { runId, status } = await client.triggerSiteAudit(project, {
|
|
13528
13790
|
sitemapUrl: opts.sitemapUrl,
|
|
13529
13791
|
limit: opts.limit
|
|
@@ -13882,7 +14144,7 @@ var VISIBILITY_STATS_CLI_COMMANDS = [
|
|
|
13882
14144
|
import fs15 from "fs";
|
|
13883
14145
|
|
|
13884
14146
|
// src/commands/wordpress.ts
|
|
13885
|
-
function
|
|
14147
|
+
function getClient28() {
|
|
13886
14148
|
return createApiClient();
|
|
13887
14149
|
}
|
|
13888
14150
|
async function loadYamlModule() {
|
|
@@ -14032,7 +14294,7 @@ async function wordpressConnect(project, opts) {
|
|
|
14032
14294
|
details: { project }
|
|
14033
14295
|
});
|
|
14034
14296
|
}
|
|
14035
|
-
const client =
|
|
14297
|
+
const client = getClient28();
|
|
14036
14298
|
const result = await client.wordpressConnect(project, {
|
|
14037
14299
|
url: opts.url,
|
|
14038
14300
|
stagingUrl: opts.stagingUrl,
|
|
@@ -14049,7 +14311,7 @@ async function wordpressConnect(project, opts) {
|
|
|
14049
14311
|
printWordpressStatus(project, result);
|
|
14050
14312
|
}
|
|
14051
14313
|
async function wordpressDisconnect(project, format) {
|
|
14052
|
-
const client =
|
|
14314
|
+
const client = getClient28();
|
|
14053
14315
|
await client.wordpressDisconnect(project);
|
|
14054
14316
|
if (isMachineFormat(format)) {
|
|
14055
14317
|
printJson2({ project, disconnected: true });
|
|
@@ -14058,7 +14320,7 @@ async function wordpressDisconnect(project, format) {
|
|
|
14058
14320
|
console.log(`WordPress disconnected from project "${project}".`);
|
|
14059
14321
|
}
|
|
14060
14322
|
async function wordpressStatus(project, format) {
|
|
14061
|
-
const client =
|
|
14323
|
+
const client = getClient28();
|
|
14062
14324
|
const result = await client.wordpressStatus(project);
|
|
14063
14325
|
if (isMachineFormat(format)) {
|
|
14064
14326
|
printJson2(result);
|
|
@@ -14067,7 +14329,7 @@ async function wordpressStatus(project, format) {
|
|
|
14067
14329
|
printWordpressStatus(project, result);
|
|
14068
14330
|
}
|
|
14069
14331
|
async function wordpressPages(project, opts) {
|
|
14070
|
-
const client =
|
|
14332
|
+
const client = getClient28();
|
|
14071
14333
|
const result = await client.wordpressPages(project, opts.env);
|
|
14072
14334
|
if (isMachineFormat(opts.format)) {
|
|
14073
14335
|
printJson2(result);
|
|
@@ -14076,7 +14338,7 @@ async function wordpressPages(project, opts) {
|
|
|
14076
14338
|
printPages(project, result.env, result.pages);
|
|
14077
14339
|
}
|
|
14078
14340
|
async function wordpressPage(project, slug, opts) {
|
|
14079
|
-
const client =
|
|
14341
|
+
const client = getClient28();
|
|
14080
14342
|
const result = await client.wordpressPage(project, slug, opts.env);
|
|
14081
14343
|
if (isMachineFormat(opts.format)) {
|
|
14082
14344
|
printJson2(result);
|
|
@@ -14085,7 +14347,7 @@ async function wordpressPage(project, slug, opts) {
|
|
|
14085
14347
|
printPageDetail(result);
|
|
14086
14348
|
}
|
|
14087
14349
|
async function wordpressCreatePage(project, body) {
|
|
14088
|
-
const client =
|
|
14350
|
+
const client = getClient28();
|
|
14089
14351
|
const result = await client.wordpressCreatePage(project, body);
|
|
14090
14352
|
if (isMachineFormat(body.format)) {
|
|
14091
14353
|
printJson2(result);
|
|
@@ -14096,7 +14358,7 @@ async function wordpressCreatePage(project, body) {
|
|
|
14096
14358
|
printPageDetail(result);
|
|
14097
14359
|
}
|
|
14098
14360
|
async function wordpressUpdatePage(project, body) {
|
|
14099
|
-
const client =
|
|
14361
|
+
const client = getClient28();
|
|
14100
14362
|
const result = await client.wordpressUpdatePage(project, body);
|
|
14101
14363
|
if (isMachineFormat(body.format)) {
|
|
14102
14364
|
printJson2(result);
|
|
@@ -14107,7 +14369,7 @@ async function wordpressUpdatePage(project, body) {
|
|
|
14107
14369
|
printPageDetail(result);
|
|
14108
14370
|
}
|
|
14109
14371
|
async function wordpressSetMeta(project, body) {
|
|
14110
|
-
const client =
|
|
14372
|
+
const client = getClient28();
|
|
14111
14373
|
const result = await client.wordpressSetMeta(project, body);
|
|
14112
14374
|
if (isMachineFormat(body.format)) {
|
|
14113
14375
|
printJson2(result);
|
|
@@ -14118,12 +14380,12 @@ async function wordpressSetMeta(project, body) {
|
|
|
14118
14380
|
printPageDetail(result);
|
|
14119
14381
|
}
|
|
14120
14382
|
async function wordpressBulkSetMeta(project, opts) {
|
|
14121
|
-
const
|
|
14383
|
+
const fs17 = await import("fs/promises");
|
|
14122
14384
|
const path12 = await import("path");
|
|
14123
14385
|
const filePath = path12.resolve(opts.from);
|
|
14124
14386
|
let raw;
|
|
14125
14387
|
try {
|
|
14126
|
-
raw = await
|
|
14388
|
+
raw = await fs17.readFile(filePath, "utf8");
|
|
14127
14389
|
} catch {
|
|
14128
14390
|
throw new CliError({
|
|
14129
14391
|
code: "FILE_READ_ERROR",
|
|
@@ -14157,7 +14419,7 @@ async function wordpressBulkSetMeta(project, opts) {
|
|
|
14157
14419
|
details: { path: filePath }
|
|
14158
14420
|
});
|
|
14159
14421
|
}
|
|
14160
|
-
const client =
|
|
14422
|
+
const client = getClient28();
|
|
14161
14423
|
const result = await client.wordpressBulkSetMeta(project, { entries, env: opts.env });
|
|
14162
14424
|
if (isMachineFormat(opts.format)) {
|
|
14163
14425
|
printJson2(result);
|
|
@@ -14200,7 +14462,7 @@ async function wordpressBulkSetMeta(project, opts) {
|
|
|
14200
14462
|
Total: ${applied.length} applied, ${skipped.length} skipped, ${manual.length} manual`);
|
|
14201
14463
|
}
|
|
14202
14464
|
async function wordpressSchema(project, slug, opts) {
|
|
14203
|
-
const client =
|
|
14465
|
+
const client = getClient28();
|
|
14204
14466
|
const result = await client.wordpressSchema(project, slug, opts.env);
|
|
14205
14467
|
if (isMachineFormat(opts.format)) {
|
|
14206
14468
|
printJson2(result);
|
|
@@ -14211,7 +14473,7 @@ async function wordpressSchema(project, slug, opts) {
|
|
|
14211
14473
|
printSchemaBlocks(result.blocks);
|
|
14212
14474
|
}
|
|
14213
14475
|
async function wordpressSetSchema(project, body) {
|
|
14214
|
-
const client =
|
|
14476
|
+
const client = getClient28();
|
|
14215
14477
|
const result = await client.wordpressSetSchema(project, body);
|
|
14216
14478
|
if (isMachineFormat(body.format)) {
|
|
14217
14479
|
printJson2(result);
|
|
@@ -14220,13 +14482,13 @@ async function wordpressSetSchema(project, body) {
|
|
|
14220
14482
|
printManualAssist(`Schema update for "${body.slug}"`, result);
|
|
14221
14483
|
}
|
|
14222
14484
|
async function wordpressSchemaDeploy(project, opts) {
|
|
14223
|
-
const
|
|
14485
|
+
const fs17 = await import("fs/promises");
|
|
14224
14486
|
const path12 = await import("path");
|
|
14225
14487
|
const yaml = await loadYamlModule();
|
|
14226
14488
|
const filePath = path12.resolve(opts.profile);
|
|
14227
14489
|
let raw;
|
|
14228
14490
|
try {
|
|
14229
|
-
raw = await
|
|
14491
|
+
raw = await fs17.readFile(filePath, "utf8");
|
|
14230
14492
|
} catch {
|
|
14231
14493
|
throw new CliError({
|
|
14232
14494
|
code: "FILE_READ_ERROR",
|
|
@@ -14259,7 +14521,7 @@ async function wordpressSchemaDeploy(project, opts) {
|
|
|
14259
14521
|
details: { path: filePath }
|
|
14260
14522
|
});
|
|
14261
14523
|
}
|
|
14262
|
-
const client =
|
|
14524
|
+
const client = getClient28();
|
|
14263
14525
|
const result = await client.wordpressSchemaDeploy(project, { profile: parsed, env: opts.env });
|
|
14264
14526
|
if (isMachineFormat(opts.format)) {
|
|
14265
14527
|
printJson2(result);
|
|
@@ -14298,7 +14560,7 @@ async function wordpressSchemaDeploy(project, opts) {
|
|
|
14298
14560
|
Total: ${deployed} deployed, ${stripped} stripped, ${skipped} skipped, ${failed} failed`);
|
|
14299
14561
|
}
|
|
14300
14562
|
async function wordpressSchemaStatus(project, opts) {
|
|
14301
|
-
const client =
|
|
14563
|
+
const client = getClient28();
|
|
14302
14564
|
const result = await client.wordpressSchemaStatus(project, opts.env);
|
|
14303
14565
|
if (isMachineFormat(opts.format)) {
|
|
14304
14566
|
printJson2(result);
|
|
@@ -14331,13 +14593,13 @@ async function wordpressOnboard(project, opts) {
|
|
|
14331
14593
|
}
|
|
14332
14594
|
let profileData;
|
|
14333
14595
|
if (opts.profile) {
|
|
14334
|
-
const
|
|
14596
|
+
const fs17 = await import("fs/promises");
|
|
14335
14597
|
const path12 = await import("path");
|
|
14336
14598
|
const yaml = await loadYamlModule();
|
|
14337
14599
|
const filePath = path12.resolve(opts.profile);
|
|
14338
14600
|
let raw;
|
|
14339
14601
|
try {
|
|
14340
|
-
raw = await
|
|
14602
|
+
raw = await fs17.readFile(filePath, "utf8");
|
|
14341
14603
|
} catch {
|
|
14342
14604
|
throw new CliError({
|
|
14343
14605
|
code: "FILE_READ_ERROR",
|
|
@@ -14357,7 +14619,7 @@ async function wordpressOnboard(project, opts) {
|
|
|
14357
14619
|
});
|
|
14358
14620
|
}
|
|
14359
14621
|
}
|
|
14360
|
-
const client =
|
|
14622
|
+
const client = getClient28();
|
|
14361
14623
|
const result = await client.wordpressOnboard(project, {
|
|
14362
14624
|
url: opts.url,
|
|
14363
14625
|
username: opts.user,
|
|
@@ -14382,7 +14644,7 @@ async function wordpressOnboard(project, opts) {
|
|
|
14382
14644
|
}
|
|
14383
14645
|
}
|
|
14384
14646
|
async function wordpressLlmsTxt(project, opts) {
|
|
14385
|
-
const client =
|
|
14647
|
+
const client = getClient28();
|
|
14386
14648
|
const result = await client.wordpressLlmsTxt(project, opts.env);
|
|
14387
14649
|
if (isMachineFormat(opts.format)) {
|
|
14388
14650
|
printJson2(result);
|
|
@@ -14393,7 +14655,7 @@ async function wordpressLlmsTxt(project, opts) {
|
|
|
14393
14655
|
console.log(result.content ?? "(not found)");
|
|
14394
14656
|
}
|
|
14395
14657
|
async function wordpressSetLlmsTxt(project, body) {
|
|
14396
|
-
const client =
|
|
14658
|
+
const client = getClient28();
|
|
14397
14659
|
const result = await client.wordpressSetLlmsTxt(project, body);
|
|
14398
14660
|
if (isMachineFormat(body.format)) {
|
|
14399
14661
|
printJson2(result);
|
|
@@ -14402,7 +14664,7 @@ async function wordpressSetLlmsTxt(project, body) {
|
|
|
14402
14664
|
printManualAssist(`llms.txt update for "${project}"`, result);
|
|
14403
14665
|
}
|
|
14404
14666
|
async function wordpressAudit(project, opts) {
|
|
14405
|
-
const client =
|
|
14667
|
+
const client = getClient28();
|
|
14406
14668
|
const result = await client.wordpressAudit(project, opts.env);
|
|
14407
14669
|
if (isMachineFormat(opts.format)) {
|
|
14408
14670
|
printJson2(result);
|
|
@@ -14416,7 +14678,7 @@ async function wordpressAudit(project, opts) {
|
|
|
14416
14678
|
printAuditIssues(result.issues);
|
|
14417
14679
|
}
|
|
14418
14680
|
async function wordpressDiff(project, slug, format) {
|
|
14419
|
-
const client =
|
|
14681
|
+
const client = getClient28();
|
|
14420
14682
|
const result = await client.wordpressDiff(project, slug);
|
|
14421
14683
|
if (isMachineFormat(format)) {
|
|
14422
14684
|
printJson2(result);
|
|
@@ -14425,7 +14687,7 @@ async function wordpressDiff(project, slug, format) {
|
|
|
14425
14687
|
printDiff(result);
|
|
14426
14688
|
}
|
|
14427
14689
|
async function wordpressStagingStatus(project, format) {
|
|
14428
|
-
const client =
|
|
14690
|
+
const client = getClient28();
|
|
14429
14691
|
const result = await client.wordpressStagingStatus(project);
|
|
14430
14692
|
if (isMachineFormat(format)) {
|
|
14431
14693
|
printJson2(result);
|
|
@@ -14439,7 +14701,7 @@ async function wordpressStagingStatus(project, format) {
|
|
|
14439
14701
|
console.log(` Admin URL: ${result.adminUrl}`);
|
|
14440
14702
|
}
|
|
14441
14703
|
async function wordpressStagingPush(project, format) {
|
|
14442
|
-
const client =
|
|
14704
|
+
const client = getClient28();
|
|
14443
14705
|
const result = await client.wordpressStagingPush(project);
|
|
14444
14706
|
if (isMachineFormat(format)) {
|
|
14445
14707
|
printJson2(result);
|
|
@@ -15451,6 +15713,112 @@ Usage: ${usage}`, {
|
|
|
15451
15713
|
}
|
|
15452
15714
|
];
|
|
15453
15715
|
|
|
15716
|
+
// src/commands/measurement-plan.ts
|
|
15717
|
+
import fs16 from "fs";
|
|
15718
|
+
import { parse } from "yaml";
|
|
15719
|
+
function readPlan(source) {
|
|
15720
|
+
const content = source === "-" ? fs16.readFileSync(0, "utf8") : fs16.readFileSync(source, "utf8");
|
|
15721
|
+
const parsed = source.endsWith(".json") ? JSON.parse(content) : parse(content);
|
|
15722
|
+
return measurementPlanInputSchema.parse(parsed);
|
|
15723
|
+
}
|
|
15724
|
+
function readDiscoveryRule(source) {
|
|
15725
|
+
const content = source === "-" ? fs16.readFileSync(0, "utf8") : fs16.readFileSync(source, "utf8");
|
|
15726
|
+
const parsed = source.endsWith(".json") ? JSON.parse(content) : parse(content);
|
|
15727
|
+
return measurementDiscoveryRuleSchema.parse(parsed);
|
|
15728
|
+
}
|
|
15729
|
+
async function showMeasurementPlan(project, revision) {
|
|
15730
|
+
const client = createApiClient();
|
|
15731
|
+
console.log(JSON.stringify(revision === void 0 ? await client.getMeasurementPlan(project) : await client.getMeasurementPlanVersion(project, revision), null, 2));
|
|
15732
|
+
}
|
|
15733
|
+
async function listMeasurementPlanVersions(project) {
|
|
15734
|
+
console.log(JSON.stringify(await createApiClient().listMeasurementPlanVersions(project), null, 2));
|
|
15735
|
+
}
|
|
15736
|
+
async function publishMeasurementPlan(project, source) {
|
|
15737
|
+
const client = createApiClient();
|
|
15738
|
+
const plan = readPlan(source);
|
|
15739
|
+
const current = await client.getMeasurementPlan(project);
|
|
15740
|
+
console.log(JSON.stringify(await client.publishMeasurementPlan(project, {
|
|
15741
|
+
expectedActiveRevision: current.active?.revision ?? null,
|
|
15742
|
+
plan
|
|
15743
|
+
}), null, 2));
|
|
15744
|
+
}
|
|
15745
|
+
async function retireMeasurementPlanSegment(project, stableKey) {
|
|
15746
|
+
console.log(JSON.stringify(await createApiClient().retireMeasurementPlanSegment(project, stableKey), null, 2));
|
|
15747
|
+
}
|
|
15748
|
+
async function discoverMeasurementTargets(project, sitemapUrl, ruleSource, maxUrls) {
|
|
15749
|
+
const request = measurementDiscoveryRequestSchema.parse({
|
|
15750
|
+
sitemapUrl,
|
|
15751
|
+
rule: readDiscoveryRule(ruleSource),
|
|
15752
|
+
...maxUrls === void 0 ? {} : { maxUrls }
|
|
15753
|
+
});
|
|
15754
|
+
console.log(JSON.stringify(await createApiClient().discoverMeasurementTargets(project, request), null, 2));
|
|
15755
|
+
}
|
|
15756
|
+
async function showMeasurementReport(project, revision) {
|
|
15757
|
+
console.log(JSON.stringify(await createApiClient().getMeasurementReport(project, revision), null, 2));
|
|
15758
|
+
}
|
|
15759
|
+
|
|
15760
|
+
// src/cli-commands/measurement-plan.ts
|
|
15761
|
+
var MEASUREMENT_PLAN_CLI_COMMANDS = [
|
|
15762
|
+
{ path: ["measurement-plan", "show"], usage: "canonry measurement-plan show <project> [--revision N] [--format json]", options: { revision: stringOption() }, run: async (input) => {
|
|
15763
|
+
const value = getString(input.values, "revision");
|
|
15764
|
+
const revision = value === void 0 ? void 0 : Number(value);
|
|
15765
|
+
if (revision !== void 0 && (!Number.isInteger(revision) || revision <= 0)) throw usageError("--revision must be a positive integer");
|
|
15766
|
+
await showMeasurementPlan(requireProject(input, "measurement-plan.show", "canonry measurement-plan show <project> [--revision N]"), revision);
|
|
15767
|
+
} },
|
|
15768
|
+
{ path: ["measurement-plan", "versions"], usage: "canonry measurement-plan versions <project> [--format json]", run: (input) => listMeasurementPlanVersions(requireProject(input, "measurement-plan.versions", "canonry measurement-plan versions <project>")) },
|
|
15769
|
+
{ path: ["measurement-plan", "publish"], usage: "canonry measurement-plan publish <project> <yaml|json|-> [--format json]", run: (input) => {
|
|
15770
|
+
const project = requireProject(input, "measurement-plan.publish", "canonry measurement-plan publish <project> <yaml|json|->");
|
|
15771
|
+
const source = input.positionals[1];
|
|
15772
|
+
if (!source) throw usageError("plan file path or - is required");
|
|
15773
|
+
return publishMeasurementPlan(project, source);
|
|
15774
|
+
} },
|
|
15775
|
+
{ path: ["measurement-plan", "retire"], usage: "canonry measurement-plan retire <project> <stable-key> [--format json]", run: (input) => {
|
|
15776
|
+
const project = requireProject(input, "measurement-plan.retire", "canonry measurement-plan retire <project> <stable-key>");
|
|
15777
|
+
const stableKey = input.positionals[1];
|
|
15778
|
+
if (!stableKey) throw usageError("stable segment key is required");
|
|
15779
|
+
return retireMeasurementPlanSegment(project, stableKey);
|
|
15780
|
+
} },
|
|
15781
|
+
{
|
|
15782
|
+
path: ["measurement-plan", "discover"],
|
|
15783
|
+
usage: "canonry measurement-plan discover <project> --sitemap-url <url> --rule <yaml|json|-> [--max-urls N] [--format json]",
|
|
15784
|
+
options: { "sitemap-url": stringOption(), rule: stringOption(), "max-urls": stringOption() },
|
|
15785
|
+
run: (input) => {
|
|
15786
|
+
const usage = "canonry measurement-plan discover <project> --sitemap-url <url> --rule <yaml|json|-> [--max-urls N]";
|
|
15787
|
+
const project = requireProject(input, "measurement-plan.discover", usage);
|
|
15788
|
+
const sitemapUrl = requireStringOption(input, "sitemap-url", {
|
|
15789
|
+
command: "measurement-plan.discover",
|
|
15790
|
+
usage,
|
|
15791
|
+
message: "--sitemap-url is required"
|
|
15792
|
+
});
|
|
15793
|
+
const rule = requireStringOption(input, "rule", {
|
|
15794
|
+
command: "measurement-plan.discover",
|
|
15795
|
+
usage,
|
|
15796
|
+
message: "--rule is required"
|
|
15797
|
+
});
|
|
15798
|
+
const maxUrlsValue = getString(input.values, "max-urls");
|
|
15799
|
+
const maxUrls = maxUrlsValue === void 0 ? void 0 : Number(maxUrlsValue);
|
|
15800
|
+
if (maxUrls !== void 0 && (!Number.isInteger(maxUrls) || maxUrls < 1 || maxUrls > 1e4)) {
|
|
15801
|
+
throw usageError("--max-urls must be an integer from 1 to 10000");
|
|
15802
|
+
}
|
|
15803
|
+
return discoverMeasurementTargets(project, sitemapUrl, rule, maxUrls);
|
|
15804
|
+
}
|
|
15805
|
+
},
|
|
15806
|
+
{
|
|
15807
|
+
path: ["measurement-plan", "report"],
|
|
15808
|
+
usage: "canonry measurement-plan report <project> --revision N [--format json]",
|
|
15809
|
+
options: { revision: stringOption() },
|
|
15810
|
+
run: (input) => {
|
|
15811
|
+
const project = requireProject(input, "measurement-plan.report", "canonry measurement-plan report <project> --revision N");
|
|
15812
|
+
const value = getString(input.values, "revision");
|
|
15813
|
+
const revision = value === void 0 ? void 0 : Number(value);
|
|
15814
|
+
if (revision === void 0 || !Number.isInteger(revision) || revision <= 0) {
|
|
15815
|
+
throw usageError("--revision must be a positive integer");
|
|
15816
|
+
}
|
|
15817
|
+
return showMeasurementReport(project, revision);
|
|
15818
|
+
}
|
|
15819
|
+
}
|
|
15820
|
+
];
|
|
15821
|
+
|
|
15454
15822
|
// src/cli-commands.ts
|
|
15455
15823
|
var REGISTERED_CLI_COMMANDS = [
|
|
15456
15824
|
...BACKFILL_CLI_COMMANDS,
|
|
@@ -15462,6 +15830,7 @@ var REGISTERED_CLI_COMMANDS = [
|
|
|
15462
15830
|
...QUERY_CLI_COMMANDS,
|
|
15463
15831
|
...KEYWORD_CLI_COMMANDS,
|
|
15464
15832
|
...KEYS_CLI_COMMANDS,
|
|
15833
|
+
...USERS_CLI_COMMANDS,
|
|
15465
15834
|
...COMPETITOR_CLI_COMMANDS,
|
|
15466
15835
|
...SETTINGS_CLI_COMMANDS,
|
|
15467
15836
|
...SKILLS_CLI_COMMANDS,
|
|
@@ -15487,7 +15856,8 @@ var REGISTERED_CLI_COMMANDS = [
|
|
|
15487
15856
|
...TECHNICAL_AEO_CLI_COMMANDS,
|
|
15488
15857
|
...DOCTOR_CLI_COMMANDS,
|
|
15489
15858
|
...GET_CLI_COMMANDS,
|
|
15490
|
-
...MCP_CLI_COMMANDS
|
|
15859
|
+
...MCP_CLI_COMMANDS,
|
|
15860
|
+
...MEASUREMENT_PLAN_CLI_COMMANDS
|
|
15491
15861
|
];
|
|
15492
15862
|
|
|
15493
15863
|
// src/setup-nudge.ts
|