@canonry/canonry 7.10.0 → 7.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/agent-workspace/skills/aero/references/reporting.md +2 -0
- package/assets/agent-workspace/skills/canonry/references/aeo-analysis.md +1 -1
- package/assets/agent-workspace/skills/canonry/references/canonry-cli.md +30 -4
- package/assets/assets/{AuditHistoryPanel-BgcvPo6g.js → AuditHistoryPanel-Bpkuj-iF.js} +1 -1
- package/assets/assets/{BacklinksPage-DZ4tauAs.js → BacklinksPage-CbRIZhu5.js} +1 -1
- package/assets/assets/{HistoryPage-DWG52dz1.js → HistoryPage-Dfq1vK9k.js} +1 -1
- package/assets/assets/{MeasurementPropertyPage-DTx2iQLV.js → MeasurementPropertyPage-DcH0zYNN.js} +1 -1
- package/assets/assets/ProjectPage-enF4twWt.js +8 -0
- package/assets/assets/{RunsPage-B6MhRqxN.js → RunsPage-aOeJ60pX.js} +1 -1
- package/assets/assets/{SettingsPage-Bxv7OSHT.js → SettingsPage-nA0_ImoQ.js} +1 -1
- package/assets/assets/{SiteHealthSection-C5x7oiFL.js → SiteHealthSection-CUOt7jeo.js} +3 -3
- package/assets/assets/{TrafficPage-C5gyQopi.js → TrafficPage-C0fVYizx.js} +1 -1
- package/assets/assets/{TrafficSourceDetailPage-Dv2ZRNvN.js → TrafficSourceDetailPage-LMhXbFlA.js} +1 -1
- package/assets/assets/{extract-error-message-C5pr51ph.js → extract-error-message-5aHy0fsK.js} +1 -1
- package/assets/assets/index-BJh8cX5E.js +86 -0
- package/assets/assets/index-BNeiohKS.css +1 -0
- package/assets/assets/{react-sigma_core.esm.min-P5bVaYly.js → react-sigma_core.esm.min-ldX35rMq.js} +1 -1
- package/assets/assets/{v2-overview-adapter-QtI4xO_4.js → v2-overview-adapter-CaO9vY-l.js} +1 -1
- package/assets/index.html +2 -2
- package/dist/{chunk-5ZBN3EEK.js → chunk-7I64KEGM.js} +2 -2
- package/dist/{chunk-66DVP4DN.js → chunk-AU7OUDWR.js} +5786 -4450
- package/dist/{chunk-VSZJVBVR.js → chunk-BTHEFJCI.js} +60 -8
- package/dist/{chunk-FVMWUT2R.js → chunk-DXI2FTSW.js} +706 -257
- package/dist/{chunk-HL3C6Z7T.js → chunk-EPSHIH63.js} +3 -3
- package/dist/{chunk-52PHEGHT.js → chunk-GQMSJEMZ.js} +3515 -2266
- package/dist/{chunk-IKXVLT4M.js → chunk-SM6ZZAPK.js} +93 -5
- package/dist/cli.js +177 -40
- package/dist/{demo-server-WZIB4JKJ.js → demo-server-WJUA4EIG.js} +4 -4
- package/dist/index.js +6 -6
- package/dist/{intelligence-service-KC62A4X5.js → intelligence-service-DJRH4Z3D.js} +2 -2
- package/dist/mcp.js +4 -4
- package/package.json +12 -12
- package/assets/assets/ProjectPage-CCf70zbI.js +0 -8
- package/assets/assets/index-BhXHm5nG.js +0 -86
- package/assets/assets/index-Rcbm8bK1.css +0 -1
|
@@ -29,6 +29,7 @@ import {
|
|
|
29
29
|
calendarDateSchema,
|
|
30
30
|
canonicalizeGtmAccountId,
|
|
31
31
|
canonicalizeGtmResourceSelection,
|
|
32
|
+
competitorAliasBlockRequestSchema,
|
|
32
33
|
competitorAliasesRequestSchema,
|
|
33
34
|
competitorAppendRequestSchema,
|
|
34
35
|
competitorBatchRequestSchema,
|
|
@@ -138,7 +139,7 @@ import {
|
|
|
138
139
|
trafficSeriesGranularitySchema,
|
|
139
140
|
visibilityCompareSelectionSchema,
|
|
140
141
|
visibilityReportRequestSchema
|
|
141
|
-
} from "./chunk-
|
|
142
|
+
} from "./chunk-AU7OUDWR.js";
|
|
142
143
|
|
|
143
144
|
// src/cli-error.ts
|
|
144
145
|
function isMachineFormat(format) {
|
|
@@ -523,6 +524,8 @@ var runsListInputSchema = z3.object({
|
|
|
523
524
|
project: projectNameSchema,
|
|
524
525
|
limit: z3.number().int().positive().max(500).optional(),
|
|
525
526
|
kind: runListFilterQuerySchema.shape.kind.describe('Restrict to a single run kind (e.g. "answer-visibility"). Unknown values are rejected.'),
|
|
527
|
+
excludeKind: runListFilterQuerySchema.shape.excludeKind.describe('Exclude one run kind before applying the limit (e.g. "bing-inspect" omits single-URL inspections). Combines with kind and status.'),
|
|
528
|
+
excludeKinds: runListFilterQuerySchema.shape.excludeKinds.describe('Exclude multiple run kinds before applying the limit (e.g. ["bing-inspect", "traffic-sync"] keeps meaningful Activity jobs). Combines with excludeKind, kind, and status.'),
|
|
526
529
|
status: runListFilterQuerySchema.shape.status.describe('Restrict to a single run status (e.g. "running" for in-flight work, "failed" to triage). Unknown values are rejected.')
|
|
527
530
|
});
|
|
528
531
|
var runGetInputSchema = z3.object({
|
|
@@ -909,9 +912,14 @@ var competitorsAddInputSchema = z3.object({
|
|
|
909
912
|
project: projectNameSchema,
|
|
910
913
|
request: competitorAppendRequestSchema
|
|
911
914
|
});
|
|
915
|
+
var competitorDomainInputSchema = z3.string().trim().min(1).describe("Tracked competitor domain (any spelling; it resolves to the stored registrable domain).");
|
|
912
916
|
var competitorAliasesInputSchema = competitorAliasesRequestSchema.safeExtend({
|
|
913
917
|
project: projectNameSchema,
|
|
914
|
-
domain:
|
|
918
|
+
domain: competitorDomainInputSchema
|
|
919
|
+
});
|
|
920
|
+
var competitorAliasBlockInputSchema = competitorAliasBlockRequestSchema.safeExtend({
|
|
921
|
+
project: projectNameSchema,
|
|
922
|
+
domain: competitorDomainInputSchema
|
|
915
923
|
});
|
|
916
924
|
var latestSweepRunIdDescription = "A run id, or latest for the latest sweep (the run the measurement reads display). With queryClass branded or non-brand and neither runId nor window, this tool reads latest; pass window to pool every sweep in it.";
|
|
917
925
|
var competitorLandscapeInputSchema = competitorLandscapeQuerySchema.safeExtend({
|
|
@@ -1637,13 +1645,13 @@ var canonryMcpTools = [
|
|
|
1637
1645
|
defineTool({
|
|
1638
1646
|
name: "canonry_runs_list",
|
|
1639
1647
|
title: "List project runs",
|
|
1640
|
-
description: "List runs for a Canonry project. Includes both real runs (trigger='manual'/'scheduled'/'config-apply'/'backfill') AND probe runs (trigger='probe'). Probe runs are operator/agent test runs that don't influence dashboard, analytics, intelligence, or notifications \u2014 filter by `trigger !== 'probe'` if you only want runs that feed project metrics. Narrow with `kind` and/or `status` (e.g. status='running' lists only in-flight work).",
|
|
1648
|
+
description: "List runs for a Canonry project. Includes both real runs (trigger='manual'/'scheduled'/'config-apply'/'backfill') AND probe runs (trigger='probe'). Probe runs are operator/agent test runs that don't influence dashboard, analytics, intelligence, or notifications \u2014 filter by `trigger !== 'probe'` if you only want runs that feed project metrics. Narrow with `kind` and/or `status` (e.g. status='running' lists only in-flight work). Use `excludeKind` or `excludeKinds` to remove kinds before applying the limit.",
|
|
1641
1649
|
access: "read",
|
|
1642
1650
|
tier: "monitoring",
|
|
1643
1651
|
inputSchema: runsListInputSchema,
|
|
1644
1652
|
annotations: readAnnotations(),
|
|
1645
1653
|
openApiOperations: ["GET /api/v1/projects/{name}/runs"],
|
|
1646
|
-
handler: (client, input) => client.listRuns(input.project, input.limit, input.kind, input.status)
|
|
1654
|
+
handler: (client, input) => client.listRuns(input.project, input.limit, input.kind, input.status, input.excludeKind, input.excludeKinds)
|
|
1647
1655
|
}),
|
|
1648
1656
|
defineTool({
|
|
1649
1657
|
name: "canonry_runs_latest",
|
|
@@ -1957,7 +1965,7 @@ var canonryMcpTools = [
|
|
|
1957
1965
|
defineTool({
|
|
1958
1966
|
name: "canonry_competitors_list",
|
|
1959
1967
|
title: "List competitors",
|
|
1960
|
-
description: "List tracked competitors for a Canonry project, each with its operator-curated `aliases` (the names it goes by in answer text; `[]` means the domain label alone identifies it).",
|
|
1968
|
+
description: "List tracked competitors for a Canonry project, each with its operator-curated `aliases` (the names it goes by in answer text; `[]` means the domain label alone identifies it), its `autoAliases` (names detected automatically from the project's stored answers, each with its evidence) and its `blockedAliases` (names the operator blocked from auto-detection).",
|
|
1961
1969
|
access: "read",
|
|
1962
1970
|
tier: "setup",
|
|
1963
1971
|
inputSchema: projectInputSchema,
|
|
@@ -2693,7 +2701,7 @@ var canonryMcpTools = [
|
|
|
2693
2701
|
defineTool({
|
|
2694
2702
|
name: "canonry_project_upsert",
|
|
2695
2703
|
title: "Create or replace project",
|
|
2696
|
-
description: "Create or replace a Canonry project. PUT semantics: fields not in the request are reset to their defaults. Provide the full intended project shape. Exceptions: an omitted providerDispatchModes (provider \u2192 sync|batch for scheduled sweeps) keeps the stored preference; send {} to clear it. An omitted qualifiedAliases (the aliases Simple sentiment treats as this brand's own names) keeps the stored list, minus names that no longer qualify (a removed alias, a spelling of the display name, or a competitor's name); send [] to clear it. Competitors are not part of this request, but a new identity (display name, aliases, domains) that claims a tracked competitor's curated alias drops that alias, and the drop is audited. An omitted siteAuditMaxPages (the Site Health page budget for scans that set none, 1 to 50,000) keeps the stored budget; send null for the full site.",
|
|
2704
|
+
description: "Create or replace a Canonry project. PUT semantics: fields not in the request are reset to their defaults. Provide the full intended project shape. Exceptions: an omitted providerDispatchModes (provider \u2192 sync|batch for scheduled sweeps) keeps the stored preference; send {} to clear it. An omitted qualifiedAliases (the aliases Simple sentiment treats as this brand's own names) keeps the stored list, minus names that no longer qualify (a removed alias, a spelling of the display name, or a competitor's name); send [] to clear it. Competitors are not part of this request, but a new identity (display name, aliases, domains) that claims a tracked competitor's curated alias drops that alias, and the drop is audited. An omitted siteAuditMaxPages (the Site Health page budget for scans that set none, 1 to 50,000) keeps the stored budget; send null for the full site. An omitted competitorAutoAliases keeps the stored answer-derived competitor alias mode: `off` (no unattended detection pass), `preview` (the default: detect and log, store nothing) or `apply` (store the detected names, which restates history).",
|
|
2697
2705
|
access: "write",
|
|
2698
2706
|
tier: "setup",
|
|
2699
2707
|
inputSchema: projectUpsertInputSchema,
|
|
@@ -2704,7 +2712,7 @@ var canonryMcpTools = [
|
|
|
2704
2712
|
defineTool({
|
|
2705
2713
|
name: "canonry_apply_config",
|
|
2706
2714
|
title: "Apply project config",
|
|
2707
|
-
description: "Apply one Canonry config-as-code project document. Replaces the project to match the config; fields omitted from the spec are reset to defaults, with these exceptions: a spec with neither queries nor keywords leaves the tracked-query basket unchanged (to clear the basket, pass an explicit empty queries list); an omitted providerDispatchModes keeps the stored preference; an omitted qualifiedAliases keeps the stored list, minus names that no longer qualify (a removed alias, a spelling of the display name, or a competitor's name); send [] to clear it; and a competitor given as a plain domain keeps its stored curated aliases, while `{ domain, aliases }` sets them exactly (`[]` clears). A spec identity that claims a competitor's alias drops that alias (audited); a new competitor whose name overlaps another competitor's alias (one brand key contains the other) or that is the project's own site fails the apply. An omitted siteAuditMaxPages keeps the stored Site Health page budget (null means the full site). For multi-document YAML, call this tool once per project document.",
|
|
2715
|
+
description: "Apply one Canonry config-as-code project document. Replaces the project to match the config; fields omitted from the spec are reset to defaults, with these exceptions: a spec with neither queries nor keywords leaves the tracked-query basket unchanged (to clear the basket, pass an explicit empty queries list); an omitted providerDispatchModes keeps the stored preference; an omitted qualifiedAliases keeps the stored list, minus names that no longer qualify (a removed alias, a spelling of the display name, or a competitor's name); send [] to clear it; and a competitor given as a plain domain keeps its stored curated aliases, while `{ domain, aliases }` sets them exactly (`[]` clears). A spec identity that claims a competitor's alias drops that alias (audited); a new competitor whose name overlaps another competitor's alias (one brand key contains the other) or that is the project's own site fails the apply. An omitted siteAuditMaxPages keeps the stored Site Health page budget (null means the full site). An omitted competitorAutoAliases keeps the stored answer-derived competitor alias mode (off, preview or apply). For multi-document YAML, call this tool once per project document.",
|
|
2708
2716
|
access: "write",
|
|
2709
2717
|
tier: "core",
|
|
2710
2718
|
inputSchema: applyConfigInputSchema,
|
|
@@ -3273,7 +3281,7 @@ var canonryMcpTools = [
|
|
|
3273
3281
|
defineTool({
|
|
3274
3282
|
name: "canonry_competitors_aliases_set",
|
|
3275
3283
|
title: "Set competitor aliases",
|
|
3276
|
-
description:
|
|
3284
|
+
description: 'Set one tracked competitor\'s operator-curated aliases exactly (`[]` clears): the brand names it goes by in answer text when they differ from its domain, e.g. "TuneSpoke" for spoketuneworks.example or a 3-letter brand the domain label floor drops. Every competitor mention matcher (mention share, competitor landscape, mention gaps, run and history signals) uses them on stored answers at read time. Rejected: aliases under 3 letters or digits, over 80 characters, more than 10, or whose brand key contains, or sits inside, one of the project\'s own names or hosts or a name another tracked competitor answers to (its aliases, domain label or written host), because answers may split or join the words: "Tune" cannot belong to one competitor while another answers to "Tune Spoke", "TuneSpoke" or tunespoke.example, and joined-word lookalikes ("Tune" and "Tuner") are refused too. A competitor an Advanced market pins (active revision, pending draft, or a superseded revision the project\'s runs were measured under) counts as another competitor. Names detected automatically from stored answers (`autoAliases`) are matched the same way; a curated alias always wins, so an auto name the new list overlaps is dropped. Idempotent; returns the competitor.',
|
|
3277
3285
|
access: "write",
|
|
3278
3286
|
tier: "setup",
|
|
3279
3287
|
inputSchema: competitorAliasesInputSchema,
|
|
@@ -3281,6 +3289,50 @@ var canonryMcpTools = [
|
|
|
3281
3289
|
openApiOperations: ["PUT /api/v1/projects/{name}/competitors/{domain}/aliases"],
|
|
3282
3290
|
handler: (client, input) => client.setCompetitorAliases(input.project, input.domain, input.aliases)
|
|
3283
3291
|
}),
|
|
3292
|
+
defineTool({
|
|
3293
|
+
name: "canonry_competitors_auto_aliases_detect",
|
|
3294
|
+
title: "Preview competitor auto-aliases",
|
|
3295
|
+
description: `Dry run of automatic competitor alias detection from the project's stored answers only (never a provider, never a competitor's website). Per competitor: the names the answers pair with its site (provider citations anchoring the name to a page on the domain, named links, \`Name (domain)\`), with evidence (direct pairs, sweeps, co-occurrences, answers naming it, precision = share of those that cite the site, lift = how much more often the site is cited when the name appears, answers writing it as a name; an answer names a candidate only where it writes it outside the competitor's longer names: domain label, curated aliases, longer stored names, and for a market-only competitor its plan label and aliases), and each name's status: added, kept, removed, review or rejected with a reason. A name is applied only if it passes the evidence bars, reads as a business name, not a place ("Larkfield, CO", "Oakvale County", "Metro Larkfield"), and visibly belongs to the domain: consecutive words of it spell the domain label; or a name of two or more words opens the label whole (at its start or after a lead word such as "my" or "get") and covers at least half of it; or two or more of its words sit back to back in the label from that opening and cover at least half of it, one of them 4+ letters and inside fewer than two tracked identity labels; or a name of two or more words is an in-order abbreviation that opens like the label ("FoamSeal" for foamandsealworks.example). One shared word is never enough unless it is the whole label. New names fill the cap of 10 strongest evidence first, and a name the competitor's own label, curated aliases, kept names or own active or draft market pin already cover is not learned. Review names (no such tie, or a 3-letter name) are never auto-applied; they are checked against the project's names and hosts, other competitors' domain labels, hosts and curated aliases, market pins of another domain, blocks and the competitor's own names, but not against other competitors' auto-detected names. Verify one refers to that competitor before adding it as a curated alias. A stored name is removed only when blocked, claimed by identity (its own curated names, the project's names or hosts, another competitor's domain label, host, curated alias or earlier stored auto name, a market pin of another domain), replaced by an accepted shorter name, or contradicted: named in 3+ answers with precision under 5%, lift under 1.5 or name casing under half; another tracked competitor pairing it in at least 2 answers and at least twice as often; or no tie to the domain label left. Writes nothing. The local server queues the same pass after every completed or partial sweep, a competitor add, an unblock and a market pin write that changes the pins, run by the project's competitorAutoAliases mode: \`apply\` stores its result, \`preview\` (the default) only logs it, \`off\` skips it.`,
|
|
3296
|
+
access: "read",
|
|
3297
|
+
tier: "setup",
|
|
3298
|
+
inputSchema: projectInputSchema,
|
|
3299
|
+
annotations: readAnnotations(),
|
|
3300
|
+
openApiOperations: ["GET /api/v1/projects/{name}/competitor-auto-aliases"],
|
|
3301
|
+
handler: (client, input) => client.previewCompetitorAutoAliases(input.project)
|
|
3302
|
+
}),
|
|
3303
|
+
defineTool({
|
|
3304
|
+
name: "canonry_competitors_auto_aliases_apply",
|
|
3305
|
+
title: "Apply competitor auto-aliases",
|
|
3306
|
+
description: "Run automatic competitor alias detection now from the project's stored answers and store the result, whatever the project's competitorAutoAliases mode (a one-off apply; a project in `apply` mode also gets this pass after every completed or partial sweep, a competitor add, an unblock and a market pin write that changes the pins). Stored names restate history at read time: every period's competitor counts change, and so does share of voice for a tracked competitor; competitorIdentityChangedAt on the landscape, project-frame visibility-compare and analytics metrics marks when. Idempotent: unchanged answers write nothing. Curated aliases and blocked names always win. A change is audited as the system pass plus competitors.auto-aliases-apply-requested naming who asked. Not available to the built-in Aero agent. Returns what was stored, per competitor, with evidence.",
|
|
3307
|
+
access: "write",
|
|
3308
|
+
tier: "setup",
|
|
3309
|
+
inputSchema: projectInputSchema,
|
|
3310
|
+
annotations: writeAnnotations({ idempotentHint: true }),
|
|
3311
|
+
openApiOperations: ["POST /api/v1/projects/{name}/competitor-auto-aliases"],
|
|
3312
|
+
handler: (client, input) => client.applyCompetitorAutoAliases(input.project)
|
|
3313
|
+
}),
|
|
3314
|
+
defineTool({
|
|
3315
|
+
name: "canonry_competitors_aliases_block",
|
|
3316
|
+
title: "Block competitor auto-aliases",
|
|
3317
|
+
description: "Block names from automatic, answer-derived alias detection for one competitor, by domain: a tracked competitor, else a competitor the active Advanced plan pins without tracking it, else a domain with stored market competitor names and no active pin (names learned for a pin a later revision dropped, or the blocks a removed competitor left). A blocked name is never auto-applied again until unblocked, and a stored auto name among them is removed now. Blocks survive removing and re-adding the competitor. Names compare by brand key (case, spacing and punctuation variants are one name). A curated alias cannot be blocked; remove it with canonry_competitors_aliases_set. A name the measurement plan's own pin of that competitor carries (active revision or pending draft) cannot be blocked either, because the pin keeps counting it; change the pin's names in a measurement draft. Idempotent; returns the competitor.",
|
|
3318
|
+
access: "write",
|
|
3319
|
+
tier: "setup",
|
|
3320
|
+
inputSchema: competitorAliasBlockInputSchema,
|
|
3321
|
+
annotations: writeAnnotations({ idempotentHint: true }),
|
|
3322
|
+
openApiOperations: ["POST /api/v1/projects/{name}/competitors/{domain}/aliases/block"],
|
|
3323
|
+
handler: (client, input) => client.blockCompetitorAliases(input.project, input.domain, input.aliases)
|
|
3324
|
+
}),
|
|
3325
|
+
defineTool({
|
|
3326
|
+
name: "canonry_competitors_aliases_unblock",
|
|
3327
|
+
title: "Unblock competitor auto-aliases",
|
|
3328
|
+
description: "Release blocked names back to automatic, answer-derived alias detection for one competitor, by domain: a tracked competitor, else a competitor the active Advanced plan pins without tracking it, else a domain with stored market competitor names and no active pin (names learned for a pin a later revision dropped, or the blocks a removed competitor left, which this releases). The unblock stores nothing new; a detection pass is requested and, for a project in `apply` mode, stores a name only if the stored answers still support it (in `preview` it only logs, in `off` it does not run; canonry_competitors_auto_aliases_apply stores now). A learned name still stored for a market-only competitor counts again at once. Idempotent; returns the competitor.",
|
|
3329
|
+
access: "write",
|
|
3330
|
+
tier: "setup",
|
|
3331
|
+
inputSchema: competitorAliasBlockInputSchema,
|
|
3332
|
+
annotations: writeAnnotations({ idempotentHint: true }),
|
|
3333
|
+
openApiOperations: ["POST /api/v1/projects/{name}/competitors/{domain}/aliases/unblock"],
|
|
3334
|
+
handler: (client, input) => client.unblockCompetitorAliases(input.project, input.domain, input.aliases)
|
|
3335
|
+
}),
|
|
3284
3336
|
defineTool({
|
|
3285
3337
|
name: "canonry_competitors_remove",
|
|
3286
3338
|
title: "Remove competitors",
|