@ainyc/canonry 4.72.4 → 4.75.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 +1 -1
- 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 +17 -0
- package/assets/assets/{BacklinksPage-CjfpwZEH.js → BacklinksPage-CwAplOLo.js} +1 -1
- package/assets/assets/{ChartPrimitives-Ckf2FrUy.js → ChartPrimitives-EGp5HFxn.js} +1 -1
- package/assets/assets/ProjectPage-C-zhkBKK.js +6 -0
- package/assets/assets/{RunRow-BuFyG0V_.js → RunRow-YFN2PwH-.js} +1 -1
- package/assets/assets/{RunsPage-D-pr000K.js → RunsPage-DlKS8zaS.js} +1 -1
- package/assets/assets/{SettingsPage-CiaapCYn.js → SettingsPage-Q0OZKjMD.js} +1 -1
- package/assets/assets/{TrafficPage-B40xytJD.js → TrafficPage-BbySUnhy.js} +1 -1
- package/assets/assets/{TrafficSourceDetailPage-7hHem-gM.js → TrafficSourceDetailPage-BGzuvTYp.js} +1 -1
- package/assets/assets/{extract-error-message-3GkDsu1h.js → extract-error-message-Czt2jFxA.js} +1 -1
- package/assets/assets/index-CFVX11lK.css +1 -0
- package/assets/assets/{index-BVdH2O9w.js → index-DYsYdWV8.js} +118 -118
- package/assets/assets/{server-traffic-CsgPsudZ.js → server-traffic-BzIFKqGS.js} +1 -1
- package/assets/assets/{trash-2-B8Ipf9rI.js → trash-2-DKCkbZUb.js} +1 -1
- package/assets/index.html +2 -2
- package/dist/{chunk-JXFNERK4.js → chunk-JNAKRK77.js} +1103 -998
- package/dist/{chunk-HOKVBMOD.js → chunk-JUWU2DV6.js} +402 -81
- package/dist/{chunk-SRBO33HB.js → chunk-QY5WZWU4.js} +403 -202
- package/dist/{chunk-ZUBBADMR.js → chunk-WFMEK34V.js} +162 -1
- package/dist/cli.js +237 -31
- package/dist/index.d.ts +10 -0
- package/dist/index.js +4 -4
- package/dist/{intelligence-service-CSW4R4I7.js → intelligence-service-L2A5MFB4.js} +2 -2
- package/dist/mcp.js +2 -2
- package/package.json +10 -10
- package/assets/assets/ProjectPage-DZeplYeC.js +0 -6
- package/assets/assets/index-B3nENtU0.css +0 -1
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
trafficConnectVercelRequestSchema,
|
|
23
23
|
trafficConnectWordpressRequestSchema,
|
|
24
24
|
trafficEventKindSchema
|
|
25
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-JNAKRK77.js";
|
|
26
26
|
|
|
27
27
|
// src/config.ts
|
|
28
28
|
import fs from "fs";
|
|
@@ -3345,6 +3345,58 @@ var postApiV1ProjectsByNameDiscoverSessionsByIdPromote = (options) => {
|
|
|
3345
3345
|
}
|
|
3346
3346
|
});
|
|
3347
3347
|
};
|
|
3348
|
+
var getApiV1ProjectsByNameTechnicalAeo = (options) => {
|
|
3349
|
+
return (options.client ?? client).get({
|
|
3350
|
+
security: [
|
|
3351
|
+
{
|
|
3352
|
+
scheme: "bearer",
|
|
3353
|
+
type: "http"
|
|
3354
|
+
}
|
|
3355
|
+
],
|
|
3356
|
+
url: "/api/v1/projects/{name}/technical-aeo",
|
|
3357
|
+
...options
|
|
3358
|
+
});
|
|
3359
|
+
};
|
|
3360
|
+
var getApiV1ProjectsByNameTechnicalAeoPages = (options) => {
|
|
3361
|
+
return (options.client ?? client).get({
|
|
3362
|
+
security: [
|
|
3363
|
+
{
|
|
3364
|
+
scheme: "bearer",
|
|
3365
|
+
type: "http"
|
|
3366
|
+
}
|
|
3367
|
+
],
|
|
3368
|
+
url: "/api/v1/projects/{name}/technical-aeo/pages",
|
|
3369
|
+
...options
|
|
3370
|
+
});
|
|
3371
|
+
};
|
|
3372
|
+
var getApiV1ProjectsByNameTechnicalAeoTrend = (options) => {
|
|
3373
|
+
return (options.client ?? client).get({
|
|
3374
|
+
security: [
|
|
3375
|
+
{
|
|
3376
|
+
scheme: "bearer",
|
|
3377
|
+
type: "http"
|
|
3378
|
+
}
|
|
3379
|
+
],
|
|
3380
|
+
url: "/api/v1/projects/{name}/technical-aeo/trend",
|
|
3381
|
+
...options
|
|
3382
|
+
});
|
|
3383
|
+
};
|
|
3384
|
+
var postApiV1ProjectsByNameTechnicalAeoRuns = (options) => {
|
|
3385
|
+
return (options.client ?? client).post({
|
|
3386
|
+
security: [
|
|
3387
|
+
{
|
|
3388
|
+
scheme: "bearer",
|
|
3389
|
+
type: "http"
|
|
3390
|
+
}
|
|
3391
|
+
],
|
|
3392
|
+
url: "/api/v1/projects/{name}/technical-aeo/runs",
|
|
3393
|
+
...options,
|
|
3394
|
+
headers: {
|
|
3395
|
+
"Content-Type": "application/json",
|
|
3396
|
+
...options.headers
|
|
3397
|
+
}
|
|
3398
|
+
});
|
|
3399
|
+
};
|
|
3348
3400
|
var deleteApiV1ProjectsByNameAgentTranscript = (options) => {
|
|
3349
3401
|
return (options.client ?? client).delete({
|
|
3350
3402
|
security: [
|
|
@@ -4539,6 +4591,44 @@ var ApiClient = class {
|
|
|
4539
4591
|
})
|
|
4540
4592
|
);
|
|
4541
4593
|
}
|
|
4594
|
+
// ── Technical AEO (site-audit) ──────────────────────────────────────────
|
|
4595
|
+
async getTechnicalAeoScore(project) {
|
|
4596
|
+
return this.invoke(
|
|
4597
|
+
() => getApiV1ProjectsByNameTechnicalAeo({ client: this.heyClient, path: { name: project } })
|
|
4598
|
+
);
|
|
4599
|
+
}
|
|
4600
|
+
async getTechnicalAeoPages(project, opts) {
|
|
4601
|
+
return this.invoke(
|
|
4602
|
+
() => getApiV1ProjectsByNameTechnicalAeoPages({
|
|
4603
|
+
client: this.heyClient,
|
|
4604
|
+
path: { name: project },
|
|
4605
|
+
query: {
|
|
4606
|
+
status: opts?.status,
|
|
4607
|
+
sort: opts?.sort,
|
|
4608
|
+
limit: opts?.limit !== void 0 ? String(opts.limit) : void 0,
|
|
4609
|
+
offset: opts?.offset !== void 0 ? String(opts.offset) : void 0
|
|
4610
|
+
}
|
|
4611
|
+
})
|
|
4612
|
+
);
|
|
4613
|
+
}
|
|
4614
|
+
async getTechnicalAeoTrend(project, opts) {
|
|
4615
|
+
return this.invoke(
|
|
4616
|
+
() => getApiV1ProjectsByNameTechnicalAeoTrend({
|
|
4617
|
+
client: this.heyClient,
|
|
4618
|
+
path: { name: project },
|
|
4619
|
+
query: { limit: opts?.limit !== void 0 ? String(opts.limit) : void 0 }
|
|
4620
|
+
})
|
|
4621
|
+
);
|
|
4622
|
+
}
|
|
4623
|
+
async triggerSiteAudit(project, body) {
|
|
4624
|
+
return this.invoke(
|
|
4625
|
+
() => postApiV1ProjectsByNameTechnicalAeoRuns({
|
|
4626
|
+
client: this.heyClient,
|
|
4627
|
+
path: { name: project },
|
|
4628
|
+
body: body ?? {}
|
|
4629
|
+
})
|
|
4630
|
+
);
|
|
4631
|
+
}
|
|
4542
4632
|
// ── WordPress ──────────────────────────────────────────────────────────
|
|
4543
4633
|
async wordpressConnect(project, body) {
|
|
4544
4634
|
return this.invoke(
|
|
@@ -5190,6 +5280,25 @@ var discoveryPromoteInputSchema = z2.object({
|
|
|
5190
5280
|
competitorTypes: z2.array(discoveryCompetitorTypeSchema).min(1).optional().describe("Which classified competitor types to merge. Omitted promotes direct-competitor only; pass an explicit list to also adopt editorial-media channels or to recover legacy unknown entries. Ignored when includeCompetitors is false.")
|
|
5191
5281
|
}).optional()
|
|
5192
5282
|
});
|
|
5283
|
+
var technicalAeoScoreInputSchema = z2.object({
|
|
5284
|
+
project: projectNameSchema
|
|
5285
|
+
});
|
|
5286
|
+
var technicalAeoPagesInputSchema = z2.object({
|
|
5287
|
+
project: projectNameSchema,
|
|
5288
|
+
status: z2.enum(["success", "error"]).optional().describe("Filter to successfully-audited or errored pages."),
|
|
5289
|
+
sort: z2.enum(["score-asc", "score-desc", "url"]).optional().describe("Sort order. Defaults to score-asc (worst pages first)."),
|
|
5290
|
+
limit: z2.number().int().positive().max(500).optional(),
|
|
5291
|
+
offset: z2.number().int().nonnegative().optional()
|
|
5292
|
+
});
|
|
5293
|
+
var technicalAeoTrendInputSchema = z2.object({
|
|
5294
|
+
project: projectNameSchema,
|
|
5295
|
+
limit: z2.number().int().positive().max(365).optional()
|
|
5296
|
+
});
|
|
5297
|
+
var technicalAeoRunInputSchema = z2.object({
|
|
5298
|
+
project: projectNameSchema,
|
|
5299
|
+
sitemapUrl: z2.string().url().optional().describe("Override the sitemap URL. Defaults to https://<canonicalDomain>/sitemap.xml."),
|
|
5300
|
+
limit: z2.number().int().positive().max(2e3).optional().describe("Cap pages audited (highest sitemap <priority> first).")
|
|
5301
|
+
});
|
|
5193
5302
|
var AGENT_WEBHOOK_EVENTS = [
|
|
5194
5303
|
notificationEventSchema.enum["run.completed"],
|
|
5195
5304
|
notificationEventSchema.enum["insight.critical"],
|
|
@@ -6403,6 +6512,58 @@ var canonryMcpTools = [
|
|
|
6403
6512
|
annotations: writeAnnotations({ idempotentHint: true }),
|
|
6404
6513
|
openApiOperations: ["POST /api/v1/projects/{name}/discover/sessions/{id}/promote"],
|
|
6405
6514
|
handler: (client2, input) => client2.promoteDiscovery(input.project, input.sessionId, input.request)
|
|
6515
|
+
}),
|
|
6516
|
+
defineTool({
|
|
6517
|
+
name: "canonry_technical_aeo_score",
|
|
6518
|
+
title: "Get Technical AEO score",
|
|
6519
|
+
description: "Get the Technical AEO scorecard for a project: the latest site-audit aggregate 0\u2013100 score, per-factor site-level averages (with pass/partial/fail distribution), cross-cutting issues, prioritized fixes, and the delta vs the previous audit. When `hasData` is false the project has never been audited \u2014 call canonry_technical_aeo_run first.",
|
|
6520
|
+
access: "read",
|
|
6521
|
+
tier: "monitoring",
|
|
6522
|
+
inputSchema: technicalAeoScoreInputSchema,
|
|
6523
|
+
annotations: readAnnotations(),
|
|
6524
|
+
openApiOperations: ["GET /api/v1/projects/{name}/technical-aeo"],
|
|
6525
|
+
handler: (client2, input) => client2.getTechnicalAeoScore(input.project)
|
|
6526
|
+
}),
|
|
6527
|
+
defineTool({
|
|
6528
|
+
name: "canonry_technical_aeo_pages",
|
|
6529
|
+
title: "List Technical AEO pages",
|
|
6530
|
+
description: "List the per-page breakdown of the latest site-audit run (paginated). Filter status=error to surface unreachable pages, or sort score-asc (default) to surface the worst-scoring pages first. Use after canonry_technical_aeo_score to drill into which pages drag the site score down.",
|
|
6531
|
+
access: "read",
|
|
6532
|
+
tier: "monitoring",
|
|
6533
|
+
inputSchema: technicalAeoPagesInputSchema,
|
|
6534
|
+
annotations: readAnnotations(),
|
|
6535
|
+
openApiOperations: ["GET /api/v1/projects/{name}/technical-aeo/pages"],
|
|
6536
|
+
handler: (client2, input) => client2.getTechnicalAeoPages(input.project, {
|
|
6537
|
+
status: input.status,
|
|
6538
|
+
sort: input.sort,
|
|
6539
|
+
limit: input.limit,
|
|
6540
|
+
offset: input.offset
|
|
6541
|
+
})
|
|
6542
|
+
}),
|
|
6543
|
+
defineTool({
|
|
6544
|
+
name: "canonry_technical_aeo_trend",
|
|
6545
|
+
title: "Get Technical AEO trend",
|
|
6546
|
+
description: 'Get the aggregate Technical AEO score over time (oldest-first) across past site-audit runs. Use to answer "is our technical AEO improving?".',
|
|
6547
|
+
access: "read",
|
|
6548
|
+
tier: "monitoring",
|
|
6549
|
+
inputSchema: technicalAeoTrendInputSchema,
|
|
6550
|
+
annotations: readAnnotations(),
|
|
6551
|
+
openApiOperations: ["GET /api/v1/projects/{name}/technical-aeo/trend"],
|
|
6552
|
+
handler: (client2, input) => client2.getTechnicalAeoTrend(input.project, input.limit !== void 0 ? { limit: input.limit } : void 0)
|
|
6553
|
+
}),
|
|
6554
|
+
defineTool({
|
|
6555
|
+
name: "canonry_technical_aeo_run",
|
|
6556
|
+
title: "Run Technical AEO site audit",
|
|
6557
|
+
description: "Trigger a site-audit run: crawl the project sitemap and audit every reachable page across the aeo-audit ranking factors. Returns {runId, status}; the audit runs in the background (a large site can take minutes). Idempotent \u2014 if a site-audit is already in flight it returns that run. Poll canonry_run_get with the returned runId, then read canonry_technical_aeo_score.",
|
|
6558
|
+
access: "write",
|
|
6559
|
+
tier: "monitoring",
|
|
6560
|
+
inputSchema: technicalAeoRunInputSchema,
|
|
6561
|
+
annotations: writeAnnotations({ idempotentHint: false, openWorldHint: true }),
|
|
6562
|
+
openApiOperations: ["POST /api/v1/projects/{name}/technical-aeo/runs"],
|
|
6563
|
+
handler: (client2, input) => client2.triggerSiteAudit(input.project, {
|
|
6564
|
+
sitemapUrl: input.sitemapUrl,
|
|
6565
|
+
limit: input.limit
|
|
6566
|
+
})
|
|
6406
6567
|
})
|
|
6407
6568
|
];
|
|
6408
6569
|
var CANONRY_MCP_TOOL_COUNT = canonryMcpTools.length;
|
package/dist/cli.js
CHANGED
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
setTelemetrySource,
|
|
28
28
|
showFirstRunNotice,
|
|
29
29
|
trackEvent
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-QY5WZWU4.js";
|
|
31
31
|
import {
|
|
32
32
|
CliError,
|
|
33
33
|
EXIT_SYSTEM_ERROR,
|
|
@@ -44,7 +44,7 @@ import {
|
|
|
44
44
|
saveConfig,
|
|
45
45
|
saveConfigPatch,
|
|
46
46
|
usageError
|
|
47
|
-
} from "./chunk-
|
|
47
|
+
} from "./chunk-WFMEK34V.js";
|
|
48
48
|
import {
|
|
49
49
|
apiKeys,
|
|
50
50
|
createClient,
|
|
@@ -52,7 +52,7 @@ import {
|
|
|
52
52
|
projects,
|
|
53
53
|
queries,
|
|
54
54
|
renderReportHtml
|
|
55
|
-
} from "./chunk-
|
|
55
|
+
} from "./chunk-JUWU2DV6.js";
|
|
56
56
|
import {
|
|
57
57
|
CcReleaseSyncStatuses,
|
|
58
58
|
CheckScopes,
|
|
@@ -63,6 +63,7 @@ import {
|
|
|
63
63
|
discoveryBucketSchema,
|
|
64
64
|
discoveryCompetitorTypeSchema,
|
|
65
65
|
effectiveDomains,
|
|
66
|
+
factorStatusFromScore,
|
|
66
67
|
formatGbpMetricLabel,
|
|
67
68
|
formatIsoDate,
|
|
68
69
|
formatRunErrorOneLine,
|
|
@@ -71,7 +72,7 @@ import {
|
|
|
71
72
|
providerQuotaPolicySchema,
|
|
72
73
|
resolveProviderInput,
|
|
73
74
|
winnabilityClassSchema
|
|
74
|
-
} from "./chunk-
|
|
75
|
+
} from "./chunk-JNAKRK77.js";
|
|
75
76
|
|
|
76
77
|
// src/cli.ts
|
|
77
78
|
import { pathToFileURL } from "url";
|
|
@@ -8510,7 +8511,7 @@ function renderCover(pdf, report) {
|
|
|
8510
8511
|
hour: "numeric",
|
|
8511
8512
|
minute: "2-digit"
|
|
8512
8513
|
}));
|
|
8513
|
-
pdf.keyValue("AEO Audit", `${report.audit.overallScore}/100
|
|
8514
|
+
pdf.keyValue("AEO Audit", `${report.audit.overallScore}/100`);
|
|
8514
8515
|
pdf.keyValue("Visibility Gap (Citations + Mentions)", report.summary.visibilityGap);
|
|
8515
8516
|
pdf.paragraph(report.profile.summary, { size: 11, color: INK, lineHeight: 16 });
|
|
8516
8517
|
pdf.rule();
|
|
@@ -8532,7 +8533,7 @@ function renderAudit(pdf, report) {
|
|
|
8532
8533
|
const factorRows = [...report.audit.factors].sort((a, b) => a.score - b.score || a.name.localeCompare(b.name)).slice(0, 5).map((factor) => [
|
|
8533
8534
|
factor.name,
|
|
8534
8535
|
formatAuditFactorScore(factor),
|
|
8535
|
-
factor.
|
|
8536
|
+
factorStatusFromScore(factor.score)
|
|
8536
8537
|
]);
|
|
8537
8538
|
if (factorRows.length > 0) {
|
|
8538
8539
|
pdf.table(["Weakest factor", "Score / Weight", "Status"], factorRows, [270, 120, 126]);
|
|
@@ -8664,7 +8665,7 @@ function formatSnapshotMarkdown(report) {
|
|
|
8664
8665
|
lines.push("");
|
|
8665
8666
|
lines.push(`**Domain:** ${report.domain}`);
|
|
8666
8667
|
lines.push(`**Generated:** ${new Date(report.generatedAt).toLocaleString("en-US", { year: "numeric", month: "long", day: "numeric", hour: "numeric", minute: "2-digit" })}`);
|
|
8667
|
-
lines.push(`**AEO Audit Score:** ${report.audit.overallScore}/100
|
|
8668
|
+
lines.push(`**AEO Audit Score:** ${report.audit.overallScore}/100`);
|
|
8668
8669
|
lines.push("");
|
|
8669
8670
|
lines.push("## Visibility Gap (Citations + Mentions)");
|
|
8670
8671
|
lines.push("");
|
|
@@ -8725,7 +8726,7 @@ function formatSnapshotMarkdown(report) {
|
|
|
8725
8726
|
lines.push("|--------|-------|--------|--------|");
|
|
8726
8727
|
const sorted = [...report.audit.factors].sort((a, b) => a.score - b.score);
|
|
8727
8728
|
for (const factor of sorted) {
|
|
8728
|
-
lines.push(`| ${factor.name} | ${factor.score} | ${factor.weight} | ${factor.
|
|
8729
|
+
lines.push(`| ${factor.name} | ${factor.score} | ${factor.weight} | ${factorStatusFromScore(factor.score)} |`);
|
|
8729
8730
|
}
|
|
8730
8731
|
lines.push("");
|
|
8731
8732
|
}
|
|
@@ -8736,7 +8737,7 @@ function formatSnapshotMarkdown(report) {
|
|
|
8736
8737
|
function formatSnapshotText(report) {
|
|
8737
8738
|
const lines = [];
|
|
8738
8739
|
lines.push(`Snapshot: ${report.companyName} (${report.domain})`);
|
|
8739
|
-
lines.push(`AEO audit: ${report.audit.overallScore}/100
|
|
8740
|
+
lines.push(`AEO audit: ${report.audit.overallScore}/100`);
|
|
8740
8741
|
lines.push(report.summary.visibilityGap);
|
|
8741
8742
|
lines.push("");
|
|
8742
8743
|
if (report.summary.topCompetitors.length > 0) {
|
|
@@ -10375,7 +10376,7 @@ async function serveCommand(format = "text") {
|
|
|
10375
10376
|
process.stderr.write(`warning: ai-referral-paths backfill skipped: ${msg}
|
|
10376
10377
|
`);
|
|
10377
10378
|
}
|
|
10378
|
-
const app = await createServer({ config, db });
|
|
10379
|
+
const app = await createServer({ config, db, host });
|
|
10379
10380
|
let shuttingDown = false;
|
|
10380
10381
|
const shutdown = (signal) => {
|
|
10381
10382
|
if (shuttingDown) return;
|
|
@@ -10698,11 +10699,215 @@ var SYSTEM_CLI_COMMANDS = [
|
|
|
10698
10699
|
}
|
|
10699
10700
|
];
|
|
10700
10701
|
|
|
10702
|
+
// src/commands/technical-aeo.ts
|
|
10703
|
+
function getClient24() {
|
|
10704
|
+
return createApiClient();
|
|
10705
|
+
}
|
|
10706
|
+
async function technicalAeoScore(project, opts) {
|
|
10707
|
+
const client = getClient24();
|
|
10708
|
+
const score = await client.getTechnicalAeoScore(project);
|
|
10709
|
+
if (isMachineFormat(opts.format)) {
|
|
10710
|
+
console.log(JSON.stringify(score, null, 2));
|
|
10711
|
+
return;
|
|
10712
|
+
}
|
|
10713
|
+
if (!score.hasData) {
|
|
10714
|
+
console.log(
|
|
10715
|
+
`No technical audit yet for "${project}". Run \`canonry technical-aeo run ${project}\` to generate one.`
|
|
10716
|
+
);
|
|
10717
|
+
return;
|
|
10718
|
+
}
|
|
10719
|
+
const lines = [];
|
|
10720
|
+
const delta = score.deltaScore == null ? "" : ` (${score.deltaScore >= 0 ? "+" : ""}${score.deltaScore} vs prev)`;
|
|
10721
|
+
lines.push(`Technical AEO: ${score.aggregateScore}/100${delta}`);
|
|
10722
|
+
lines.push(
|
|
10723
|
+
`Audited ${score.pagesAudited} page(s) \xB7 ${score.pagesSkipped} skipped \xB7 ${score.pagesErrored} errored \xB7 sitemap ${score.sitemapUrl}`
|
|
10724
|
+
);
|
|
10725
|
+
lines.push(`As of ${score.auditedAt}`);
|
|
10726
|
+
if (score.factors.length > 0) {
|
|
10727
|
+
lines.push("");
|
|
10728
|
+
lines.push(`${"Factor".padEnd(32)}${"Wt".padStart(4)}${"Avg".padStart(6)}${"Status".padStart(9)} Pass/Part/Fail`);
|
|
10729
|
+
for (const f of score.factors) {
|
|
10730
|
+
lines.push(
|
|
10731
|
+
`${f.name.slice(0, 31).padEnd(32)}${String(f.weight).padStart(4)}${String(f.avgScore).padStart(6)}${f.status.padStart(9)} ${f.pagesPassing}/${f.pagesPartial}/${f.pagesFailing}`
|
|
10732
|
+
);
|
|
10733
|
+
}
|
|
10734
|
+
}
|
|
10735
|
+
if (score.prioritizedFixes.length > 0) {
|
|
10736
|
+
lines.push("");
|
|
10737
|
+
lines.push("Prioritized fixes:");
|
|
10738
|
+
score.prioritizedFixes.forEach((fix, i) => lines.push(` ${i + 1}. ${fix}`));
|
|
10739
|
+
}
|
|
10740
|
+
console.log(lines.join("\n"));
|
|
10741
|
+
}
|
|
10742
|
+
async function technicalAeoPages(project, opts) {
|
|
10743
|
+
const client = getClient24();
|
|
10744
|
+
const status = opts.status === "success" || opts.status === "error" ? opts.status : void 0;
|
|
10745
|
+
const res = await client.getTechnicalAeoPages(project, { status, sort: opts.sort, limit: opts.limit });
|
|
10746
|
+
if (opts.format === "jsonl") {
|
|
10747
|
+
emitJsonl(res.pages.map((p) => ({ project, runId: res.runId, ...p })));
|
|
10748
|
+
return;
|
|
10749
|
+
}
|
|
10750
|
+
if (opts.format === "json") {
|
|
10751
|
+
console.log(JSON.stringify(res, null, 2));
|
|
10752
|
+
return;
|
|
10753
|
+
}
|
|
10754
|
+
if (res.pages.length === 0) {
|
|
10755
|
+
console.log(`No audited pages for "${project}". Run \`canonry technical-aeo run ${project}\` first.`);
|
|
10756
|
+
return;
|
|
10757
|
+
}
|
|
10758
|
+
const lines = [];
|
|
10759
|
+
lines.push(`${res.pages.length} of ${res.total} page(s) from run ${res.runId}:
|
|
10760
|
+
`);
|
|
10761
|
+
lines.push(`${"Score".padStart(5)} ${"Status".padEnd(7)} URL`);
|
|
10762
|
+
for (const p of res.pages) {
|
|
10763
|
+
const tail = p.status === "error" ? ` ${p.error ?? "error"}` : "";
|
|
10764
|
+
lines.push(`${String(p.overallScore).padStart(5)} ${p.status.padEnd(7)} ${p.url}${tail}`);
|
|
10765
|
+
}
|
|
10766
|
+
console.log(lines.join("\n"));
|
|
10767
|
+
}
|
|
10768
|
+
async function technicalAeoTrend(project, opts) {
|
|
10769
|
+
const client = getClient24();
|
|
10770
|
+
const res = await client.getTechnicalAeoTrend(project, { limit: opts.limit });
|
|
10771
|
+
if (opts.format === "jsonl") {
|
|
10772
|
+
emitJsonl(res.points.map((p) => ({ project, ...p })));
|
|
10773
|
+
return;
|
|
10774
|
+
}
|
|
10775
|
+
if (opts.format === "json") {
|
|
10776
|
+
console.log(JSON.stringify(res, null, 2));
|
|
10777
|
+
return;
|
|
10778
|
+
}
|
|
10779
|
+
if (res.points.length === 0) {
|
|
10780
|
+
console.log(`No audits yet for "${project}". Run \`canonry technical-aeo run ${project}\` first.`);
|
|
10781
|
+
return;
|
|
10782
|
+
}
|
|
10783
|
+
const lines = [];
|
|
10784
|
+
lines.push(`${"Date".padEnd(26)} ${"Score".padStart(5)} Pages`);
|
|
10785
|
+
for (const p of res.points) {
|
|
10786
|
+
lines.push(`${p.auditedAt.padEnd(26)} ${String(p.aggregateScore).padStart(5)} ${p.pagesAudited}`);
|
|
10787
|
+
}
|
|
10788
|
+
console.log(lines.join("\n"));
|
|
10789
|
+
}
|
|
10790
|
+
async function technicalAeoRun(project, opts) {
|
|
10791
|
+
const client = getClient24();
|
|
10792
|
+
const { runId, status } = await client.triggerSiteAudit(project, {
|
|
10793
|
+
sitemapUrl: opts.sitemapUrl,
|
|
10794
|
+
limit: opts.limit
|
|
10795
|
+
});
|
|
10796
|
+
if (!opts.wait) {
|
|
10797
|
+
if (isMachineFormat(opts.format)) {
|
|
10798
|
+
console.log(JSON.stringify({ runId, status }, null, 2));
|
|
10799
|
+
return;
|
|
10800
|
+
}
|
|
10801
|
+
console.log(
|
|
10802
|
+
`Site audit started (run ${runId}, status ${status}). Use \`canonry runs get ${runId}\` to check status, or pass --wait.`
|
|
10803
|
+
);
|
|
10804
|
+
return;
|
|
10805
|
+
}
|
|
10806
|
+
const terminal = /* @__PURE__ */ new Set(["completed", "partial", "failed", "cancelled"]);
|
|
10807
|
+
const start = Date.now();
|
|
10808
|
+
const timeoutMs = 15 * 60 * 1e3;
|
|
10809
|
+
if (!isMachineFormat(opts.format)) process.stderr.write("Auditing");
|
|
10810
|
+
let final = status;
|
|
10811
|
+
while (!terminal.has(final) && Date.now() - start < timeoutMs) {
|
|
10812
|
+
await new Promise((r) => setTimeout(r, 2e3));
|
|
10813
|
+
const run = await client.getRun(runId);
|
|
10814
|
+
if (!isMachineFormat(opts.format)) process.stderr.write(".");
|
|
10815
|
+
final = run.status;
|
|
10816
|
+
}
|
|
10817
|
+
if (!isMachineFormat(opts.format)) process.stderr.write("\n");
|
|
10818
|
+
if (isMachineFormat(opts.format)) {
|
|
10819
|
+
console.log(JSON.stringify({ runId, status: final }, null, 2));
|
|
10820
|
+
return;
|
|
10821
|
+
}
|
|
10822
|
+
console.log(`Site audit ${final} (run ${runId}).`);
|
|
10823
|
+
}
|
|
10824
|
+
|
|
10825
|
+
// src/cli-commands/technical-aeo.ts
|
|
10826
|
+
var TECHNICAL_AEO_CLI_COMMANDS = [
|
|
10827
|
+
{
|
|
10828
|
+
path: ["technical-aeo", "score"],
|
|
10829
|
+
usage: "canonry technical-aeo score <project> [--format json]",
|
|
10830
|
+
run: async (input) => {
|
|
10831
|
+
const project = requireProject(
|
|
10832
|
+
input,
|
|
10833
|
+
"technical-aeo.score",
|
|
10834
|
+
"canonry technical-aeo score <project> [--format json]"
|
|
10835
|
+
);
|
|
10836
|
+
await technicalAeoScore(project, { format: input.format });
|
|
10837
|
+
}
|
|
10838
|
+
},
|
|
10839
|
+
{
|
|
10840
|
+
path: ["technical-aeo", "pages"],
|
|
10841
|
+
usage: "canonry technical-aeo pages <project> [--status success|error] [--sort score-asc|score-desc|url] [--limit <n>] [--format json|jsonl]",
|
|
10842
|
+
options: {
|
|
10843
|
+
status: stringOption(),
|
|
10844
|
+
sort: stringOption(),
|
|
10845
|
+
limit: stringOption()
|
|
10846
|
+
},
|
|
10847
|
+
run: async (input) => {
|
|
10848
|
+
const usage = "canonry technical-aeo pages <project> [--status success|error] [--sort score-asc|score-desc|url] [--limit <n>] [--format json|jsonl]";
|
|
10849
|
+
const project = requireProject(input, "technical-aeo.pages", usage);
|
|
10850
|
+
await technicalAeoPages(project, {
|
|
10851
|
+
status: getString(input.values, "status"),
|
|
10852
|
+
sort: getString(input.values, "sort"),
|
|
10853
|
+
limit: parseIntegerOption(input, "limit", {
|
|
10854
|
+
command: "technical-aeo.pages",
|
|
10855
|
+
usage,
|
|
10856
|
+
message: "--limit must be an integer"
|
|
10857
|
+
}),
|
|
10858
|
+
format: input.format
|
|
10859
|
+
});
|
|
10860
|
+
}
|
|
10861
|
+
},
|
|
10862
|
+
{
|
|
10863
|
+
path: ["technical-aeo", "trend"],
|
|
10864
|
+
usage: "canonry technical-aeo trend <project> [--limit <n>] [--format json|jsonl]",
|
|
10865
|
+
options: {
|
|
10866
|
+
limit: stringOption()
|
|
10867
|
+
},
|
|
10868
|
+
run: async (input) => {
|
|
10869
|
+
const usage = "canonry technical-aeo trend <project> [--limit <n>] [--format json|jsonl]";
|
|
10870
|
+
const project = requireProject(input, "technical-aeo.trend", usage);
|
|
10871
|
+
await technicalAeoTrend(project, {
|
|
10872
|
+
limit: parseIntegerOption(input, "limit", {
|
|
10873
|
+
command: "technical-aeo.trend",
|
|
10874
|
+
usage,
|
|
10875
|
+
message: "--limit must be an integer"
|
|
10876
|
+
}),
|
|
10877
|
+
format: input.format
|
|
10878
|
+
});
|
|
10879
|
+
}
|
|
10880
|
+
},
|
|
10881
|
+
{
|
|
10882
|
+
path: ["technical-aeo", "run"],
|
|
10883
|
+
usage: "canonry technical-aeo run <project> [--sitemap-url <url>] [--limit <n>] [--wait] [--format json]",
|
|
10884
|
+
options: {
|
|
10885
|
+
"sitemap-url": stringOption(),
|
|
10886
|
+
limit: stringOption(),
|
|
10887
|
+
wait: { type: "boolean", default: false }
|
|
10888
|
+
},
|
|
10889
|
+
run: async (input) => {
|
|
10890
|
+
const usage = "canonry technical-aeo run <project> [--sitemap-url <url>] [--limit <n>] [--wait] [--format json]";
|
|
10891
|
+
const project = requireProject(input, "technical-aeo.run", usage);
|
|
10892
|
+
await technicalAeoRun(project, {
|
|
10893
|
+
sitemapUrl: getString(input.values, "sitemap-url"),
|
|
10894
|
+
limit: parseIntegerOption(input, "limit", {
|
|
10895
|
+
command: "technical-aeo.run",
|
|
10896
|
+
usage,
|
|
10897
|
+
message: "--limit must be an integer"
|
|
10898
|
+
}),
|
|
10899
|
+
wait: getBoolean(input.values, "wait"),
|
|
10900
|
+
format: input.format
|
|
10901
|
+
});
|
|
10902
|
+
}
|
|
10903
|
+
}
|
|
10904
|
+
];
|
|
10905
|
+
|
|
10701
10906
|
// src/cli-commands/wordpress.ts
|
|
10702
10907
|
import fs11 from "fs";
|
|
10703
10908
|
|
|
10704
10909
|
// src/commands/wordpress.ts
|
|
10705
|
-
function
|
|
10910
|
+
function getClient25() {
|
|
10706
10911
|
return createApiClient();
|
|
10707
10912
|
}
|
|
10708
10913
|
async function loadYamlModule() {
|
|
@@ -10852,7 +11057,7 @@ async function wordpressConnect(project, opts) {
|
|
|
10852
11057
|
details: { project }
|
|
10853
11058
|
});
|
|
10854
11059
|
}
|
|
10855
|
-
const client =
|
|
11060
|
+
const client = getClient25();
|
|
10856
11061
|
const result = await client.wordpressConnect(project, {
|
|
10857
11062
|
url: opts.url,
|
|
10858
11063
|
stagingUrl: opts.stagingUrl,
|
|
@@ -10869,7 +11074,7 @@ async function wordpressConnect(project, opts) {
|
|
|
10869
11074
|
printWordpressStatus(project, result);
|
|
10870
11075
|
}
|
|
10871
11076
|
async function wordpressDisconnect(project, format) {
|
|
10872
|
-
const client =
|
|
11077
|
+
const client = getClient25();
|
|
10873
11078
|
await client.wordpressDisconnect(project);
|
|
10874
11079
|
if (isMachineFormat(format)) {
|
|
10875
11080
|
printJson2({ project, disconnected: true });
|
|
@@ -10878,7 +11083,7 @@ async function wordpressDisconnect(project, format) {
|
|
|
10878
11083
|
console.log(`WordPress disconnected from project "${project}".`);
|
|
10879
11084
|
}
|
|
10880
11085
|
async function wordpressStatus(project, format) {
|
|
10881
|
-
const client =
|
|
11086
|
+
const client = getClient25();
|
|
10882
11087
|
const result = await client.wordpressStatus(project);
|
|
10883
11088
|
if (isMachineFormat(format)) {
|
|
10884
11089
|
printJson2(result);
|
|
@@ -10887,7 +11092,7 @@ async function wordpressStatus(project, format) {
|
|
|
10887
11092
|
printWordpressStatus(project, result);
|
|
10888
11093
|
}
|
|
10889
11094
|
async function wordpressPages(project, opts) {
|
|
10890
|
-
const client =
|
|
11095
|
+
const client = getClient25();
|
|
10891
11096
|
const result = await client.wordpressPages(project, opts.env);
|
|
10892
11097
|
if (isMachineFormat(opts.format)) {
|
|
10893
11098
|
printJson2(result);
|
|
@@ -10896,7 +11101,7 @@ async function wordpressPages(project, opts) {
|
|
|
10896
11101
|
printPages(project, result.env, result.pages);
|
|
10897
11102
|
}
|
|
10898
11103
|
async function wordpressPage(project, slug, opts) {
|
|
10899
|
-
const client =
|
|
11104
|
+
const client = getClient25();
|
|
10900
11105
|
const result = await client.wordpressPage(project, slug, opts.env);
|
|
10901
11106
|
if (isMachineFormat(opts.format)) {
|
|
10902
11107
|
printJson2(result);
|
|
@@ -10905,7 +11110,7 @@ async function wordpressPage(project, slug, opts) {
|
|
|
10905
11110
|
printPageDetail(result);
|
|
10906
11111
|
}
|
|
10907
11112
|
async function wordpressCreatePage(project, body) {
|
|
10908
|
-
const client =
|
|
11113
|
+
const client = getClient25();
|
|
10909
11114
|
const result = await client.wordpressCreatePage(project, body);
|
|
10910
11115
|
if (isMachineFormat(body.format)) {
|
|
10911
11116
|
printJson2(result);
|
|
@@ -10916,7 +11121,7 @@ async function wordpressCreatePage(project, body) {
|
|
|
10916
11121
|
printPageDetail(result);
|
|
10917
11122
|
}
|
|
10918
11123
|
async function wordpressUpdatePage(project, body) {
|
|
10919
|
-
const client =
|
|
11124
|
+
const client = getClient25();
|
|
10920
11125
|
const result = await client.wordpressUpdatePage(project, body);
|
|
10921
11126
|
if (isMachineFormat(body.format)) {
|
|
10922
11127
|
printJson2(result);
|
|
@@ -10927,7 +11132,7 @@ async function wordpressUpdatePage(project, body) {
|
|
|
10927
11132
|
printPageDetail(result);
|
|
10928
11133
|
}
|
|
10929
11134
|
async function wordpressSetMeta(project, body) {
|
|
10930
|
-
const client =
|
|
11135
|
+
const client = getClient25();
|
|
10931
11136
|
const result = await client.wordpressSetMeta(project, body);
|
|
10932
11137
|
if (isMachineFormat(body.format)) {
|
|
10933
11138
|
printJson2(result);
|
|
@@ -10977,7 +11182,7 @@ async function wordpressBulkSetMeta(project, opts) {
|
|
|
10977
11182
|
details: { path: filePath }
|
|
10978
11183
|
});
|
|
10979
11184
|
}
|
|
10980
|
-
const client =
|
|
11185
|
+
const client = getClient25();
|
|
10981
11186
|
const result = await client.wordpressBulkSetMeta(project, { entries, env: opts.env });
|
|
10982
11187
|
if (isMachineFormat(opts.format)) {
|
|
10983
11188
|
printJson2(result);
|
|
@@ -11020,7 +11225,7 @@ async function wordpressBulkSetMeta(project, opts) {
|
|
|
11020
11225
|
Total: ${applied.length} applied, ${skipped.length} skipped, ${manual.length} manual`);
|
|
11021
11226
|
}
|
|
11022
11227
|
async function wordpressSchema(project, slug, opts) {
|
|
11023
|
-
const client =
|
|
11228
|
+
const client = getClient25();
|
|
11024
11229
|
const result = await client.wordpressSchema(project, slug, opts.env);
|
|
11025
11230
|
if (isMachineFormat(opts.format)) {
|
|
11026
11231
|
printJson2(result);
|
|
@@ -11031,7 +11236,7 @@ async function wordpressSchema(project, slug, opts) {
|
|
|
11031
11236
|
printSchemaBlocks(result.blocks);
|
|
11032
11237
|
}
|
|
11033
11238
|
async function wordpressSetSchema(project, body) {
|
|
11034
|
-
const client =
|
|
11239
|
+
const client = getClient25();
|
|
11035
11240
|
const result = await client.wordpressSetSchema(project, body);
|
|
11036
11241
|
if (isMachineFormat(body.format)) {
|
|
11037
11242
|
printJson2(result);
|
|
@@ -11079,7 +11284,7 @@ async function wordpressSchemaDeploy(project, opts) {
|
|
|
11079
11284
|
details: { path: filePath }
|
|
11080
11285
|
});
|
|
11081
11286
|
}
|
|
11082
|
-
const client =
|
|
11287
|
+
const client = getClient25();
|
|
11083
11288
|
const result = await client.wordpressSchemaDeploy(project, { profile: parsed, env: opts.env });
|
|
11084
11289
|
if (isMachineFormat(opts.format)) {
|
|
11085
11290
|
printJson2(result);
|
|
@@ -11118,7 +11323,7 @@ async function wordpressSchemaDeploy(project, opts) {
|
|
|
11118
11323
|
Total: ${deployed} deployed, ${stripped} stripped, ${skipped} skipped, ${failed} failed`);
|
|
11119
11324
|
}
|
|
11120
11325
|
async function wordpressSchemaStatus(project, opts) {
|
|
11121
|
-
const client =
|
|
11326
|
+
const client = getClient25();
|
|
11122
11327
|
const result = await client.wordpressSchemaStatus(project, opts.env);
|
|
11123
11328
|
if (isMachineFormat(opts.format)) {
|
|
11124
11329
|
printJson2(result);
|
|
@@ -11177,7 +11382,7 @@ async function wordpressOnboard(project, opts) {
|
|
|
11177
11382
|
});
|
|
11178
11383
|
}
|
|
11179
11384
|
}
|
|
11180
|
-
const client =
|
|
11385
|
+
const client = getClient25();
|
|
11181
11386
|
const result = await client.wordpressOnboard(project, {
|
|
11182
11387
|
url: opts.url,
|
|
11183
11388
|
username: opts.user,
|
|
@@ -11202,7 +11407,7 @@ async function wordpressOnboard(project, opts) {
|
|
|
11202
11407
|
}
|
|
11203
11408
|
}
|
|
11204
11409
|
async function wordpressLlmsTxt(project, opts) {
|
|
11205
|
-
const client =
|
|
11410
|
+
const client = getClient25();
|
|
11206
11411
|
const result = await client.wordpressLlmsTxt(project, opts.env);
|
|
11207
11412
|
if (isMachineFormat(opts.format)) {
|
|
11208
11413
|
printJson2(result);
|
|
@@ -11213,7 +11418,7 @@ async function wordpressLlmsTxt(project, opts) {
|
|
|
11213
11418
|
console.log(result.content ?? "(not found)");
|
|
11214
11419
|
}
|
|
11215
11420
|
async function wordpressSetLlmsTxt(project, body) {
|
|
11216
|
-
const client =
|
|
11421
|
+
const client = getClient25();
|
|
11217
11422
|
const result = await client.wordpressSetLlmsTxt(project, body);
|
|
11218
11423
|
if (isMachineFormat(body.format)) {
|
|
11219
11424
|
printJson2(result);
|
|
@@ -11222,7 +11427,7 @@ async function wordpressSetLlmsTxt(project, body) {
|
|
|
11222
11427
|
printManualAssist(`llms.txt update for "${project}"`, result);
|
|
11223
11428
|
}
|
|
11224
11429
|
async function wordpressAudit(project, opts) {
|
|
11225
|
-
const client =
|
|
11430
|
+
const client = getClient25();
|
|
11226
11431
|
const result = await client.wordpressAudit(project, opts.env);
|
|
11227
11432
|
if (isMachineFormat(opts.format)) {
|
|
11228
11433
|
printJson2(result);
|
|
@@ -11236,7 +11441,7 @@ async function wordpressAudit(project, opts) {
|
|
|
11236
11441
|
printAuditIssues(result.issues);
|
|
11237
11442
|
}
|
|
11238
11443
|
async function wordpressDiff(project, slug, format) {
|
|
11239
|
-
const client =
|
|
11444
|
+
const client = getClient25();
|
|
11240
11445
|
const result = await client.wordpressDiff(project, slug);
|
|
11241
11446
|
if (isMachineFormat(format)) {
|
|
11242
11447
|
printJson2(result);
|
|
@@ -11245,7 +11450,7 @@ async function wordpressDiff(project, slug, format) {
|
|
|
11245
11450
|
printDiff(result);
|
|
11246
11451
|
}
|
|
11247
11452
|
async function wordpressStagingStatus(project, format) {
|
|
11248
|
-
const client =
|
|
11453
|
+
const client = getClient25();
|
|
11249
11454
|
const result = await client.wordpressStagingStatus(project);
|
|
11250
11455
|
if (isMachineFormat(format)) {
|
|
11251
11456
|
printJson2(result);
|
|
@@ -11259,7 +11464,7 @@ async function wordpressStagingStatus(project, format) {
|
|
|
11259
11464
|
console.log(` Admin URL: ${result.adminUrl}`);
|
|
11260
11465
|
}
|
|
11261
11466
|
async function wordpressStagingPush(project, format) {
|
|
11262
|
-
const client =
|
|
11467
|
+
const client = getClient25();
|
|
11263
11468
|
const result = await client.wordpressStagingPush(project);
|
|
11264
11469
|
if (isMachineFormat(format)) {
|
|
11265
11470
|
printJson2(result);
|
|
@@ -12284,6 +12489,7 @@ var REGISTERED_CLI_COMMANDS = [
|
|
|
12284
12489
|
...CONTENT_CLI_COMMANDS,
|
|
12285
12490
|
...AGENT_CLI_COMMANDS,
|
|
12286
12491
|
...DISCOVER_CLI_COMMANDS,
|
|
12492
|
+
...TECHNICAL_AEO_CLI_COMMANDS,
|
|
12287
12493
|
...DOCTOR_CLI_COMMANDS,
|
|
12288
12494
|
...GET_CLI_COMMANDS,
|
|
12289
12495
|
...MCP_CLI_COMMANDS
|