@ainyc/canonry 2.2.1 → 2.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -17,6 +17,7 @@ import {
17
17
  getConfigDir,
18
18
  getConfigPath,
19
19
  getOrCreateAnonymousId,
20
+ isEndpointMissing,
20
21
  isFirstRun,
21
22
  isTelemetryEnabled,
22
23
  listAgentProviders,
@@ -35,7 +36,7 @@ import {
35
36
  showFirstRunNotice,
36
37
  trackEvent,
37
38
  usageError
38
- } from "./chunk-2QNWFP6R.js";
39
+ } from "./chunk-JXOUZ6JH.js";
39
40
  import {
40
41
  apiKeys,
41
42
  competitors,
@@ -45,7 +46,7 @@ import {
45
46
  projects,
46
47
  querySnapshots,
47
48
  runs
48
- } from "./chunk-TAII35VC.js";
49
+ } from "./chunk-CW6CAPBQ.js";
49
50
 
50
51
  // src/cli.ts
51
52
  import { pathToFileURL } from "url";
@@ -292,7 +293,7 @@ async function backfillAnswerVisibilityCommand(opts) {
292
293
  console.log(` Errors: ${providerErrors}`);
293
294
  }
294
295
  async function backfillInsightsCommand(project, opts) {
295
- const { IntelligenceService } = await import("./intelligence-service-C5LAYDFM.js");
296
+ const { IntelligenceService } = await import("./intelligence-service-232P7625.js");
296
297
  const config = loadConfig();
297
298
  const db = createClient(config.database);
298
299
  migrate(db);
@@ -501,10 +502,308 @@ var BACKFILL_CLI_COMMANDS = [
501
502
  }
502
503
  ];
503
504
 
504
- // src/commands/bing.ts
505
+ // src/commands/backlinks.ts
505
506
  function getClient() {
506
507
  return createApiClient();
507
508
  }
509
+ function printJson(value) {
510
+ console.log(JSON.stringify(value, null, 2));
511
+ }
512
+ function formatInstallStatus(status) {
513
+ const lines = [];
514
+ lines.push(status.duckdbInstalled ? "DuckDB: installed" : "DuckDB: not installed");
515
+ if (status.duckdbVersion) lines.push(`Version: ${status.duckdbVersion}`);
516
+ lines.push(`Spec: ${status.duckdbSpec}`);
517
+ lines.push(`Plugin: ${status.pluginDir}`);
518
+ if (!status.duckdbInstalled) {
519
+ lines.push("");
520
+ lines.push("Run `canonry backlinks install` to enable backlinks.");
521
+ }
522
+ return lines.join("\n");
523
+ }
524
+ function formatSync(sync) {
525
+ const lines = [];
526
+ lines.push(`Release: ${sync.release}`);
527
+ lines.push(`Status: ${sync.status}`);
528
+ if (sync.phaseDetail) lines.push(`Phase: ${sync.phaseDetail}`);
529
+ if (typeof sync.projectsProcessed === "number") lines.push(`Projects: ${sync.projectsProcessed}`);
530
+ if (typeof sync.domainsDiscovered === "number") lines.push(`Domains: ${sync.domainsDiscovered}`);
531
+ if (sync.error) lines.push(`Error: ${sync.error}`);
532
+ return lines.join("\n");
533
+ }
534
+ function formatSummaryAndDomains(project, response) {
535
+ const lines = [];
536
+ lines.push(`Project: ${project}`);
537
+ if (!response.summary) {
538
+ lines.push("No ready release \u2014 run `canonry backlinks sync --release <id>` first.");
539
+ return lines.join("\n");
540
+ }
541
+ const s = response.summary;
542
+ lines.push(`Release: ${s.release}`);
543
+ lines.push(`Target: ${s.targetDomain}`);
544
+ lines.push(`Linking domains: ${s.totalLinkingDomains}`);
545
+ lines.push(`Total hosts: ${s.totalHosts}`);
546
+ lines.push(`Top-10 share: ${s.top10HostsShare}`);
547
+ if (response.rows.length > 0) {
548
+ lines.push("");
549
+ lines.push(`Top ${response.rows.length} linking domains (of ${response.total}):`);
550
+ for (const r of response.rows) {
551
+ lines.push(` ${String(r.numHosts).padStart(9)} ${r.linkingDomain}`);
552
+ }
553
+ }
554
+ return lines.join("\n");
555
+ }
556
+ function formatCachedReleases(rows) {
557
+ if (rows.length === 0) return "No cached releases.";
558
+ const lines = [];
559
+ lines.push("Release Status Bytes Last used");
560
+ for (const r of rows) {
561
+ const status = (r.syncStatus ?? "unknown").padEnd(12);
562
+ const bytes = String(r.bytes).padStart(12);
563
+ const lastUsed = r.lastUsedAt ?? "-";
564
+ lines.push(`${r.release.padEnd(30)} ${status} ${bytes} ${lastUsed}`);
565
+ }
566
+ return lines.join("\n");
567
+ }
568
+ function formatInstallResult(result) {
569
+ if (result.alreadyPresent) {
570
+ return `DuckDB already installed (${result.version}) at ${result.path}`;
571
+ }
572
+ return `DuckDB installed (${result.version}) at ${result.path}`;
573
+ }
574
+ async function pollSync(id, format) {
575
+ const client = getClient();
576
+ const terminal = /* @__PURE__ */ new Set(["ready", "failed"]);
577
+ while (true) {
578
+ const syncs = await client.backlinksListSyncs();
579
+ const row = syncs.find((s) => s.id === id);
580
+ if (!row) throw new Error(`Release sync ${id} not found`);
581
+ if (terminal.has(row.status)) return row;
582
+ if (format !== "json") {
583
+ process.stderr.write(`\r${row.status}${row.phaseDetail ? ": " + row.phaseDetail : ""}`.padEnd(80));
584
+ }
585
+ await new Promise((r) => setTimeout(r, 2e3));
586
+ }
587
+ }
588
+ async function pollRun(runId, format) {
589
+ const client = getClient();
590
+ const terminal = /* @__PURE__ */ new Set(["completed", "failed", "partial"]);
591
+ while (true) {
592
+ const run = await client.getRun(runId);
593
+ if (terminal.has(run.status)) return run;
594
+ if (format !== "json") {
595
+ process.stderr.write(`\r${run.status}`.padEnd(40));
596
+ }
597
+ await new Promise((r) => setTimeout(r, 2e3));
598
+ }
599
+ }
600
+ async function backlinksInstall(opts = {}) {
601
+ const result = await getClient().backlinksInstall();
602
+ if (opts.format === "json") {
603
+ printJson(result);
604
+ return;
605
+ }
606
+ console.log(formatInstallResult(result));
607
+ }
608
+ async function backlinksDoctor(opts = {}) {
609
+ const status = await getClient().backlinksStatus();
610
+ if (opts.format === "json") {
611
+ printJson(status);
612
+ return;
613
+ }
614
+ console.log(formatInstallStatus(status));
615
+ }
616
+ async function backlinksSync(opts) {
617
+ const client = getClient();
618
+ const sync = await client.backlinksTriggerSync(opts.release);
619
+ const final = opts.wait ? await pollSync(sync.id, opts.format) : sync;
620
+ if (opts.format === "json") {
621
+ printJson(final);
622
+ return;
623
+ }
624
+ if (opts.wait) process.stderr.write("\n");
625
+ console.log(formatSync(final));
626
+ }
627
+ async function backlinksStatus(opts = {}) {
628
+ const sync = await getClient().backlinksLatestSync();
629
+ if (opts.format === "json") {
630
+ printJson(sync);
631
+ return;
632
+ }
633
+ if (!sync) {
634
+ console.log("No release syncs yet.");
635
+ return;
636
+ }
637
+ console.log(formatSync(sync));
638
+ }
639
+ async function backlinksList(opts) {
640
+ const client = getClient();
641
+ const response = await client.backlinksDomains(opts.project, {
642
+ limit: opts.limit ?? 50,
643
+ release: opts.release
644
+ });
645
+ if (opts.format === "json") {
646
+ printJson(response);
647
+ return;
648
+ }
649
+ console.log(formatSummaryAndDomains(opts.project, response));
650
+ }
651
+ async function backlinksReleases(opts = {}) {
652
+ const rows = await getClient().backlinksCachedReleases();
653
+ if (opts.format === "json") {
654
+ printJson(rows);
655
+ return;
656
+ }
657
+ console.log(formatCachedReleases(rows));
658
+ }
659
+ async function backlinksExtract(opts) {
660
+ const client = getClient();
661
+ const run = await client.backlinksExtract(opts.project, opts.release);
662
+ const final = opts.wait ? await pollRun(run.id, opts.format) : run;
663
+ if (opts.format === "json") {
664
+ printJson(final);
665
+ return;
666
+ }
667
+ if (opts.wait) process.stderr.write("\n");
668
+ console.log(`Run ${final.id} (${final.status})${final.error ? " \u2014 " + final.error : ""}`);
669
+ }
670
+ async function backlinksCachePrune(opts) {
671
+ if (!opts.release) {
672
+ throw new Error("Usage: canonry backlinks cache prune --release <id>");
673
+ }
674
+ const result = await getClient().backlinksPruneCache(opts.release);
675
+ if (opts.format === "json") {
676
+ printJson({ pruned: opts.release, ...result });
677
+ return;
678
+ }
679
+ console.log(`Pruned cache for ${opts.release}`);
680
+ }
681
+
682
+ // src/cli-commands/backlinks.ts
683
+ var BACKLINKS_CLI_COMMANDS = [
684
+ {
685
+ path: ["backlinks", "install"],
686
+ usage: "canonry backlinks install [--format json]",
687
+ options: {},
688
+ run: async (input) => {
689
+ await backlinksInstall({ format: input.format });
690
+ }
691
+ },
692
+ {
693
+ path: ["backlinks", "doctor"],
694
+ usage: "canonry backlinks doctor [--format json]",
695
+ options: {},
696
+ run: async (input) => {
697
+ await backlinksDoctor({ format: input.format });
698
+ }
699
+ },
700
+ {
701
+ path: ["backlinks", "sync"],
702
+ usage: "canonry backlinks sync --release <id> [--wait] [--format json]",
703
+ options: {
704
+ release: stringOption(),
705
+ wait: { type: "boolean" }
706
+ },
707
+ run: async (input) => {
708
+ const release = requireStringOption(input, "release", {
709
+ message: "--release is required",
710
+ usage: "canonry backlinks sync --release <id> [--wait]",
711
+ command: "backlinks sync"
712
+ });
713
+ await backlinksSync({
714
+ release,
715
+ wait: getBoolean(input.values, "wait"),
716
+ format: input.format
717
+ });
718
+ }
719
+ },
720
+ {
721
+ path: ["backlinks", "status"],
722
+ usage: "canonry backlinks status [--format json]",
723
+ options: {},
724
+ run: async (input) => {
725
+ await backlinksStatus({ format: input.format });
726
+ }
727
+ },
728
+ {
729
+ path: ["backlinks", "list"],
730
+ usage: "canonry backlinks list <project> [--limit <n>] [--release <id>] [--format json]",
731
+ options: {
732
+ limit: stringOption(),
733
+ release: stringOption()
734
+ },
735
+ run: async (input) => {
736
+ const project = requireProject(
737
+ input,
738
+ "backlinks list",
739
+ "canonry backlinks list <project> [--limit <n>] [--release <id>]"
740
+ );
741
+ const limit = parseIntegerOption(input, "limit", {
742
+ message: "--limit must be an integer",
743
+ usage: "canonry backlinks list <project> --limit <n>",
744
+ command: "backlinks list"
745
+ });
746
+ await backlinksList({
747
+ project,
748
+ limit,
749
+ release: getString(input.values, "release"),
750
+ format: input.format
751
+ });
752
+ }
753
+ },
754
+ {
755
+ path: ["backlinks", "releases"],
756
+ usage: "canonry backlinks releases [--format json]",
757
+ options: {},
758
+ run: async (input) => {
759
+ await backlinksReleases({ format: input.format });
760
+ }
761
+ },
762
+ {
763
+ path: ["backlinks", "extract"],
764
+ usage: "canonry backlinks extract <project> [--release <id>] [--wait] [--format json]",
765
+ options: {
766
+ release: stringOption(),
767
+ wait: { type: "boolean" }
768
+ },
769
+ run: async (input) => {
770
+ const project = requireProject(
771
+ input,
772
+ "backlinks extract",
773
+ "canonry backlinks extract <project> [--release <id>] [--wait]"
774
+ );
775
+ await backlinksExtract({
776
+ project,
777
+ release: getString(input.values, "release"),
778
+ wait: getBoolean(input.values, "wait"),
779
+ format: input.format
780
+ });
781
+ }
782
+ },
783
+ {
784
+ path: ["backlinks", "cache", "prune"],
785
+ usage: "canonry backlinks cache prune --release <id> [--format json]",
786
+ options: {
787
+ release: stringOption()
788
+ },
789
+ run: async (input) => {
790
+ const release = requireStringOption(input, "release", {
791
+ message: "--release is required",
792
+ usage: "canonry backlinks cache prune --release <id>",
793
+ command: "backlinks cache prune"
794
+ });
795
+ await backlinksCachePrune({
796
+ release,
797
+ format: input.format
798
+ });
799
+ }
800
+ }
801
+ ];
802
+
803
+ // src/commands/bing.ts
804
+ function getClient2() {
805
+ return createApiClient();
806
+ }
508
807
  async function bingConnect(project, opts) {
509
808
  const apiKey = opts?.apiKey;
510
809
  if (!apiKey) {
@@ -517,7 +816,7 @@ async function bingConnect(project, opts) {
517
816
  }
518
817
  });
519
818
  }
520
- const client = getClient();
819
+ const client = getClient2();
521
820
  const result = await client.bingConnect(project, { apiKey });
522
821
  if (opts?.format === "json") {
523
822
  console.log(JSON.stringify(result, null, 2));
@@ -538,7 +837,7 @@ Set the active site with: canonry bing set-site ${project} <url>`);
538
837
  }
539
838
  }
540
839
  async function bingDisconnect(project, format) {
541
- const client = getClient();
840
+ const client = getClient2();
542
841
  await client.bingDisconnect(project);
543
842
  if (format === "json") {
544
843
  console.log(JSON.stringify({ project, disconnected: true }, null, 2));
@@ -547,7 +846,7 @@ async function bingDisconnect(project, format) {
547
846
  console.log(`Bing Webmaster Tools disconnected from project "${project}".`);
548
847
  }
549
848
  async function bingStatus(project, format) {
550
- const client = getClient();
849
+ const client = getClient2();
551
850
  const result = await client.bingStatus(project);
552
851
  if (format === "json") {
553
852
  console.log(JSON.stringify(result, null, 2));
@@ -565,7 +864,7 @@ async function bingStatus(project, format) {
565
864
  console.log(` Updated: ${result.updatedAt}`);
566
865
  }
567
866
  async function bingSites(project, format) {
568
- const client = getClient();
867
+ const client = getClient2();
569
868
  const result = await client.bingSites(project);
570
869
  if (format === "json") {
571
870
  console.log(JSON.stringify(result, null, 2));
@@ -587,7 +886,7 @@ async function bingSites(project, format) {
587
886
  Use "canonry bing set-site <project> <url>" to select a site.`);
588
887
  }
589
888
  async function bingSetSite(project, siteUrl, format) {
590
- const client = getClient();
889
+ const client = getClient2();
591
890
  await client.bingSetSite(project, siteUrl);
592
891
  if (format === "json") {
593
892
  console.log(JSON.stringify({ project, siteUrl }, null, 2));
@@ -596,7 +895,7 @@ async function bingSetSite(project, siteUrl, format) {
596
895
  console.log(`Bing site set to "${siteUrl}" for project "${project}".`);
597
896
  }
598
897
  async function bingCoverage(project, format) {
599
- const client = getClient();
898
+ const client = getClient2();
600
899
  const result = await client.bingCoverage(project);
601
900
  if (format === "json") {
602
901
  console.log(JSON.stringify(result, null, 2));
@@ -644,7 +943,7 @@ Bing Index Coverage for "${project}"
644
943
  }
645
944
  }
646
945
  async function bingCoverageHistory(project, opts) {
647
- const client = getClient();
946
+ const client = getClient2();
648
947
  const rows = await client.bingCoverageHistory(project, { limit: opts.limit });
649
948
  if (opts.format === "json") {
650
949
  console.log(JSON.stringify(rows, null, 2));
@@ -664,7 +963,7 @@ Bing Coverage History for "${project}" (${rows.length} snapshots):
664
963
  }
665
964
  }
666
965
  async function bingInspect(project, url, format) {
667
- const client = getClient();
966
+ const client = getClient2();
668
967
  const result = await client.bingInspectUrl(project, url);
669
968
  if (format === "json") {
670
969
  console.log(JSON.stringify(result, null, 2));
@@ -683,7 +982,7 @@ Bing URL Inspection: ${result.url}
683
982
  console.log(` Inspected At: ${result.inspectedAt}`);
684
983
  }
685
984
  async function bingInspections(project, opts) {
686
- const client = getClient();
985
+ const client = getClient2();
687
986
  const params = {};
688
987
  if (opts.url) params.url = opts.url;
689
988
  const rows = await client.bingInspections(project, Object.keys(params).length > 0 ? params : void 0);
@@ -709,7 +1008,7 @@ async function bingInspections(project, opts) {
709
1008
  }
710
1009
  }
711
1010
  async function bingRefresh(project, format) {
712
- const client = getClient();
1011
+ const client = getClient2();
713
1012
  const rows = await client.bingInspections(project);
714
1013
  const uniqueUrls = [...new Set(rows.map((r) => r.url))];
715
1014
  if (uniqueUrls.length === 0) {
@@ -749,7 +1048,7 @@ async function bingRefresh(project, format) {
749
1048
  await bingCoverage(project, format);
750
1049
  }
751
1050
  async function bingRequestIndexing(project, opts) {
752
- const client = getClient();
1051
+ const client = getClient2();
753
1052
  const body = {};
754
1053
  if (opts.allUnindexed) {
755
1054
  body.allUnindexed = true;
@@ -784,7 +1083,7 @@ async function bingRequestIndexing(project, opts) {
784
1083
  }
785
1084
  }
786
1085
  async function bingPerformance(project, format) {
787
- const client = getClient();
1086
+ const client = getClient2();
788
1087
  const rows = await client.bingPerformance(project);
789
1088
  if (format === "json") {
790
1089
  console.log(JSON.stringify(rows, null, 2));
@@ -970,7 +1269,7 @@ var BING_CLI_COMMANDS = [
970
1269
  ];
971
1270
 
972
1271
  // src/commands/cdp.ts
973
- function getClient2() {
1272
+ function getClient3() {
974
1273
  return createApiClient();
975
1274
  }
976
1275
  async function cdpConnect(opts) {
@@ -996,7 +1295,7 @@ async function cdpConnect(opts) {
996
1295
  console.log("Restart canonry server for changes to take effect.");
997
1296
  }
998
1297
  async function cdpStatus(format) {
999
- const client = getClient2();
1298
+ const client = getClient3();
1000
1299
  try {
1001
1300
  const status = await client.getCdpStatus();
1002
1301
  if (format === "json") {
@@ -1054,7 +1353,7 @@ async function cdpScreenshot(query, opts) {
1054
1353
  }
1055
1354
  });
1056
1355
  }
1057
- const client = getClient2();
1356
+ const client = getClient3();
1058
1357
  const body = { query };
1059
1358
  if (opts?.targets) {
1060
1359
  body.targets = opts.targets.split(",").map((s) => s.trim());
@@ -1161,7 +1460,7 @@ var CDP_CLI_COMMANDS = [
1161
1460
  ];
1162
1461
 
1163
1462
  // src/commands/ga.ts
1164
- function getClient3() {
1463
+ function getClient4() {
1165
1464
  return createApiClient();
1166
1465
  }
1167
1466
  async function gaConnect(project, opts) {
@@ -1194,7 +1493,7 @@ async function gaConnect(project, opts) {
1194
1493
  } else if (opts.keyJson) {
1195
1494
  body.keyJson = opts.keyJson;
1196
1495
  }
1197
- const client = getClient3();
1496
+ const client = getClient4();
1198
1497
  const result = await client.gaConnect(project, body);
1199
1498
  if (opts.format === "json") {
1200
1499
  console.log(JSON.stringify(result, null, 2));
@@ -1209,7 +1508,7 @@ async function gaConnect(project, opts) {
1209
1508
  }
1210
1509
  }
1211
1510
  async function gaDisconnect(project, format) {
1212
- const client = getClient3();
1511
+ const client = getClient4();
1213
1512
  await client.gaDisconnect(project);
1214
1513
  if (format === "json") {
1215
1514
  console.log(JSON.stringify({ project, disconnected: true }, null, 2));
@@ -1218,7 +1517,7 @@ async function gaDisconnect(project, format) {
1218
1517
  console.log(`GA4 disconnected from project "${project}".`);
1219
1518
  }
1220
1519
  async function gaStatus(project, format) {
1221
- const client = getClient3();
1520
+ const client = getClient4();
1222
1521
  const result = await client.gaStatus(project);
1223
1522
  if (format === "json") {
1224
1523
  console.log(JSON.stringify(result, null, 2));
@@ -1244,7 +1543,7 @@ async function gaStatus(project, format) {
1244
1543
  console.log(` Connected: ${result.createdAt ?? "unknown"}`);
1245
1544
  }
1246
1545
  async function gaSync(project, opts) {
1247
- const client = getClient3();
1546
+ const client = getClient4();
1248
1547
  const body = {};
1249
1548
  if (opts?.days) body.days = opts.days;
1250
1549
  if (opts?.only) body.only = opts.only;
@@ -1264,7 +1563,7 @@ async function gaSync(project, opts) {
1264
1563
  console.log(` Synced at: ${result.syncedAt}`);
1265
1564
  }
1266
1565
  async function gaTraffic(project, opts) {
1267
- const client = getClient3();
1566
+ const client = getClient4();
1268
1567
  const params = {};
1269
1568
  if (opts?.limit) params.limit = String(opts.limit);
1270
1569
  if (opts?.window) params.window = opts.window;
@@ -1339,7 +1638,7 @@ async function gaTraffic(project, opts) {
1339
1638
  }
1340
1639
  }
1341
1640
  async function gaAiReferralHistory(project, opts) {
1342
- const client = getClient3();
1641
+ const client = getClient4();
1343
1642
  const result = await client.gaAiReferralHistory(project, opts?.window ? { window: opts.window } : void 0);
1344
1643
  if (opts?.format === "json") {
1345
1644
  console.log(JSON.stringify(result, null, 2));
@@ -1364,7 +1663,7 @@ async function gaAiReferralHistory(project, opts) {
1364
1663
  }
1365
1664
  }
1366
1665
  async function gaSocialReferralHistory(project, opts) {
1367
- const client = getClient3();
1666
+ const client = getClient4();
1368
1667
  const result = await client.gaSocialReferralHistory(project, opts?.window ? { window: opts.window } : void 0);
1369
1668
  if (opts?.format === "json") {
1370
1669
  console.log(JSON.stringify(result, null, 2));
@@ -1389,7 +1688,7 @@ async function gaSocialReferralHistory(project, opts) {
1389
1688
  }
1390
1689
  }
1391
1690
  async function gaSessionHistory(project, opts) {
1392
- const client = getClient3();
1691
+ const client = getClient4();
1393
1692
  const result = await client.gaSessionHistory(project, opts?.window ? { window: opts.window } : void 0);
1394
1693
  if (opts?.format === "json") {
1395
1694
  console.log(JSON.stringify(result, null, 2));
@@ -1411,7 +1710,7 @@ async function gaSessionHistory(project, opts) {
1411
1710
  }
1412
1711
  }
1413
1712
  async function gaCoverage(project, format) {
1414
- const client = getClient3();
1713
+ const client = getClient4();
1415
1714
  const result = await client.gaCoverage(project);
1416
1715
  if (format === "json") {
1417
1716
  console.log(JSON.stringify(result, null, 2));
@@ -1434,7 +1733,7 @@ async function gaCoverage(project, format) {
1434
1733
  }
1435
1734
  }
1436
1735
  async function gaSocialReferralSummary(project, opts) {
1437
- const client = getClient3();
1736
+ const client = getClient4();
1438
1737
  const traffic = await client.gaTraffic(project);
1439
1738
  if (opts?.trend) {
1440
1739
  const trend = await client.gaSocialReferralTrend(project);
@@ -1495,7 +1794,7 @@ async function gaSocialReferralSummary(project, opts) {
1495
1794
  }
1496
1795
  }
1497
1796
  async function gaAttribution(project, opts) {
1498
- const client = getClient3();
1797
+ const client = getClient4();
1499
1798
  const traffic = await client.gaTraffic(project);
1500
1799
  const fmtTrend = (pct) => pct === null ? "n/a" : `${pct >= 0 ? "+" : ""}${pct}%`;
1501
1800
  if (opts?.trend) {
@@ -1788,11 +2087,11 @@ var GA_CLI_COMMANDS = [
1788
2087
  ];
1789
2088
 
1790
2089
  // src/commands/competitor.ts
1791
- function getClient4() {
2090
+ function getClient5() {
1792
2091
  return createApiClient();
1793
2092
  }
1794
2093
  async function addCompetitors(project, domains, format) {
1795
- const client = getClient4();
2094
+ const client = getClient5();
1796
2095
  const existing = await client.listCompetitors(project);
1797
2096
  const existingDomains = existing.map((c) => c.domain);
1798
2097
  const addedDomains = domains.filter((domain) => !existingDomains.includes(domain));
@@ -1814,7 +2113,7 @@ async function addCompetitors(project, domains, format) {
1814
2113
  }
1815
2114
  }
1816
2115
  async function listCompetitors(project, format) {
1817
- const client = getClient4();
2116
+ const client = getClient5();
1818
2117
  const comps = await client.listCompetitors(project);
1819
2118
  if (format === "json") {
1820
2119
  console.log(JSON.stringify(comps, null, 2));
@@ -1873,7 +2172,7 @@ var COMPETITOR_CLI_COMMANDS = [
1873
2172
  ];
1874
2173
 
1875
2174
  // src/commands/google.ts
1876
- function getClient5() {
2175
+ function getClient6() {
1877
2176
  return createApiClient();
1878
2177
  }
1879
2178
  async function waitForRunStatus(client, runId, config) {
@@ -1913,7 +2212,7 @@ async function waitForRunStatus(client, runId, config) {
1913
2212
  });
1914
2213
  }
1915
2214
  async function googleConnect(project, opts) {
1916
- const client = getClient5();
2215
+ const client = getClient6();
1917
2216
  const { authUrl, redirectUri } = await client.googleConnect(project, {
1918
2217
  type: opts.type,
1919
2218
  publicUrl: opts.publicUrl
@@ -1947,7 +2246,7 @@ Open this URL in your browser to authorize Google ${opts.type.toUpperCase()} acc
1947
2246
  }
1948
2247
  }
1949
2248
  async function googleDisconnect(project, opts) {
1950
- const client = getClient5();
2249
+ const client = getClient6();
1951
2250
  await client.googleDisconnect(project, opts.type);
1952
2251
  if (opts.format === "json") {
1953
2252
  console.log(JSON.stringify({ project, type: opts.type, disconnected: true }, null, 2));
@@ -1956,7 +2255,7 @@ async function googleDisconnect(project, opts) {
1956
2255
  console.log(`Disconnected Google ${opts.type.toUpperCase()} from project "${project}".`);
1957
2256
  }
1958
2257
  async function googleStatus(project, format) {
1959
- const client = getClient5();
2258
+ const client = getClient6();
1960
2259
  const connections = await client.googleConnections(project);
1961
2260
  if (format === "json") {
1962
2261
  console.log(JSON.stringify({ connections }, null, 2));
@@ -1980,7 +2279,7 @@ async function googleStatus(project, format) {
1980
2279
  }
1981
2280
  }
1982
2281
  async function googleProperties(project, format) {
1983
- const client = getClient5();
2282
+ const client = getClient6();
1984
2283
  const { sites } = await client.googleProperties(project);
1985
2284
  if (format === "json") {
1986
2285
  console.log(JSON.stringify({ sites }, null, 2));
@@ -2001,7 +2300,7 @@ async function googleProperties(project, format) {
2001
2300
  Use "canonry google set-property <project> <siteUrl>" to select a property.`);
2002
2301
  }
2003
2302
  async function googleSetProperty(project, propertyUrl, format) {
2004
- const client = getClient5();
2303
+ const client = getClient6();
2005
2304
  await client.googleSetProperty(project, "gsc", propertyUrl);
2006
2305
  if (format === "json") {
2007
2306
  console.log(JSON.stringify({ project, type: "gsc", propertyUrl }, null, 2));
@@ -2010,7 +2309,7 @@ async function googleSetProperty(project, propertyUrl, format) {
2010
2309
  console.log(`GSC property set to "${propertyUrl}" for project "${project}".`);
2011
2310
  }
2012
2311
  async function googleSync(project, opts) {
2013
- const client = getClient5();
2312
+ const client = getClient6();
2014
2313
  const run = await client.gscSync(project, { days: opts.days, full: opts.full });
2015
2314
  if (!opts.wait && opts.format === "json") {
2016
2315
  console.log(JSON.stringify(run, null, 2));
@@ -2040,7 +2339,7 @@ async function googleSync(project, opts) {
2040
2339
  }
2041
2340
  }
2042
2341
  async function googlePerformance(project, opts) {
2043
- const client = getClient5();
2342
+ const client = getClient6();
2044
2343
  const params = {};
2045
2344
  if (opts.days) {
2046
2345
  const end = /* @__PURE__ */ new Date();
@@ -2076,7 +2375,7 @@ async function googlePerformance(project, opts) {
2076
2375
  }
2077
2376
  }
2078
2377
  async function googleInspect(project, url, format) {
2079
- const client = getClient5();
2378
+ const client = getClient6();
2080
2379
  const result = await client.gscInspect(project, url);
2081
2380
  if (format === "json") {
2082
2381
  console.log(JSON.stringify(result, null, 2));
@@ -2096,7 +2395,7 @@ URL Inspection: ${result.url}
2096
2395
  console.log(` Inspected At: ${result.inspectedAt}`);
2097
2396
  }
2098
2397
  async function googleInspections(project, opts) {
2099
- const client = getClient5();
2398
+ const client = getClient6();
2100
2399
  const params = {};
2101
2400
  if (opts.url) params.url = opts.url;
2102
2401
  const rows = await client.gscInspections(project, Object.keys(params).length > 0 ? params : void 0);
@@ -2121,7 +2420,7 @@ async function googleInspections(project, opts) {
2121
2420
  }
2122
2421
  }
2123
2422
  async function googleCoverage(project, format) {
2124
- const client = getClient5();
2423
+ const client = getClient6();
2125
2424
  const result = await client.gscCoverage(project);
2126
2425
  if (format === "json") {
2127
2426
  console.log(JSON.stringify(result, null, 2));
@@ -2167,7 +2466,7 @@ Index Coverage for "${project}"
2167
2466
  }
2168
2467
  }
2169
2468
  async function googleSetSitemap(project, sitemapUrl, format) {
2170
- const client = getClient5();
2469
+ const client = getClient6();
2171
2470
  await client.googleSetSitemap(project, "gsc", sitemapUrl);
2172
2471
  if (format === "json") {
2173
2472
  console.log(JSON.stringify({ project, type: "gsc", sitemapUrl }, null, 2));
@@ -2176,7 +2475,7 @@ async function googleSetSitemap(project, sitemapUrl, format) {
2176
2475
  console.log(`GSC sitemap URL set to "${sitemapUrl}" for project "${project}".`);
2177
2476
  }
2178
2477
  async function googleListSitemaps(project, opts) {
2179
- const client = getClient5();
2478
+ const client = getClient6();
2180
2479
  const result = await client.gscSitemaps(project);
2181
2480
  if (opts.format === "json") {
2182
2481
  console.log(JSON.stringify(result, null, 2));
@@ -2198,7 +2497,7 @@ Sitemaps for project "${project}":
2198
2497
  }
2199
2498
  }
2200
2499
  async function googleInspectSitemap(project, opts) {
2201
- const client = getClient5();
2500
+ const client = getClient6();
2202
2501
  const run = await client.gscInspectSitemap(project, {
2203
2502
  sitemapUrl: opts.sitemapUrl
2204
2503
  });
@@ -2234,7 +2533,7 @@ async function googleInspectSitemap(project, opts) {
2234
2533
  }
2235
2534
  }
2236
2535
  async function googleCoverageHistory(project, opts) {
2237
- const client = getClient5();
2536
+ const client = getClient6();
2238
2537
  const rows = await client.gscCoverageHistory(project, { limit: opts.limit });
2239
2538
  if (opts.format === "json") {
2240
2539
  console.log(JSON.stringify(rows, null, 2));
@@ -2256,7 +2555,7 @@ GSC Coverage History for "${project}" (${rows.length} snapshots):
2256
2555
  }
2257
2556
  }
2258
2557
  async function googleDiscoverSitemaps(project, opts) {
2259
- const client = getClient5();
2558
+ const client = getClient6();
2260
2559
  const result = await client.gscDiscoverSitemaps(project);
2261
2560
  if (!opts.wait && opts.format === "json") {
2262
2561
  console.log(JSON.stringify(result, null, 2));
@@ -2308,7 +2607,7 @@ Primary sitemap: ${result.primarySitemapUrl}`);
2308
2607
  }
2309
2608
  }
2310
2609
  async function googleRequestIndexing(project, opts) {
2311
- const client = getClient5();
2610
+ const client = getClient6();
2312
2611
  const body = { urls: [] };
2313
2612
  if (opts.allUnindexed) {
2314
2613
  body.allUnindexed = true;
@@ -2388,7 +2687,7 @@ async function googleRequestIndexing(project, opts) {
2388
2687
  }
2389
2688
  }
2390
2689
  async function googleRefresh(project, format) {
2391
- const client = getClient5();
2690
+ const client = getClient6();
2392
2691
  const run = await client.gscSync(project, {});
2393
2692
  if (format !== "json") {
2394
2693
  process.stderr.write("Refreshing GSC coverage data");
@@ -2411,7 +2710,7 @@ async function googleRefresh(project, format) {
2411
2710
  await googleCoverage(project, format);
2412
2711
  }
2413
2712
  async function googleDeindexed(project, format) {
2414
- const client = getClient5();
2713
+ const client = getClient6();
2415
2714
  const rows = await client.gscDeindexed(project);
2416
2715
  if (format === "json") {
2417
2716
  console.log(JSON.stringify(rows, null, 2));
@@ -2700,11 +2999,11 @@ var GOOGLE_CLI_COMMANDS = [
2700
2999
 
2701
3000
  // src/commands/keyword.ts
2702
3001
  import fs from "fs";
2703
- function getClient6() {
3002
+ function getClient7() {
2704
3003
  return createApiClient();
2705
3004
  }
2706
3005
  async function addKeywords(project, keywords, format) {
2707
- const client = getClient6();
3006
+ const client = getClient7();
2708
3007
  await client.appendKeywords(project, keywords);
2709
3008
  if (format === "json") {
2710
3009
  console.log(JSON.stringify({
@@ -2717,7 +3016,7 @@ async function addKeywords(project, keywords, format) {
2717
3016
  console.log(`Added ${keywords.length} key phrase(s) to "${project}".`);
2718
3017
  }
2719
3018
  async function removeKeywords(project, keywords, format) {
2720
- const client = getClient6();
3019
+ const client = getClient7();
2721
3020
  const existing = await client.listKeywords(project);
2722
3021
  const existingSet = new Set(existing.map((k) => k.keyword));
2723
3022
  const removedKeywords = keywords.filter((k) => existingSet.has(k));
@@ -2734,7 +3033,7 @@ async function removeKeywords(project, keywords, format) {
2734
3033
  console.log(`Removed ${removedKeywords.length} key phrase(s) from "${project}".`);
2735
3034
  }
2736
3035
  async function listKeywords(project, format) {
2737
- const client = getClient6();
3036
+ const client = getClient7();
2738
3037
  const kws = await client.listKeywords(project);
2739
3038
  if (format === "json") {
2740
3039
  console.log(JSON.stringify(kws, null, 2));
@@ -2777,7 +3076,7 @@ async function importKeywords(project, filePath, format) {
2777
3076
  console.log("No key phrases found in file.");
2778
3077
  return;
2779
3078
  }
2780
- const client = getClient6();
3079
+ const client = getClient7();
2781
3080
  await client.appendKeywords(project, keywords);
2782
3081
  if (format === "json") {
2783
3082
  console.log(JSON.stringify({
@@ -2791,7 +3090,7 @@ async function importKeywords(project, filePath, format) {
2791
3090
  console.log(`Imported ${keywords.length} key phrase(s) to "${project}".`);
2792
3091
  }
2793
3092
  async function generateKeywords(project, provider, opts) {
2794
- const client = getClient6();
3093
+ const client = getClient7();
2795
3094
  const result = await client.generateKeywords(project, provider, opts.count);
2796
3095
  const saved = Boolean(opts.save && result.keywords.length > 0);
2797
3096
  if (opts.format !== "json") {
@@ -2945,11 +3244,11 @@ var KEYWORD_CLI_COMMANDS = [
2945
3244
  ];
2946
3245
 
2947
3246
  // src/commands/notify.ts
2948
- function getClient7() {
3247
+ function getClient8() {
2949
3248
  return createApiClient();
2950
3249
  }
2951
3250
  async function addNotification(project, opts) {
2952
- const client = getClient7();
3251
+ const client = getClient8();
2953
3252
  const result = await client.createNotification(project, {
2954
3253
  channel: "webhook",
2955
3254
  url: opts.webhook,
@@ -2963,7 +3262,7 @@ async function addNotification(project, opts) {
2963
3262
  printNotification(result);
2964
3263
  }
2965
3264
  async function listNotifications(project, format) {
2966
- const client = getClient7();
3265
+ const client = getClient8();
2967
3266
  const results = await client.listNotifications(project);
2968
3267
  if (format === "json") {
2969
3268
  console.log(JSON.stringify(results, null, 2));
@@ -2981,7 +3280,7 @@ async function listNotifications(project, format) {
2981
3280
  }
2982
3281
  }
2983
3282
  async function removeNotification(project, id, format) {
2984
- const client = getClient7();
3283
+ const client = getClient8();
2985
3284
  await client.deleteNotification(project, id);
2986
3285
  if (format === "json") {
2987
3286
  console.log(JSON.stringify({ project, id, removed: true }, null, 2));
@@ -2990,7 +3289,7 @@ async function removeNotification(project, id, format) {
2990
3289
  console.log(`Notification ${id} removed from "${project}"`);
2991
3290
  }
2992
3291
  async function testNotification(project, id, format) {
2993
- const client = getClient7();
3292
+ const client = getClient8();
2994
3293
  const result = await client.testNotification(project, id);
2995
3294
  if (format === "json") {
2996
3295
  console.log(JSON.stringify({ project, id, ...result }, null, 2));
@@ -3181,11 +3480,11 @@ async function applyConfigs(filePaths, format) {
3181
3480
  }
3182
3481
 
3183
3482
  // src/commands/analytics.ts
3184
- function getClient8() {
3483
+ function getClient9() {
3185
3484
  return createApiClient();
3186
3485
  }
3187
3486
  async function showAnalytics(project, options) {
3188
- const client = getClient8();
3487
+ const client = getClient9();
3189
3488
  const features = options.feature ? [options.feature] : ["metrics", "gaps", "sources"];
3190
3489
  const results = {};
3191
3490
  for (const feature of features) {
@@ -3288,11 +3587,11 @@ Source Origin Breakdown`);
3288
3587
  }
3289
3588
 
3290
3589
  // src/commands/evidence.ts
3291
- function getClient9() {
3590
+ function getClient10() {
3292
3591
  return createApiClient();
3293
3592
  }
3294
3593
  async function showEvidence(project, format) {
3295
- const client = getClient9();
3594
+ const client = getClient10();
3296
3595
  const timeline = await client.getTimeline(project);
3297
3596
  if (format === "json") {
3298
3597
  const enriched = timeline.map((entry) => ({
@@ -3327,14 +3626,8 @@ async function exportProject(project, opts) {
3327
3626
  const client = createApiClient();
3328
3627
  const data = await client.getExport(project);
3329
3628
  if (opts.includeResults) {
3330
- try {
3331
- const runs2 = await client.listRuns(project);
3332
- if (runs2.length > 0) {
3333
- const latestRun = await client.getRun(runs2[runs2.length - 1].id);
3334
- data.results = latestRun;
3335
- }
3336
- } catch {
3337
- }
3629
+ const results = await loadLatestRunForExport(client, project);
3630
+ if (results) data.results = results;
3338
3631
  }
3339
3632
  if (opts.format === "json") {
3340
3633
  console.log(JSON.stringify(data, null, 2));
@@ -3342,13 +3635,27 @@ async function exportProject(project, opts) {
3342
3635
  }
3343
3636
  console.log(stringify(data));
3344
3637
  }
3638
+ async function loadLatestRunForExport(client, project) {
3639
+ try {
3640
+ const latest = await client.getLatestRun(project);
3641
+ return latest.run ?? null;
3642
+ } catch (err) {
3643
+ if (!isEndpointMissing(err)) throw err;
3644
+ }
3645
+ const runs2 = await client.listRuns(project);
3646
+ if (runs2.length === 0) return null;
3647
+ const latestRun = runs2.reduce(
3648
+ (current, candidate) => candidate.createdAt > current.createdAt ? candidate : current
3649
+ );
3650
+ return client.getRun(latestRun.id);
3651
+ }
3345
3652
 
3346
3653
  // src/commands/history.ts
3347
- function getClient10() {
3654
+ function getClient11() {
3348
3655
  return createApiClient();
3349
3656
  }
3350
3657
  async function showHistory(project, format) {
3351
- const client = getClient10();
3658
+ const client = getClient11();
3352
3659
  try {
3353
3660
  const entries = await client.getHistory(project);
3354
3661
  if (format === "json") {
@@ -3383,19 +3690,25 @@ async function showHistory(project, format) {
3383
3690
  }
3384
3691
 
3385
3692
  // src/commands/status.ts
3386
- function getClient11() {
3693
+ function getClient12() {
3387
3694
  return createApiClient();
3388
3695
  }
3389
3696
  async function showStatus(project, format) {
3390
- const client = getClient11();
3697
+ const client = getClient12();
3391
3698
  const projectData = await client.getProject(project);
3392
- let runs2 = [];
3393
- try {
3394
- runs2 = await client.listRuns(project);
3395
- } catch {
3396
- }
3699
+ const latest = await getLatestRunSummary(client, project);
3397
3700
  if (format === "json") {
3398
- console.log(JSON.stringify({ project: projectData, runs: runs2 }, null, 2));
3701
+ let runs2 = [];
3702
+ try {
3703
+ runs2 = await client.listRuns(project);
3704
+ } catch {
3705
+ }
3706
+ console.log(JSON.stringify({
3707
+ project: projectData,
3708
+ runs: runs2,
3709
+ latestRun: latest.run,
3710
+ totalRuns: latest.totalRuns
3711
+ }, null, 2));
3399
3712
  return;
3400
3713
  }
3401
3714
  console.log(`Status: ${projectData.displayName ?? projectData.name} (${projectData.name})
@@ -3403,24 +3716,39 @@ async function showStatus(project, format) {
3403
3716
  console.log(` Domain: ${projectData.canonicalDomain}`);
3404
3717
  console.log(` Country: ${projectData.country}`);
3405
3718
  console.log(` Language: ${projectData.language}`);
3406
- if (runs2.length > 0) {
3407
- const latest = runs2.reduce(
3408
- (current, candidate) => candidate.createdAt > current.createdAt ? candidate : current
3409
- );
3719
+ if (latest.run) {
3410
3720
  console.log(`
3411
3721
  Latest run:`);
3412
- console.log(` ID: ${latest.id}`);
3413
- console.log(` Status: ${latest.status}`);
3414
- console.log(` Created: ${latest.createdAt}`);
3415
- if (latest.finishedAt) {
3416
- console.log(` Finished: ${latest.finishedAt}`);
3722
+ console.log(` ID: ${latest.run.id}`);
3723
+ console.log(` Status: ${latest.run.status}`);
3724
+ console.log(` Created: ${latest.run.createdAt}`);
3725
+ if (latest.run.finishedAt) {
3726
+ console.log(` Finished: ${latest.run.finishedAt}`);
3417
3727
  }
3418
3728
  console.log(`
3419
- Total runs: ${runs2.length}`);
3729
+ Total runs: ${latest.totalRuns}`);
3420
3730
  } else {
3421
3731
  console.log('\n No runs yet. Use "canonry run" to trigger one.');
3422
3732
  }
3423
3733
  }
3734
+ async function getLatestRunSummary(client, project) {
3735
+ try {
3736
+ return await client.getLatestRun(project);
3737
+ } catch (err) {
3738
+ if (!isEndpointMissing(err)) throw err;
3739
+ const runs2 = await client.listRuns(project);
3740
+ if (runs2.length === 0) {
3741
+ return { totalRuns: 0, run: null };
3742
+ }
3743
+ const latestRun = runs2.reduce(
3744
+ (current, candidate) => candidate.createdAt > current.createdAt ? candidate : current
3745
+ );
3746
+ return {
3747
+ totalRuns: runs2.length,
3748
+ run: latestRun
3749
+ };
3750
+ }
3751
+ }
3424
3752
 
3425
3753
  // src/cli-commands/operator.ts
3426
3754
  var OPERATOR_CLI_COMMANDS = [
@@ -3497,11 +3825,11 @@ var OPERATOR_CLI_COMMANDS = [
3497
3825
  ];
3498
3826
 
3499
3827
  // src/commands/project.ts
3500
- function getClient12() {
3828
+ function getClient13() {
3501
3829
  return createApiClient();
3502
3830
  }
3503
3831
  async function createProject(name, opts) {
3504
- const client = getClient12();
3832
+ const client = getClient13();
3505
3833
  const result = await client.putProject(name, {
3506
3834
  displayName: opts.displayName,
3507
3835
  canonicalDomain: opts.domain,
@@ -3516,7 +3844,7 @@ async function createProject(name, opts) {
3516
3844
  console.log(`Project created: ${result.name} (${result.id})`);
3517
3845
  }
3518
3846
  async function listProjects(format) {
3519
- const client = getClient12();
3847
+ const client = getClient13();
3520
3848
  const projects2 = await client.listProjects();
3521
3849
  if (format === "json") {
3522
3850
  console.log(JSON.stringify(projects2, null, 2));
@@ -3544,7 +3872,7 @@ async function listProjects(format) {
3544
3872
  }
3545
3873
  }
3546
3874
  async function showProject(name, format) {
3547
- const client = getClient12();
3875
+ const client = getClient13();
3548
3876
  const project = await client.getProject(name);
3549
3877
  if (format === "json") {
3550
3878
  console.log(JSON.stringify(project, null, 2));
@@ -3570,7 +3898,7 @@ async function showProject(name, format) {
3570
3898
  if (project.updatedAt) console.log(` Updated: ${project.updatedAt}`);
3571
3899
  }
3572
3900
  async function updateProjectSettings(name, opts) {
3573
- const client = getClient12();
3901
+ const client = getClient13();
3574
3902
  const project = await client.getProject(name);
3575
3903
  let ownedDomains = opts.ownedDomains ?? project.ownedDomains ?? [];
3576
3904
  if (opts.addOwnedDomain) {
@@ -3595,7 +3923,7 @@ async function updateProjectSettings(name, opts) {
3595
3923
  console.log(`Project updated: ${result.name}`);
3596
3924
  }
3597
3925
  async function deleteProject(name, format) {
3598
- const client = getClient12();
3926
+ const client = getClient13();
3599
3927
  await client.deleteProject(name);
3600
3928
  if (format === "json") {
3601
3929
  console.log(JSON.stringify({ name, deleted: true }, null, 2));
@@ -3604,7 +3932,7 @@ async function deleteProject(name, format) {
3604
3932
  console.log(`Project deleted: ${name}`);
3605
3933
  }
3606
3934
  async function addLocation(project, opts) {
3607
- const client = getClient12();
3935
+ const client = getClient13();
3608
3936
  const location = await client.addLocation(project, {
3609
3937
  label: opts.label,
3610
3938
  city: opts.city,
@@ -3619,7 +3947,7 @@ async function addLocation(project, opts) {
3619
3947
  console.log(`Location added: ${opts.label} (${opts.city}, ${opts.region}, ${opts.country})`);
3620
3948
  }
3621
3949
  async function listLocations(project, format) {
3622
- const client = getClient12();
3950
+ const client = getClient13();
3623
3951
  const result = await client.listLocations(project);
3624
3952
  if (format === "json") {
3625
3953
  console.log(JSON.stringify(result, null, 2));
@@ -3645,7 +3973,7 @@ async function listLocations(project, format) {
3645
3973
  }
3646
3974
  }
3647
3975
  async function removeLocation(project, label, format) {
3648
- const client = getClient12();
3976
+ const client = getClient13();
3649
3977
  await client.removeLocation(project, label);
3650
3978
  if (format === "json") {
3651
3979
  console.log(JSON.stringify({ project, label, removed: true }, null, 2));
@@ -3654,7 +3982,7 @@ async function removeLocation(project, label, format) {
3654
3982
  console.log(`Location removed: ${label}`);
3655
3983
  }
3656
3984
  async function setDefaultLocation(project, label, format) {
3657
- const client = getClient12();
3985
+ const client = getClient13();
3658
3986
  const result = await client.setDefaultLocation(project, label);
3659
3987
  if (format === "json") {
3660
3988
  console.log(JSON.stringify({ project, ...result }, null, 2));
@@ -3833,12 +4161,12 @@ var PROJECT_CLI_COMMANDS = [
3833
4161
  ];
3834
4162
 
3835
4163
  // src/commands/run.ts
3836
- function getClient13() {
4164
+ function getClient14() {
3837
4165
  return createApiClient();
3838
4166
  }
3839
4167
  var TERMINAL_STATUSES = /* @__PURE__ */ new Set(["completed", "partial", "failed", "cancelled"]);
3840
4168
  async function triggerRun(project, opts) {
3841
- const client = getClient13();
4169
+ const client = getClient14();
3842
4170
  const body = {};
3843
4171
  if (opts?.provider) {
3844
4172
  const providerInputs = opts.provider.split(",").map((s) => s.trim()).filter(Boolean);
@@ -3862,7 +4190,7 @@ async function triggerRun(project, opts) {
3862
4190
  const settled = await Promise.all(
3863
4191
  locationRuns.map(async (r) => {
3864
4192
  if (!r.id || r.status === "conflict") return r;
3865
- const final = await pollRun(client, r.id);
4193
+ const final = await pollRun2(client, r.id);
3866
4194
  return { ...r, ...final };
3867
4195
  })
3868
4196
  );
@@ -3887,7 +4215,7 @@ async function triggerRun(project, opts) {
3887
4215
  process.stderr.write(`Waiting for ${pending.length} run(s)`);
3888
4216
  await Promise.all(
3889
4217
  pending.map(async (r) => {
3890
- const final = await pollRun(client, r.id);
4218
+ const final = await pollRun2(client, r.id);
3891
4219
  r.status = final.status;
3892
4220
  })
3893
4221
  );
@@ -3904,7 +4232,7 @@ async function triggerRun(project, opts) {
3904
4232
  const run = response;
3905
4233
  if (opts?.wait && run.id && !TERMINAL_STATUSES.has(run.status)) {
3906
4234
  process.stderr.write(`Run ${run.id} started`);
3907
- const result = await pollRun(client, run.id);
4235
+ const result = await pollRun2(client, run.id);
3908
4236
  if (opts?.format === "json") {
3909
4237
  console.log(JSON.stringify(result, null, 2));
3910
4238
  } else {
@@ -3934,7 +4262,7 @@ async function triggerRun(project, opts) {
3934
4262
  }
3935
4263
  }
3936
4264
  async function triggerRunAll(opts) {
3937
- const client = getClient13();
4265
+ const client = getClient14();
3938
4266
  const projects2 = await client.listProjects();
3939
4267
  if (projects2.length === 0) {
3940
4268
  if (opts?.format === "json") {
@@ -3971,7 +4299,7 @@ async function triggerRunAll(opts) {
3971
4299
  if (pending.length > 0) {
3972
4300
  process.stderr.write(`Waiting for ${pending.length} run(s)`);
3973
4301
  await Promise.all(pending.map(async (r) => {
3974
- const final = await pollRun(client, r.runId);
4302
+ const final = await pollRun2(client, r.runId);
3975
4303
  r.status = final.status;
3976
4304
  }));
3977
4305
  process.stderr.write("\n");
@@ -3992,7 +4320,7 @@ async function triggerRunAll(opts) {
3992
4320
  }
3993
4321
  }
3994
4322
  async function cancelRun(project, runId, format) {
3995
- const client = getClient13();
4323
+ const client = getClient14();
3996
4324
  let targetId = runId;
3997
4325
  if (!targetId) {
3998
4326
  const runs2 = await client.listRuns(project);
@@ -4024,7 +4352,7 @@ To cancel by ID : canonry run cancel ${project} <run-id>`,
4024
4352
  console.log(`Run ${result.id} cancelled.`);
4025
4353
  }
4026
4354
  async function showRun(id, format) {
4027
- const client = getClient13();
4355
+ const client = getClient14();
4028
4356
  const run = await client.getRun(id);
4029
4357
  if (format === "json") {
4030
4358
  console.log(JSON.stringify(run, null, 2));
@@ -4033,7 +4361,7 @@ async function showRun(id, format) {
4033
4361
  printRunDetail(run);
4034
4362
  }
4035
4363
  async function listRuns(project, opts) {
4036
- const client = getClient13();
4364
+ const client = getClient14();
4037
4365
  const runs2 = await client.listRuns(project, opts?.limit);
4038
4366
  if (opts?.format === "json") {
4039
4367
  console.log(JSON.stringify(runs2, null, 2));
@@ -4054,7 +4382,7 @@ async function listRuns(project, opts) {
4054
4382
  }
4055
4383
  }
4056
4384
  var POLL_TIMEOUT_MS = 10 * 60 * 1e3;
4057
- async function pollRun(client, runId) {
4385
+ async function pollRun2(client, runId) {
4058
4386
  const deadline = Date.now() + POLL_TIMEOUT_MS;
4059
4387
  for (; ; ) {
4060
4388
  await new Promise((r) => setTimeout(r, 2e3));
@@ -4178,11 +4506,11 @@ var RUN_CLI_COMMANDS = [
4178
4506
  ];
4179
4507
 
4180
4508
  // src/commands/schedule.ts
4181
- function getClient14() {
4509
+ function getClient15() {
4182
4510
  return createApiClient();
4183
4511
  }
4184
4512
  async function setSchedule(project, opts) {
4185
- const client = getClient14();
4513
+ const client = getClient15();
4186
4514
  const body = {};
4187
4515
  if (opts.preset) body.preset = opts.preset;
4188
4516
  if (opts.cron) body.cron = opts.cron;
@@ -4197,7 +4525,7 @@ async function setSchedule(project, opts) {
4197
4525
  printSchedule(result);
4198
4526
  }
4199
4527
  async function showSchedule(project, format) {
4200
- const client = getClient14();
4528
+ const client = getClient15();
4201
4529
  const result = await client.getSchedule(project);
4202
4530
  if (format === "json") {
4203
4531
  console.log(JSON.stringify(result, null, 2));
@@ -4206,7 +4534,7 @@ async function showSchedule(project, format) {
4206
4534
  printSchedule(result);
4207
4535
  }
4208
4536
  async function enableSchedule(project, format) {
4209
- const client = getClient14();
4537
+ const client = getClient15();
4210
4538
  const current = await client.getSchedule(project);
4211
4539
  const body = { timezone: current.timezone, enabled: true };
4212
4540
  if (current.preset) body.preset = current.preset;
@@ -4220,7 +4548,7 @@ async function enableSchedule(project, format) {
4220
4548
  console.log(`Schedule enabled for "${project}"`);
4221
4549
  }
4222
4550
  async function disableSchedule(project, format) {
4223
- const client = getClient14();
4551
+ const client = getClient15();
4224
4552
  const current = await client.getSchedule(project);
4225
4553
  const body = { timezone: current.timezone, enabled: false };
4226
4554
  if (current.preset) body.preset = current.preset;
@@ -4234,7 +4562,7 @@ async function disableSchedule(project, format) {
4234
4562
  console.log(`Schedule disabled for "${project}"`);
4235
4563
  }
4236
4564
  async function removeSchedule(project, format) {
4237
- const client = getClient14();
4565
+ const client = getClient15();
4238
4566
  await client.deleteSchedule(project);
4239
4567
  if (format === "json") {
4240
4568
  console.log(JSON.stringify({ project, removed: true }, null, 2));
@@ -4341,11 +4669,11 @@ var SCHEDULE_CLI_COMMANDS = [
4341
4669
  ];
4342
4670
 
4343
4671
  // src/commands/settings.ts
4344
- function getClient15() {
4672
+ function getClient16() {
4345
4673
  return createApiClient();
4346
4674
  }
4347
4675
  async function setProvider(name, opts) {
4348
- const client = getClient15();
4676
+ const client = getClient16();
4349
4677
  const { format, ...payload } = opts;
4350
4678
  const result = await client.updateProvider(name, payload);
4351
4679
  if (format === "json") {
@@ -4361,7 +4689,7 @@ async function setProvider(name, opts) {
4361
4689
  }
4362
4690
  }
4363
4691
  async function showSettings(format) {
4364
- const client = getClient15();
4692
+ const client = getClient16();
4365
4693
  const config = loadConfig();
4366
4694
  const settings = await client.getSettings();
4367
4695
  if (format === "json") {
@@ -4864,7 +5192,7 @@ function wrapText(font, text, size, maxWidth) {
4864
5192
  }
4865
5193
 
4866
5194
  // src/commands/snapshot.ts
4867
- function getClient16() {
5195
+ function getClient17() {
4868
5196
  return createApiClient();
4869
5197
  }
4870
5198
  function slugify(value) {
@@ -4875,7 +5203,7 @@ function autoOutputPath(companyName, ext) {
4875
5203
  return `${slugify(companyName)}-snapshot-${date}.${ext}`;
4876
5204
  }
4877
5205
  async function createSnapshotReport(companyName, opts) {
4878
- const client = getClient16();
5206
+ const client = getClient17();
4879
5207
  const report = await client.createSnapshot({
4880
5208
  companyName,
4881
5209
  domain: opts.domain,
@@ -6168,10 +6496,10 @@ var SYSTEM_CLI_COMMANDS = [
6168
6496
  import fs7 from "fs";
6169
6497
 
6170
6498
  // src/commands/wordpress.ts
6171
- function getClient17() {
6499
+ function getClient18() {
6172
6500
  return createApiClient();
6173
6501
  }
6174
- function printJson(value) {
6502
+ function printJson2(value) {
6175
6503
  console.log(JSON.stringify(value, null, 2));
6176
6504
  }
6177
6505
  function printSiteStatus(label, status) {
@@ -6315,7 +6643,7 @@ async function wordpressConnect(project, opts) {
6315
6643
  details: { project }
6316
6644
  });
6317
6645
  }
6318
- const client = getClient17();
6646
+ const client = getClient18();
6319
6647
  const result = await client.wordpressConnect(project, {
6320
6648
  url: opts.url,
6321
6649
  stagingUrl: opts.stagingUrl,
@@ -6324,7 +6652,7 @@ async function wordpressConnect(project, opts) {
6324
6652
  defaultEnv: opts.defaultEnv
6325
6653
  });
6326
6654
  if (opts.format === "json") {
6327
- printJson(result);
6655
+ printJson2(result);
6328
6656
  return;
6329
6657
  }
6330
6658
  console.log(`WordPress connected for project "${project}".
@@ -6332,46 +6660,46 @@ async function wordpressConnect(project, opts) {
6332
6660
  printWordpressStatus(project, result);
6333
6661
  }
6334
6662
  async function wordpressDisconnect(project, format) {
6335
- const client = getClient17();
6663
+ const client = getClient18();
6336
6664
  await client.wordpressDisconnect(project);
6337
6665
  if (format === "json") {
6338
- printJson({ project, disconnected: true });
6666
+ printJson2({ project, disconnected: true });
6339
6667
  return;
6340
6668
  }
6341
6669
  console.log(`WordPress disconnected from project "${project}".`);
6342
6670
  }
6343
6671
  async function wordpressStatus(project, format) {
6344
- const client = getClient17();
6672
+ const client = getClient18();
6345
6673
  const result = await client.wordpressStatus(project);
6346
6674
  if (format === "json") {
6347
- printJson(result);
6675
+ printJson2(result);
6348
6676
  return;
6349
6677
  }
6350
6678
  printWordpressStatus(project, result);
6351
6679
  }
6352
6680
  async function wordpressPages(project, opts) {
6353
- const client = getClient17();
6681
+ const client = getClient18();
6354
6682
  const result = await client.wordpressPages(project, opts.env);
6355
6683
  if (opts.format === "json") {
6356
- printJson(result);
6684
+ printJson2(result);
6357
6685
  return;
6358
6686
  }
6359
6687
  printPages(project, result.env, result.pages);
6360
6688
  }
6361
6689
  async function wordpressPage(project, slug, opts) {
6362
- const client = getClient17();
6690
+ const client = getClient18();
6363
6691
  const result = await client.wordpressPage(project, slug, opts.env);
6364
6692
  if (opts.format === "json") {
6365
- printJson(result);
6693
+ printJson2(result);
6366
6694
  return;
6367
6695
  }
6368
6696
  printPageDetail(result);
6369
6697
  }
6370
6698
  async function wordpressCreatePage(project, body) {
6371
- const client = getClient17();
6699
+ const client = getClient18();
6372
6700
  const result = await client.wordpressCreatePage(project, body);
6373
6701
  if (body.format === "json") {
6374
- printJson(result);
6702
+ printJson2(result);
6375
6703
  return;
6376
6704
  }
6377
6705
  console.log(`Created WordPress page "${result.slug}" in ${result.env}.
@@ -6379,10 +6707,10 @@ async function wordpressCreatePage(project, body) {
6379
6707
  printPageDetail(result);
6380
6708
  }
6381
6709
  async function wordpressUpdatePage(project, body) {
6382
- const client = getClient17();
6710
+ const client = getClient18();
6383
6711
  const result = await client.wordpressUpdatePage(project, body);
6384
6712
  if (body.format === "json") {
6385
- printJson(result);
6713
+ printJson2(result);
6386
6714
  return;
6387
6715
  }
6388
6716
  console.log(`Updated WordPress page "${body.currentSlug}" in ${result.env}.
@@ -6390,10 +6718,10 @@ async function wordpressUpdatePage(project, body) {
6390
6718
  printPageDetail(result);
6391
6719
  }
6392
6720
  async function wordpressSetMeta(project, body) {
6393
- const client = getClient17();
6721
+ const client = getClient18();
6394
6722
  const result = await client.wordpressSetMeta(project, body);
6395
6723
  if (body.format === "json") {
6396
- printJson(result);
6724
+ printJson2(result);
6397
6725
  return;
6398
6726
  }
6399
6727
  console.log(`Updated SEO meta for "${body.slug}" in ${result.env}.
@@ -6440,10 +6768,10 @@ async function wordpressBulkSetMeta(project, opts) {
6440
6768
  details: { path: filePath }
6441
6769
  });
6442
6770
  }
6443
- const client = getClient17();
6771
+ const client = getClient18();
6444
6772
  const result = await client.wordpressBulkSetMeta(project, { entries, env: opts.env });
6445
6773
  if (opts.format === "json") {
6446
- printJson(result);
6774
+ printJson2(result);
6447
6775
  return;
6448
6776
  }
6449
6777
  const applied = result.results.filter((r) => r.status === "applied");
@@ -6483,10 +6811,10 @@ async function wordpressBulkSetMeta(project, opts) {
6483
6811
  Total: ${applied.length} applied, ${skipped.length} skipped, ${manual.length} manual`);
6484
6812
  }
6485
6813
  async function wordpressSchema(project, slug, opts) {
6486
- const client = getClient17();
6814
+ const client = getClient18();
6487
6815
  const result = await client.wordpressSchema(project, slug, opts.env);
6488
6816
  if (opts.format === "json") {
6489
- printJson(result);
6817
+ printJson2(result);
6490
6818
  return;
6491
6819
  }
6492
6820
  console.log(`Schema for "${slug}" (${result.env}):
@@ -6494,10 +6822,10 @@ async function wordpressSchema(project, slug, opts) {
6494
6822
  printSchemaBlocks(result.blocks);
6495
6823
  }
6496
6824
  async function wordpressSetSchema(project, body) {
6497
- const client = getClient17();
6825
+ const client = getClient18();
6498
6826
  const result = await client.wordpressSetSchema(project, body);
6499
6827
  if (body.format === "json") {
6500
- printJson(result);
6828
+ printJson2(result);
6501
6829
  return;
6502
6830
  }
6503
6831
  printManualAssist(`Schema update for "${body.slug}"`, result);
@@ -6542,10 +6870,10 @@ async function wordpressSchemaDeploy(project, opts) {
6542
6870
  details: { path: filePath }
6543
6871
  });
6544
6872
  }
6545
- const client = getClient17();
6873
+ const client = getClient18();
6546
6874
  const result = await client.wordpressSchemaDeploy(project, { profile: parsed, env: opts.env });
6547
6875
  if (opts.format === "json") {
6548
- printJson(result);
6876
+ printJson2(result);
6549
6877
  return;
6550
6878
  }
6551
6879
  console.log(`Schema deploy (${result.env}):
@@ -6581,10 +6909,10 @@ async function wordpressSchemaDeploy(project, opts) {
6581
6909
  Total: ${deployed} deployed, ${stripped} stripped, ${skipped} skipped, ${failed} failed`);
6582
6910
  }
6583
6911
  async function wordpressSchemaStatus(project, opts) {
6584
- const client = getClient17();
6912
+ const client = getClient18();
6585
6913
  const result = await client.wordpressSchemaStatus(project, opts.env);
6586
6914
  if (opts.format === "json") {
6587
- printJson(result);
6915
+ printJson2(result);
6588
6916
  return;
6589
6917
  }
6590
6918
  console.log(`Schema status (${result.env}):
@@ -6640,7 +6968,7 @@ async function wordpressOnboard(project, opts) {
6640
6968
  });
6641
6969
  }
6642
6970
  }
6643
- const client = getClient17();
6971
+ const client = getClient18();
6644
6972
  const result = await client.wordpressOnboard(project, {
6645
6973
  url: opts.url,
6646
6974
  username: opts.user,
@@ -6652,7 +6980,7 @@ async function wordpressOnboard(project, opts) {
6652
6980
  skipSubmit: opts.skipSubmit
6653
6981
  });
6654
6982
  if (opts.format === "json") {
6655
- printJson(result);
6983
+ printJson2(result);
6656
6984
  return;
6657
6985
  }
6658
6986
  console.log(`WordPress onboarding for "${project}":
@@ -6665,10 +6993,10 @@ async function wordpressOnboard(project, opts) {
6665
6993
  }
6666
6994
  }
6667
6995
  async function wordpressLlmsTxt(project, opts) {
6668
- const client = getClient17();
6996
+ const client = getClient18();
6669
6997
  const result = await client.wordpressLlmsTxt(project, opts.env);
6670
6998
  if (opts.format === "json") {
6671
- printJson(result);
6999
+ printJson2(result);
6672
7000
  return;
6673
7001
  }
6674
7002
  console.log(`llms.txt for "${project}" (${result.env}): ${result.url}
@@ -6676,19 +7004,19 @@ async function wordpressLlmsTxt(project, opts) {
6676
7004
  console.log(result.content ?? "(not found)");
6677
7005
  }
6678
7006
  async function wordpressSetLlmsTxt(project, body) {
6679
- const client = getClient17();
7007
+ const client = getClient18();
6680
7008
  const result = await client.wordpressSetLlmsTxt(project, body);
6681
7009
  if (body.format === "json") {
6682
- printJson(result);
7010
+ printJson2(result);
6683
7011
  return;
6684
7012
  }
6685
7013
  printManualAssist(`llms.txt update for "${project}"`, result);
6686
7014
  }
6687
7015
  async function wordpressAudit(project, opts) {
6688
- const client = getClient17();
7016
+ const client = getClient18();
6689
7017
  const result = await client.wordpressAudit(project, opts.env);
6690
7018
  if (opts.format === "json") {
6691
- printJson(result);
7019
+ printJson2(result);
6692
7020
  return;
6693
7021
  }
6694
7022
  console.log(`WordPress audit for "${project}" (${result.env}):
@@ -6699,19 +7027,19 @@ async function wordpressAudit(project, opts) {
6699
7027
  printAuditIssues(result.issues);
6700
7028
  }
6701
7029
  async function wordpressDiff(project, slug, format) {
6702
- const client = getClient17();
7030
+ const client = getClient18();
6703
7031
  const result = await client.wordpressDiff(project, slug);
6704
7032
  if (format === "json") {
6705
- printJson(result);
7033
+ printJson2(result);
6706
7034
  return;
6707
7035
  }
6708
7036
  printDiff(result);
6709
7037
  }
6710
7038
  async function wordpressStagingStatus(project, format) {
6711
- const client = getClient17();
7039
+ const client = getClient18();
6712
7040
  const result = await client.wordpressStagingStatus(project);
6713
7041
  if (format === "json") {
6714
- printJson(result);
7042
+ printJson2(result);
6715
7043
  return;
6716
7044
  }
6717
7045
  console.log(`WordPress staging status for "${project}":
@@ -6722,10 +7050,10 @@ async function wordpressStagingStatus(project, format) {
6722
7050
  console.log(` Admin URL: ${result.adminUrl}`);
6723
7051
  }
6724
7052
  async function wordpressStagingPush(project, format) {
6725
- const client = getClient17();
7053
+ const client = getClient18();
6726
7054
  const result = await client.wordpressStagingPush(project);
6727
7055
  if (format === "json") {
6728
- printJson(result);
7056
+ printJson2(result);
6729
7057
  return;
6730
7058
  }
6731
7059
  printManualAssist(`Staging push for "${project}"`, result);
@@ -7519,27 +7847,48 @@ var AGENT_CLI_COMMANDS = [
7519
7847
  scope: stringOption()
7520
7848
  },
7521
7849
  run: async (input) => {
7522
- const [project, ...rest] = input.positionals;
7523
- if (!project || rest.length === 0) {
7524
- console.error('Usage: canonry agent ask <project> "<prompt>"');
7525
- process.exitCode = 1;
7526
- return;
7850
+ const usage = `canonry agent ask <project> "<prompt>" [--provider ${listAgentProviders().join("|")}] [--model <id>] [--scope all|read-only] [--format json]`;
7851
+ const project = requireProject(input, "agent.ask", usage);
7852
+ const prompt2 = input.positionals.slice(1).join(" ").trim();
7853
+ if (!prompt2) {
7854
+ throw usageError(`Error: prompt is required
7855
+ Usage: ${usage}`, {
7856
+ message: "prompt is required",
7857
+ details: {
7858
+ command: "agent.ask",
7859
+ usage
7860
+ }
7861
+ });
7527
7862
  }
7528
7863
  const providerInput = getString(input.values, "provider");
7529
7864
  if (providerInput && !coerceAgentProvider(providerInput)) {
7530
- console.error(`--provider must be one of: ${listAgentProviders().join(", ")}`);
7531
- process.exitCode = 1;
7532
- return;
7865
+ throw usageError(`Error: --provider must be one of: ${listAgentProviders().join(", ")}
7866
+ Usage: ${usage}`, {
7867
+ message: `--provider must be one of: ${listAgentProviders().join(", ")}`,
7868
+ details: {
7869
+ command: "agent.ask",
7870
+ usage,
7871
+ provider: providerInput,
7872
+ validProviders: listAgentProviders()
7873
+ }
7874
+ });
7533
7875
  }
7534
7876
  const scopeInput = getString(input.values, "scope");
7535
7877
  if (scopeInput && !AGENT_ASK_SCOPES.includes(scopeInput)) {
7536
- console.error(`--scope must be one of: ${AGENT_ASK_SCOPES.join(", ")}`);
7537
- process.exitCode = 1;
7538
- return;
7878
+ throw usageError(`Error: --scope must be one of: ${AGENT_ASK_SCOPES.join(", ")}
7879
+ Usage: ${usage}`, {
7880
+ message: `--scope must be one of: ${AGENT_ASK_SCOPES.join(", ")}`,
7881
+ details: {
7882
+ command: "agent.ask",
7883
+ usage,
7884
+ scope: scopeInput,
7885
+ validScopes: AGENT_ASK_SCOPES
7886
+ }
7887
+ });
7539
7888
  }
7540
7889
  await agentAsk({
7541
7890
  project,
7542
- prompt: rest.join(" "),
7891
+ prompt: prompt2,
7543
7892
  provider: coerceAgentProvider(providerInput),
7544
7893
  modelId: getString(input.values, "model"),
7545
7894
  scope: scopeInput,
@@ -7552,12 +7901,7 @@ var AGENT_CLI_COMMANDS = [
7552
7901
  usage: "canonry agent providers <project> [--format json]",
7553
7902
  options: {},
7554
7903
  run: async (input) => {
7555
- const project = input.positionals[0];
7556
- if (!project) {
7557
- console.error("Usage: canonry agent providers <project>");
7558
- process.exitCode = 1;
7559
- return;
7560
- }
7904
+ const project = requireProject(input, "agent.providers", "canonry agent providers <project> [--format json]");
7561
7905
  await agentProviders({ project, format: input.format });
7562
7906
  }
7563
7907
  },
@@ -7568,18 +7912,16 @@ var AGENT_CLI_COMMANDS = [
7568
7912
  url: stringOption()
7569
7913
  },
7570
7914
  run: async (input) => {
7571
- const project = input.positionals[0];
7572
- if (!project) {
7573
- console.error("Usage: canonry agent attach <project> --url <webhook-url>");
7574
- process.exitCode = 1;
7575
- return;
7576
- }
7577
- const url = getString(input.values, "url");
7578
- if (!url) {
7579
- console.error("Missing required --url flag. Specify the agent webhook URL to attach.");
7580
- process.exitCode = 1;
7581
- return;
7582
- }
7915
+ const usage = "canonry agent attach <project> --url <webhook-url> [--format json]";
7916
+ const project = requireProject(input, "agent.attach", usage);
7917
+ const url = requireStringOption(input, "url", {
7918
+ command: "agent.attach",
7919
+ usage,
7920
+ message: "--url is required",
7921
+ details: {
7922
+ flag: "url"
7923
+ }
7924
+ });
7583
7925
  await agentAttach({ project, url, format: input.format });
7584
7926
  }
7585
7927
  },
@@ -7588,12 +7930,7 @@ var AGENT_CLI_COMMANDS = [
7588
7930
  usage: "canonry agent detach <project> [--format json]",
7589
7931
  options: {},
7590
7932
  run: async (input) => {
7591
- const project = input.positionals[0];
7592
- if (!project) {
7593
- console.error("Usage: canonry agent detach <project>");
7594
- process.exitCode = 1;
7595
- return;
7596
- }
7933
+ const project = requireProject(input, "agent.detach", "canonry agent detach <project> [--format json]");
7597
7934
  await agentDetach({ project, format: input.format });
7598
7935
  }
7599
7936
  },
@@ -7602,12 +7939,7 @@ var AGENT_CLI_COMMANDS = [
7602
7939
  usage: "canonry agent transcript <project> [--format json]",
7603
7940
  options: {},
7604
7941
  run: async (input) => {
7605
- const project = input.positionals[0];
7606
- if (!project) {
7607
- console.error("Usage: canonry agent transcript <project>");
7608
- process.exitCode = 1;
7609
- return;
7610
- }
7942
+ const project = requireProject(input, "agent.transcript", "canonry agent transcript <project> [--format json]");
7611
7943
  await agentTranscript({ project, format: input.format });
7612
7944
  }
7613
7945
  },
@@ -7616,12 +7948,7 @@ var AGENT_CLI_COMMANDS = [
7616
7948
  usage: "canonry agent reset <project> [--format json]",
7617
7949
  options: {},
7618
7950
  run: async (input) => {
7619
- const project = input.positionals[0];
7620
- if (!project) {
7621
- console.error("Usage: canonry agent reset <project>");
7622
- process.exitCode = 1;
7623
- return;
7624
- }
7951
+ const project = requireProject(input, "agent.reset", "canonry agent reset <project> [--format json]");
7625
7952
  await agentTranscriptReset({ project, format: input.format });
7626
7953
  }
7627
7954
  },
@@ -7630,12 +7957,8 @@ var AGENT_CLI_COMMANDS = [
7630
7957
  usage: "canonry agent memory list <project> [--format json]",
7631
7958
  options: {},
7632
7959
  run: async (input) => {
7633
- const project = input.positionals[0];
7634
- if (!project) {
7635
- throw usageError("Usage: canonry agent memory list <project>", {
7636
- message: "project name is required"
7637
- });
7638
- }
7960
+ const usage = "canonry agent memory list <project> [--format json]";
7961
+ const project = requireProject(input, "agent.memory.list", usage);
7639
7962
  await agentMemoryList({ project, format: input.format });
7640
7963
  }
7641
7964
  },
@@ -7647,19 +7970,24 @@ var AGENT_CLI_COMMANDS = [
7647
7970
  value: stringOption()
7648
7971
  },
7649
7972
  run: async (input) => {
7650
- const project = input.positionals[0];
7651
- if (!project) {
7652
- throw usageError("Usage: canonry agent memory set <project> --key <k> --value <v>", {
7653
- message: "project name is required"
7654
- });
7655
- }
7656
- const key = getString(input.values, "key");
7657
- const value = getString(input.values, "value");
7658
- if (!key || !value) {
7659
- throw usageError("--key and --value are both required.", {
7660
- message: "--key and --value are both required"
7661
- });
7662
- }
7973
+ const usage = "canonry agent memory set <project> --key <k> --value <v> [--format json]";
7974
+ const project = requireProject(input, "agent.memory.set", usage);
7975
+ const key = requireStringOption(input, "key", {
7976
+ command: "agent.memory.set",
7977
+ usage,
7978
+ message: "--key is required",
7979
+ details: {
7980
+ flag: "key"
7981
+ }
7982
+ });
7983
+ const value = requireStringOption(input, "value", {
7984
+ command: "agent.memory.set",
7985
+ usage,
7986
+ message: "--value is required",
7987
+ details: {
7988
+ flag: "value"
7989
+ }
7990
+ });
7663
7991
  await agentMemorySet({ project, key, value, format: input.format });
7664
7992
  }
7665
7993
  },
@@ -7670,18 +7998,16 @@ var AGENT_CLI_COMMANDS = [
7670
7998
  key: stringOption()
7671
7999
  },
7672
8000
  run: async (input) => {
7673
- const project = input.positionals[0];
7674
- if (!project) {
7675
- throw usageError("Usage: canonry agent memory forget <project> --key <k>", {
7676
- message: "project name is required"
7677
- });
7678
- }
7679
- const key = getString(input.values, "key");
7680
- if (!key) {
7681
- throw usageError("--key is required.", {
7682
- message: "--key is required"
7683
- });
7684
- }
8001
+ const usage = "canonry agent memory forget <project> --key <k> [--format json]";
8002
+ const project = requireProject(input, "agent.memory.forget", usage);
8003
+ const key = requireStringOption(input, "key", {
8004
+ command: "agent.memory.forget",
8005
+ usage,
8006
+ message: "--key is required",
8007
+ details: {
8008
+ flag: "key"
8009
+ }
8010
+ });
7685
8011
  await agentMemoryForget({ project, key, format: input.format });
7686
8012
  }
7687
8013
  }
@@ -7690,6 +8016,7 @@ var AGENT_CLI_COMMANDS = [
7690
8016
  // src/cli-commands.ts
7691
8017
  var REGISTERED_CLI_COMMANDS = [
7692
8018
  ...BACKFILL_CLI_COMMANDS,
8019
+ ...BACKLINKS_CLI_COMMANDS,
7693
8020
  ...SYSTEM_CLI_COMMANDS,
7694
8021
  ...PROJECT_CLI_COMMANDS,
7695
8022
  ...KEYWORD_CLI_COMMANDS,