@canonry/canonry 5.19.0 → 5.20.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/SKILL.md +13 -8
- package/assets/agent-workspace/skills/aero/references/portfolio-analysis.md +27 -10
- package/assets/agent-workspace/skills/canonry/references/canonry-cli.md +7 -2
- package/assets/assets/{AuditHistoryPanel-C_p8jX7Q.js → AuditHistoryPanel-BSh3Oezj.js} +1 -1
- package/assets/assets/{BacklinksPage-jD4nOGw1.js → BacklinksPage-DQ59dhCx.js} +1 -1
- package/assets/assets/{HistoryPage-DJGBbtBY.js → HistoryPage-BBvgid3o.js} +1 -1
- package/assets/assets/{MeasurementPropertyPage-Dmr3TVlo.js → MeasurementPropertyPage-Dmb18JbT.js} +1 -1
- package/assets/assets/{ProjectPage-B_haCKiA.js → ProjectPage-CPg0q2Dy.js} +1 -1
- package/assets/assets/{RunRow-BMbwR2yk.js → RunRow-BK8sZCID.js} +1 -1
- package/assets/assets/{RunsPage-D8hHakq2.js → RunsPage-CIcVBTdP.js} +1 -1
- package/assets/assets/{SettingsPage-QKnRcFA9.js → SettingsPage-Bc3aR-gz.js} +1 -1
- package/assets/assets/{SiteHealthSection-CDkUXqmb.js → SiteHealthSection-FF14aIXT.js} +3 -3
- package/assets/assets/{TrafficPage-CMif8RlM.js → TrafficPage-C_qoeGDl.js} +1 -1
- package/assets/assets/{TrafficSourceDetailPage-DOCTP_4-.js → TrafficSourceDetailPage-B3i_B2MI.js} +1 -1
- package/assets/assets/{extract-error-message-Dm8RvYE5.js → extract-error-message-BisUn6nN.js} +1 -1
- package/assets/assets/{index-lj0fuFl4.js → index-Dht7JNX5.js} +44 -44
- package/assets/assets/{react-sigma_core.esm.min-DOPuwLtN.js → react-sigma_core.esm.min-tWhS09SS.js} +1 -1
- package/assets/assets/{v2-overview-adapter-C19tUcDS.js → v2-overview-adapter-CAoeWKQJ.js} +1 -1
- package/assets/index.html +1 -1
- package/dist/{chunk-QJWIOCEO.js → chunk-4PENJKRN.js} +2 -2
- package/dist/{chunk-SPCEXW3B.js → chunk-5FKR2K76.js} +11 -4
- package/dist/{chunk-GUJY3RIM.js → chunk-DRZWMFRV.js} +627 -263
- package/dist/{chunk-WLL7Q7JD.js → chunk-QF7SY7AF.js} +222 -29
- package/dist/{chunk-ABUO27BV.js → chunk-TSFKNQ5X.js} +3 -3
- package/dist/{chunk-P2EFPLIO.js → chunk-WL27HO5C.js} +565 -139
- package/dist/{chunk-YHKKCXGY.js → chunk-XBGPHZKA.js} +24 -8
- package/dist/cli.js +73 -17
- package/dist/{demo-server-BOIBS74F.js → demo-server-OCBV5OMS.js} +4 -4
- package/dist/index.js +6 -6
- package/dist/{intelligence-service-IWR2H6OW.js → intelligence-service-MKHINDHN.js} +2 -2
- package/dist/mcp.js +4 -4
- package/package.json +14 -14
|
@@ -105,7 +105,7 @@ import {
|
|
|
105
105
|
trafficEventKindSchema,
|
|
106
106
|
trafficSeriesGranularitySchema,
|
|
107
107
|
visibilityReportRequestSchema
|
|
108
|
-
} from "./chunk-
|
|
108
|
+
} from "./chunk-QF7SY7AF.js";
|
|
109
109
|
|
|
110
110
|
// src/cli-error.ts
|
|
111
111
|
function isMachineFormat(format) {
|
|
@@ -398,7 +398,12 @@ var measurementPropertyEvidenceInputSchema = measurementPropertyEvidenceQuerySch
|
|
|
398
398
|
)
|
|
399
399
|
}).strict();
|
|
400
400
|
var measurementPortfolioSummaryInputSchema = measurementPortfolioSummaryQuerySchema.extend({
|
|
401
|
-
project: projectNameSchema
|
|
401
|
+
project: projectNameSchema,
|
|
402
|
+
groupKey: measurementPortfolioSummaryQuerySchema.shape.groupKey.describe("A market stable key (a row's metro.groupKey). Scopes rows to that market and lists its direct submarkets."),
|
|
403
|
+
// Capped below the route's 50: past about 10 rows the per-row evidence
|
|
404
|
+
// (names given instead, cited domains) no longer fits the tool-result cap.
|
|
405
|
+
limit: z3.number().int().positive().max(10).optional().describe("Rows per list, at most 10. Default 4 keeps the whole result under the tool-result cap; prefer groupKey over a larger limit."),
|
|
406
|
+
includeNestedMarkets: measurementPortfolioSummaryQuerySchema.shape.includeNestedMarkets.describe("Every market at every level, uncapped. Off by default; large portfolios exceed the cap with it on.")
|
|
402
407
|
}).strict();
|
|
403
408
|
var measurementPropertyQuestionsInputSchema = measurementPropertyQuestionsQuerySchema.extend({
|
|
404
409
|
project: projectNameSchema
|
|
@@ -1279,22 +1284,33 @@ var canonryMcpTools = [
|
|
|
1279
1284
|
defineTool({
|
|
1280
1285
|
name: "canonry_analytics_sources",
|
|
1281
1286
|
title: "Get cited-source rankings",
|
|
1282
|
-
description: "Where AI engines
|
|
1287
|
+
description: "Where AI engines cite from for a project: cited domains ranked by how many answers cite them, each tagged with a category and a surface class (own / direct-competitor / ota-aggregator / editorial-media / other), plus a surface-class roll-up and a per-provider breakdown. Project-wide: without `runId` it pools every sweep in the window (`runCount` says how many); without `queryClass` it pools branded and non-brand answers, where branded queries inflate your own domain. For the sources behind non-brand answers, set `queryClass=non-brand` and the latest `runId`; on a v2 measurement plan the class comes from the plan, the same answers as canonry_competitor_landscape with scope=all-markets. Counts come from each answer's stored source list, so every engine is included, Gemini too. A domain counts at most once per answer; `answerShare` is the share of all answers in scope that cite it. `providersWithoutSources` names engines that answered but cited nothing. `limit` caps each ranked list (default 10 for this tool, which keeps each engine list whole); a long-tail rollup keeps the totals. The per-query breakdown is omitted unless `includeByQuery` is true. No LLM calls; probe runs excluded.",
|
|
1283
1288
|
access: "read",
|
|
1284
1289
|
tier: "monitoring",
|
|
1285
1290
|
inputSchema: z3.object({
|
|
1286
1291
|
project: projectNameSchema,
|
|
1287
1292
|
window: analyticsWindowSchema.optional().describe("Time range: 7d, 30d, 90d, or all (default all)."),
|
|
1288
|
-
limit: z3.number().int().positive().optional().describe("Cap each ranked list to the top N domains.
|
|
1293
|
+
limit: z3.number().int().positive().max(50).optional().describe("Cap each ranked list to the top N domains. Default 10; larger lists can exceed the tool-result cap."),
|
|
1294
|
+
runId: z3.string().trim().min(1).optional().describe("Read one answer-visibility run (for example the latest sweep) instead of pooling every run in the window."),
|
|
1295
|
+
queryClass: z3.enum(["all", "branded", "non-brand"]).optional().describe("Branded or non-brand answers only. With an active v2 measurement plan the class comes from the plan assignments. Default all pools both classes."),
|
|
1296
|
+
includeByQuery: z3.boolean().optional().describe("Include the per-query breakdown. It is large; default false for this tool.")
|
|
1289
1297
|
}),
|
|
1290
1298
|
annotations: readAnnotations(),
|
|
1291
1299
|
openApiOperations: ["GET /api/v1/projects/{name}/analytics/sources"],
|
|
1292
|
-
handler: (client, input) => client.getAnalyticsSources(input.project, {
|
|
1300
|
+
handler: (client, input) => client.getAnalyticsSources(input.project, {
|
|
1301
|
+
window: input.window,
|
|
1302
|
+
// The full ranked lists run past the agent's tool-result cap on a large
|
|
1303
|
+
// project, and the per-engine lists are the first thing lost.
|
|
1304
|
+
limit: input.limit ?? 10,
|
|
1305
|
+
runId: input.runId,
|
|
1306
|
+
queryClass: input.queryClass,
|
|
1307
|
+
includeByQuery: input.includeByQuery ?? false
|
|
1308
|
+
})
|
|
1293
1309
|
}),
|
|
1294
1310
|
defineTool({
|
|
1295
1311
|
name: "canonry_competitor_landscape",
|
|
1296
1312
|
title: "Get historical competitor landscape",
|
|
1297
|
-
description: "Returns pinned competitors first, then observed direct competitors and other cited sources from stored answer/source evidence only. Mention share is percentage points (0..100) from answer text; citations are independent. The response carries basis (tracked or observed), availability, and reason. Pins exclusively define the comparison set when present. Otherwise at least 3 stored direct competitors must each be mentioned in 3 answers in the selected scope; raw names and platforms never enter that denominator. Without a comparison set the ratio is null, never 100%. The full comparison array is uncapped. Share of voice needs ONE query class: `queryClass=all`, and omitting it, pool branded and non-brand, so every `shareOfVoice` comes back null and only the counts are published. Pass `queryClass=non-brand` (or `branded`) for a ratio, exactly as visibility-stats does. A project with no brand name or alias cannot be split by class, so a class-scoped read on one is refused rather than answered empty. Optional groupBy: model adds provider/requested-model groups with separate served-model evidence and sample counts. Optional model filters one exact requested model ID and requires provider. Unknown historical models remain explicit. Groups are not a matched-query or equal-weight comparison. Advanced reads support one market group or explicit scope: all-markets. No provider, discovery, or classifier work runs. Ranked lists are capped at 100 observed/other-source rows per group; pins remain complete. Model groups are capped at 50 and disclose truncation.",
|
|
1313
|
+
description: "Returns pinned competitors first, then observed direct competitors and other cited sources from stored answer/source evidence only. Mention share is percentage points (0..100) from answer text; citations are independent. The response carries basis (tracked or observed), availability, and reason. Pins exclusively define the comparison set when present. Otherwise at least 3 stored direct competitors must each be mentioned in 3 answers in the selected scope; raw names and platforms never enter that denominator. Without a comparison set the ratio is null, never 100%. The full comparison array is uncapped. Share of voice needs ONE query class: `queryClass=all`, and omitting it, pool branded and non-brand, so every `shareOfVoice` comes back null and only the counts are published. Pass `queryClass=non-brand` (or `branded`) for a ratio, exactly as visibility-stats does. A project with no brand name or alias cannot be split by class, so a class-scoped read on one is refused rather than answered empty. Optional groupBy: model adds provider/requested-model groups with separate served-model evidence and sample counts. Optional model filters one exact requested model ID and requires provider. Unknown historical models remain explicit. Groups are not a matched-query or equal-weight comparison. Advanced reads support one market group or explicit scope: all-markets. On a project with an active v2 measurement plan, queryClass=branded or non-brand with no scope or groupKey defaults to scope=all-markets, so classes come from the plan; pass scope=project to force the text classifier. No provider, discovery, or classifier work runs. Ranked lists are capped at 100 observed/other-source rows per group; pins remain complete. `observedNames` are names written in answer text, not cited sources, capped at the top 50 by answer count; `observedNamesTotal` is the full count. Model groups are capped at 50 and disclose truncation.",
|
|
1298
1314
|
access: "read",
|
|
1299
1315
|
tier: "monitoring",
|
|
1300
1316
|
inputSchema: competitorLandscapeInputSchema,
|
|
@@ -2438,7 +2454,7 @@ var canonryMcpTools = [
|
|
|
2438
2454
|
defineTool({
|
|
2439
2455
|
name: "canonry_measurement_plan_get",
|
|
2440
2456
|
title: "Get measurement plan",
|
|
2441
|
-
description: "Get the active measurement plan for a project.",
|
|
2457
|
+
description: "Get the active measurement plan for a project: plan structure only (targets, groups, query assignments), no metrics. It can be very large on a big portfolio; for analysis prefer canonry_measurement_portfolio_summary and canonry_measurement_overview.",
|
|
2442
2458
|
access: "read",
|
|
2443
2459
|
tier: "setup",
|
|
2444
2460
|
inputSchema: projectInputSchema,
|
|
@@ -2557,7 +2573,7 @@ var canonryMcpTools = [
|
|
|
2557
2573
|
defineTool({
|
|
2558
2574
|
name: "canonry_measurement_portfolio_summary",
|
|
2559
2575
|
title: "Summarize measured Properties",
|
|
2560
|
-
description: "Start here for best
|
|
2576
|
+
description: "Start here for best and worst Properties. One call returns the weakest Properties, the names answers wrote instead of them, and the domains engines cited for them. Defaults to non-brand queries; state the returned queryClass and never pool branded with non-brand. Keep the default limit; for more rows narrow with groupKey (a metro) rather than raising limit, which can overflow the tool-result cap. Mention (answer text names the Property) and citation (a source URL on its page) are separate: report each as numerator/denominator, with any unattributed count beside mention. Denominators count answers, one per query per engine (queries x engines = answers). Group Properties only by each row's metro and submarkets, never by label. namedInsteadInAnswerText lists names written in the answer text of answers that neither named nor cited the Property, counted by answer: they are not citations. citedDomains and weakestAnswerSources count answers citing each domain, every engine included; weakestAnswerSources covers the weakest rows plus every tied Property, each answer once. When tiedAtWeakest is set, that many Properties share the weakest rates and are ordered by name, not ranked. mentionRanking.strongest/.weakest rank every Property with an available mention rate; .excluded lists the rest with reasons. markets lists one level worst-first (metros, or a groupKey's submarkets), capped at limit, with totalMarkets; includeNestedMarkets returns every level. Markets may share Properties and never sum to portfolio totals. Reads stored data only; never starts provider work.",
|
|
2561
2577
|
access: "read",
|
|
2562
2578
|
tier: "monitoring",
|
|
2563
2579
|
inputSchema: measurementPortfolioSummaryInputSchema,
|
package/dist/cli.js
CHANGED
|
@@ -35,11 +35,11 @@ import {
|
|
|
35
35
|
trackCliCommandFinished,
|
|
36
36
|
trackEvent,
|
|
37
37
|
waitForServerRuntimeStartup
|
|
38
|
-
} from "./chunk-
|
|
38
|
+
} from "./chunk-DRZWMFRV.js";
|
|
39
39
|
import {
|
|
40
40
|
autoSyncSkills,
|
|
41
41
|
formatAutoSyncNotice
|
|
42
|
-
} from "./chunk-
|
|
42
|
+
} from "./chunk-TSFKNQ5X.js";
|
|
43
43
|
import {
|
|
44
44
|
configExists,
|
|
45
45
|
createApiClient,
|
|
@@ -56,13 +56,13 @@ import {
|
|
|
56
56
|
saveConfig,
|
|
57
57
|
saveConfigPatch,
|
|
58
58
|
shouldPrintServeSkillsNudge
|
|
59
|
-
} from "./chunk-
|
|
59
|
+
} from "./chunk-5FKR2K76.js";
|
|
60
60
|
import {
|
|
61
61
|
DEFAULT_DEMO_TRUSTED_PROXIES,
|
|
62
62
|
trustedProxiesProblem,
|
|
63
63
|
trustedProxyProblem
|
|
64
64
|
} from "./chunk-RB2F4D3Z.js";
|
|
65
|
-
import "./chunk-
|
|
65
|
+
import "./chunk-4PENJKRN.js";
|
|
66
66
|
import {
|
|
67
67
|
CliError,
|
|
68
68
|
EXIT_SYSTEM_ERROR,
|
|
@@ -74,7 +74,7 @@ import {
|
|
|
74
74
|
runMeasurementDraftAction,
|
|
75
75
|
systemError,
|
|
76
76
|
usageError
|
|
77
|
-
} from "./chunk-
|
|
77
|
+
} from "./chunk-XBGPHZKA.js";
|
|
78
78
|
import {
|
|
79
79
|
CLOUDFLARE_WORKER_BINDINGS,
|
|
80
80
|
CLOUDFLARE_WORKER_GENERATED_MARKER,
|
|
@@ -89,7 +89,7 @@ import {
|
|
|
89
89
|
queries,
|
|
90
90
|
renderReportHtml,
|
|
91
91
|
runs
|
|
92
|
-
} from "./chunk-
|
|
92
|
+
} from "./chunk-WL27HO5C.js";
|
|
93
93
|
import {
|
|
94
94
|
AdsDeliverySnapshotStatuses,
|
|
95
95
|
AdsHistoricalCampaignRollupStatuses,
|
|
@@ -165,6 +165,7 @@ import {
|
|
|
165
165
|
normalizeProjectAliases,
|
|
166
166
|
normalizeTelemetryStatus,
|
|
167
167
|
notificationEventSchema,
|
|
168
|
+
queryClassFilterSchema,
|
|
168
169
|
queryTrackingCommitRequestSchema,
|
|
169
170
|
queryTrackingPreviewRequestSchema,
|
|
170
171
|
reportUnattributedAnswers,
|
|
@@ -176,7 +177,7 @@ import {
|
|
|
176
177
|
snapshotProviderModeSchema,
|
|
177
178
|
visibilityReportRequestSchema,
|
|
178
179
|
winnabilityClassSchema
|
|
179
|
-
} from "./chunk-
|
|
180
|
+
} from "./chunk-QF7SY7AF.js";
|
|
180
181
|
|
|
181
182
|
// src/cli.ts
|
|
182
183
|
import { pathToFileURL } from "url";
|
|
@@ -441,7 +442,7 @@ function parseDemoTrustedProxies(values) {
|
|
|
441
442
|
async function demoCommand(options) {
|
|
442
443
|
const { host, port } = parseDemoListenOptions(options);
|
|
443
444
|
const trustProxy = parseDemoTrustedProxies(options.trustProxy);
|
|
444
|
-
const { createDemoServer } = await import("./demo-server-
|
|
445
|
+
const { createDemoServer } = await import("./demo-server-OCBV5OMS.js");
|
|
445
446
|
const app = await createDemoServer({ trustProxy });
|
|
446
447
|
let stopping = false;
|
|
447
448
|
const stop = () => {
|
|
@@ -7808,7 +7809,8 @@ function printCompetitorLandscape(data) {
|
|
|
7808
7809
|
`Evidence: ${data.evidence.answeredResults} answer-text result(s), ${data.evidence.sourceResults} source result(s); excluded: ${data.evidence.excludedProbeResults} probe, ${data.evidence.excludedNonCompletedResults} non-completed.`
|
|
7809
7810
|
);
|
|
7810
7811
|
if (data.observedNames?.length) {
|
|
7811
|
-
|
|
7812
|
+
const total = data.observedNamesTotal ?? data.observedNames.length;
|
|
7813
|
+
console.log(total > data.observedNames.length ? `Names observed in answers (not a comparison set), top ${data.observedNames.length} of ${total}:` : "Names observed in answers (not a comparison set):");
|
|
7812
7814
|
for (const row of data.observedNames) console.log(` ${row.name} \xB7 ${row.answerCount} answers`);
|
|
7813
7815
|
}
|
|
7814
7816
|
if (data.modelComparison) printModelComparison(data.modelComparison, data.filters.queryClass);
|
|
@@ -11435,16 +11437,46 @@ Source Origin Breakdown`);
|
|
|
11435
11437
|
function getClient18() {
|
|
11436
11438
|
return createApiClient();
|
|
11437
11439
|
}
|
|
11440
|
+
var SOURCES_USAGE = "canonry sources <project> [--rank] [--limit N] [--by-provider] [--window 7d|30d|90d|all] [--query-class all|branded|non-brand] [--run-id <id>] [--include-by-query true|false] [--format json|jsonl]";
|
|
11441
|
+
function parseSourcesQueryClass(value) {
|
|
11442
|
+
if (value === void 0) return void 0;
|
|
11443
|
+
const parsed = queryClassFilterSchema.safeParse(value);
|
|
11444
|
+
if (parsed.success) return parsed.data;
|
|
11445
|
+
const message = `--query-class must be one of ${queryClassFilterSchema.options.join(", ")}`;
|
|
11446
|
+
throw usageError(`Error: ${message}
|
|
11447
|
+
Usage: ${SOURCES_USAGE}`, {
|
|
11448
|
+
message,
|
|
11449
|
+
details: { command: "sources", usage: SOURCES_USAGE, option: "query-class", value }
|
|
11450
|
+
});
|
|
11451
|
+
}
|
|
11452
|
+
function parseSourcesIncludeByQuery(value) {
|
|
11453
|
+
if (value === void 0) return void 0;
|
|
11454
|
+
if (value === "true") return true;
|
|
11455
|
+
if (value === "false") return false;
|
|
11456
|
+
const message = "--include-by-query must be true or false";
|
|
11457
|
+
throw usageError(`Error: ${message}
|
|
11458
|
+
Usage: ${SOURCES_USAGE}`, {
|
|
11459
|
+
message,
|
|
11460
|
+
details: { command: "sources", usage: SOURCES_USAGE, option: "include-by-query", value }
|
|
11461
|
+
});
|
|
11462
|
+
}
|
|
11438
11463
|
var pct = (n) => `${(n * 100).toFixed(1)}%`;
|
|
11439
11464
|
async function showSources(project, options) {
|
|
11440
11465
|
if (options.limit !== void 0 && (!Number.isInteger(options.limit) || options.limit <= 0)) {
|
|
11441
|
-
throw usageError(
|
|
11466
|
+
throw usageError(`Error: --limit must be a positive integer
|
|
11467
|
+
Usage: ${SOURCES_USAGE}`, {
|
|
11442
11468
|
message: "--limit must be a positive integer",
|
|
11443
11469
|
details: { command: "sources", option: "limit", value: options.limit }
|
|
11444
11470
|
});
|
|
11445
11471
|
}
|
|
11446
11472
|
const client = getClient18();
|
|
11447
|
-
const data = await client.getAnalyticsSources(project, {
|
|
11473
|
+
const data = await client.getAnalyticsSources(project, {
|
|
11474
|
+
window: options.window,
|
|
11475
|
+
limit: options.limit,
|
|
11476
|
+
...options.runId === void 0 ? {} : { runId: options.runId },
|
|
11477
|
+
...options.queryClass === void 0 ? {} : { queryClass: options.queryClass },
|
|
11478
|
+
...options.includeByQuery === void 0 ? {} : { includeByQuery: options.includeByQuery }
|
|
11479
|
+
});
|
|
11448
11480
|
if (options.format === "jsonl") {
|
|
11449
11481
|
emitJsonl(data.ranked.entries.map((e) => ({ project, ...e })));
|
|
11450
11482
|
return;
|
|
@@ -11459,6 +11491,8 @@ function printSourceRankings(data, options) {
|
|
|
11459
11491
|
console.log(`
|
|
11460
11492
|
Source Rankings (${data.window})`);
|
|
11461
11493
|
console.log("\u2500".repeat(50));
|
|
11494
|
+
const scope = describeScope(data);
|
|
11495
|
+
if (scope) console.log(` ${scope}`);
|
|
11462
11496
|
if (data.ranked.totalCitedSlots === 0) {
|
|
11463
11497
|
console.log(" No source data available");
|
|
11464
11498
|
return;
|
|
@@ -11476,8 +11510,25 @@ Source Rankings (${data.window})`);
|
|
|
11476
11510
|
${provider} (${list.totalCitedSlots} cited slots):`);
|
|
11477
11511
|
printRankedEntries(list, " ");
|
|
11478
11512
|
}
|
|
11513
|
+
for (const provider of data.providersWithoutSources ?? []) {
|
|
11514
|
+
console.log(`
|
|
11515
|
+
${provider}: answered, but no answer named a source`);
|
|
11516
|
+
}
|
|
11479
11517
|
}
|
|
11480
11518
|
}
|
|
11519
|
+
function describeScope(data) {
|
|
11520
|
+
const parts = [];
|
|
11521
|
+
if (data.answerTotal !== void 0) parts.push(`${data.answerTotal} answers`);
|
|
11522
|
+
if (data.filters?.runId) parts.push(`run ${data.filters.runId}`);
|
|
11523
|
+
else if (data.runCount !== void 0) parts.push(`${data.runCount} ${data.runCount === 1 ? "run" : "runs"} pooled`);
|
|
11524
|
+
if (data.filters) {
|
|
11525
|
+
parts.push(data.filters.queryClass === "all" ? "branded and non-brand pooled" : `${data.filters.queryClass} queries only`);
|
|
11526
|
+
}
|
|
11527
|
+
if (data.unclassifiedAnswers) {
|
|
11528
|
+
parts.push(`${data.unclassifiedAnswers} unclassified ${data.unclassifiedAnswers === 1 ? "answer" : "answers"} excluded`);
|
|
11529
|
+
}
|
|
11530
|
+
return parts.length > 0 ? parts.join(" \xB7 ") : null;
|
|
11531
|
+
}
|
|
11481
11532
|
function printSurfaceClasses(list) {
|
|
11482
11533
|
for (const c of list.bySurfaceClass) {
|
|
11483
11534
|
const noun = c.domainCount === 1 ? "domain" : "domains";
|
|
@@ -11840,25 +11891,30 @@ var OPERATOR_CLI_COMMANDS = [
|
|
|
11840
11891
|
},
|
|
11841
11892
|
{
|
|
11842
11893
|
path: ["sources"],
|
|
11843
|
-
usage:
|
|
11894
|
+
usage: SOURCES_USAGE,
|
|
11844
11895
|
options: {
|
|
11845
11896
|
rank: { type: "boolean", default: false },
|
|
11846
11897
|
"by-provider": { type: "boolean", default: false },
|
|
11847
11898
|
limit: stringOption(),
|
|
11848
|
-
window: stringOption()
|
|
11899
|
+
window: stringOption(),
|
|
11900
|
+
"query-class": stringOption(),
|
|
11901
|
+
"run-id": stringOption(),
|
|
11902
|
+
"include-by-query": stringOption()
|
|
11849
11903
|
},
|
|
11850
11904
|
run: async (input) => {
|
|
11851
|
-
const
|
|
11852
|
-
const project = requireProject(input, "sources", usage);
|
|
11905
|
+
const project = requireProject(input, "sources", SOURCES_USAGE);
|
|
11853
11906
|
await showSources(project, {
|
|
11854
11907
|
rank: getBoolean(input.values, "rank"),
|
|
11855
11908
|
byProvider: getBoolean(input.values, "by-provider"),
|
|
11856
11909
|
limit: parseIntegerOption(input, "limit", {
|
|
11857
11910
|
message: "--limit must be an integer",
|
|
11858
|
-
usage,
|
|
11911
|
+
usage: SOURCES_USAGE,
|
|
11859
11912
|
command: "sources"
|
|
11860
11913
|
}),
|
|
11861
11914
|
window: getString(input.values, "window"),
|
|
11915
|
+
runId: getString(input.values, "run-id"),
|
|
11916
|
+
queryClass: parseSourcesQueryClass(getString(input.values, "query-class")),
|
|
11917
|
+
includeByQuery: parseSourcesIncludeByQuery(getString(input.values, "include-by-query")),
|
|
11862
11918
|
format: input.format
|
|
11863
11919
|
});
|
|
11864
11920
|
}
|
|
@@ -15455,7 +15511,7 @@ async function initCommand(opts) {
|
|
|
15455
15511
|
}
|
|
15456
15512
|
const perplexityApiKey = await promptProviderApiKey("Perplexity", "PERPLEXITY_API_KEY");
|
|
15457
15513
|
if (perplexityApiKey) {
|
|
15458
|
-
const perplexityModel = await prompt(" Perplexity model [
|
|
15514
|
+
const perplexityModel = await prompt(" Perplexity preset or model [fast]: ") || "fast";
|
|
15459
15515
|
providers.perplexity = { apiKey: perplexityApiKey, model: perplexityModel, quota: DEFAULT_QUOTA };
|
|
15460
15516
|
}
|
|
15461
15517
|
console.log("\nLocal LLM (Ollama, LM Studio, llama.cpp, vLLM \u2014 any OpenAI-compatible API):");
|
|
@@ -4,11 +4,11 @@ import {
|
|
|
4
4
|
import {
|
|
5
5
|
layoutSiteCrawlGraphInput,
|
|
6
6
|
persistSiteCrawlGraphLayout
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-4PENJKRN.js";
|
|
8
8
|
import {
|
|
9
9
|
PACKAGE_VERSION,
|
|
10
10
|
canonryMcpTools
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-XBGPHZKA.js";
|
|
12
12
|
import {
|
|
13
13
|
HISTORY_WINDOW_RUNS,
|
|
14
14
|
IntelligenceService,
|
|
@@ -84,7 +84,7 @@ import {
|
|
|
84
84
|
siteCrawlPages,
|
|
85
85
|
siteCrawlSnapshots,
|
|
86
86
|
trafficSources
|
|
87
|
-
} from "./chunk-
|
|
87
|
+
} from "./chunk-WL27HO5C.js";
|
|
88
88
|
import {
|
|
89
89
|
RunKinds,
|
|
90
90
|
SiteCrawlFetchStates,
|
|
@@ -108,7 +108,7 @@ import {
|
|
|
108
108
|
placementLinkDecision,
|
|
109
109
|
siteAuditPageFactorSchema,
|
|
110
110
|
wilsonInterval
|
|
111
|
-
} from "./chunk-
|
|
111
|
+
} from "./chunk-QF7SY7AF.js";
|
|
112
112
|
|
|
113
113
|
// src/demo-server.ts
|
|
114
114
|
import { dirname, join as join2 } from "path";
|
package/dist/index.js
CHANGED
|
@@ -3,14 +3,14 @@ import {
|
|
|
3
3
|
createGoogleMarketingCredentialStore,
|
|
4
4
|
createGoogleMarketingRuntime,
|
|
5
5
|
createServer
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-DRZWMFRV.js";
|
|
7
7
|
import {
|
|
8
8
|
loadConfig
|
|
9
|
-
} from "./chunk-
|
|
10
|
-
import "./chunk-
|
|
11
|
-
import "./chunk-
|
|
12
|
-
import "./chunk-
|
|
13
|
-
import "./chunk-
|
|
9
|
+
} from "./chunk-5FKR2K76.js";
|
|
10
|
+
import "./chunk-4PENJKRN.js";
|
|
11
|
+
import "./chunk-XBGPHZKA.js";
|
|
12
|
+
import "./chunk-WL27HO5C.js";
|
|
13
|
+
import "./chunk-QF7SY7AF.js";
|
|
14
14
|
export {
|
|
15
15
|
GoogleMarketingRuntimeError,
|
|
16
16
|
createGoogleMarketingCredentialStore,
|
package/dist/mcp.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
autoSyncSkills
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-TSFKNQ5X.js";
|
|
4
4
|
import {
|
|
5
5
|
createApiClient,
|
|
6
6
|
createCanonryMcpServer
|
|
7
|
-
} from "./chunk-
|
|
8
|
-
import "./chunk-
|
|
7
|
+
} from "./chunk-5FKR2K76.js";
|
|
8
|
+
import "./chunk-XBGPHZKA.js";
|
|
9
9
|
import {
|
|
10
10
|
isReadOnlyKey,
|
|
11
11
|
updateCheckEnvOptOut
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-QF7SY7AF.js";
|
|
13
13
|
|
|
14
14
|
// src/mcp/cli.ts
|
|
15
15
|
import { randomUUID } from "crypto";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@canonry/canonry",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.20.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Self-hosted AI visibility (AEO) platform: track how ChatGPT, Claude, Gemini, and Perplexity cite your domain, join it with Search Console, GA4, server-side traffic, and paid media, and fix what you find through agent tools (CLI, REST, MCP). Local SQLite.",
|
|
6
6
|
"keywords": [
|
|
@@ -86,32 +86,32 @@
|
|
|
86
86
|
"@types/node-cron": "^3.0.11",
|
|
87
87
|
"tsup": "^8.5.1",
|
|
88
88
|
"tsx": "^4.19.0",
|
|
89
|
-
"@ainyc/canonry-api-client": "0.0.0",
|
|
90
|
-
"@ainyc/canonry-api-routes": "0.0.0",
|
|
91
89
|
"@ainyc/canonry-web": "0.0.0",
|
|
90
|
+
"@ainyc/canonry-api-routes": "0.0.0",
|
|
91
|
+
"@ainyc/canonry-api-client": "0.0.0",
|
|
92
92
|
"@ainyc/canonry-contracts": "0.0.0",
|
|
93
93
|
"@ainyc/canonry-config": "0.0.0",
|
|
94
94
|
"@ainyc/canonry-db": "0.0.0",
|
|
95
|
-
"@ainyc/canonry-integration-cloud-run": "0.0.0",
|
|
96
95
|
"@ainyc/canonry-integration-bing": "0.0.0",
|
|
96
|
+
"@ainyc/canonry-integration-cloud-run": "0.0.0",
|
|
97
97
|
"@ainyc/canonry-integration-cloudflare-queue": "0.0.0",
|
|
98
|
-
"@ainyc/canonry-integration-google-ads": "0.0.0",
|
|
99
|
-
"@ainyc/canonry-integration-commoncrawl": "0.0.0",
|
|
100
98
|
"@ainyc/canonry-integration-cloudflare-worker": "0.0.0",
|
|
101
|
-
"@ainyc/canonry-integration-
|
|
102
|
-
"@ainyc/canonry-integration-google-
|
|
99
|
+
"@ainyc/canonry-integration-commoncrawl": "0.0.0",
|
|
100
|
+
"@ainyc/canonry-integration-google-ads": "0.0.0",
|
|
103
101
|
"@ainyc/canonry-integration-google-business-profile": "0.0.0",
|
|
104
|
-
"@ainyc/canonry-integration-
|
|
105
|
-
"@ainyc/canonry-provider-cdp": "0.0.0",
|
|
102
|
+
"@ainyc/canonry-integration-google-tag-manager": "0.0.0",
|
|
106
103
|
"@ainyc/canonry-integration-traffic": "0.0.0",
|
|
104
|
+
"@ainyc/canonry-integration-openai-ads": "0.0.0",
|
|
105
|
+
"@ainyc/canonry-integration-google": "0.0.0",
|
|
107
106
|
"@ainyc/canonry-integration-wordpress": "0.0.0",
|
|
108
|
-
"@ainyc/canonry-provider-claude": "0.0.0",
|
|
109
|
-
"@ainyc/canonry-integration-google-tag-manager": "0.0.0",
|
|
110
107
|
"@ainyc/canonry-intelligence": "0.0.0",
|
|
108
|
+
"@ainyc/canonry-integration-google-places": "0.0.0",
|
|
109
|
+
"@ainyc/canonry-provider-claude": "0.0.0",
|
|
110
|
+
"@ainyc/canonry-provider-cdp": "0.0.0",
|
|
111
111
|
"@ainyc/canonry-provider-gemini": "0.0.0",
|
|
112
|
-
"@ainyc/canonry-provider-
|
|
112
|
+
"@ainyc/canonry-provider-local": "0.0.0",
|
|
113
113
|
"@ainyc/canonry-provider-perplexity": "0.0.0",
|
|
114
|
-
"@ainyc/canonry-provider-
|
|
114
|
+
"@ainyc/canonry-provider-openai": "0.0.0"
|
|
115
115
|
},
|
|
116
116
|
"scripts": {
|
|
117
117
|
"build": "pnpm run build:cli && pnpm run build:web",
|