@canonry/canonry 7.3.0 → 7.4.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.
Files changed (31) hide show
  1. package/assets/agent-workspace/skills/aero/references/orchestration.md +1 -1
  2. package/assets/agent-workspace/skills/canonry/references/canonry-cli.md +2 -1
  3. package/assets/assets/{AuditHistoryPanel-DP92khTY.js → AuditHistoryPanel-DIL5oTHF.js} +1 -1
  4. package/assets/assets/{BacklinksPage-BI_9t1iI.js → BacklinksPage-BpCURZh8.js} +1 -1
  5. package/assets/assets/{HistoryPage-tDE6Nv0J.js → HistoryPage-TPbexxzA.js} +1 -1
  6. package/assets/assets/{MeasurementPropertyPage-Y2F334Qs.js → MeasurementPropertyPage-H991GW9h.js} +1 -1
  7. package/assets/assets/{ProjectPage-DW581TNr.js → ProjectPage-l1NAl-9k.js} +7 -7
  8. package/assets/assets/{RunsPage-Bl_c9-vA.js → RunsPage-Dhu7Qe7B.js} +1 -1
  9. package/assets/assets/{SettingsPage-DQ5_Q2rc.js → SettingsPage-BCG1QJ07.js} +1 -1
  10. package/assets/assets/SiteHealthSection-BXueYSiu.js +4 -0
  11. package/assets/assets/{TrafficPage-CROectSE.js → TrafficPage-ua9wsccA.js} +3 -3
  12. package/assets/assets/{TrafficSourceDetailPage-Bthvvwg5.js → TrafficSourceDetailPage-pwATnkp8.js} +1 -1
  13. package/assets/assets/{extract-error-message-DOLCGQMa.js → extract-error-message-DJfNdKqh.js} +1 -1
  14. package/assets/assets/{index-CCOcEGdz.js → index-DvWWyhGp.js} +20 -20
  15. package/assets/assets/{react-sigma_core.esm.min-TWiq-VWU.js → react-sigma_core.esm.min-DnbWY5j_.js} +1 -1
  16. package/assets/assets/{v2-overview-adapter-CxmV639A.js → v2-overview-adapter-BIOvZAlo.js} +1 -1
  17. package/assets/index.html +1 -1
  18. package/dist/{chunk-MQPBOQUH.js → chunk-GEKMHZS2.js} +7 -7
  19. package/dist/{chunk-FWV6IIYY.js → chunk-JU6TPMCJ.js} +6 -5
  20. package/dist/{chunk-YQXQBFHT.js → chunk-PXRUWG75.js} +9843 -9823
  21. package/dist/{chunk-XODXE6PT.js → chunk-SWSWCUHS.js} +26 -3
  22. package/dist/{chunk-RVELNJAW.js → chunk-TNLOOXUP.js} +2 -2
  23. package/dist/{chunk-QND5LEAC.js → chunk-XFVJ6QVE.js} +2 -2
  24. package/dist/{chunk-3JEUZ2K5.js → chunk-ZP6GF32R.js} +3 -3
  25. package/dist/cli.js +47 -18
  26. package/dist/{demo-server-BXABH765.js → demo-server-INMOE4BA.js} +4 -4
  27. package/dist/index.js +6 -6
  28. package/dist/{intelligence-service-EIWYQYVG.js → intelligence-service-IBUS2IND.js} +2 -2
  29. package/dist/mcp.js +4 -4
  30. package/package.json +13 -13
  31. package/assets/assets/SiteHealthSection-DdZruU72.js +0 -4
@@ -795,7 +795,7 @@ import {
795
795
  wordpressSchemaDeployResultDtoSchema,
796
796
  wordpressSchemaStatusResultDtoSchema,
797
797
  wordpressStatusDtoSchema
798
- } from "./chunk-YQXQBFHT.js";
798
+ } from "./chunk-PXRUWG75.js";
799
799
 
800
800
  // src/intelligence-service.ts
801
801
  import { eq as eq84, desc as desc37, asc as asc15, and as and71, ne as ne15, or as or20, inArray as inArray33, gte as gte22, lte as lte20, isNull as isNull16, sql as sql31, exists as exists2 } from "drizzle-orm";
@@ -953,6 +953,8 @@ var projects = sqliteTable("projects", {
953
953
  * sidecar at dispatch; never read by mention detection or query classes.
954
954
  */
955
955
  qualifiedAliases: text("qualified_aliases", { mode: "json" }).$type().notNull().default([]),
956
+ /** Site Health page budget for scans that set none; null means the full site (up to 50,000 pages). */
957
+ siteAuditMaxPages: integer("site_audit_max_pages"),
956
958
  country: text("country").notNull(),
957
959
  language: text("language").notNull(),
958
960
  tags: text("tags", { mode: "json" }).$type().notNull().default([]),
@@ -8152,6 +8154,16 @@ var MIGRATION_VERSIONS = [
8152
8154
  statements: [
8153
8155
  `ALTER TABLE competitors ADD COLUMN aliases TEXT NOT NULL DEFAULT '[]'`
8154
8156
  ]
8157
+ },
8158
+ {
8159
+ // Saved Site Health page budget for scans that set none. Nullable with no
8160
+ // default: every existing project reads as full site, and an older writer
8161
+ // that never sets it leaves it null.
8162
+ version: 169,
8163
+ name: "projects-site-audit-max-pages",
8164
+ statements: [
8165
+ `ALTER TABLE projects ADD COLUMN site_audit_max_pages INTEGER`
8166
+ ]
8155
8167
  }
8156
8168
  ];
8157
8169
  var AERO_LEDGER_REBUILDS = [
@@ -17088,6 +17100,7 @@ async function projectRoutes(app, opts) {
17088
17100
  locations: nextLocations,
17089
17101
  defaultLocation: nextDefaultLocation,
17090
17102
  autoExtractBacklinks: body.autoExtractBacklinks ?? false,
17103
+ siteAuditMaxPages: body.siteAuditMaxPages ?? null,
17091
17104
  configSource: body.configSource ?? "api",
17092
17105
  configRevision: 1,
17093
17106
  createdAt: now,
@@ -17160,6 +17173,7 @@ async function projectRoutes(app, opts) {
17160
17173
  });
17161
17174
  }
17162
17175
  const nextAutoExtractBacklinks = body.autoExtractBacklinks !== void 0 ? body.autoExtractBacklinks : existing?.autoExtractBacklinks ?? false;
17176
+ const nextSiteAuditMaxPages = body.siteAuditMaxPages !== void 0 ? body.siteAuditMaxPages : existing?.siteAuditMaxPages ?? null;
17163
17177
  const nextNegativeReviewMaxStars = body.negativeReviewMaxStars !== void 0 ? body.negativeReviewMaxStars : existing ? readNegativeReviewMaxStars(app.db, existing.id) : null;
17164
17178
  const nextMeasurement = body.measurement ?? existing?.measurement ?? DEFAULT_MEASUREMENT_CONFIG;
17165
17179
  const nextAliases = normalizeProjectAliases(body.displayName, body.aliases ?? []);
@@ -17199,6 +17213,7 @@ async function projectRoutes(app, opts) {
17199
17213
  locations: nextLocations,
17200
17214
  defaultLocation: nextDefaultLocation,
17201
17215
  autoExtractBacklinks: nextAutoExtractBacklinks,
17216
+ siteAuditMaxPages: nextSiteAuditMaxPages,
17202
17217
  configSource: body.configSource ?? "api",
17203
17218
  configRevision: existing.configRevision + 1,
17204
17219
  updatedAt: now
@@ -17247,6 +17262,7 @@ async function projectRoutes(app, opts) {
17247
17262
  locations: nextLocations,
17248
17263
  defaultLocation: nextDefaultLocation,
17249
17264
  autoExtractBacklinks: nextAutoExtractBacklinks,
17265
+ siteAuditMaxPages: nextSiteAuditMaxPages,
17250
17266
  configSource: body.configSource ?? "api",
17251
17267
  configRevision: 1,
17252
17268
  createdAt: now,
@@ -17457,6 +17473,7 @@ async function projectRoutes(app, opts) {
17457
17473
  ...project.defaultLocation ? { defaultLocation: project.defaultLocation } : {},
17458
17474
  ...project.autoExtractBacklinks ? { autoExtractBacklinks: true } : {},
17459
17475
  ...negativeReviewMaxStars !== null ? { negativeReviewMaxStars } : {},
17476
+ ...project.siteAuditMaxPages !== null ? { siteAuditMaxPages: project.siteAuditMaxPages } : {},
17460
17477
  notifications: notificationRows.map((row) => {
17461
17478
  const cfg = row.config;
17462
17479
  return {
@@ -17536,6 +17553,7 @@ function formatProject(row, negativeReviewMaxStars) {
17536
17553
  defaultLocation: row.defaultLocation,
17537
17554
  autoExtractBacklinks: row.autoExtractBacklinks,
17538
17555
  negativeReviewMaxStars,
17556
+ siteAuditMaxPages: row.siteAuditMaxPages ?? null,
17539
17557
  configSource: row.configSource,
17540
17558
  configRevision: row.configRevision,
17541
17559
  createdAt: row.createdAt,
@@ -29977,6 +29995,8 @@ async function applyRoutes(app, opts) {
29977
29995
  locations: config.spec.locations ?? [],
29978
29996
  defaultLocation: config.spec.defaultLocation ?? null,
29979
29997
  autoExtractBacklinks: config.spec.autoExtractBacklinks ?? false,
29998
+ // Present sets (null = full site); absent leaves the stored budget alone.
29999
+ ...config.spec.siteAuditMaxPages !== void 0 ? { siteAuditMaxPages: config.spec.siteAuditMaxPages } : {},
29980
30000
  configSource: "config-file",
29981
30001
  configRevision: existing.configRevision + 1,
29982
30002
  updatedAt: now
@@ -30010,6 +30030,7 @@ async function applyRoutes(app, opts) {
30010
30030
  locations: config.spec.locations ?? [],
30011
30031
  defaultLocation: config.spec.defaultLocation ?? null,
30012
30032
  autoExtractBacklinks: config.spec.autoExtractBacklinks ?? false,
30033
+ siteAuditMaxPages: config.spec.siteAuditMaxPages ?? null,
30013
30034
  configSource: "config-file",
30014
30035
  configRevision: 1,
30015
30036
  createdAt: now,
@@ -30156,6 +30177,7 @@ async function applyRoutes(app, opts) {
30156
30177
  defaultLocation: project.defaultLocation,
30157
30178
  autoExtractBacklinks: project.autoExtractBacklinks,
30158
30179
  negativeReviewMaxStars: readNegativeReviewMaxStars(app.db, project.id),
30180
+ siteAuditMaxPages: project.siteAuditMaxPages ?? null,
30159
30181
  configSource: project.configSource,
30160
30182
  configRevision: project.configRevision,
30161
30183
  createdAt: project.createdAt,
@@ -35327,6 +35349,7 @@ function formatProject2(row, negativeReviewMaxStars) {
35327
35349
  defaultLocation: row.defaultLocation,
35328
35350
  autoExtractBacklinks: row.autoExtractBacklinks,
35329
35351
  negativeReviewMaxStars,
35352
+ siteAuditMaxPages: row.siteAuditMaxPages ?? null,
35330
35353
  configSource: row.configSource,
35331
35354
  configRevision: row.configRevision,
35332
35355
  createdAt: row.createdAt,
@@ -43838,7 +43861,7 @@ var routeCatalog = [
43838
43861
  properties: {
43839
43862
  sitemapUrl: { ...stringSchema, description: "Deprecated compatibility alias for the sitemap override." },
43840
43863
  limit: { ...integerSchema, minimum: 1, maximum: 2e3, description: "Deprecated compatibility alias for maxPages. Max 2000." },
43841
- maxPages: { ...integerSchema, minimum: 1, maximum: 5e4, description: "Crawl page budget. Defaults to 1000; max 50000." },
43864
+ maxPages: { ...integerSchema, minimum: 1, maximum: 5e4, description: "Crawl page budget. When omitted, the project's saved budget (siteAuditMaxPages) applies, else the full site; max 50000." },
43842
43865
  maxEdges: { ...integerSchema, minimum: 1, maximum: 1e6, description: "Internal-link observation budget. When omitted the crawl engine derives it from the page count; max 1000000." },
43843
43866
  maxDepth: { ...integerSchema, minimum: 0, maximum: 100, description: "Maximum crawl depth from the root. Max 100." },
43844
43867
  checkDeadLinks: { ...booleanSchema, default: false, description: "Enable dead-link checking. Defaults to false." }
@@ -86752,7 +86775,7 @@ async function technicalAeoRoutes(app, opts) {
86752
86775
  reason: "no-site-audit-handler"
86753
86776
  });
86754
86777
  }
86755
- const effectiveRequest = normalizeSiteAuditRunRequest(parsed.data);
86778
+ const effectiveRequest = normalizeSiteAuditRunRequest(parsed.data, project.siteAuditMaxPages);
86756
86779
  const identityKey = siteAuditRequestIdentity(effectiveRequest);
86757
86780
  const result = app.db.transaction((tx) => {
86758
86781
  const existing = tx.select({
@@ -5,7 +5,7 @@ import {
5
5
  PACKAGE_VERSION,
6
6
  canonryMcpTools,
7
7
  isMachineFormat
8
- } from "./chunk-FWV6IIYY.js";
8
+ } from "./chunk-JU6TPMCJ.js";
9
9
  import {
10
10
  AGENT_PROVIDER_IDS,
11
11
  CANONRY_NPM_PACKAGE_URL,
@@ -50,7 +50,7 @@ import {
50
50
  skillsClientSchema,
51
51
  upgradeCaveatFor,
52
52
  upgradeCommandFor
53
- } from "./chunk-YQXQBFHT.js";
53
+ } from "./chunk-PXRUWG75.js";
54
54
 
55
55
  // src/config.ts
56
56
  import fs from "fs";
@@ -5,7 +5,7 @@ import {
5
5
  siteCrawlGraphNodes,
6
6
  siteCrawlPages,
7
7
  siteCrawlSnapshots
8
- } from "./chunk-XODXE6PT.js";
8
+ } from "./chunk-SWSWCUHS.js";
9
9
  import {
10
10
  SITE_CRAWL_GRAPH_MAX_EDGES,
11
11
  SITE_CRAWL_GRAPH_MAX_NODES,
@@ -13,7 +13,7 @@ import {
13
13
  TEMPLATE_LINK_RATIO_THRESHOLD,
14
14
  factorStatusFromScore,
15
15
  roundPreservingTotal
16
- } from "./chunk-YQXQBFHT.js";
16
+ } from "./chunk-PXRUWG75.js";
17
17
 
18
18
  // src/site-audit-factors.ts
19
19
  function recordedSharePct(factor) {
@@ -4,14 +4,14 @@ import {
4
4
  installSkills,
5
5
  loadConfigRaw,
6
6
  saveConfigPatch
7
- } from "./chunk-RVELNJAW.js";
7
+ } from "./chunk-TNLOOXUP.js";
8
8
  import {
9
9
  PACKAGE_VERSION
10
- } from "./chunk-FWV6IIYY.js";
10
+ } from "./chunk-JU6TPMCJ.js";
11
11
  import {
12
12
  SKILL_MANIFEST_FILENAME,
13
13
  SkillsClients
14
- } from "./chunk-YQXQBFHT.js";
14
+ } from "./chunk-PXRUWG75.js";
15
15
 
16
16
  // src/skills-autosync.ts
17
17
  import fs from "fs";
package/dist/cli.js CHANGED
@@ -32,11 +32,11 @@ import {
32
32
  trackCliCommandFinished,
33
33
  trackEvent,
34
34
  waitForServerRuntimeStartup
35
- } from "./chunk-MQPBOQUH.js";
35
+ } from "./chunk-GEKMHZS2.js";
36
36
  import {
37
37
  autoSyncSkills,
38
38
  formatAutoSyncNotice
39
- } from "./chunk-3JEUZ2K5.js";
39
+ } from "./chunk-ZP6GF32R.js";
40
40
  import {
41
41
  configExists,
42
42
  createApiClient,
@@ -53,13 +53,13 @@ import {
53
53
  saveConfig,
54
54
  saveConfigPatch,
55
55
  shouldPrintServeSkillsNudge
56
- } from "./chunk-RVELNJAW.js";
56
+ } from "./chunk-TNLOOXUP.js";
57
57
  import {
58
58
  DEFAULT_DEMO_TRUSTED_PROXIES,
59
59
  trustedProxiesProblem,
60
60
  trustedProxyProblem
61
61
  } from "./chunk-RB2F4D3Z.js";
62
- import "./chunk-QND5LEAC.js";
62
+ import "./chunk-XFVJ6QVE.js";
63
63
  import {
64
64
  CliError,
65
65
  EXIT_SYSTEM_ERROR,
@@ -71,7 +71,7 @@ import {
71
71
  runMeasurementDraftAction,
72
72
  systemError,
73
73
  usageError
74
- } from "./chunk-FWV6IIYY.js";
74
+ } from "./chunk-JU6TPMCJ.js";
75
75
  import {
76
76
  CLOUDFLARE_WORKER_BINDINGS,
77
77
  CLOUDFLARE_WORKER_GENERATED_MARKER,
@@ -100,7 +100,7 @@ import {
100
100
  querySnapshots,
101
101
  rawEventSamples,
102
102
  runs
103
- } from "./chunk-XODXE6PT.js";
103
+ } from "./chunk-SWSWCUHS.js";
104
104
  import {
105
105
  AdsDeliverySnapshotStatuses,
106
106
  AdsHistoricalCampaignRollupStatuses,
@@ -127,6 +127,7 @@ import {
127
127
  RunKinds,
128
128
  RunStatuses,
129
129
  RunTriggers,
130
+ SITE_AUDIT_MAX_PAGE_LIMIT,
130
131
  TrafficEventConfidences,
131
132
  TrafficEventKinds,
132
133
  TrafficEvidenceKinds,
@@ -173,6 +174,7 @@ import {
173
174
  formatPercent,
174
175
  formatRunErrorOneLine,
175
176
  formatSignedPointDelta,
177
+ formatSiteAuditPageBudget,
176
178
  gbpNegativeReviewMaxStarsSchema,
177
179
  googleAdsMetricsWindowSchema,
178
180
  isRetiredAgentProviderId,
@@ -219,12 +221,13 @@ import {
219
221
  sentimentSummaryRequestSchema,
220
222
  shareOfVoiceLabel,
221
223
  shareOfVoiceReason,
224
+ siteAuditPageBudgetSchema,
222
225
  snapshotProviderModeSchema,
223
226
  unattributedAnswersLabel,
224
227
  visibilityCompareSelectionSchema,
225
228
  visibilityReportRequestSchema,
226
229
  winnabilityClassSchema
227
- } from "./chunk-YQXQBFHT.js";
230
+ } from "./chunk-PXRUWG75.js";
228
231
 
229
232
  // src/cli.ts
230
233
  import { pathToFileURL } from "url";
@@ -774,7 +777,7 @@ function parseDemoTrustedProxies(values) {
774
777
  async function demoCommand(options) {
775
778
  const { host, port } = parseDemoListenOptions(options);
776
779
  const trustProxy = parseDemoTrustedProxies(options.trustProxy);
777
- const { createDemoServer } = await import("./demo-server-BXABH765.js");
780
+ const { createDemoServer } = await import("./demo-server-INMOE4BA.js");
778
781
  const app = await createDemoServer({ trustProxy });
779
782
  let stopping = false;
780
783
  const stop = () => {
@@ -1188,7 +1191,7 @@ No DB writes performed. Re-run without --dry-run to apply.`);
1188
1191
  }
1189
1192
  }
1190
1193
  async function backfillInsightsCommand(project2, opts) {
1191
- const { IntelligenceService } = await import("./intelligence-service-EIWYQYVG.js");
1194
+ const { IntelligenceService } = await import("./intelligence-service-IBUS2IND.js");
1192
1195
  const config = loadConfig();
1193
1196
  const db = createClient(config.database);
1194
1197
  migrate(db);
@@ -13571,7 +13574,10 @@ async function createProject(name, opts) {
13571
13574
  language: opts.language,
13572
13575
  providers: opts.providers ?? [],
13573
13576
  providerModels: opts.providerModels ?? {},
13574
- ...opts.providerDispatchModes && Object.keys(opts.providerDispatchModes).length > 0 ? { providerDispatchModes: opts.providerDispatchModes } : {}
13577
+ ...opts.providerDispatchModes && Object.keys(opts.providerDispatchModes).length > 0 ? { providerDispatchModes: opts.providerDispatchModes } : {},
13578
+ // Sent only when given: this PUT also re-runs over an existing project,
13579
+ // and an omitted budget keeps the stored one.
13580
+ ...opts.siteAuditMaxPages !== void 0 ? { siteAuditMaxPages: opts.siteAuditMaxPages } : {}
13575
13581
  });
13576
13582
  warnDroppedDispatchModes(opts.providerDispatchModes ?? {}, result);
13577
13583
  if (isMachineFormat(opts.format)) {
@@ -13655,6 +13661,9 @@ async function showProject(name, format) {
13655
13661
  const dispatchModes = Object.entries(project2.providerDispatchModes ?? {}).sort(([left], [right]) => left.localeCompare(right));
13656
13662
  console.log(` Dispatch modes: ${dispatchModes.length > 0 ? `${dispatchModes.map(([provider, mode]) => `${provider}=${mode}`).join(", ")} (scheduled sweeps; others sync)` : "(none; every provider runs sync)"}`);
13657
13663
  console.log(` Negative reviews: ${resolveNegativeReviewMaxStars(project2.negativeReviewMaxStars)} stars or fewer${project2.negativeReviewMaxStars == null ? " (default)" : ""}`);
13664
+ if (project2.siteAuditMaxPages !== void 0) {
13665
+ console.log(` Site Health page budget: ${formatSiteAuditPageBudget(project2.siteAuditMaxPages)}`);
13666
+ }
13658
13667
  console.log(` Tags: ${project2.tags.length > 0 ? project2.tags.join(", ") : "(none)"}`);
13659
13668
  const labelEntries = Object.entries(project2.labels);
13660
13669
  console.log(` Labels: ${labelEntries.length > 0 ? labelEntries.map(([k, v]) => `${k}=${v}`).join(", ") : "(none)"}`);
@@ -13738,7 +13747,10 @@ async function updateProjectSettings(name, opts) {
13738
13747
  autoExtractBacklinks: project2.autoExtractBacklinks,
13739
13748
  // Sent only when asked for: the server keeps the stored threshold when the
13740
13749
  // field is absent, so a stale read cannot overwrite a newer setting.
13741
- ...opts.negativeReviewMaxStars !== void 0 ? { negativeReviewMaxStars: opts.negativeReviewMaxStars } : {}
13750
+ ...opts.negativeReviewMaxStars !== void 0 ? { negativeReviewMaxStars: opts.negativeReviewMaxStars } : {},
13751
+ // Same for the page budget: never echoed from the read above, so an edit
13752
+ // that does not touch it cannot overwrite a newer one or send a stray null.
13753
+ ...opts.siteAuditMaxPages !== void 0 ? { siteAuditMaxPages: opts.siteAuditMaxPages } : {}
13742
13754
  });
13743
13755
  warnDroppedDispatchModes(touchesDispatch ? providerDispatchModes : project2.providerDispatchModes ?? {}, result);
13744
13756
  if (isMachineFormat(opts.format)) {
@@ -13853,7 +13865,7 @@ async function setDefaultLocation(project2, label, format) {
13853
13865
  var PROJECT_CLI_COMMANDS = [
13854
13866
  {
13855
13867
  path: ["project", "create"],
13856
- usage: "canonry project create <name> [--domain <domain>] [--owned-domain <domain>...] [--alias <name>...] [--qualified-alias <name>...] [--country <code>] [--language <lang>] [--display-name <name>] [--provider <name>...] [--provider-model provider=model...] [--dispatch-mode provider=sync|batch...] [--format json]",
13868
+ usage: "canonry project create <name> [--domain <domain>] [--owned-domain <domain>...] [--alias <name>...] [--qualified-alias <name>...] [--country <code>] [--language <lang>] [--display-name <name>] [--provider <name>...] [--provider-model provider=model...] [--dispatch-mode provider=sync|batch...] [--site-audit-max-pages <1-50000|full>] [--format json]",
13857
13869
  help: "Create a project. Pass --domain for the public site to scan. Provider credentials are not required for Page Health.",
13858
13870
  options: {
13859
13871
  domain: { type: "string", short: "d" },
@@ -13865,13 +13877,14 @@ var PROJECT_CLI_COMMANDS = [
13865
13877
  "display-name": stringOption(),
13866
13878
  provider: multiStringOption(),
13867
13879
  "provider-model": multiStringOption(),
13868
- "dispatch-mode": multiStringOption()
13880
+ "dispatch-mode": multiStringOption(),
13881
+ "site-audit-max-pages": stringOption()
13869
13882
  },
13870
13883
  run: async (input) => {
13871
13884
  const name = requireProject(
13872
13885
  input,
13873
13886
  "project.create",
13874
- "canonry project create <name> [--domain <domain>] [--owned-domain <domain>...] [--alias <name>...] [--qualified-alias <name>...] [--country <code>] [--language <lang>] [--display-name <name>] [--provider <name>...] [--provider-model provider=model...] [--dispatch-mode provider=sync|batch...] [--format json]"
13887
+ "canonry project create <name> [--domain <domain>] [--owned-domain <domain>...] [--alias <name>...] [--qualified-alias <name>...] [--country <code>] [--language <lang>] [--display-name <name>] [--provider <name>...] [--provider-model provider=model...] [--dispatch-mode provider=sync|batch...] [--site-audit-max-pages <1-50000|full>] [--format json]"
13875
13888
  );
13876
13889
  await createProject(name, {
13877
13890
  domain: getString(input.values, "domain") ?? name,
@@ -13884,13 +13897,14 @@ var PROJECT_CLI_COMMANDS = [
13884
13897
  providers: getStringArray(input.values, "provider") ?? [],
13885
13898
  providerModels: parseProviderModelAssignments(getStringArray(input.values, "provider-model")),
13886
13899
  providerDispatchModes: parseDispatchModeAssignments(getStringArray(input.values, "dispatch-mode")),
13900
+ siteAuditMaxPages: parseSiteAuditMaxPages(getString(input.values, "site-audit-max-pages"), "project.create"),
13887
13901
  format: input.format
13888
13902
  });
13889
13903
  }
13890
13904
  },
13891
13905
  {
13892
13906
  path: ["project", "update"],
13893
- usage: "canonry project update <name> [--domain <domain>] [--owned-domain <domain>...] [--add-domain <domain>...] [--remove-domain <domain>...] [--alias <name>...] [--add-alias <name>...] [--remove-alias <name>...] [--add-qualified-alias <name>...] [--remove-qualified-alias <name>...] [--country <code>] [--language <lang>] [--display-name <name>] [--provider <name>...] [--all-providers] [--provider-model provider=model...] [--clear-provider-model <provider>...] [--dispatch-mode provider=sync|batch...] [--clear-dispatch-mode <provider>...] [--negative-review-max-stars <1-4|default>] [--format json]",
13907
+ usage: "canonry project update <name> [--domain <domain>] [--owned-domain <domain>...] [--add-domain <domain>...] [--remove-domain <domain>...] [--alias <name>...] [--add-alias <name>...] [--remove-alias <name>...] [--add-qualified-alias <name>...] [--remove-qualified-alias <name>...] [--country <code>] [--language <lang>] [--display-name <name>] [--provider <name>...] [--all-providers] [--provider-model provider=model...] [--clear-provider-model <provider>...] [--dispatch-mode provider=sync|batch...] [--clear-dispatch-mode <provider>...] [--negative-review-max-stars <1-4|default>] [--site-audit-max-pages <1-50000|full>] [--format json]",
13894
13908
  options: {
13895
13909
  domain: { type: "string", short: "d" },
13896
13910
  "owned-domain": multiStringOption(),
@@ -13910,13 +13924,14 @@ var PROJECT_CLI_COMMANDS = [
13910
13924
  "clear-provider-model": multiStringOption(),
13911
13925
  "dispatch-mode": multiStringOption(),
13912
13926
  "clear-dispatch-mode": multiStringOption(),
13913
- "negative-review-max-stars": stringOption()
13927
+ "negative-review-max-stars": stringOption(),
13928
+ "site-audit-max-pages": stringOption()
13914
13929
  },
13915
13930
  run: async (input) => {
13916
13931
  const name = requireProject(
13917
13932
  input,
13918
13933
  "project.update",
13919
- "canonry project update <name> [--domain <domain>] [--owned-domain <domain>...] [--add-domain <domain>...] [--remove-domain <domain>...] [--alias <name>...] [--add-alias <name>...] [--remove-alias <name>...] [--add-qualified-alias <name>...] [--remove-qualified-alias <name>...] [--country <code>] [--language <lang>] [--display-name <name>] [--provider <name>...] [--all-providers] [--provider-model provider=model...] [--clear-provider-model <provider>...] [--dispatch-mode provider=sync|batch...] [--clear-dispatch-mode <provider>...] [--negative-review-max-stars <1-4|default>] [--format json]"
13934
+ "canonry project update <name> [--domain <domain>] [--owned-domain <domain>...] [--add-domain <domain>...] [--remove-domain <domain>...] [--alias <name>...] [--add-alias <name>...] [--remove-alias <name>...] [--add-qualified-alias <name>...] [--remove-qualified-alias <name>...] [--country <code>] [--language <lang>] [--display-name <name>] [--provider <name>...] [--all-providers] [--provider-model provider=model...] [--clear-provider-model <provider>...] [--dispatch-mode provider=sync|batch...] [--clear-dispatch-mode <provider>...] [--negative-review-max-stars <1-4|default>] [--site-audit-max-pages <1-50000|full>] [--format json]"
13920
13935
  );
13921
13936
  const providers = getStringArray(input.values, "provider");
13922
13937
  const allProviders = getBoolean(input.values, "all-providers");
@@ -13950,6 +13965,7 @@ var PROJECT_CLI_COMMANDS = [
13950
13965
  dispatchModes,
13951
13966
  clearDispatchModes,
13952
13967
  negativeReviewMaxStars: parseNegativeReviewMaxStars(getString(input.values, "negative-review-max-stars")),
13968
+ siteAuditMaxPages: parseSiteAuditMaxPages(getString(input.values, "site-audit-max-pages"), "project.update"),
13953
13969
  format: input.format
13954
13970
  });
13955
13971
  }
@@ -14101,6 +14117,19 @@ function parseNegativeReviewMaxStars(raw) {
14101
14117
  }
14102
14118
  return parsed.data;
14103
14119
  }
14120
+ function parseSiteAuditMaxPages(raw, command) {
14121
+ if (raw === void 0) return void 0;
14122
+ const value = raw.trim();
14123
+ if (value.toLowerCase() === "full") return null;
14124
+ const parsed = /^\d+$/.test(value) ? siteAuditPageBudgetSchema.safeParse(Number(value)) : void 0;
14125
+ if (!parsed?.success) {
14126
+ throw usageError(`Error: --site-audit-max-pages must be a whole number of pages from 1 to ${SITE_AUDIT_MAX_PAGE_LIMIT}, or "full" for the full site`, {
14127
+ message: `--site-audit-max-pages must be 1-${SITE_AUDIT_MAX_PAGE_LIMIT} or "full"`,
14128
+ details: { command, option: "site-audit-max-pages", value: raw }
14129
+ });
14130
+ }
14131
+ return parsed.data;
14132
+ }
14104
14133
 
14105
14134
  // src/commands/organic-evidence.ts
14106
14135
  async function showOrganicEvidence(project2, opts) {
@@ -18909,7 +18938,7 @@ var TECHNICAL_AEO_CLI_COMMANDS_BASE = [
18909
18938
  {
18910
18939
  path: ["technical-aeo", "run"],
18911
18940
  usage: "canonry technical-aeo run <project> [--sitemap-url <url>] [--max-pages <n>] [--max-edges <n>] [--max-depth <n>] [--check-dead-links] [--wait] [--format json]",
18912
- help: "Start a Site Health crawl. No answer-engine provider is required. --wait polls for up to 15 minutes. Dead-link checking is off unless --check-dead-links is set.",
18941
+ help: "Start a Site Health crawl. No answer-engine provider is required. Without --max-pages the scan uses the project's saved page budget (canonry project update <project> --site-audit-max-pages <n|full>), else the full site, up to 50,000 pages. --wait polls for up to 15 minutes, so a large full-site scan can outlast it; follow it with canonry technical-aeo progress <project> --run-id <id>. Dead-link checking is off unless --check-dead-links is set.",
18913
18942
  options: {
18914
18943
  "sitemap-url": stringOption(),
18915
18944
  limit: stringOption(),
@@ -5,11 +5,11 @@ import {
5
5
  computeFactorAverages,
6
6
  layoutSiteCrawlGraphInput,
7
7
  persistSiteCrawlGraphLayout
8
- } from "./chunk-QND5LEAC.js";
8
+ } from "./chunk-XFVJ6QVE.js";
9
9
  import {
10
10
  PACKAGE_VERSION,
11
11
  canonryMcpTools
12
- } from "./chunk-FWV6IIYY.js";
12
+ } from "./chunk-JU6TPMCJ.js";
13
13
  import {
14
14
  HISTORY_WINDOW_RUNS,
15
15
  IntelligenceService,
@@ -83,7 +83,7 @@ import {
83
83
  siteCrawlPages,
84
84
  siteCrawlSnapshots,
85
85
  trafficSources
86
- } from "./chunk-XODXE6PT.js";
86
+ } from "./chunk-SWSWCUHS.js";
87
87
  import {
88
88
  RunKinds,
89
89
  SiteCrawlFetchStates,
@@ -112,7 +112,7 @@ import {
112
112
  roundPreservingTotal,
113
113
  siteAuditPageFactorSchema,
114
114
  wilsonInterval
115
- } from "./chunk-YQXQBFHT.js";
115
+ } from "./chunk-PXRUWG75.js";
116
116
 
117
117
  // src/demo-server.ts
118
118
  import { dirname, join as join2 } from "path";
package/dist/index.js CHANGED
@@ -3,14 +3,14 @@ import {
3
3
  createGoogleMarketingCredentialStore,
4
4
  createGoogleMarketingRuntime,
5
5
  createServer
6
- } from "./chunk-MQPBOQUH.js";
6
+ } from "./chunk-GEKMHZS2.js";
7
7
  import {
8
8
  loadConfig
9
- } from "./chunk-RVELNJAW.js";
10
- import "./chunk-QND5LEAC.js";
11
- import "./chunk-FWV6IIYY.js";
12
- import "./chunk-XODXE6PT.js";
13
- import "./chunk-YQXQBFHT.js";
9
+ } from "./chunk-TNLOOXUP.js";
10
+ import "./chunk-XFVJ6QVE.js";
11
+ import "./chunk-JU6TPMCJ.js";
12
+ import "./chunk-SWSWCUHS.js";
13
+ import "./chunk-PXRUWG75.js";
14
14
  export {
15
15
  GoogleMarketingRuntimeError,
16
16
  createGoogleMarketingCredentialStore,
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  HISTORY_WINDOW_RUNS,
3
3
  IntelligenceService
4
- } from "./chunk-XODXE6PT.js";
5
- import "./chunk-YQXQBFHT.js";
4
+ } from "./chunk-SWSWCUHS.js";
5
+ import "./chunk-PXRUWG75.js";
6
6
  export {
7
7
  HISTORY_WINDOW_RUNS,
8
8
  IntelligenceService
package/dist/mcp.js CHANGED
@@ -1,15 +1,15 @@
1
1
  import {
2
2
  autoSyncSkills
3
- } from "./chunk-3JEUZ2K5.js";
3
+ } from "./chunk-ZP6GF32R.js";
4
4
  import {
5
5
  createApiClient,
6
6
  createCanonryMcpServer
7
- } from "./chunk-RVELNJAW.js";
8
- import "./chunk-FWV6IIYY.js";
7
+ } from "./chunk-TNLOOXUP.js";
8
+ import "./chunk-JU6TPMCJ.js";
9
9
  import {
10
10
  isReadOnlyKey,
11
11
  updateCheckEnvOptOut
12
- } from "./chunk-YQXQBFHT.js";
12
+ } from "./chunk-PXRUWG75.js";
13
13
 
14
14
  // src/mcp/cli.ts
15
15
  import { randomUUID } from "crypto";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@canonry/canonry",
3
- "version": "7.3.0",
3
+ "version": "7.4.0",
4
4
  "type": "module",
5
5
  "description": "Self-hosted AI visibility (AEO) platform: track how ChatGPT, Claude, Gemini, and Perplexity cite your domain, join it with Search Console, GA4, server-side traffic, and paid media, and fix what you find through agent tools (CLI, REST, MCP). Local SQLite.",
6
6
  "keywords": [
@@ -92,27 +92,27 @@
92
92
  "@ainyc/canonry-contracts": "0.0.0",
93
93
  "@ainyc/canonry-db": "0.0.0",
94
94
  "@ainyc/canonry-integration-bing": "0.0.0",
95
- "@ainyc/canonry-integration-cloudflare-queue": "0.0.0",
96
95
  "@ainyc/canonry-integration-cloud-run": "0.0.0",
97
- "@ainyc/canonry-integration-google": "0.0.0",
98
- "@ainyc/canonry-integration-google-ads": "0.0.0",
96
+ "@ainyc/canonry-integration-cloudflare-queue": "0.0.0",
99
97
  "@ainyc/canonry-integration-cloudflare-worker": "0.0.0",
100
- "@ainyc/canonry-integration-google-business-profile": "0.0.0",
101
98
  "@ainyc/canonry-integration-commoncrawl": "0.0.0",
102
- "@ainyc/canonry-integration-openai-ads": "0.0.0",
103
- "@ainyc/canonry-integration-google-places": "0.0.0",
99
+ "@ainyc/canonry-integration-google-ads": "0.0.0",
100
+ "@ainyc/canonry-integration-google-business-profile": "0.0.0",
101
+ "@ainyc/canonry-integration-google": "0.0.0",
104
102
  "@ainyc/canonry-integration-google-tag-manager": "0.0.0",
105
- "@ainyc/canonry-integration-wordpress": "0.0.0",
103
+ "@ainyc/canonry-integration-google-places": "0.0.0",
104
+ "@ainyc/canonry-integration-openai-ads": "0.0.0",
106
105
  "@ainyc/canonry-integration-traffic": "0.0.0",
106
+ "@ainyc/canonry-provider-claude": "0.0.0",
107
+ "@ainyc/canonry-integration-wordpress": "0.0.0",
107
108
  "@ainyc/canonry-provider-cdp": "0.0.0",
109
+ "@ainyc/canonry-provider-gemini": "0.0.0",
110
+ "@ainyc/canonry-provider-muse": "0.0.0",
108
111
  "@ainyc/canonry-intelligence": "0.0.0",
109
112
  "@ainyc/canonry-provider-local": "0.0.0",
110
- "@ainyc/canonry-provider-claude": "0.0.0",
111
- "@ainyc/canonry-provider-gemini": "0.0.0",
112
- "@ainyc/canonry-provider-perplexity": "0.0.0",
113
+ "@ainyc/canonry-provider-openai": "0.0.0",
113
114
  "@ainyc/canonry-integration-typesafe": "0.0.0",
114
- "@ainyc/canonry-provider-muse": "0.0.0",
115
- "@ainyc/canonry-provider-openai": "0.0.0"
115
+ "@ainyc/canonry-provider-perplexity": "0.0.0"
116
116
  },
117
117
  "scripts": {
118
118
  "build": "pnpm run build:cli && pnpm run build:web",