@canonry/canonry 4.154.0 → 4.155.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/README.md +2 -2
- package/assets/agent-workspace/AGENTS.md +2 -2
- package/assets/agent-workspace/skills/aero/references/orchestration.md +3 -3
- package/assets/agent-workspace/skills/canonry/SKILL.md +6 -21
- package/assets/agent-workspace/skills/canonry/references/canonry-cli.md +14 -6
- package/assets/assets/{AuditHistoryPanel-WWT1n8jp.js → AuditHistoryPanel-BlbMBxOY.js} +1 -1
- package/assets/assets/BacklinksPage-DA9EaV9q.js +1 -0
- package/assets/assets/HistoryPage-BTrIHjMQ.js +1 -0
- package/assets/assets/MeasurementPropertyPage-CN6o5xFg.js +1 -0
- package/assets/assets/{ProjectPage-BR5ECwUP.js → ProjectPage-CsDbgp_0.js} +9 -9
- package/assets/assets/{RunRow-OE5tiuih.js → RunRow-ch_OlCPs.js} +1 -1
- package/assets/assets/RunsPage-T89Y_yS8.js +1 -0
- package/assets/assets/SettingsPage-DnmEq3F9.js +1 -0
- package/assets/assets/TrafficPage-CW1UhaJt.js +1 -0
- package/assets/assets/TrafficSourceDetailPage-r4Ji3wJm.js +1 -0
- package/assets/assets/extract-error-message-a8EErBoZ.js +1 -0
- package/assets/assets/index-BKq6k5Of.js +83 -0
- package/assets/assets/vendor-lucide-ByU7vBHt.js +1 -0
- package/assets/assets/vendor-yaml-GWJz5H2G.js +131 -0
- package/assets/index.html +3 -1
- package/dist/{chunk-ANSQ6JNO.js → chunk-OSHRDV36.js} +317 -4
- package/dist/{chunk-NNW7TJUZ.js → chunk-VIKPFI6F.js} +200 -5
- package/dist/{chunk-IFZS2TXV.js → chunk-VOL2BSM5.js} +1133 -104
- package/dist/{chunk-X5I7CAXH.js → chunk-YSESZNVT.js} +609 -165
- package/dist/cli.js +342 -7
- package/dist/index.js +4 -4
- package/dist/{intelligence-service-B5AETQ5N.js → intelligence-service-G4NV3X36.js} +2 -2
- package/dist/mcp.js +2 -2
- package/package.json +9 -9
- package/assets/assets/BacklinksPage-DIjUnsVL.js +0 -1
- package/assets/assets/HistoryPage-CrIBhGuW.js +0 -1
- package/assets/assets/MeasurementPropertyPage-uN4BWigS.js +0 -1
- package/assets/assets/RunsPage-C6xBmjps.js +0 -1
- package/assets/assets/SettingsPage-CUjjr8U0.js +0 -1
- package/assets/assets/TrafficPage-DrEfsHiE.js +0 -1
- package/assets/assets/TrafficSourceDetailPage-B3DX5BEk.js +0 -1
- package/assets/assets/arrow-left-CLmqvCqU.js +0 -1
- package/assets/assets/extract-error-message-BEBd1a5v.js +0 -1
- package/assets/assets/index-CsM-Xxia.js +0 -213
- package/assets/assets/refresh-cw-DYSS2Wd-.js +0 -1
- package/assets/assets/trash-2-VoiF_ckU.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-YSESZNVT.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-OSHRDV36.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-VOL2BSM5.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-VIKPFI6F.js";
|
|
126
126
|
|
|
127
127
|
// src/cli.ts
|
|
128
128
|
import { pathToFileURL } from "url";
|
|
@@ -13163,6 +13163,8 @@ import fs14 from "fs";
|
|
|
13163
13163
|
import path11 from "path";
|
|
13164
13164
|
var CANONRY_PLUGIN_ID = "canonry@canonry";
|
|
13165
13165
|
var REQUIRED_SKILLS = ["canonry", "aero"];
|
|
13166
|
+
var AGENT_PLUGINS_SCHEMA = "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json";
|
|
13167
|
+
var AGENT_PLUGINS_MCP_SCHEMA = "https://agent-plugins.org/schemas/1.0.0/mcp.schema.json";
|
|
13166
13168
|
function parseSemver(version) {
|
|
13167
13169
|
const match = /^(\d+)\.(\d+)\.(\d+)(?:-([0-9a-z.-]+))?(?:\+[0-9a-z.-]+)?$/i.exec(version);
|
|
13168
13170
|
if (!match) return null;
|
|
@@ -13254,6 +13256,27 @@ function readCodexPluginConfigured(filePath) {
|
|
|
13254
13256
|
}
|
|
13255
13257
|
}
|
|
13256
13258
|
function verifiedPluginVersion(root, client) {
|
|
13259
|
+
if (client === "codex" && fs14.existsSync(path11.join(root, "plugin.json"))) {
|
|
13260
|
+
const manifest2 = readJson(path11.join(root, "plugin.json"));
|
|
13261
|
+
if (manifest2 && typeof manifest2 === "object") {
|
|
13262
|
+
const plugin2 = manifest2;
|
|
13263
|
+
if (plugin2.$schema === AGENT_PLUGINS_SCHEMA) {
|
|
13264
|
+
if (plugin2.name !== "canonry" || typeof plugin2.version !== "string" || !parseSemver(plugin2.version)) {
|
|
13265
|
+
return null;
|
|
13266
|
+
}
|
|
13267
|
+
const mcp2 = readJson(path11.join(root, "mcp.json"));
|
|
13268
|
+
if (!mcp2 || typeof mcp2 !== "object") return null;
|
|
13269
|
+
const portableMcp = mcp2;
|
|
13270
|
+
if (portableMcp.$schema !== AGENT_PLUGINS_MCP_SCHEMA || portableMcp.mcpServers?.canonry?.type !== "stdio" || portableMcp.mcpServers.canonry.command !== "canonry-mcp") {
|
|
13271
|
+
return null;
|
|
13272
|
+
}
|
|
13273
|
+
return REQUIRED_SKILLS.every((name) => fs14.existsSync(path11.join(root, "skills", name, "SKILL.md"))) ? plugin2.version : null;
|
|
13274
|
+
}
|
|
13275
|
+
if (typeof plugin2.$schema === "string" && plugin2.$schema.startsWith("https://agent-plugins.org/schemas/")) {
|
|
13276
|
+
return null;
|
|
13277
|
+
}
|
|
13278
|
+
}
|
|
13279
|
+
}
|
|
13257
13280
|
const manifestDir = client === "claude-code" ? ".claude-plugin" : ".codex-plugin";
|
|
13258
13281
|
const manifest = readJson(path11.join(root, manifestDir, "plugin.json"));
|
|
13259
13282
|
if (!manifest || typeof manifest !== "object") return null;
|
|
@@ -13806,11 +13829,154 @@ async function technicalAeoTrend(project, opts) {
|
|
|
13806
13829
|
}
|
|
13807
13830
|
console.log(lines.join("\n"));
|
|
13808
13831
|
}
|
|
13832
|
+
async function technicalAeoCrawl(project, opts) {
|
|
13833
|
+
const crawl = await getClient27().getTechnicalAeoCrawl(project, { runId: opts.runId });
|
|
13834
|
+
if (isMachineFormat(opts.format)) {
|
|
13835
|
+
console.log(JSON.stringify(crawl, null, 2));
|
|
13836
|
+
return;
|
|
13837
|
+
}
|
|
13838
|
+
if (!crawl.hasCrawlData) {
|
|
13839
|
+
console.log(`No persisted site crawl for "${project}". Run \`canonry technical-aeo run ${project}\` first.`);
|
|
13840
|
+
return;
|
|
13841
|
+
}
|
|
13842
|
+
const lines = [
|
|
13843
|
+
`Site crawl: ${crawl.complete ? "complete" : "partial"} (${crawl.runStatus ?? "unknown"})`,
|
|
13844
|
+
`Root: ${crawl.rootUrl ?? "-"}`,
|
|
13845
|
+
`Pages: ${crawl.counts.pagesFetched} fetched \xB7 ${crawl.counts.pagesDiscovered} discovered \xB7 ${crawl.counts.pagesEligible} eligible`,
|
|
13846
|
+
`Links: ${crawl.counts.edges} internal/external observations \xB7 ${crawl.counts.findings} findings`,
|
|
13847
|
+
`Dead links: ${formatDeadLinkState(crawl.deadLinks)}`
|
|
13848
|
+
];
|
|
13849
|
+
if (crawl.termination) lines.push(`Stopped: ${crawl.termination}`);
|
|
13850
|
+
console.log(lines.join("\n"));
|
|
13851
|
+
}
|
|
13852
|
+
async function technicalAeoCrawlPages(project, opts) {
|
|
13853
|
+
const res = await getClient27().getTechnicalAeoCrawlPages(project, opts);
|
|
13854
|
+
if (opts.format === "jsonl") {
|
|
13855
|
+
emitJsonl(res.pages.map((page) => ({ project, runId: res.runId, ...page })));
|
|
13856
|
+
return;
|
|
13857
|
+
}
|
|
13858
|
+
if (opts.format === "json") {
|
|
13859
|
+
console.log(JSON.stringify(res, null, 2));
|
|
13860
|
+
return;
|
|
13861
|
+
}
|
|
13862
|
+
if (res.pages.length === 0) {
|
|
13863
|
+
console.log(`No persisted crawl pages for "${project}".`);
|
|
13864
|
+
return;
|
|
13865
|
+
}
|
|
13866
|
+
const lines = [`${res.pages.length} of ${res.total} crawl page(s)${res.nextCursor ? " (more available)" : ""}:`, ""];
|
|
13867
|
+
lines.push(`${"Depth".padStart(5)} ${"Score".padStart(5)} ${"Indexability".padEnd(15)} URL`);
|
|
13868
|
+
for (const page of res.pages) {
|
|
13869
|
+
lines.push(`${String(page.depth ?? "-").padStart(5)} ${String(page.auditScore ?? "-").padStart(5)} ${page.indexabilityState.slice(0, 15).padEnd(15)} ${page.url}`);
|
|
13870
|
+
}
|
|
13871
|
+
if (res.nextCursor) lines.push(`
|
|
13872
|
+
Next cursor: ${res.nextCursor}`);
|
|
13873
|
+
console.log(lines.join("\n"));
|
|
13874
|
+
}
|
|
13875
|
+
async function technicalAeoStructure(project, opts) {
|
|
13876
|
+
const res = await getClient27().getTechnicalAeoStructure(project, opts);
|
|
13877
|
+
if (opts.format === "jsonl") {
|
|
13878
|
+
emitJsonl(res.children.map((child) => ({ project, runId: res.runId, parentPath: res.parentPath, ...child })));
|
|
13879
|
+
return;
|
|
13880
|
+
}
|
|
13881
|
+
if (opts.format === "json") {
|
|
13882
|
+
console.log(JSON.stringify(res, null, 2));
|
|
13883
|
+
return;
|
|
13884
|
+
}
|
|
13885
|
+
if (res.children.length === 0) {
|
|
13886
|
+
console.log(`No crawl structure below ${res.parentPath} for "${project}".`);
|
|
13887
|
+
return;
|
|
13888
|
+
}
|
|
13889
|
+
const lines = [`${res.children.length} child path(s) below ${res.parentPath}${res.nextCursor ? " (more available)" : ""}:`, ""];
|
|
13890
|
+
for (const child of res.children) {
|
|
13891
|
+
lines.push(`${String(child.pageCount).padStart(5)} pages ${String(child.inventoryEligibleCount).padStart(5)} eligible ${child.path}`);
|
|
13892
|
+
}
|
|
13893
|
+
if (res.nextCursor) lines.push(`
|
|
13894
|
+
Next cursor: ${res.nextCursor}`);
|
|
13895
|
+
console.log(lines.join("\n"));
|
|
13896
|
+
}
|
|
13897
|
+
async function technicalAeoInternalLinks(project, opts) {
|
|
13898
|
+
const res = await getClient27().getTechnicalAeoInternalLinks(project, opts);
|
|
13899
|
+
if (opts.format === "jsonl") {
|
|
13900
|
+
emitJsonl(res.edges.map((edge) => ({ project, runId: res.runId, ...edge })));
|
|
13901
|
+
return;
|
|
13902
|
+
}
|
|
13903
|
+
if (opts.format === "json") {
|
|
13904
|
+
console.log(JSON.stringify(res, null, 2));
|
|
13905
|
+
return;
|
|
13906
|
+
}
|
|
13907
|
+
if (res.edges.length === 0) {
|
|
13908
|
+
console.log(`No persisted internal links for "${project}".`);
|
|
13909
|
+
return;
|
|
13910
|
+
}
|
|
13911
|
+
const lines = [`${res.edges.length} of ${res.total} internal link(s)${res.nextCursor ? " (more available)" : ""}:`, ""];
|
|
13912
|
+
for (const edge of res.edges) {
|
|
13913
|
+
lines.push(`${edge.followable ? "follow" : "nofollow"} \xD7${edge.occurrences} ${edge.sourceUrl} \u2192 ${edge.targetUrl}`);
|
|
13914
|
+
}
|
|
13915
|
+
if (res.nextCursor) lines.push(`
|
|
13916
|
+
Next cursor: ${res.nextCursor}`);
|
|
13917
|
+
console.log(lines.join("\n"));
|
|
13918
|
+
}
|
|
13919
|
+
async function technicalAeoLinkNeighbors(project, opts) {
|
|
13920
|
+
const res = await getClient27().getTechnicalAeoInternalLinkNeighbors(project, opts);
|
|
13921
|
+
if (isMachineFormat(opts.format)) {
|
|
13922
|
+
console.log(JSON.stringify(res, null, 2));
|
|
13923
|
+
return;
|
|
13924
|
+
}
|
|
13925
|
+
const title = res.url ?? res.nodeKey ?? "page";
|
|
13926
|
+
const lines = [`Internal links for ${title}:`, "", "Inbound:"];
|
|
13927
|
+
for (const edge of res.inbound) lines.push(` ${edge.sourceUrl} \u2192 ${edge.targetUrl}`);
|
|
13928
|
+
if (res.inbound.length === 0) lines.push(" (none)");
|
|
13929
|
+
if (res.inboundTruncated) lines.push(" (truncated)");
|
|
13930
|
+
lines.push("", "Outbound:");
|
|
13931
|
+
for (const edge of res.outbound) lines.push(` ${edge.sourceUrl} \u2192 ${edge.targetUrl}`);
|
|
13932
|
+
if (res.outbound.length === 0) lines.push(" (none)");
|
|
13933
|
+
if (res.outboundTruncated) lines.push(" (truncated)");
|
|
13934
|
+
console.log(lines.join("\n"));
|
|
13935
|
+
}
|
|
13936
|
+
async function technicalAeoDeadLinks(project, opts) {
|
|
13937
|
+
const res = await getClient27().getTechnicalAeoDeadLinks(project, opts);
|
|
13938
|
+
if (opts.format === "jsonl") {
|
|
13939
|
+
if ("deadLinks" in res) {
|
|
13940
|
+
const { deadLinks, ...header } = res;
|
|
13941
|
+
emitJsonl([{ kind: "technical-aeo-dead-links-header", ...header }]);
|
|
13942
|
+
emitJsonl(deadLinks.map((finding) => ({ project, runId: res.runId, state: res.state, ...finding })));
|
|
13943
|
+
} else {
|
|
13944
|
+
emitJsonl([{ kind: "technical-aeo-dead-links-header", ...res }]);
|
|
13945
|
+
}
|
|
13946
|
+
return;
|
|
13947
|
+
}
|
|
13948
|
+
if (isMachineFormat(opts.format)) {
|
|
13949
|
+
console.log(JSON.stringify(res, null, 2));
|
|
13950
|
+
return;
|
|
13951
|
+
}
|
|
13952
|
+
if (res.state === "disabled") {
|
|
13953
|
+
console.log(`Dead-link checks were disabled for crawl ${res.runId}. Re-run with \`--check-dead-links\` to enable them.`);
|
|
13954
|
+
return;
|
|
13955
|
+
}
|
|
13956
|
+
if (res.state === "unavailable") {
|
|
13957
|
+
console.log(`No dead-link check is available for "${project}".`);
|
|
13958
|
+
return;
|
|
13959
|
+
}
|
|
13960
|
+
const lines = [`Dead links: ${res.found} found from ${res.checked} checked (${res.state})`];
|
|
13961
|
+
for (const finding of res.deadLinks) lines.push(`${finding.sourceUrl ?? "-"} \u2192 ${finding.targetUrl ?? "-"}`);
|
|
13962
|
+
if (res.nextCursor) lines.push(`Next cursor: ${res.nextCursor}`);
|
|
13963
|
+
console.log(lines.join("\n"));
|
|
13964
|
+
}
|
|
13965
|
+
function formatDeadLinkState(value) {
|
|
13966
|
+
if (value.state === "disabled") return "disabled (opt in with --check-dead-links)";
|
|
13967
|
+
if (value.state === "unavailable") return "unavailable";
|
|
13968
|
+
return `${value.found ?? 0} found / ${value.checked ?? 0} checked (${value.state})`;
|
|
13969
|
+
}
|
|
13809
13970
|
async function technicalAeoRun(project, opts) {
|
|
13810
13971
|
const client = getClient27();
|
|
13811
13972
|
const { runId, status } = await client.triggerSiteAudit(project, {
|
|
13812
13973
|
sitemapUrl: opts.sitemapUrl,
|
|
13813
|
-
limit: opts.limit
|
|
13974
|
+
limit: opts.limit,
|
|
13975
|
+
maxPages: opts.maxPages,
|
|
13976
|
+
maxEdges: opts.maxEdges,
|
|
13977
|
+
maxDepth: opts.maxDepth,
|
|
13978
|
+
// Explicit opt-in: absence and false are both intentionally disabled.
|
|
13979
|
+
checkDeadLinks: opts.checkDeadLinks === true
|
|
13814
13980
|
});
|
|
13815
13981
|
if (!opts.wait) {
|
|
13816
13982
|
if (isMachineFormat(opts.format)) {
|
|
@@ -13842,6 +14008,17 @@ async function technicalAeoRun(project, opts) {
|
|
|
13842
14008
|
}
|
|
13843
14009
|
|
|
13844
14010
|
// src/cli-commands/technical-aeo.ts
|
|
14011
|
+
function parseOptionalBoolean(input, key, config) {
|
|
14012
|
+
const value = getString(input.values, key);
|
|
14013
|
+
if (value === void 0) return void 0;
|
|
14014
|
+
if (value === "true") return true;
|
|
14015
|
+
if (value === "false") return false;
|
|
14016
|
+
throw usageError(`Error: --${key} must be true or false
|
|
14017
|
+
Usage: ${config.usage}`, {
|
|
14018
|
+
message: `--${key} must be true or false`,
|
|
14019
|
+
details: { command: config.command, usage: config.usage, option: key, value }
|
|
14020
|
+
});
|
|
14021
|
+
}
|
|
13845
14022
|
var TECHNICAL_AEO_CLI_COMMANDS = [
|
|
13846
14023
|
{
|
|
13847
14024
|
path: ["technical-aeo", "score"],
|
|
@@ -13904,14 +14081,18 @@ var TECHNICAL_AEO_CLI_COMMANDS = [
|
|
|
13904
14081
|
},
|
|
13905
14082
|
{
|
|
13906
14083
|
path: ["technical-aeo", "run"],
|
|
13907
|
-
usage: "canonry technical-aeo run <project> [--sitemap-url <url>] [--
|
|
14084
|
+
usage: "canonry technical-aeo run <project> [--sitemap-url <url>] [--max-pages <n>] [--max-edges <n>] [--max-depth <n>] [--check-dead-links] [--wait] [--format json]",
|
|
13908
14085
|
options: {
|
|
13909
14086
|
"sitemap-url": stringOption(),
|
|
13910
14087
|
limit: stringOption(),
|
|
14088
|
+
"max-pages": stringOption(),
|
|
14089
|
+
"max-edges": stringOption(),
|
|
14090
|
+
"max-depth": stringOption(),
|
|
14091
|
+
"check-dead-links": { type: "boolean", default: false },
|
|
13911
14092
|
wait: { type: "boolean", default: false }
|
|
13912
14093
|
},
|
|
13913
14094
|
run: async (input) => {
|
|
13914
|
-
const usage = "canonry technical-aeo run <project> [--sitemap-url <url>] [--
|
|
14095
|
+
const usage = "canonry technical-aeo run <project> [--sitemap-url <url>] [--max-pages <n>] [--max-edges <n>] [--max-depth <n>] [--check-dead-links] [--wait] [--format json]";
|
|
13915
14096
|
const project = requireProject(input, "technical-aeo.run", usage);
|
|
13916
14097
|
await technicalAeoRun(project, {
|
|
13917
14098
|
sitemapUrl: getString(input.values, "sitemap-url"),
|
|
@@ -13920,10 +14101,164 @@ var TECHNICAL_AEO_CLI_COMMANDS = [
|
|
|
13920
14101
|
usage,
|
|
13921
14102
|
message: "--limit must be an integer"
|
|
13922
14103
|
}),
|
|
14104
|
+
maxPages: parseIntegerOption(input, "max-pages", {
|
|
14105
|
+
command: "technical-aeo.run",
|
|
14106
|
+
usage,
|
|
14107
|
+
message: "--max-pages must be an integer"
|
|
14108
|
+
}),
|
|
14109
|
+
maxEdges: parseIntegerOption(input, "max-edges", {
|
|
14110
|
+
command: "technical-aeo.run",
|
|
14111
|
+
usage,
|
|
14112
|
+
message: "--max-edges must be an integer"
|
|
14113
|
+
}),
|
|
14114
|
+
maxDepth: parseIntegerOption(input, "max-depth", {
|
|
14115
|
+
command: "technical-aeo.run",
|
|
14116
|
+
usage,
|
|
14117
|
+
message: "--max-depth must be an integer"
|
|
14118
|
+
}),
|
|
14119
|
+
checkDeadLinks: getBoolean(input.values, "check-dead-links"),
|
|
13923
14120
|
wait: getBoolean(input.values, "wait"),
|
|
13924
14121
|
format: input.format
|
|
13925
14122
|
});
|
|
13926
14123
|
}
|
|
14124
|
+
},
|
|
14125
|
+
{
|
|
14126
|
+
path: ["technical-aeo", "crawl"],
|
|
14127
|
+
usage: "canonry technical-aeo crawl <project> [--run-id <id>] [--format json]",
|
|
14128
|
+
options: { "run-id": stringOption() },
|
|
14129
|
+
run: async (input) => {
|
|
14130
|
+
const usage = "canonry technical-aeo crawl <project> [--run-id <id>] [--format json]";
|
|
14131
|
+
const project = requireProject(input, "technical-aeo.crawl", usage);
|
|
14132
|
+
await technicalAeoCrawl(project, { runId: getString(input.values, "run-id"), format: input.format });
|
|
14133
|
+
}
|
|
14134
|
+
},
|
|
14135
|
+
{
|
|
14136
|
+
path: ["technical-aeo", "crawl-pages"],
|
|
14137
|
+
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]",
|
|
14138
|
+
options: {
|
|
14139
|
+
"run-id": stringOption(),
|
|
14140
|
+
"inventory-eligible": stringOption(),
|
|
14141
|
+
"fetch-state": stringOption(),
|
|
14142
|
+
"indexability-state": stringOption(),
|
|
14143
|
+
"audit-state": stringOption(),
|
|
14144
|
+
sort: stringOption(),
|
|
14145
|
+
cursor: stringOption(),
|
|
14146
|
+
limit: stringOption()
|
|
14147
|
+
},
|
|
14148
|
+
run: async (input) => {
|
|
14149
|
+
const 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]";
|
|
14150
|
+
const project = requireProject(input, "technical-aeo.crawl-pages", usage);
|
|
14151
|
+
const sort = getString(input.values, "sort");
|
|
14152
|
+
if (sort !== void 0 && !["url", "path", "score-asc", "score-desc"].includes(sort)) {
|
|
14153
|
+
throw usageError(`Error: --sort must be url, path, score-asc, or score-desc
|
|
14154
|
+
Usage: ${usage}`, {
|
|
14155
|
+
message: "--sort must be url, path, score-asc, or score-desc",
|
|
14156
|
+
details: { command: "technical-aeo.crawl-pages", usage, option: "sort", value: sort }
|
|
14157
|
+
});
|
|
14158
|
+
}
|
|
14159
|
+
await technicalAeoCrawlPages(project, {
|
|
14160
|
+
runId: getString(input.values, "run-id"),
|
|
14161
|
+
inventoryEligible: parseOptionalBoolean(input, "inventory-eligible", { command: "technical-aeo.crawl-pages", usage }),
|
|
14162
|
+
fetchState: getString(input.values, "fetch-state"),
|
|
14163
|
+
indexabilityState: getString(input.values, "indexability-state"),
|
|
14164
|
+
auditState: getString(input.values, "audit-state"),
|
|
14165
|
+
sort,
|
|
14166
|
+
cursor: getString(input.values, "cursor"),
|
|
14167
|
+
limit: parseIntegerOption(input, "limit", { command: "technical-aeo.crawl-pages", usage, message: "--limit must be an integer" }),
|
|
14168
|
+
format: input.format
|
|
14169
|
+
});
|
|
14170
|
+
}
|
|
14171
|
+
},
|
|
14172
|
+
{
|
|
14173
|
+
path: ["technical-aeo", "structure"],
|
|
14174
|
+
usage: "canonry technical-aeo structure <project> [--run-id <id>] [--parent-path <path>] [--cursor <cursor>] [--limit <n>] [--format json|jsonl]",
|
|
14175
|
+
options: { "run-id": stringOption(), "parent-path": stringOption(), cursor: stringOption(), limit: stringOption() },
|
|
14176
|
+
run: async (input) => {
|
|
14177
|
+
const usage = "canonry technical-aeo structure <project> [--run-id <id>] [--parent-path <path>] [--cursor <cursor>] [--limit <n>] [--format json|jsonl]";
|
|
14178
|
+
const project = requireProject(input, "technical-aeo.structure", usage);
|
|
14179
|
+
await technicalAeoStructure(project, {
|
|
14180
|
+
runId: getString(input.values, "run-id"),
|
|
14181
|
+
parentPath: getString(input.values, "parent-path"),
|
|
14182
|
+
cursor: getString(input.values, "cursor"),
|
|
14183
|
+
limit: parseIntegerOption(input, "limit", { command: "technical-aeo.structure", usage, message: "--limit must be an integer" }),
|
|
14184
|
+
format: input.format
|
|
14185
|
+
});
|
|
14186
|
+
}
|
|
14187
|
+
},
|
|
14188
|
+
{
|
|
14189
|
+
path: ["technical-aeo", "links"],
|
|
14190
|
+
usage: "canonry technical-aeo links <project> [--run-id <id>] [--source-url <url>] [--target-url <url>] [--followable|--nofollow] [--cursor <cursor>] [--limit <n>] [--format json|jsonl]",
|
|
14191
|
+
options: {
|
|
14192
|
+
"run-id": stringOption(),
|
|
14193
|
+
"source-url": stringOption(),
|
|
14194
|
+
"target-url": stringOption(),
|
|
14195
|
+
followable: { type: "boolean", default: false },
|
|
14196
|
+
nofollow: { type: "boolean", default: false },
|
|
14197
|
+
cursor: stringOption(),
|
|
14198
|
+
limit: stringOption()
|
|
14199
|
+
},
|
|
14200
|
+
run: async (input) => {
|
|
14201
|
+
const usage = "canonry technical-aeo links <project> [--run-id <id>] [--source-url <url>] [--target-url <url>] [--followable|--nofollow] [--cursor <cursor>] [--limit <n>] [--format json|jsonl]";
|
|
14202
|
+
const project = requireProject(input, "technical-aeo.links", usage);
|
|
14203
|
+
const followable = getBoolean(input.values, "followable");
|
|
14204
|
+
const nofollow = getBoolean(input.values, "nofollow");
|
|
14205
|
+
if (followable && nofollow) {
|
|
14206
|
+
throw usageError(`Error: --followable and --nofollow cannot be combined
|
|
14207
|
+
Usage: ${usage}`, {
|
|
14208
|
+
message: "--followable and --nofollow cannot be combined",
|
|
14209
|
+
details: { command: "technical-aeo.links", usage }
|
|
14210
|
+
});
|
|
14211
|
+
}
|
|
14212
|
+
await technicalAeoInternalLinks(project, {
|
|
14213
|
+
runId: getString(input.values, "run-id"),
|
|
14214
|
+
sourceUrl: getString(input.values, "source-url"),
|
|
14215
|
+
targetUrl: getString(input.values, "target-url"),
|
|
14216
|
+
followable: followable ? true : nofollow ? false : void 0,
|
|
14217
|
+
cursor: getString(input.values, "cursor"),
|
|
14218
|
+
limit: parseIntegerOption(input, "limit", { command: "technical-aeo.links", usage, message: "--limit must be an integer" }),
|
|
14219
|
+
format: input.format
|
|
14220
|
+
});
|
|
14221
|
+
}
|
|
14222
|
+
},
|
|
14223
|
+
{
|
|
14224
|
+
path: ["technical-aeo", "links", "neighbors"],
|
|
14225
|
+
usage: "canonry technical-aeo links neighbors <project> (--node-key <key>|--url <url>) [--run-id <id>] [--limit <n>] [--format json]",
|
|
14226
|
+
options: { "run-id": stringOption(), "node-key": stringOption(), url: stringOption(), limit: stringOption() },
|
|
14227
|
+
run: async (input) => {
|
|
14228
|
+
const usage = "canonry technical-aeo links neighbors <project> (--node-key <key>|--url <url>) [--run-id <id>] [--limit <n>] [--format json]";
|
|
14229
|
+
const project = requireProject(input, "technical-aeo.links.neighbors", usage);
|
|
14230
|
+
const nodeKey = getString(input.values, "node-key");
|
|
14231
|
+
const url = getString(input.values, "url");
|
|
14232
|
+
if (!nodeKey && !url) {
|
|
14233
|
+
throw usageError(`Error: --node-key or --url is required
|
|
14234
|
+
Usage: ${usage}`, {
|
|
14235
|
+
message: "--node-key or --url is required",
|
|
14236
|
+
details: { command: "technical-aeo.links.neighbors", usage }
|
|
14237
|
+
});
|
|
14238
|
+
}
|
|
14239
|
+
await technicalAeoLinkNeighbors(project, {
|
|
14240
|
+
runId: getString(input.values, "run-id"),
|
|
14241
|
+
nodeKey,
|
|
14242
|
+
url,
|
|
14243
|
+
limit: parseIntegerOption(input, "limit", { command: "technical-aeo.links.neighbors", usage, message: "--limit must be an integer" }),
|
|
14244
|
+
format: input.format
|
|
14245
|
+
});
|
|
14246
|
+
}
|
|
14247
|
+
},
|
|
14248
|
+
{
|
|
14249
|
+
path: ["technical-aeo", "dead-links"],
|
|
14250
|
+
usage: "canonry technical-aeo dead-links <project> [--run-id <id>] [--cursor <cursor>] [--limit <n>] [--format json|jsonl]",
|
|
14251
|
+
options: { "run-id": stringOption(), cursor: stringOption(), limit: stringOption() },
|
|
14252
|
+
run: async (input) => {
|
|
14253
|
+
const usage = "canonry technical-aeo dead-links <project> [--run-id <id>] [--cursor <cursor>] [--limit <n>] [--format json|jsonl]";
|
|
14254
|
+
const project = requireProject(input, "technical-aeo.dead-links", usage);
|
|
14255
|
+
await technicalAeoDeadLinks(project, {
|
|
14256
|
+
runId: getString(input.values, "run-id"),
|
|
14257
|
+
cursor: getString(input.values, "cursor"),
|
|
14258
|
+
limit: parseIntegerOption(input, "limit", { command: "technical-aeo.dead-links", usage, message: "--limit must be an integer" }),
|
|
14259
|
+
format: input.format
|
|
14260
|
+
});
|
|
14261
|
+
}
|
|
13927
14262
|
}
|
|
13928
14263
|
];
|
|
13929
14264
|
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createServer
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-YSESZNVT.js";
|
|
4
4
|
import {
|
|
5
5
|
loadConfig
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
8
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-OSHRDV36.js";
|
|
7
|
+
import "./chunk-VOL2BSM5.js";
|
|
8
|
+
import "./chunk-VIKPFI6F.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-OSHRDV36.js";
|
|
7
7
|
import {
|
|
8
8
|
isReadOnlyKey
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-VIKPFI6F.js";
|
|
10
10
|
|
|
11
11
|
// src/mcp/cli.ts
|
|
12
12
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@canonry/canonry",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.155.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",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"node": ">=22.14.0"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@
|
|
42
|
+
"@canonry/aeo-audit": "4.6.2",
|
|
43
43
|
"@anthropic-ai/sdk": "^0.91.1",
|
|
44
44
|
"@fastify/rate-limit": "^11.2.0",
|
|
45
45
|
"@fastify/static": "^9.1.1",
|
|
@@ -68,25 +68,25 @@
|
|
|
68
68
|
"tsx": "^4.19.0",
|
|
69
69
|
"@ainyc/canonry-api-client": "0.0.0",
|
|
70
70
|
"@ainyc/canonry-api-routes": "0.0.0",
|
|
71
|
-
"@ainyc/canonry-config": "0.0.0",
|
|
72
|
-
"@ainyc/canonry-db": "0.0.0",
|
|
73
71
|
"@ainyc/canonry-contracts": "0.0.0",
|
|
72
|
+
"@ainyc/canonry-db": "0.0.0",
|
|
73
|
+
"@ainyc/canonry-config": "0.0.0",
|
|
74
74
|
"@ainyc/canonry-integration-bing": "0.0.0",
|
|
75
|
-
"@ainyc/canonry-integration-cloud-run": "0.0.0",
|
|
76
75
|
"@ainyc/canonry-integration-openai-ads": "0.0.0",
|
|
77
|
-
"@ainyc/canonry-integration-google-business-profile": "0.0.0",
|
|
78
76
|
"@ainyc/canonry-integration-google": "0.0.0",
|
|
77
|
+
"@ainyc/canonry-integration-google-business-profile": "0.0.0",
|
|
78
|
+
"@ainyc/canonry-integration-cloud-run": "0.0.0",
|
|
79
79
|
"@ainyc/canonry-integration-google-places": "0.0.0",
|
|
80
|
-
"@ainyc/canonry-integration-traffic": "0.0.0",
|
|
81
80
|
"@ainyc/canonry-integration-commoncrawl": "0.0.0",
|
|
82
81
|
"@ainyc/canonry-integration-wordpress": "0.0.0",
|
|
83
82
|
"@ainyc/canonry-provider-cdp": "0.0.0",
|
|
84
83
|
"@ainyc/canonry-intelligence": "0.0.0",
|
|
84
|
+
"@ainyc/canonry-integration-traffic": "0.0.0",
|
|
85
85
|
"@ainyc/canonry-provider-claude": "0.0.0",
|
|
86
86
|
"@ainyc/canonry-provider-gemini": "0.0.0",
|
|
87
87
|
"@ainyc/canonry-provider-local": "0.0.0",
|
|
88
|
-
"@ainyc/canonry-provider-
|
|
89
|
-
"@ainyc/canonry-provider-
|
|
88
|
+
"@ainyc/canonry-provider-perplexity": "0.0.0",
|
|
89
|
+
"@ainyc/canonry-provider-openai": "0.0.0"
|
|
90
90
|
},
|
|
91
91
|
"scripts": {
|
|
92
92
|
"build": "tsx scripts/copy-agent-assets.ts && tsup && tsx build-web.ts",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{r as n,j as e}from"./vendor-tanstack-BjS7iY3g.js";import{cD as W,ak as _,cE as U,cF as V,cG as J,f as x,T as j,i as u,B as w,j as P,aV as K,at as Y,cH as X,cI as Z,an as ee,cJ as se}from"./index-CsM-Xxia.js";import{D as te,E as ae,T as ne,C as re}from"./trash-2-VoiF_ckU.js";import"./vendor-radix-DnzzbllM.js";import"./vendor-recharts-33ACLxsD.js";import"./vendor-markdown-CpDJch4G.js";function g({children:t,label:h="More info",placement:a="top",className:i}){const d=n.useId(),[y,c]=n.useState(!1);return e.jsxs("span",{className:`relative inline-flex ${i??""}`,children:[e.jsx("button",{type:"button","aria-label":h,"aria-describedby":y?d:void 0,className:"inline-flex h-4 w-4 items-center justify-center rounded-full text-muted hover:text-strong focus:text-strong focus:outline-none focus-visible:ring-1 focus-visible:ring-mono-500",onMouseEnter:()=>c(!0),onMouseLeave:()=>c(!1),onFocus:()=>c(!0),onBlur:()=>c(!1),children:e.jsx(re,{className:"h-3.5 w-3.5","aria-hidden":!0})}),y&&e.jsx("span",{id:d,role:"tooltip",className:`absolute z-50 w-64 rounded border border-strong bg-bg-elevated px-3 py-2 text-xs font-normal leading-relaxed text-strong shadow-lg ${a==="top"?"bottom-full mb-2":"top-full mt-2"} left-1/2 -translate-x-1/2 whitespace-normal`,children:t})]})}const le="https://commoncrawl.org/web-graphs";function S(t){return t==null?"—":t>=1e12?`${(t/1e12).toFixed(1)} TB`:t>=1e9?`${(t/1e9).toFixed(1)} GB`:t>=1e6?`${(t/1e6).toFixed(1)} MB`:t>=1e3?`${(t/1e3).toFixed(1)} KB`:`${t} B`}function b(t){if(!t)return"—";const h=Date.now()-new Date(t).getTime(),a=Math.floor(h/6e4);if(a<1)return"just now";if(a<60)return`${a}m ago`;const i=Math.floor(a/60);return i<24?`${i}h ago`:`${Math.floor(i/24)}d ago`}function C(t){switch(t){case"ready":return"positive";case"failed":return"negative";case"downloading":case"querying":case"queued":return"caution"}}function he(){const[t,h]=n.useState(null),[a,i]=n.useState(null),[d,y]=n.useState([]),[c,$]=n.useState([]),[m,L]=n.useState(null),[B,D]=n.useState(!0),[R,E]=n.useState(!1),[p,I]=n.useState(!1),[N,v]=n.useState(""),[M,k]=n.useState(!1),[A,l]=n.useState(null),[F,o]=n.useState(null),f=n.useCallback(async()=>{D(!0),l(null);try{const[s,r,z,H,O]=await Promise.all([W(),_().catch(()=>null),U().catch(()=>[]),V().catch(()=>[]),J().catch(()=>null)]);h(s),i(r),y(z),$(H),L(O)}catch(s){l(s instanceof Error?s.message:"Failed to load backlinks status")}finally{D(!1)}},[]);n.useEffect(()=>{f()},[f]);async function T(){E(!0),l(null),o(null);try{const s=await X();o(s.alreadyPresent?`DuckDB already installed (${s.version}).`:`Installed DuckDB ${s.version}.`),await f()}catch(s){l(s instanceof Error?s.message:"Failed to install DuckDB")}finally{E(!1)}}async function q(){const s=N.trim()||void 0;I(!0),l(null),o(null);try{const r=await Z(s);o(s?`Queued sync for ${r.release}. Download + query runs in the background.`:`Queued sync for auto-discovered release ${r.release}. Download + query runs in the background.`),v(""),k(!1),await f()}catch(r){r instanceof ee&&r.code==="MISSING_DEPENDENCY"?l("DuckDB is not installed. Install it first."):l(r instanceof Error?r.message:"Failed to trigger sync")}finally{I(!1)}}async function G(s){l(null),o(null);try{await se(s),o(`Pruned cached release ${s}.`),await f()}catch(r){l(r instanceof Error?r.message:"Failed to prune release")}}const Q=a?.status==="ready"&&c.every(s=>s.release!==a.release);return e.jsxs("div",{className:"page-container",children:[e.jsx("div",{className:"page-header",children:e.jsxs("div",{className:"page-header-left",children:[e.jsx("h1",{className:"page-title",children:"Backlink data"}),e.jsx("p",{className:"page-subtitle",children:"Manage the shared backlink source and review its latest data."})]})}),A&&e.jsx(x,{className:"surface-card p-4 mb-4 border-negative-800/60",children:e.jsx("p",{className:"text-sm text-negative",children:A})}),F&&e.jsx(x,{className:"surface-card p-4 mb-4 border-positive-800/60",children:e.jsx("p",{className:"text-sm text-positive",children:F})}),e.jsxs("section",{className:"page-section-divider",children:[e.jsxs("div",{className:"section-head section-head-inline",children:[e.jsxs("div",{children:[e.jsx("p",{className:"eyebrow eyebrow-soft",children:"Readiness"}),e.jsx("h2",{children:"Backlink source"})]}),t?.duckdbInstalled?e.jsx(j,{tone:"positive",children:"Installed"}):e.jsx(j,{tone:"caution",children:"Not installed"})]}),e.jsx(x,{className:"surface-card p-4",children:B?e.jsx("p",{className:"text-sm text-muted",children:"Checking…"}):t?.duckdbInstalled?e.jsx("p",{className:"text-sm text-secondary",children:"Ready to sync a Common Crawl release."}):e.jsxs("div",{className:"flex items-center justify-between gap-4",children:[e.jsx("p",{className:"text-sm text-secondary",children:"Install the local query engine to enable release syncs."}),!u()&&e.jsxs(w,{type:"button",size:"sm",disabled:R,onClick:P(T),children:[e.jsx(te,{className:"h-4 w-4 mr-1.5","aria-hidden":!0}),R?"Installing…":"Install DuckDB"]})]})})]}),e.jsxs("section",{className:"page-section-divider",children:[e.jsxs("div",{className:"section-head section-head-inline",children:[e.jsxs("div",{children:[e.jsx("p",{className:"eyebrow eyebrow-soft",children:"Latest sync"}),e.jsxs("h2",{className:"flex items-center gap-2",children:["Release sync",e.jsx(g,{label:"What is a release sync?",children:"A release sync downloads one Common Crawl dump (~16 GB) and extracts backlinks for every project in this workspace in one pass. This is the heavy job — subsequent per-project re-runs skip the download and just re-query the cached files."})]})]}),a&&e.jsx(j,{tone:C(a.status),children:a.status})]}),e.jsxs(x,{className:"surface-card p-5",children:[a?e.jsxs("div",{className:"space-y-2 text-sm",children:[e.jsxs("p",{className:"text-strong",children:["Release ",e.jsx("code",{className:"text-neutral",children:a.release})]}),a.phaseDetail&&e.jsx("p",{className:"text-secondary",children:a.phaseDetail}),e.jsxs("div",{className:"grid grid-cols-2 md:grid-cols-4 gap-4 text-xs text-muted pt-2",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-faint uppercase tracking-wide",children:"Projects"}),e.jsx("p",{className:"text-neutral mt-0.5",children:a.projectsProcessed??"—"})]}),e.jsxs("div",{children:[e.jsxs("p",{className:"text-faint uppercase tracking-wide flex items-center gap-1",children:["Rows",e.jsx(g,{label:"What are rows?",children:"Total number of (project, referring domain) pairs persisted in SQLite from this sync, across every project in the workspace."})]}),e.jsx("p",{className:"text-neutral mt-0.5",children:a.domainsDiscovered??"—"})]}),e.jsxs("div",{children:[e.jsx("p",{className:"text-faint uppercase tracking-wide",children:"Started"}),e.jsx("p",{className:"text-neutral mt-0.5",children:b(a.downloadStartedAt??a.createdAt)})]}),e.jsxs("div",{children:[e.jsx("p",{className:"text-faint uppercase tracking-wide",children:"Finished"}),e.jsx("p",{className:"text-neutral mt-0.5",children:b(a.queryFinishedAt)})]})]}),a.error&&e.jsx("p",{className:"text-sm text-negative-400 pt-2",children:a.error})]}):e.jsx("p",{className:"text-sm text-muted",children:"No release sync has run in this workspace yet."}),Q&&e.jsx("div",{className:"mt-4 rounded border border-caution-800/60 bg-caution-950/20 p-3",children:e.jsxs("div",{className:"flex items-start gap-2",children:[e.jsx(K,{className:"h-4 w-4 text-caution-400 shrink-0 mt-0.5","aria-hidden":!0}),e.jsxs("div",{className:"text-sm text-neutral leading-relaxed",children:[e.jsx("p",{className:"font-medium text-caution-200",children:"Cached files for this release are missing."}),e.jsx("p",{className:"mt-1 text-secondary",children:"Sync this release again, or sync the newest release, before refreshing individual projects."})]})]})}),e.jsxs("div",{className:"mt-4 rounded border border-base bg-bg-elevated/40 p-3",children:[e.jsxs("div",{className:"flex items-start justify-between gap-3 mb-3",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-[10px] uppercase tracking-wide text-muted",children:"Auto-detected release"}),m?e.jsxs("p",{className:"text-sm text-strong mt-0.5",children:[e.jsx("code",{className:"text-heading",children:m.release}),e.jsxs("span",{className:"ml-2 text-xs text-muted",children:["Vertex ",S(m.vertexBytes),", edges ",S(m.edgesBytes)]})]}):e.jsx("p",{className:"text-sm text-muted mt-0.5",children:B?"Checking Common Crawl…":"Could not find a release. Choose one below."}),e.jsxs("a",{href:le,target:"_blank",rel:"noopener noreferrer",className:"mt-1 inline-flex items-center gap-1 text-xs text-secondary hover:text-strong focus:text-strong focus:outline-none focus-visible:ring-1 focus-visible:ring-mono-500 rounded",children:["Browse all Common Crawl web-graph releases",e.jsx(ae,{className:"h-3 w-3","aria-hidden":!0})]})]}),!u()&&e.jsxs("div",{className:"flex items-center gap-2 shrink-0",children:[e.jsxs(w,{type:"button",size:"sm",disabled:p||!t?.duckdbInstalled||!m&&!N.trim(),onClick:P(q),children:[e.jsx(Y,{className:"h-4 w-4 mr-1.5","aria-hidden":!0}),p?"Queuing…":"Run sync"]}),e.jsxs(g,{label:"What does Run sync do?",children:[e.jsxs("span",{className:"block",children:["Downloads the auto-detected (or chosen) Common Crawl release (~16 GB) to"," ",e.jsx("code",{className:"text-neutral",children:"~/.canonry/cache/commoncrawl/"}),", then runs a single DuckDB query that extracts referring domains for every project in this workspace."]}),e.jsxs("span",{className:"mt-2 block text-secondary",children:["First time for a release: ",e.jsx("span",{className:"text-strong",children:"~10–20 min download + ~5 min query"}),". Re-running the same release later: ",e.jsx("span",{className:"text-strong",children:"skips download, just re-queries"})," (~5 min)."]})]})]})]}),u()?null:M?e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx("input",{type:"text",className:"flex-1 min-w-[240px] rounded border border-strong bg-transparent px-2.5 py-1.5 text-sm text-strong placeholder-mono-600 focus:border-mono-500 focus:outline-none",placeholder:"cc-main-2026-jan-feb-mar",value:N,onChange:s=>v(s.target.value),disabled:p,autoFocus:!0}),e.jsx("button",{type:"button",className:"text-sm text-secondary hover:text-neutral focus:text-neutral focus:outline-none focus-visible:ring-1 focus-visible:ring-mono-500 rounded",onClick:()=>{v(""),k(!1)},disabled:p,children:"Cancel"})]}):e.jsx("button",{type:"button",className:"text-sm text-secondary hover:text-neutral focus:text-neutral focus:outline-none focus-visible:ring-1 focus-visible:ring-mono-500 rounded",onClick:()=>k(!0),disabled:p,children:"Use a different release →"})]}),!t?.duckdbInstalled&&e.jsx("p",{className:"text-sm text-secondary mt-2",children:"Install DuckDB first to enable sync."})]})]}),e.jsxs("details",{className:"page-section-divider group",children:[e.jsx("summary",{className:"cursor-pointer text-sm font-medium text-secondary hover:text-strong focus:outline-none focus-visible:ring-1 focus-visible:ring-mono-500 rounded",children:"Technical details and cache"}),e.jsxs("div",{className:"mt-4",children:[e.jsx("p",{className:"text-sm text-secondary mb-3",children:"Cached releases support project re-extracts. Pruning a release does not remove saved backlink results."}),e.jsx(x,{className:"surface-card overflow-hidden",children:e.jsxs("table",{className:"w-full text-sm",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"border-b border-base text-left text-xs uppercase tracking-wide text-faint",children:[e.jsx("th",{className:"px-4 py-2 font-medium",children:"Release"}),e.jsx("th",{className:"px-4 py-2 font-medium",children:"Sync status"}),e.jsx("th",{className:"px-4 py-2 text-right font-medium",children:"Size"}),e.jsx("th",{className:"px-4 py-2 font-medium",children:"Last used"}),!u()&&e.jsx("th",{className:"px-4 py-2 font-medium sr-only",children:"Actions"})]})}),e.jsxs("tbody",{children:[c.map(s=>e.jsxs("tr",{className:"border-b border-mono-900 last:border-0",children:[e.jsx("td",{className:"px-4 py-2 text-strong",children:e.jsx("code",{children:s.release})}),e.jsx("td",{className:"px-4 py-2",children:s.syncStatus?e.jsx(j,{tone:C(s.syncStatus),children:s.syncStatus}):e.jsx("span",{className:"text-faint",children:"—"})}),e.jsx("td",{className:"px-4 py-2 text-right text-secondary tabular-nums",children:S(s.bytes)}),e.jsx("td",{className:"px-4 py-2 text-secondary",children:b(s.lastUsedAt)}),!u()&&e.jsx("td",{className:"px-4 py-2 text-right",children:e.jsxs("div",{className:"inline-flex items-center gap-1",children:[e.jsxs(w,{type:"button",variant:"outline",size:"sm",onClick:()=>{G(s.release)},children:[e.jsx(ne,{className:"h-4 w-4 mr-1.5","aria-hidden":!0}),"Prune"]}),e.jsx(g,{label:"What does Prune do?",placement:"top",children:"Deletes the ~16 GB cache for this release from disk. Backlink results already in SQLite remain untouched. To re-run extracts against this release, you’d have to sync it again (another ~16 GB download)."})]})})]},s.release)),c.length===0&&e.jsx("tr",{children:e.jsx("td",{className:"px-4 py-4 text-sm text-muted",colSpan:u()?4:5,children:"No cached releases on this machine. If you ran a sync from a different machine (or deleted the cache), the backlink data is still in the database — but you’ll need to re-sync a release to run new extracts."})})]})]})}),e.jsx("p",{className:"mt-3 text-xs text-muted",children:"Common Crawl files are stored locally. DuckDB reads them; Canonry stores results in its normal database."})]})]}),d.length>1&&e.jsxs("section",{className:"page-section-divider",children:[e.jsx("div",{className:"section-head section-head-inline",children:e.jsxs("div",{children:[e.jsx("p",{className:"eyebrow eyebrow-soft",children:"History"}),e.jsx("h2",{children:"Past release syncs"})]})}),e.jsx(x,{className:"surface-card overflow-hidden",children:e.jsxs("table",{className:"w-full text-sm",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"border-b border-base text-left text-xs uppercase tracking-wide text-faint",children:[e.jsx("th",{className:"px-4 py-2 font-medium",children:"Release"}),e.jsx("th",{className:"px-4 py-2 font-medium",children:"Status"}),e.jsx("th",{className:"px-4 py-2 text-right font-medium",children:"Projects"}),e.jsx("th",{className:"px-4 py-2 text-right font-medium",children:"Rows"}),e.jsx("th",{className:"px-4 py-2 font-medium",children:"Finished"})]})}),e.jsx("tbody",{children:d.map(s=>e.jsxs("tr",{className:"border-b border-mono-900 last:border-0",children:[e.jsx("td",{className:"px-4 py-2 text-strong",children:e.jsx("code",{children:s.release})}),e.jsx("td",{className:"px-4 py-2",children:e.jsx(j,{tone:C(s.status),children:s.status})}),e.jsx("td",{className:"px-4 py-2 text-right text-secondary tabular-nums",children:s.projectsProcessed??"—"}),e.jsx("td",{className:"px-4 py-2 text-right text-secondary tabular-nums",children:s.domainsDiscovered??"—"}),e.jsx("td",{className:"px-4 py-2 text-secondary",children:b(s.queryFinishedAt??s.updatedAt)})]},s.id))})]})})]})]})}export{he as BacklinksPage};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{j as e}from"./vendor-tanstack-BjS7iY3g.js";import{A as s}from"./AuditHistoryPanel-WWT1n8jp.js";import"./index-CsM-Xxia.js";import"./vendor-radix-DnzzbllM.js";import"./vendor-recharts-33ACLxsD.js";import"./vendor-markdown-CpDJch4G.js";function p(){return e.jsxs("div",{className:"page-container",children:[e.jsx("div",{className:"page-header",children:e.jsxs("div",{className:"page-header-left",children:[e.jsx("h1",{className:"page-title",children:"History"}),e.jsx("p",{className:"page-subtitle",children:"Changes to projects and settings."})]})}),e.jsx(s,{})]})}export{p as HistoryPage};
|