@canonry/canonry 4.155.0 → 4.156.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/orchestration.md +1 -1
- package/assets/agent-workspace/skills/canonry/SKILL.md +1 -1
- package/assets/agent-workspace/skills/canonry/references/canonry-cli.md +14 -2
- package/assets/assets/{AuditHistoryPanel-BlbMBxOY.js → AuditHistoryPanel-gmJMVlXX.js} +1 -1
- package/assets/assets/{BacklinksPage-DA9EaV9q.js → BacklinksPage-Bv2sTCyN.js} +1 -1
- package/assets/assets/{HistoryPage-BTrIHjMQ.js → HistoryPage-13q7GkiI.js} +1 -1
- package/assets/assets/{MeasurementPropertyPage-CN6o5xFg.js → MeasurementPropertyPage-BgBqXT1p.js} +1 -1
- package/assets/assets/ProjectPage-EsGwKhot.js +15 -0
- package/assets/assets/{RunRow-ch_OlCPs.js → RunRow-bPzapIGJ.js} +1 -1
- package/assets/assets/{RunsPage-T89Y_yS8.js → RunsPage-Dqfz18lH.js} +1 -1
- package/assets/assets/{SettingsPage-DnmEq3F9.js → SettingsPage-_wMecn-V.js} +1 -1
- package/assets/assets/{TrafficPage-CW1UhaJt.js → TrafficPage-RYBdsOLB.js} +1 -1
- package/assets/assets/{TrafficSourceDetailPage-r4Ji3wJm.js → TrafficSourceDetailPage-DpeMMyKU.js} +1 -1
- package/assets/assets/{extract-error-message-a8EErBoZ.js → extract-error-message-DUarAlyD.js} +1 -1
- package/assets/assets/index-BxegEwic.css +1 -0
- package/assets/assets/{index-BKq6k5Of.js → index-DP-fT2uI.js} +29 -29
- package/assets/assets/react-sigma_core.esm.min-DnypJl5w.js +312 -0
- package/assets/assets/vendor-lucide-BtYdosYk.js +1 -0
- package/assets/assets/{vendor-markdown-CpDJch4G.js → vendor-markdown-D274_wsI.js} +1 -1
- package/assets/assets/{vendor-radix-DnzzbllM.js → vendor-radix-BxMXSwbC.js} +1 -1
- package/assets/assets/{vendor-recharts-33ACLxsD.js → vendor-recharts-C4ktw_aE.js} +1 -1
- package/assets/assets/{vendor-tanstack-BjS7iY3g.js → vendor-tanstack-pFxw0eGP.js} +1 -1
- package/assets/index.html +7 -7
- package/dist/{chunk-VOL2BSM5.js → chunk-ABNN2ZVR.js} +1332 -29
- package/dist/{chunk-VIKPFI6F.js → chunk-AMPT2EP7.js} +328 -1
- package/dist/{chunk-OSHRDV36.js → chunk-CPASKGUE.js} +247 -1
- package/dist/{chunk-YSESZNVT.js → chunk-ZWESOFA5.js} +711 -235
- package/dist/cli.js +427 -5
- package/dist/index.js +4 -4
- package/dist/{intelligence-service-G4NV3X36.js → intelligence-service-WHC7B32V.js} +2 -2
- package/dist/mcp.js +4 -4
- package/package.json +11 -9
- package/assets/assets/ProjectPage-CsDbgp_0.js +0 -12
- package/assets/assets/index-DyL54s8x.css +0 -1
- package/assets/assets/vendor-lucide-ByU7vBHt.js +0 -1
package/dist/cli.js
CHANGED
|
@@ -30,7 +30,7 @@ import {
|
|
|
30
30
|
showFirstRunNotice,
|
|
31
31
|
trackCliCommandFinished,
|
|
32
32
|
trackEvent
|
|
33
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-ZWESOFA5.js";
|
|
34
34
|
import {
|
|
35
35
|
CliError,
|
|
36
36
|
EXIT_SYSTEM_ERROR,
|
|
@@ -50,7 +50,7 @@ import {
|
|
|
50
50
|
saveConfigPatch,
|
|
51
51
|
systemError,
|
|
52
52
|
usageError
|
|
53
|
-
} from "./chunk-
|
|
53
|
+
} from "./chunk-CPASKGUE.js";
|
|
54
54
|
import {
|
|
55
55
|
apiKeys,
|
|
56
56
|
createClient,
|
|
@@ -58,7 +58,7 @@ import {
|
|
|
58
58
|
projects,
|
|
59
59
|
queries,
|
|
60
60
|
renderReportHtml
|
|
61
|
-
} from "./chunk-
|
|
61
|
+
} from "./chunk-ABNN2ZVR.js";
|
|
62
62
|
import {
|
|
63
63
|
AdsDeliverySnapshotStatuses,
|
|
64
64
|
AdsHistoricalCampaignRollupStatuses,
|
|
@@ -122,7 +122,7 @@ import {
|
|
|
122
122
|
providerQuotaPolicySchema,
|
|
123
123
|
resolveProviderInput,
|
|
124
124
|
winnabilityClassSchema
|
|
125
|
-
} from "./chunk-
|
|
125
|
+
} from "./chunk-AMPT2EP7.js";
|
|
126
126
|
|
|
127
127
|
// src/cli.ts
|
|
128
128
|
import { pathToFileURL } from "url";
|
|
@@ -13849,9 +13849,120 @@ async function technicalAeoCrawl(project, opts) {
|
|
|
13849
13849
|
if (crawl.termination) lines.push(`Stopped: ${crawl.termination}`);
|
|
13850
13850
|
console.log(lines.join("\n"));
|
|
13851
13851
|
}
|
|
13852
|
+
async function technicalAeoSubgraph(project, opts) {
|
|
13853
|
+
const res = await getClient27().getSiteHealthSubgraph(project, opts);
|
|
13854
|
+
if (isMachineFormat(opts.format)) {
|
|
13855
|
+
console.log(JSON.stringify(res, null, 2));
|
|
13856
|
+
return;
|
|
13857
|
+
}
|
|
13858
|
+
if (!res.hasCrawlData) {
|
|
13859
|
+
console.log(`No persisted Site Health crawl for "${project}". Run \`canonry technical-aeo run ${project}\` first.`);
|
|
13860
|
+
return;
|
|
13861
|
+
}
|
|
13862
|
+
if (res.state !== "ready") {
|
|
13863
|
+
console.log(`Site Health subgraph details are unavailable for crawl ${res.runId ?? "-"}.`);
|
|
13864
|
+
return;
|
|
13865
|
+
}
|
|
13866
|
+
const focus = res.focusUrl ?? res.focusNodeKey ?? "crawl root";
|
|
13867
|
+
const totalQualifier = res.countAccuracy === "lower-bound" ? "at least " : "";
|
|
13868
|
+
const lines = [
|
|
13869
|
+
`Site Health subgraph: ${focus} (${res.hops} hop${res.hops === 1 ? "" : "s"})`,
|
|
13870
|
+
`${res.nodes.length} of ${totalQualifier}${res.totalNodes} node(s) \xB7 ${res.edges.length} of ${totalQualifier}${res.totalEdges} edge(s)`,
|
|
13871
|
+
`Crawl: ${res.complete ? "complete" : `partial (${res.termination ?? "incomplete"})`}`
|
|
13872
|
+
];
|
|
13873
|
+
if (res.countAccuracy === "lower-bound") lines.push("Count accuracy: lower bound; traversal reached a cap, so totals and omissions may be higher.");
|
|
13874
|
+
if (res.truncated) lines.push(`Truncated: at least ${res.omittedNodes} node(s) and ${res.omittedEdges} edge(s) omitted. Narrow or refocus the request.`);
|
|
13875
|
+
if (!res.complete) lines.push(`Partial crawl: ${res.termination ?? "incomplete"}. Results describe only persisted observations.`);
|
|
13876
|
+
console.log(lines.join("\n"));
|
|
13877
|
+
}
|
|
13878
|
+
async function technicalAeoPath(project, opts) {
|
|
13879
|
+
const res = await getClient27().getSiteHealthPath(project, opts);
|
|
13880
|
+
if (isMachineFormat(opts.format)) {
|
|
13881
|
+
console.log(JSON.stringify(res, null, 2));
|
|
13882
|
+
return;
|
|
13883
|
+
}
|
|
13884
|
+
if (res.state === "no-crawl") {
|
|
13885
|
+
console.log(`No persisted Site Health crawl for "${project}". Run \`canonry technical-aeo run ${project}\` first.`);
|
|
13886
|
+
return;
|
|
13887
|
+
}
|
|
13888
|
+
if (res.state === "details-unavailable") {
|
|
13889
|
+
console.log(`Site Health path details are unavailable for crawl ${res.runId ?? "-"}.`);
|
|
13890
|
+
return;
|
|
13891
|
+
}
|
|
13892
|
+
if (res.state === "unreachable") {
|
|
13893
|
+
const qualification = res.complete ? "" : ` in the partial crawl (${res.termination ?? "incomplete"}); this is not a site-wide conclusion`;
|
|
13894
|
+
console.log(`No directed followable path found${qualification} to ${res.to?.url ?? "the requested destination"} within ${res.maxDepth} hop(s).`);
|
|
13895
|
+
return;
|
|
13896
|
+
}
|
|
13897
|
+
if (res.state === "truncated") {
|
|
13898
|
+
const qualification = res.complete ? "" : ` The crawl is partial (${res.termination ?? "incomplete"}), so this is not a site-wide conclusion.`;
|
|
13899
|
+
console.log(`Path search reached its exploration cap before resolving ${res.to?.url ?? "the requested destination"}. Narrow the route or reduce max depth.${qualification}`);
|
|
13900
|
+
return;
|
|
13901
|
+
}
|
|
13902
|
+
const lines = [res.nodes.map((node) => node.url).join("\n\u2192 ")];
|
|
13903
|
+
if (!res.complete) lines.push("", `Partial crawl: ${res.termination ?? "incomplete"}. This path covers only persisted observations.`);
|
|
13904
|
+
console.log(lines.join("\n"));
|
|
13905
|
+
}
|
|
13906
|
+
async function technicalAeoChanges(project, opts) {
|
|
13907
|
+
const res = await getClient27().getSiteHealthChanges(project, opts);
|
|
13908
|
+
if (opts.format === "jsonl") {
|
|
13909
|
+
if (res.state === "ready") {
|
|
13910
|
+
const { changes, ...header } = res;
|
|
13911
|
+
emitJsonl([{ kind: "site-health-changes-header", ...header }]);
|
|
13912
|
+
emitJsonl(changes.map((record) => ({ project, fromRunId: res.fromRunId, toRunId: res.toRunId, ...record })));
|
|
13913
|
+
} else {
|
|
13914
|
+
emitJsonl([{ kind: "site-health-changes-header", ...res }]);
|
|
13915
|
+
}
|
|
13916
|
+
return;
|
|
13917
|
+
}
|
|
13918
|
+
if (isMachineFormat(opts.format)) {
|
|
13919
|
+
console.log(JSON.stringify(res, null, 2));
|
|
13920
|
+
return;
|
|
13921
|
+
}
|
|
13922
|
+
if (res.state === "unavailable") {
|
|
13923
|
+
console.log(`Site Health changes unavailable: ${res.reason.replaceAll("-", " ")}.`);
|
|
13924
|
+
return;
|
|
13925
|
+
}
|
|
13926
|
+
if (res.state === "incompatible") {
|
|
13927
|
+
console.log(`Site Health changes unavailable: snapshots use incompatible ${res.mismatchedVersions.join(", ")} versions.`);
|
|
13928
|
+
return;
|
|
13929
|
+
}
|
|
13930
|
+
const lines = [
|
|
13931
|
+
`Site Health changes: ${res.fromRunId} \u2192 ${res.toRunId}`,
|
|
13932
|
+
`Filters: ${res.filters.scope} \xB7 ${res.filters.change}`
|
|
13933
|
+
];
|
|
13934
|
+
if (res.summaryState === "exact" && res.summary !== null && res.total !== null) {
|
|
13935
|
+
lines.push(`Pages: +${res.summary.pages.added} / -${res.summary.pages.removed} / ${res.summary.pages.changed} changed`);
|
|
13936
|
+
lines.push(`Links: +${res.summary.links.added} / -${res.summary.links.removed} / ${res.summary.links.changed}`);
|
|
13937
|
+
lines.push(`${res.changes.length} of ${res.total} change(s)${res.nextCursor ? " (more available)" : ""}`);
|
|
13938
|
+
} else {
|
|
13939
|
+
lines.push(`Summary: omitted on continuation; ${res.changes.length} returned change(s)${res.nextCursor ? " (more available)" : ""}`);
|
|
13940
|
+
}
|
|
13941
|
+
if (res.changes.length > 0) {
|
|
13942
|
+
lines.push("", "Changes:");
|
|
13943
|
+
for (const record of res.changes) lines.push(` ${formatSiteHealthChangeRecord(record)}`);
|
|
13944
|
+
}
|
|
13945
|
+
if (res.nextCursor) lines.push(`Next cursor: ${res.nextCursor}`);
|
|
13946
|
+
console.log(lines.join("\n"));
|
|
13947
|
+
}
|
|
13948
|
+
function formatSiteHealthChangeRecord(record) {
|
|
13949
|
+
const target = record.entity === "page" ? record.after?.url ?? record.before?.url ?? record.key : (() => {
|
|
13950
|
+
const edge = record.after ?? record.before;
|
|
13951
|
+
return edge ? `${edge.sourceUrl} \u2192 ${edge.targetUrl}` : record.key;
|
|
13952
|
+
})();
|
|
13953
|
+
const fields = record.changedFields.length > 0 ? ` (${record.changedFields.join(", ")})` : "";
|
|
13954
|
+
return `${record.entity} ${record.change}: ${target}${fields}`;
|
|
13955
|
+
}
|
|
13852
13956
|
async function technicalAeoCrawlPages(project, opts) {
|
|
13853
13957
|
const res = await getClient27().getTechnicalAeoCrawlPages(project, opts);
|
|
13854
13958
|
if (opts.format === "jsonl") {
|
|
13959
|
+
emitJsonl([{
|
|
13960
|
+
kind: "technical-aeo-crawl-pages-header",
|
|
13961
|
+
project,
|
|
13962
|
+
runId: res.runId,
|
|
13963
|
+
total: res.total,
|
|
13964
|
+
nextCursor: res.nextCursor
|
|
13965
|
+
}]);
|
|
13855
13966
|
emitJsonl(res.pages.map((page) => ({ project, runId: res.runId, ...page })));
|
|
13856
13967
|
return;
|
|
13857
13968
|
}
|
|
@@ -13872,9 +13983,76 @@ async function technicalAeoCrawlPages(project, opts) {
|
|
|
13872
13983
|
Next cursor: ${res.nextCursor}`);
|
|
13873
13984
|
console.log(lines.join("\n"));
|
|
13874
13985
|
}
|
|
13986
|
+
async function technicalAeoPageAudit(project, opts) {
|
|
13987
|
+
const res = await getClient27().getTechnicalAeoPageAudit(project, {
|
|
13988
|
+
runId: opts.runId,
|
|
13989
|
+
nodeKey: opts.nodeKey,
|
|
13990
|
+
url: opts.url
|
|
13991
|
+
});
|
|
13992
|
+
if (isMachineFormat(opts.format)) {
|
|
13993
|
+
console.log(JSON.stringify(res, null, 2));
|
|
13994
|
+
return;
|
|
13995
|
+
}
|
|
13996
|
+
if (res.state === "no-crawl") {
|
|
13997
|
+
console.log(`No persisted Site Health crawl for "${project}". Run \`canonry technical-aeo run ${project}\` first.`);
|
|
13998
|
+
return;
|
|
13999
|
+
}
|
|
14000
|
+
const provenance = [`Run: ${res.runId} \xB7 ${res.complete ? "complete" : "partial"}`];
|
|
14001
|
+
if (!res.complete) provenance.push(`Partial crawl: ${res.termination ?? "termination reason unavailable"}`);
|
|
14002
|
+
if (res.state === "details-unavailable") {
|
|
14003
|
+
console.log([
|
|
14004
|
+
"Page audit details are unavailable for this retained crawl.",
|
|
14005
|
+
...provenance
|
|
14006
|
+
].join("\n"));
|
|
14007
|
+
return;
|
|
14008
|
+
}
|
|
14009
|
+
if (res.state === "not-found") {
|
|
14010
|
+
console.log([
|
|
14011
|
+
"The selected page was not found in this crawl.",
|
|
14012
|
+
...provenance
|
|
14013
|
+
].join("\n"));
|
|
14014
|
+
return;
|
|
14015
|
+
}
|
|
14016
|
+
const lines = [
|
|
14017
|
+
`Page audit: ${res.auditScore == null ? "not scored" : `${res.auditScore}/100`} \xB7 ${res.url}`,
|
|
14018
|
+
...provenance
|
|
14019
|
+
];
|
|
14020
|
+
if (res.state === "not-audited") {
|
|
14021
|
+
lines.push(`Audit evidence unavailable: page state is ${res.auditState}.`);
|
|
14022
|
+
console.log(lines.join("\n"));
|
|
14023
|
+
return;
|
|
14024
|
+
}
|
|
14025
|
+
if (res.evidenceState === "scores-only") {
|
|
14026
|
+
lines.push("Evidence: scores only; this historical row predates persisted finding prose.");
|
|
14027
|
+
}
|
|
14028
|
+
if (res.criticalDefects.length > 0) {
|
|
14029
|
+
lines.push("", "Score-independent defects:");
|
|
14030
|
+
for (const defect of res.criticalDefects) {
|
|
14031
|
+
lines.push(` [${defect.severity}] [${defect.id}] ${defect.detail}`);
|
|
14032
|
+
lines.push(` Fix: ${defect.recommendation}`);
|
|
14033
|
+
}
|
|
14034
|
+
}
|
|
14035
|
+
if (res.factors.length > 0) {
|
|
14036
|
+
lines.push("", "Factors:");
|
|
14037
|
+
for (const factor of res.factors) {
|
|
14038
|
+
lines.push(` ${factor.name}: ${factor.score}/100 (${factor.status})`);
|
|
14039
|
+
for (const finding of factor.findings) lines.push(` [${finding.code}] ${finding.message}`);
|
|
14040
|
+
for (const recommendation of factor.recommendations) lines.push(` Fix: ${recommendation}`);
|
|
14041
|
+
}
|
|
14042
|
+
}
|
|
14043
|
+
console.log(lines.join("\n"));
|
|
14044
|
+
}
|
|
13875
14045
|
async function technicalAeoStructure(project, opts) {
|
|
13876
14046
|
const res = await getClient27().getTechnicalAeoStructure(project, opts);
|
|
13877
14047
|
if (opts.format === "jsonl") {
|
|
14048
|
+
emitJsonl([{
|
|
14049
|
+
kind: "technical-aeo-structure-header",
|
|
14050
|
+
project,
|
|
14051
|
+
runId: res.runId,
|
|
14052
|
+
parentPath: res.parentPath,
|
|
14053
|
+
returned: res.children.length,
|
|
14054
|
+
nextCursor: res.nextCursor
|
|
14055
|
+
}]);
|
|
13878
14056
|
emitJsonl(res.children.map((child) => ({ project, runId: res.runId, parentPath: res.parentPath, ...child })));
|
|
13879
14057
|
return;
|
|
13880
14058
|
}
|
|
@@ -13897,6 +14075,13 @@ Next cursor: ${res.nextCursor}`);
|
|
|
13897
14075
|
async function technicalAeoInternalLinks(project, opts) {
|
|
13898
14076
|
const res = await getClient27().getTechnicalAeoInternalLinks(project, opts);
|
|
13899
14077
|
if (opts.format === "jsonl") {
|
|
14078
|
+
emitJsonl([{
|
|
14079
|
+
kind: "technical-aeo-internal-links-header",
|
|
14080
|
+
project,
|
|
14081
|
+
runId: res.runId,
|
|
14082
|
+
total: res.total,
|
|
14083
|
+
nextCursor: res.nextCursor
|
|
14084
|
+
}]);
|
|
13900
14085
|
emitJsonl(res.edges.map((edge) => ({ project, runId: res.runId, ...edge })));
|
|
13901
14086
|
return;
|
|
13902
14087
|
}
|
|
@@ -14019,7 +14204,13 @@ Usage: ${config.usage}`, {
|
|
|
14019
14204
|
details: { command: config.command, usage: config.usage, option: key, value }
|
|
14020
14205
|
});
|
|
14021
14206
|
}
|
|
14022
|
-
|
|
14207
|
+
function isSiteHealthScope(value) {
|
|
14208
|
+
return value === "all" || value === "pages" || value === "links";
|
|
14209
|
+
}
|
|
14210
|
+
function isSiteHealthChange(value) {
|
|
14211
|
+
return value === "all" || value === "added" || value === "removed" || value === "changed";
|
|
14212
|
+
}
|
|
14213
|
+
var TECHNICAL_AEO_CLI_COMMANDS_BASE = [
|
|
14023
14214
|
{
|
|
14024
14215
|
path: ["technical-aeo", "score"],
|
|
14025
14216
|
usage: "canonry technical-aeo score <project> [--run-id <id>] [--format json]",
|
|
@@ -14132,6 +14323,126 @@ var TECHNICAL_AEO_CLI_COMMANDS = [
|
|
|
14132
14323
|
await technicalAeoCrawl(project, { runId: getString(input.values, "run-id"), format: input.format });
|
|
14133
14324
|
}
|
|
14134
14325
|
},
|
|
14326
|
+
{
|
|
14327
|
+
path: ["technical-aeo", "subgraph"],
|
|
14328
|
+
usage: "canonry technical-aeo subgraph <project> [--run-id <id>] [--node-key <key>|--url <url>] [--hops <n>] [--max-nodes <n>] [--max-edges <n>] [--format json]",
|
|
14329
|
+
options: {
|
|
14330
|
+
"run-id": stringOption(),
|
|
14331
|
+
"node-key": stringOption(),
|
|
14332
|
+
url: stringOption(),
|
|
14333
|
+
hops: stringOption(),
|
|
14334
|
+
"max-nodes": stringOption(),
|
|
14335
|
+
"max-edges": stringOption()
|
|
14336
|
+
},
|
|
14337
|
+
run: async (input) => {
|
|
14338
|
+
const usage = "canonry technical-aeo subgraph <project> [--run-id <id>] [--node-key <key>|--url <url>] [--hops <n>] [--max-nodes <n>] [--max-edges <n>] [--format json]";
|
|
14339
|
+
const project = requireProject(input, "technical-aeo.subgraph", usage);
|
|
14340
|
+
const nodeKey = getString(input.values, "node-key");
|
|
14341
|
+
const url = getString(input.values, "url");
|
|
14342
|
+
if (nodeKey && url) {
|
|
14343
|
+
throw usageError(`Error: --node-key and --url cannot be combined
|
|
14344
|
+
Usage: ${usage}`, {
|
|
14345
|
+
message: "--node-key and --url cannot be combined",
|
|
14346
|
+
details: { command: "technical-aeo.subgraph", usage }
|
|
14347
|
+
});
|
|
14348
|
+
}
|
|
14349
|
+
await technicalAeoSubgraph(project, {
|
|
14350
|
+
runId: getString(input.values, "run-id"),
|
|
14351
|
+
nodeKey,
|
|
14352
|
+
url,
|
|
14353
|
+
hops: parseIntegerOption(input, "hops", { command: "technical-aeo.subgraph", usage, message: "--hops must be an integer" }),
|
|
14354
|
+
maxNodes: parseIntegerOption(input, "max-nodes", { command: "technical-aeo.subgraph", usage, message: "--max-nodes must be an integer" }),
|
|
14355
|
+
maxEdges: parseIntegerOption(input, "max-edges", { command: "technical-aeo.subgraph", usage, message: "--max-edges must be an integer" }),
|
|
14356
|
+
format: input.format
|
|
14357
|
+
});
|
|
14358
|
+
}
|
|
14359
|
+
},
|
|
14360
|
+
{
|
|
14361
|
+
path: ["technical-aeo", "path"],
|
|
14362
|
+
usage: "canonry technical-aeo path <project> (--to-node-key <key>|--to-url <url>) [--run-id <id>] [--from-node-key <key>|--from-url <url>] [--max-depth <n>] [--format json]",
|
|
14363
|
+
options: {
|
|
14364
|
+
"run-id": stringOption(),
|
|
14365
|
+
"from-node-key": stringOption(),
|
|
14366
|
+
"from-url": stringOption(),
|
|
14367
|
+
"to-node-key": stringOption(),
|
|
14368
|
+
"to-url": stringOption(),
|
|
14369
|
+
"max-depth": stringOption()
|
|
14370
|
+
},
|
|
14371
|
+
run: async (input) => {
|
|
14372
|
+
const usage = "canonry technical-aeo path <project> (--to-node-key <key>|--to-url <url>) [--run-id <id>] [--from-node-key <key>|--from-url <url>] [--max-depth <n>] [--format json]";
|
|
14373
|
+
const project = requireProject(input, "technical-aeo.path", usage);
|
|
14374
|
+
const fromNodeKey = getString(input.values, "from-node-key");
|
|
14375
|
+
const fromUrl = getString(input.values, "from-url");
|
|
14376
|
+
const toNodeKey = getString(input.values, "to-node-key");
|
|
14377
|
+
const toUrl = getString(input.values, "to-url");
|
|
14378
|
+
if (!toNodeKey && !toUrl) {
|
|
14379
|
+
throw usageError(`Error: --to-node-key or --to-url is required
|
|
14380
|
+
Usage: ${usage}`, {
|
|
14381
|
+
message: "--to-node-key or --to-url is required",
|
|
14382
|
+
details: { command: "technical-aeo.path", usage }
|
|
14383
|
+
});
|
|
14384
|
+
}
|
|
14385
|
+
if (fromNodeKey && fromUrl || toNodeKey && toUrl) {
|
|
14386
|
+
throw usageError(`Error: node-key and URL selectors cannot be combined
|
|
14387
|
+
Usage: ${usage}`, {
|
|
14388
|
+
message: "node-key and URL selectors cannot be combined",
|
|
14389
|
+
details: { command: "technical-aeo.path", usage }
|
|
14390
|
+
});
|
|
14391
|
+
}
|
|
14392
|
+
await technicalAeoPath(project, {
|
|
14393
|
+
runId: getString(input.values, "run-id"),
|
|
14394
|
+
fromNodeKey,
|
|
14395
|
+
fromUrl,
|
|
14396
|
+
toNodeKey,
|
|
14397
|
+
toUrl,
|
|
14398
|
+
maxDepth: parseIntegerOption(input, "max-depth", { command: "technical-aeo.path", usage, message: "--max-depth must be an integer" }),
|
|
14399
|
+
format: input.format
|
|
14400
|
+
});
|
|
14401
|
+
}
|
|
14402
|
+
},
|
|
14403
|
+
{
|
|
14404
|
+
path: ["technical-aeo", "changes"],
|
|
14405
|
+
usage: "canonry technical-aeo changes <project> [--from-run-id <id>] [--to-run-id <id>] [--scope all|pages|links] [--change all|added|removed|changed] [--cursor <cursor>] [--limit <n>] [--format json|jsonl]",
|
|
14406
|
+
options: {
|
|
14407
|
+
"from-run-id": stringOption(),
|
|
14408
|
+
"to-run-id": stringOption(),
|
|
14409
|
+
scope: stringOption(),
|
|
14410
|
+
change: stringOption(),
|
|
14411
|
+
cursor: stringOption(),
|
|
14412
|
+
limit: stringOption()
|
|
14413
|
+
},
|
|
14414
|
+
run: async (input) => {
|
|
14415
|
+
const usage = "canonry technical-aeo changes <project> [--from-run-id <id>] [--to-run-id <id>] [--scope all|pages|links] [--change all|added|removed|changed] [--cursor <cursor>] [--limit <n>] [--format json|jsonl]";
|
|
14416
|
+
const project = requireProject(input, "technical-aeo.changes", usage);
|
|
14417
|
+
const fromRunId = getString(input.values, "from-run-id");
|
|
14418
|
+
const toRunId = getString(input.values, "to-run-id");
|
|
14419
|
+
const scope = getString(input.values, "scope");
|
|
14420
|
+
const change = getString(input.values, "change");
|
|
14421
|
+
if (scope !== void 0 && !isSiteHealthScope(scope)) {
|
|
14422
|
+
throw usageError(`Error: --scope must be all, pages, or links
|
|
14423
|
+
Usage: ${usage}`, {
|
|
14424
|
+
message: "--scope must be all, pages, or links",
|
|
14425
|
+
details: { command: "technical-aeo.changes", usage, option: "scope", value: scope }
|
|
14426
|
+
});
|
|
14427
|
+
}
|
|
14428
|
+
if (change !== void 0 && !isSiteHealthChange(change)) {
|
|
14429
|
+
throw usageError(`Error: --change must be all, added, removed, or changed
|
|
14430
|
+
Usage: ${usage}`, {
|
|
14431
|
+
message: "--change must be all, added, removed, or changed",
|
|
14432
|
+
details: { command: "technical-aeo.changes", usage, option: "change", value: change }
|
|
14433
|
+
});
|
|
14434
|
+
}
|
|
14435
|
+
await technicalAeoChanges(project, {
|
|
14436
|
+
fromRunId,
|
|
14437
|
+
toRunId,
|
|
14438
|
+
scope,
|
|
14439
|
+
change,
|
|
14440
|
+
cursor: getString(input.values, "cursor"),
|
|
14441
|
+
limit: parseIntegerOption(input, "limit", { command: "technical-aeo.changes", usage, message: "--limit must be an integer" }),
|
|
14442
|
+
format: input.format
|
|
14443
|
+
});
|
|
14444
|
+
}
|
|
14445
|
+
},
|
|
14135
14446
|
{
|
|
14136
14447
|
path: ["technical-aeo", "crawl-pages"],
|
|
14137
14448
|
usage: "canonry technical-aeo crawl-pages <project> [--run-id <id>] [--inventory-eligible true|false] [--fetch-state <state>] [--indexability-state <state>] [--audit-state <state>] [--sort url|path|score-asc|score-desc] [--cursor <cursor>] [--limit <n>] [--format json|jsonl]",
|
|
@@ -14169,6 +14480,37 @@ Usage: ${usage}`, {
|
|
|
14169
14480
|
});
|
|
14170
14481
|
}
|
|
14171
14482
|
},
|
|
14483
|
+
{
|
|
14484
|
+
path: ["technical-aeo", "page-audit"],
|
|
14485
|
+
usage: "canonry technical-aeo page-audit <project> (--node-key <key>|--url <url>) [--run-id <id>] [--format json]",
|
|
14486
|
+
options: { "run-id": stringOption(), "node-key": stringOption(), url: stringOption() },
|
|
14487
|
+
run: async (input) => {
|
|
14488
|
+
const usage = "canonry technical-aeo page-audit <project> (--node-key <key>|--url <url>) [--run-id <id>] [--format json]";
|
|
14489
|
+
const project = requireProject(input, "technical-aeo.page-audit", usage);
|
|
14490
|
+
const nodeKey = getString(input.values, "node-key");
|
|
14491
|
+
const url = getString(input.values, "url");
|
|
14492
|
+
if (!nodeKey && !url) {
|
|
14493
|
+
throw usageError(`Error: --node-key or --url is required
|
|
14494
|
+
Usage: ${usage}`, {
|
|
14495
|
+
message: "--node-key or --url is required",
|
|
14496
|
+
details: { command: "technical-aeo.page-audit", usage }
|
|
14497
|
+
});
|
|
14498
|
+
}
|
|
14499
|
+
if (nodeKey && url) {
|
|
14500
|
+
throw usageError(`Error: --node-key and --url cannot be combined
|
|
14501
|
+
Usage: ${usage}`, {
|
|
14502
|
+
message: "--node-key and --url cannot be combined",
|
|
14503
|
+
details: { command: "technical-aeo.page-audit", usage }
|
|
14504
|
+
});
|
|
14505
|
+
}
|
|
14506
|
+
await technicalAeoPageAudit(project, {
|
|
14507
|
+
runId: getString(input.values, "run-id"),
|
|
14508
|
+
nodeKey,
|
|
14509
|
+
url,
|
|
14510
|
+
format: input.format
|
|
14511
|
+
});
|
|
14512
|
+
}
|
|
14513
|
+
},
|
|
14172
14514
|
{
|
|
14173
14515
|
path: ["technical-aeo", "structure"],
|
|
14174
14516
|
usage: "canonry technical-aeo structure <project> [--run-id <id>] [--parent-path <path>] [--cursor <cursor>] [--limit <n>] [--format json|jsonl]",
|
|
@@ -14261,6 +14603,86 @@ Usage: ${usage}`, {
|
|
|
14261
14603
|
}
|
|
14262
14604
|
}
|
|
14263
14605
|
];
|
|
14606
|
+
function siteHealthAlias(sourcePath, path12, usage) {
|
|
14607
|
+
const source = TECHNICAL_AEO_CLI_COMMANDS_BASE.find(
|
|
14608
|
+
(candidate) => candidate.path.join(" ") === sourcePath.join(" ")
|
|
14609
|
+
);
|
|
14610
|
+
if (!source) throw new Error(`Missing Site Health compatibility source: ${sourcePath.join(" ")}`);
|
|
14611
|
+
return {
|
|
14612
|
+
...source,
|
|
14613
|
+
path: path12,
|
|
14614
|
+
usage,
|
|
14615
|
+
run: async (input) => {
|
|
14616
|
+
try {
|
|
14617
|
+
await source.run(input);
|
|
14618
|
+
} catch (error) {
|
|
14619
|
+
if (!(error instanceof CliError) || error.code !== "CLI_USAGE_ERROR") throw error;
|
|
14620
|
+
const firstLine = error.displayMessage?.split("\n", 1)[0] ?? `Error: ${error.message}`;
|
|
14621
|
+
throw usageError(`${firstLine}
|
|
14622
|
+
Usage: ${usage}`, {
|
|
14623
|
+
message: error.message,
|
|
14624
|
+
details: { ...error.details, command: path12.join("."), usage }
|
|
14625
|
+
});
|
|
14626
|
+
}
|
|
14627
|
+
}
|
|
14628
|
+
};
|
|
14629
|
+
}
|
|
14630
|
+
var SITE_HEALTH_COMPATIBILITY_COMMANDS = [
|
|
14631
|
+
siteHealthAlias(
|
|
14632
|
+
["technical-aeo", "crawl"],
|
|
14633
|
+
["site-health", "overview"],
|
|
14634
|
+
"canonry site-health overview <project> [--run-id <id>] [--format json]"
|
|
14635
|
+
),
|
|
14636
|
+
siteHealthAlias(
|
|
14637
|
+
["technical-aeo", "crawl-pages"],
|
|
14638
|
+
["site-health", "pages"],
|
|
14639
|
+
"canonry site-health pages <project> [--run-id <id>] [--inventory-eligible true|false] [--fetch-state <state>] [--indexability-state <state>] [--audit-state <state>] [--sort url|path|score-asc|score-desc] [--cursor <cursor>] [--limit <n>] [--format json|jsonl]"
|
|
14640
|
+
),
|
|
14641
|
+
siteHealthAlias(
|
|
14642
|
+
["technical-aeo", "page-audit"],
|
|
14643
|
+
["site-health", "page-audit"],
|
|
14644
|
+
"canonry site-health page-audit <project> (--node-key <key>|--url <url>) [--run-id <id>] [--format json]"
|
|
14645
|
+
),
|
|
14646
|
+
siteHealthAlias(
|
|
14647
|
+
["technical-aeo", "structure"],
|
|
14648
|
+
["site-health", "structure"],
|
|
14649
|
+
"canonry site-health structure <project> [--run-id <id>] [--parent-path <path>] [--cursor <cursor>] [--limit <n>] [--format json|jsonl]"
|
|
14650
|
+
),
|
|
14651
|
+
siteHealthAlias(
|
|
14652
|
+
["technical-aeo", "links"],
|
|
14653
|
+
["site-health", "links"],
|
|
14654
|
+
"canonry site-health links <project> [--run-id <id>] [--source-url <url>] [--target-url <url>] [--followable|--nofollow] [--cursor <cursor>] [--limit <n>] [--format json|jsonl]"
|
|
14655
|
+
),
|
|
14656
|
+
siteHealthAlias(
|
|
14657
|
+
["technical-aeo", "links", "neighbors"],
|
|
14658
|
+
["site-health", "neighbors"],
|
|
14659
|
+
"canonry site-health neighbors <project> (--node-key <key>|--url <url>) [--run-id <id>] [--limit <n>] [--format json]"
|
|
14660
|
+
),
|
|
14661
|
+
siteHealthAlias(
|
|
14662
|
+
["technical-aeo", "dead-links"],
|
|
14663
|
+
["site-health", "dead-links"],
|
|
14664
|
+
"canonry site-health dead-links <project> [--run-id <id>] [--cursor <cursor>] [--limit <n>] [--format json|jsonl]"
|
|
14665
|
+
),
|
|
14666
|
+
siteHealthAlias(
|
|
14667
|
+
["technical-aeo", "subgraph"],
|
|
14668
|
+
["site-health", "subgraph"],
|
|
14669
|
+
"canonry site-health subgraph <project> [--run-id <id>] [--node-key <key>|--url <url>] [--hops <n>] [--max-nodes <n>] [--max-edges <n>] [--format json]"
|
|
14670
|
+
),
|
|
14671
|
+
siteHealthAlias(
|
|
14672
|
+
["technical-aeo", "path"],
|
|
14673
|
+
["site-health", "path"],
|
|
14674
|
+
"canonry site-health path <project> (--to-node-key <key>|--to-url <url>) [--run-id <id>] [--from-node-key <key>|--from-url <url>] [--max-depth <n>] [--format json]"
|
|
14675
|
+
),
|
|
14676
|
+
siteHealthAlias(
|
|
14677
|
+
["technical-aeo", "changes"],
|
|
14678
|
+
["site-health", "changes"],
|
|
14679
|
+
"canonry site-health changes <project> [--from-run-id <id>] [--to-run-id <id>] [--scope all|pages|links] [--change all|added|removed|changed] [--cursor <cursor>] [--limit <n>] [--format json|jsonl]"
|
|
14680
|
+
)
|
|
14681
|
+
];
|
|
14682
|
+
var TECHNICAL_AEO_CLI_COMMANDS = [
|
|
14683
|
+
...TECHNICAL_AEO_CLI_COMMANDS_BASE,
|
|
14684
|
+
...SITE_HEALTH_COMPATIBILITY_COMMANDS
|
|
14685
|
+
];
|
|
14264
14686
|
|
|
14265
14687
|
// src/commands/visibility-stats.ts
|
|
14266
14688
|
async function showVisibilityStats(project, opts) {
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createServer
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-ZWESOFA5.js";
|
|
4
4
|
import {
|
|
5
5
|
loadConfig
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
8
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-CPASKGUE.js";
|
|
7
|
+
import "./chunk-ABNN2ZVR.js";
|
|
8
|
+
import "./chunk-AMPT2EP7.js";
|
|
9
9
|
export {
|
|
10
10
|
createServer,
|
|
11
11
|
loadConfig
|
package/dist/mcp.js
CHANGED
|
@@ -3,10 +3,10 @@ import {
|
|
|
3
3
|
PACKAGE_VERSION,
|
|
4
4
|
canonryMcpTools,
|
|
5
5
|
createApiClient
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-CPASKGUE.js";
|
|
7
7
|
import {
|
|
8
8
|
isReadOnlyKey
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-AMPT2EP7.js";
|
|
10
10
|
|
|
11
11
|
// src/mcp/cli.ts
|
|
12
12
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
@@ -111,8 +111,8 @@ var CANONRY_MCP_TOOLKITS = [
|
|
|
111
111
|
{
|
|
112
112
|
name: "monitoring",
|
|
113
113
|
title: "Measurement, runs, insights, health",
|
|
114
|
-
description: "Inspect portfolio and Property measurement, question results, run history, intelligence insights, and
|
|
115
|
-
whenToLoad: "Load when finding weak Properties, reviewing answers and competitors, checking data quality, comparing
|
|
114
|
+
description: "Inspect portfolio and Property measurement, question results, run history, intelligence insights, health timelines, and bounded Site Health reads (overview, page audit evidence, focused subgraphs, paths, and scan changes).",
|
|
115
|
+
whenToLoad: "Load when finding weak Properties, reviewing answers and competitors, checking data quality, tying a Site Health page score to concrete findings, investigating site architecture, comparing scans, or diagnosing regressions."
|
|
116
116
|
},
|
|
117
117
|
{
|
|
118
118
|
name: "setup",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@canonry/canonry",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.156.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Agent-first open-source AEO operating platform - track how answer engines cite your domain",
|
|
6
6
|
"license": "FSL-1.1-ALv2",
|
|
@@ -53,6 +53,8 @@
|
|
|
53
53
|
"cron-parser": "^5.5.0",
|
|
54
54
|
"drizzle-orm": "^0.45.2",
|
|
55
55
|
"fastify": "^5.8.5",
|
|
56
|
+
"graphology": "0.26.0",
|
|
57
|
+
"graphology-layout-forceatlas2": "0.10.1",
|
|
56
58
|
"node-cron": "^4.2.1",
|
|
57
59
|
"openai": "^6.0.0",
|
|
58
60
|
"pdf-lib": "^1.17.1",
|
|
@@ -67,26 +69,26 @@
|
|
|
67
69
|
"tsup": "^8.5.1",
|
|
68
70
|
"tsx": "^4.19.0",
|
|
69
71
|
"@ainyc/canonry-api-client": "0.0.0",
|
|
72
|
+
"@ainyc/canonry-config": "0.0.0",
|
|
70
73
|
"@ainyc/canonry-api-routes": "0.0.0",
|
|
71
74
|
"@ainyc/canonry-contracts": "0.0.0",
|
|
72
75
|
"@ainyc/canonry-db": "0.0.0",
|
|
73
|
-
"@ainyc/canonry-config": "0.0.0",
|
|
74
76
|
"@ainyc/canonry-integration-bing": "0.0.0",
|
|
75
77
|
"@ainyc/canonry-integration-openai-ads": "0.0.0",
|
|
76
|
-
"@ainyc/canonry-integration-google": "0.0.0",
|
|
77
|
-
"@ainyc/canonry-integration-google-business-profile": "0.0.0",
|
|
78
78
|
"@ainyc/canonry-integration-cloud-run": "0.0.0",
|
|
79
|
-
"@ainyc/canonry-integration-google
|
|
79
|
+
"@ainyc/canonry-integration-google": "0.0.0",
|
|
80
80
|
"@ainyc/canonry-integration-commoncrawl": "0.0.0",
|
|
81
|
+
"@ainyc/canonry-integration-google-business-profile": "0.0.0",
|
|
82
|
+
"@ainyc/canonry-integration-traffic": "0.0.0",
|
|
81
83
|
"@ainyc/canonry-integration-wordpress": "0.0.0",
|
|
82
|
-
"@ainyc/canonry-provider-cdp": "0.0.0",
|
|
83
84
|
"@ainyc/canonry-intelligence": "0.0.0",
|
|
84
|
-
"@ainyc/canonry-integration-traffic": "0.0.0",
|
|
85
85
|
"@ainyc/canonry-provider-claude": "0.0.0",
|
|
86
|
+
"@ainyc/canonry-provider-cdp": "0.0.0",
|
|
86
87
|
"@ainyc/canonry-provider-gemini": "0.0.0",
|
|
88
|
+
"@ainyc/canonry-provider-openai": "0.0.0",
|
|
87
89
|
"@ainyc/canonry-provider-local": "0.0.0",
|
|
88
|
-
"@ainyc/canonry-
|
|
89
|
-
"@ainyc/canonry-provider-
|
|
90
|
+
"@ainyc/canonry-integration-google-places": "0.0.0",
|
|
91
|
+
"@ainyc/canonry-provider-perplexity": "0.0.0"
|
|
90
92
|
},
|
|
91
93
|
"scripts": {
|
|
92
94
|
"build": "tsx scripts/copy-agent-assets.ts && tsup && tsx build-web.ts",
|