@canonry/canonry 5.19.0 → 5.19.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.
Files changed (32) hide show
  1. package/assets/agent-workspace/skills/aero/SKILL.md +13 -8
  2. package/assets/agent-workspace/skills/aero/references/portfolio-analysis.md +27 -10
  3. package/assets/agent-workspace/skills/canonry/references/canonry-cli.md +4 -1
  4. package/assets/assets/{AuditHistoryPanel-C_p8jX7Q.js → AuditHistoryPanel-ddq5tdlB.js} +1 -1
  5. package/assets/assets/{BacklinksPage-jD4nOGw1.js → BacklinksPage-g57_xzTX.js} +1 -1
  6. package/assets/assets/{HistoryPage-DJGBbtBY.js → HistoryPage-C-TdCUQ2.js} +1 -1
  7. package/assets/assets/{MeasurementPropertyPage-Dmr3TVlo.js → MeasurementPropertyPage-CAADmNfw.js} +1 -1
  8. package/assets/assets/{ProjectPage-B_haCKiA.js → ProjectPage-CoBwpHmA.js} +1 -1
  9. package/assets/assets/{RunRow-BMbwR2yk.js → RunRow-BpG0Zy-x.js} +1 -1
  10. package/assets/assets/{RunsPage-D8hHakq2.js → RunsPage-DK3pb1LH.js} +1 -1
  11. package/assets/assets/{SettingsPage-QKnRcFA9.js → SettingsPage-BruiY8Zh.js} +1 -1
  12. package/assets/assets/{SiteHealthSection-CDkUXqmb.js → SiteHealthSection-De4U11Gv.js} +3 -3
  13. package/assets/assets/{TrafficPage-CMif8RlM.js → TrafficPage-BVolLXT2.js} +1 -1
  14. package/assets/assets/{TrafficSourceDetailPage-DOCTP_4-.js → TrafficSourceDetailPage-CFDb6lPD.js} +1 -1
  15. package/assets/assets/{extract-error-message-Dm8RvYE5.js → extract-error-message-Bk1RTjzo.js} +1 -1
  16. package/assets/assets/{index-lj0fuFl4.js → index-B--AA1mG.js} +44 -44
  17. package/assets/assets/{react-sigma_core.esm.min-DOPuwLtN.js → react-sigma_core.esm.min--QXVK1JS.js} +1 -1
  18. package/assets/assets/{v2-overview-adapter-C19tUcDS.js → v2-overview-adapter-CpjJPZsC.js} +1 -1
  19. package/assets/index.html +1 -1
  20. package/dist/{chunk-P2EFPLIO.js → chunk-3IAIW5KH.js} +530 -132
  21. package/dist/{chunk-YHKKCXGY.js → chunk-4WROKFN6.js} +24 -8
  22. package/dist/{chunk-SPCEXW3B.js → chunk-EJXDABGU.js} +9 -3
  23. package/dist/{chunk-GUJY3RIM.js → chunk-EJZFTNZG.js} +439 -180
  24. package/dist/{chunk-ABUO27BV.js → chunk-J3JXJIST.js} +3 -3
  25. package/dist/{chunk-QJWIOCEO.js → chunk-PGOID3LE.js} +2 -2
  26. package/dist/{chunk-WLL7Q7JD.js → chunk-SOCYTKTF.js} +195 -23
  27. package/dist/cli.js +72 -16
  28. package/dist/{demo-server-BOIBS74F.js → demo-server-BLDYKCFS.js} +4 -4
  29. package/dist/index.js +6 -6
  30. package/dist/{intelligence-service-IWR2H6OW.js → intelligence-service-3MHYLKMS.js} +2 -2
  31. package/dist/mcp.js +4 -4
  32. package/package.json +11 -11
@@ -105,7 +105,7 @@ import {
105
105
  trafficEventKindSchema,
106
106
  trafficSeriesGranularitySchema,
107
107
  visibilityReportRequestSchema
108
- } from "./chunk-WLL7Q7JD.js";
108
+ } from "./chunk-SOCYTKTF.js";
109
109
 
110
110
  // src/cli-error.ts
111
111
  function isMachineFormat(format) {
@@ -398,7 +398,12 @@ var measurementPropertyEvidenceInputSchema = measurementPropertyEvidenceQuerySch
398
398
  )
399
399
  }).strict();
400
400
  var measurementPortfolioSummaryInputSchema = measurementPortfolioSummaryQuerySchema.extend({
401
- project: projectNameSchema
401
+ project: projectNameSchema,
402
+ groupKey: measurementPortfolioSummaryQuerySchema.shape.groupKey.describe("A market stable key (a row's metro.groupKey). Scopes rows to that market and lists its direct submarkets."),
403
+ // Capped below the route's 50: past about 10 rows the per-row evidence
404
+ // (names given instead, cited domains) no longer fits the tool-result cap.
405
+ limit: z3.number().int().positive().max(10).optional().describe("Rows per list, at most 10. Default 4 keeps the whole result under the tool-result cap; prefer groupKey over a larger limit."),
406
+ includeNestedMarkets: measurementPortfolioSummaryQuerySchema.shape.includeNestedMarkets.describe("Every market at every level, uncapped. Off by default; large portfolios exceed the cap with it on.")
402
407
  }).strict();
403
408
  var measurementPropertyQuestionsInputSchema = measurementPropertyQuestionsQuerySchema.extend({
404
409
  project: projectNameSchema
@@ -1279,22 +1284,33 @@ var canonryMcpTools = [
1279
1284
  defineTool({
1280
1285
  name: "canonry_analytics_sources",
1281
1286
  title: "Get cited-source rankings",
1282
- description: "Where AI engines get the facts they cite for a project. Returns the FULL ranked list of cited domains (not truncated) \u2014 each tagged with a category and an actionable surface class (own / direct-competitor / ota-aggregator / editorial-media / other) \u2014 plus a surface-class roll-up and a per-provider breakdown (each provider's cited-domain mix + total cited slots). The surface class is deterministic (own/competitor from project data, the rest from the source allow-list) and enriched by discovery's stored per-domain classifications when present \u2014 no new LLM calls. Probe-excluded, window-filterable (7d/30d/90d/all). Use `limit` to cap each ranked list to the top N domains (an explicit long-tail rollup preserves the totals). All counts/shares/classification are computed server-side.",
1287
+ description: "Where AI engines cite from for a project: cited domains ranked by how many answers cite them, each tagged with a category and a surface class (own / direct-competitor / ota-aggregator / editorial-media / other), plus a surface-class roll-up and a per-provider breakdown. Project-wide: without `runId` it pools every sweep in the window (`runCount` says how many); without `queryClass` it pools branded and non-brand answers, where branded queries inflate your own domain. For the sources behind non-brand answers, set `queryClass=non-brand` and the latest `runId`; on a v2 measurement plan the class comes from the plan, the same answers as canonry_competitor_landscape with scope=all-markets. Counts come from each answer's stored source list, so every engine is included, Gemini too. A domain counts at most once per answer; `answerShare` is the share of all answers in scope that cite it. `providersWithoutSources` names engines that answered but cited nothing. `limit` caps each ranked list (default 10 for this tool, which keeps each engine list whole); a long-tail rollup keeps the totals. The per-query breakdown is omitted unless `includeByQuery` is true. No LLM calls; probe runs excluded.",
1283
1288
  access: "read",
1284
1289
  tier: "monitoring",
1285
1290
  inputSchema: z3.object({
1286
1291
  project: projectNameSchema,
1287
1292
  window: analyticsWindowSchema.optional().describe("Time range: 7d, 30d, 90d, or all (default all)."),
1288
- limit: z3.number().int().positive().optional().describe("Cap each ranked list to the top N domains. Omit for the full list.")
1293
+ limit: z3.number().int().positive().max(50).optional().describe("Cap each ranked list to the top N domains. Default 10; larger lists can exceed the tool-result cap."),
1294
+ runId: z3.string().trim().min(1).optional().describe("Read one answer-visibility run (for example the latest sweep) instead of pooling every run in the window."),
1295
+ queryClass: z3.enum(["all", "branded", "non-brand"]).optional().describe("Branded or non-brand answers only. With an active v2 measurement plan the class comes from the plan assignments. Default all pools both classes."),
1296
+ includeByQuery: z3.boolean().optional().describe("Include the per-query breakdown. It is large; default false for this tool.")
1289
1297
  }),
1290
1298
  annotations: readAnnotations(),
1291
1299
  openApiOperations: ["GET /api/v1/projects/{name}/analytics/sources"],
1292
- handler: (client, input) => client.getAnalyticsSources(input.project, { window: input.window, limit: input.limit })
1300
+ handler: (client, input) => client.getAnalyticsSources(input.project, {
1301
+ window: input.window,
1302
+ // The full ranked lists run past the agent's tool-result cap on a large
1303
+ // project, and the per-engine lists are the first thing lost.
1304
+ limit: input.limit ?? 10,
1305
+ runId: input.runId,
1306
+ queryClass: input.queryClass,
1307
+ includeByQuery: input.includeByQuery ?? false
1308
+ })
1293
1309
  }),
1294
1310
  defineTool({
1295
1311
  name: "canonry_competitor_landscape",
1296
1312
  title: "Get historical competitor landscape",
1297
- description: "Returns pinned competitors first, then observed direct competitors and other cited sources from stored answer/source evidence only. Mention share is percentage points (0..100) from answer text; citations are independent. The response carries basis (tracked or observed), availability, and reason. Pins exclusively define the comparison set when present. Otherwise at least 3 stored direct competitors must each be mentioned in 3 answers in the selected scope; raw names and platforms never enter that denominator. Without a comparison set the ratio is null, never 100%. The full comparison array is uncapped. Share of voice needs ONE query class: `queryClass=all`, and omitting it, pool branded and non-brand, so every `shareOfVoice` comes back null and only the counts are published. Pass `queryClass=non-brand` (or `branded`) for a ratio, exactly as visibility-stats does. A project with no brand name or alias cannot be split by class, so a class-scoped read on one is refused rather than answered empty. Optional groupBy: model adds provider/requested-model groups with separate served-model evidence and sample counts. Optional model filters one exact requested model ID and requires provider. Unknown historical models remain explicit. Groups are not a matched-query or equal-weight comparison. Advanced reads support one market group or explicit scope: all-markets. No provider, discovery, or classifier work runs. Ranked lists are capped at 100 observed/other-source rows per group; pins remain complete. Model groups are capped at 50 and disclose truncation.",
1313
+ description: "Returns pinned competitors first, then observed direct competitors and other cited sources from stored answer/source evidence only. Mention share is percentage points (0..100) from answer text; citations are independent. The response carries basis (tracked or observed), availability, and reason. Pins exclusively define the comparison set when present. Otherwise at least 3 stored direct competitors must each be mentioned in 3 answers in the selected scope; raw names and platforms never enter that denominator. Without a comparison set the ratio is null, never 100%. The full comparison array is uncapped. Share of voice needs ONE query class: `queryClass=all`, and omitting it, pool branded and non-brand, so every `shareOfVoice` comes back null and only the counts are published. Pass `queryClass=non-brand` (or `branded`) for a ratio, exactly as visibility-stats does. A project with no brand name or alias cannot be split by class, so a class-scoped read on one is refused rather than answered empty. Optional groupBy: model adds provider/requested-model groups with separate served-model evidence and sample counts. Optional model filters one exact requested model ID and requires provider. Unknown historical models remain explicit. Groups are not a matched-query or equal-weight comparison. Advanced reads support one market group or explicit scope: all-markets. On a project with an active v2 measurement plan, queryClass=branded or non-brand with no scope or groupKey defaults to scope=all-markets, so classes come from the plan; pass scope=project to force the text classifier. No provider, discovery, or classifier work runs. Ranked lists are capped at 100 observed/other-source rows per group; pins remain complete. `observedNames` are names written in answer text, not cited sources, capped at the top 50 by answer count; `observedNamesTotal` is the full count. Model groups are capped at 50 and disclose truncation.",
1298
1314
  access: "read",
1299
1315
  tier: "monitoring",
1300
1316
  inputSchema: competitorLandscapeInputSchema,
@@ -2438,7 +2454,7 @@ var canonryMcpTools = [
2438
2454
  defineTool({
2439
2455
  name: "canonry_measurement_plan_get",
2440
2456
  title: "Get measurement plan",
2441
- description: "Get the active measurement plan for a project.",
2457
+ description: "Get the active measurement plan for a project: plan structure only (targets, groups, query assignments), no metrics. It can be very large on a big portfolio; for analysis prefer canonry_measurement_portfolio_summary and canonry_measurement_overview.",
2442
2458
  access: "read",
2443
2459
  tier: "setup",
2444
2460
  inputSchema: projectInputSchema,
@@ -2557,7 +2573,7 @@ var canonryMcpTools = [
2557
2573
  defineTool({
2558
2574
  name: "canonry_measurement_portfolio_summary",
2559
2575
  title: "Summarize measured Properties",
2560
- description: "Start here for best/worst Property mention performance. Defaults to non-brand questions; state the returned queryClass and keep branded comparisons separate unless all was requested. mentionRanking.strongest and .weakest rank every Property with an available mention rate before applying limit, independently of citation availability or an unavailable portfolio aggregate. mentionRanking.excluded names every excluded Property and its reason; flag those separately, never call all mention rankings unavailable because one identity is ambiguous. Report numerator/denominator with each rate, and any unattributed count beside it: answers left out of both because their Property identity was unresolved, never not-mentioned answers. Rates may tie (stable label/key order); this is descriptive coverage, not a confidence-adjusted or unique-winner claim. weakestProperties retains combined mention/citation weaknesses with stored replacement names; markets compares every named market worst-first. Each market is scoped to the displayed run; markets may share Properties, so they never sum to portfolio totals. Reads stored data only; it never starts provider work.",
2576
+ description: "Start here for best and worst Properties. One call returns the weakest Properties, the names answers wrote instead of them, and the domains engines cited for them. Defaults to non-brand queries; state the returned queryClass and never pool branded with non-brand. Keep the default limit; for more rows narrow with groupKey (a metro) rather than raising limit, which can overflow the tool-result cap. Mention (answer text names the Property) and citation (a source URL on its page) are separate: report each as numerator/denominator, with any unattributed count beside mention. Denominators count answers, one per query per engine (queries x engines = answers). Group Properties only by each row's metro and submarkets, never by label. namedInsteadInAnswerText lists names written in the answer text of answers that neither named nor cited the Property, counted by answer: they are not citations. citedDomains and weakestAnswerSources count answers citing each domain, every engine included; weakestAnswerSources covers the weakest rows plus every tied Property, each answer once. When tiedAtWeakest is set, that many Properties share the weakest rates and are ordered by name, not ranked. mentionRanking.strongest/.weakest rank every Property with an available mention rate; .excluded lists the rest with reasons. markets lists one level worst-first (metros, or a groupKey's submarkets), capped at limit, with totalMarkets; includeNestedMarkets returns every level. Markets may share Properties and never sum to portfolio totals. Reads stored data only; never starts provider work.",
2561
2577
  access: "read",
2562
2578
  tier: "monitoring",
2563
2579
  inputSchema: measurementPortfolioSummaryInputSchema,
@@ -5,7 +5,7 @@ import {
5
5
  PACKAGE_VERSION,
6
6
  canonryMcpTools,
7
7
  isMachineFormat
8
- } from "./chunk-YHKKCXGY.js";
8
+ } from "./chunk-4WROKFN6.js";
9
9
  import {
10
10
  AGENT_PROVIDER_IDS,
11
11
  CANONRY_NPM_PACKAGE_URL,
@@ -36,7 +36,7 @@ import {
36
36
  skillsClientSchema,
37
37
  upgradeCaveatFor,
38
38
  upgradeCommandFor
39
- } from "./chunk-WLL7Q7JD.js";
39
+ } from "./chunk-SOCYTKTF.js";
40
40
 
41
41
  // src/config.ts
42
42
  import fs from "fs";
@@ -7082,7 +7082,13 @@ var ApiClient = class {
7082
7082
  () => getApiV1ProjectsByNameAnalyticsSources({
7083
7083
  client: this.heyClient,
7084
7084
  path: { name: project },
7085
- query: { window: opts.window, limit: opts.limit }
7085
+ query: {
7086
+ window: opts.window,
7087
+ limit: opts.limit,
7088
+ runId: opts.runId,
7089
+ queryClass: opts.queryClass,
7090
+ ...opts.includeByQuery === void 0 ? {} : { includeByQuery: opts.includeByQuery ? "true" : "false" }
7091
+ }
7086
7092
  })
7087
7093
  );
7088
7094
  }