@ainyc/canonry 4.116.0 → 4.117.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 +0 -1
- package/assets/agent-workspace/skills/aero/references/reporting.md +10 -0
- package/assets/agent-workspace/skills/canonry/references/canonry-cli.md +6 -0
- package/assets/assets/{BacklinksPage-Dy6Xc-LT.js → BacklinksPage-Bkafm10m.js} +1 -1
- package/assets/assets/{ChartPrimitives-CHJh5M8x.js → ChartPrimitives-NV_GgqFn.js} +1 -1
- package/assets/assets/{ProjectPage-Bjfa4CI5.js → ProjectPage-0-NnRxys.js} +1 -1
- package/assets/assets/{RunRow-DmvQnWPf.js → RunRow-df0d24S6.js} +1 -1
- package/assets/assets/{RunsPage-BxkxQEKE.js → RunsPage-CU6-4YTM.js} +1 -1
- package/assets/assets/{SettingsPage-DCyqHqDh.js → SettingsPage-BKw6B6cd.js} +1 -1
- package/assets/assets/{TrafficPage-BT_ae5aO.js → TrafficPage-CzpiYHKj.js} +1 -1
- package/assets/assets/{TrafficSourceDetailPage-Cps-tSHn.js → TrafficSourceDetailPage-CC5nuqM1.js} +1 -1
- package/assets/assets/{arrow-left-D8vdqhx4.js → arrow-left-CbQcW2pL.js} +1 -1
- package/assets/assets/{extract-error-message-BOY5txUA.js → extract-error-message-CvqIZ-le.js} +1 -1
- package/assets/assets/index-LjcWHaNZ.js +210 -0
- package/assets/assets/{trash-2-ap_Fa4zA.js → trash-2-3J2u0woR.js} +1 -1
- package/assets/index.html +1 -1
- package/dist/{chunk-WEAXJ25Y.js → chunk-FVVKNMZW.js} +353 -19
- package/dist/{chunk-IQPMK36Y.js → chunk-IAJ5TQ4S.js} +155 -3
- package/dist/{chunk-RVH6QPTA.js → chunk-PJATAPZW.js} +37 -1
- package/dist/{chunk-GV665WOU.js → chunk-ZZEA774R.js} +4 -4
- package/dist/cli.js +93 -4
- package/dist/index.js +4 -4
- package/dist/{intelligence-service-HEN5HLUM.js → intelligence-service-J7G4CMI5.js} +2 -2
- package/dist/mcp.js +2 -2
- package/package.json +9 -9
- package/assets/assets/index-DxjY63VC.js +0 -210
|
@@ -1998,7 +1998,7 @@ var DEDUP_SIMILARITY_BAND_HIGH = 0.97;
|
|
|
1998
1998
|
function computeDedupSimilarityStats(vectors, indexClusters) {
|
|
1999
1999
|
const n = vectors.length;
|
|
2000
2000
|
if (n < 2) return { perClusterMinSimilarity: [], bandPairFraction: null, pairsTotal: 0 };
|
|
2001
|
-
const
|
|
2001
|
+
const round2 = (v) => Math.round(v * 1e4) / 1e4;
|
|
2002
2002
|
const perClusterMinSimilarity = [];
|
|
2003
2003
|
for (const cluster of indexClusters) {
|
|
2004
2004
|
if (cluster.length < 2) continue;
|
|
@@ -2008,7 +2008,7 @@ function computeDedupSimilarityStats(vectors, indexClusters) {
|
|
|
2008
2008
|
min = Math.min(min, cosineSimilarity(vectors[cluster[a]], vectors[cluster[b]]));
|
|
2009
2009
|
}
|
|
2010
2010
|
}
|
|
2011
|
-
perClusterMinSimilarity.push(
|
|
2011
|
+
perClusterMinSimilarity.push(round2(min));
|
|
2012
2012
|
}
|
|
2013
2013
|
let inBand = 0;
|
|
2014
2014
|
let pairsTotal = 0;
|
|
@@ -2019,7 +2019,7 @@ function computeDedupSimilarityStats(vectors, indexClusters) {
|
|
|
2019
2019
|
if (sim >= DEDUP_SIMILARITY_BAND_LOW && sim < DEDUP_SIMILARITY_BAND_HIGH) inBand++;
|
|
2020
2020
|
}
|
|
2021
2021
|
}
|
|
2022
|
-
return { perClusterMinSimilarity, bandPairFraction:
|
|
2022
|
+
return { perClusterMinSimilarity, bandPairFraction: round2(inBand / pairsTotal), pairsTotal };
|
|
2023
2023
|
}
|
|
2024
2024
|
|
|
2025
2025
|
// ../contracts/src/url-normalize.ts
|
|
@@ -2894,6 +2894,137 @@ var visibilityStatsDtoSchema = z20.object({
|
|
|
2894
2894
|
/** Pooled share of voice vs tracked competitors — present only when `shareOfVoice=1` was requested. */
|
|
2895
2895
|
shareOfVoice: visibilityStatsShareOfVoiceSchema.optional()
|
|
2896
2896
|
});
|
|
2897
|
+
var visibilityCompareVerdictSchema = z20.enum([
|
|
2898
|
+
"within-noise",
|
|
2899
|
+
"moved",
|
|
2900
|
+
"insufficient-data",
|
|
2901
|
+
"model-discontinuous",
|
|
2902
|
+
"model-unknown"
|
|
2903
|
+
]);
|
|
2904
|
+
var visibilityCompareDirectionSchema = z20.enum(["up", "down", "flat"]);
|
|
2905
|
+
var visibilityCompareMetricPeriodSchema = z20.object({
|
|
2906
|
+
/** The proportion in `[0,1]`, rounded to 4 dp; `null` when `denominator === 0` (undefined over no data). */
|
|
2907
|
+
point: z20.number().nullable(),
|
|
2908
|
+
/** Wilson 95% lower bound `[0,1]`; `null` when `denominator === 0`. */
|
|
2909
|
+
ciLow: z20.number().nullable(),
|
|
2910
|
+
/** Wilson 95% upper bound `[0,1]`; `null` when `denominator === 0`. */
|
|
2911
|
+
ciHigh: z20.number().nullable(),
|
|
2912
|
+
/** Successes (mentions / citations / project-brand mentions). */
|
|
2913
|
+
numerator: z20.number().int(),
|
|
2914
|
+
/** Sample size the proportion is over (checked snapshots / total / project+competitor brand mentions). */
|
|
2915
|
+
denominator: z20.number().int()
|
|
2916
|
+
});
|
|
2917
|
+
var visibilityCompareMetricKeySchema = z20.enum([
|
|
2918
|
+
"mention-share-of-voice",
|
|
2919
|
+
"cited-share-of-voice",
|
|
2920
|
+
"mention-rate",
|
|
2921
|
+
"cited-rate"
|
|
2922
|
+
]);
|
|
2923
|
+
var visibilityCompareMetricSchema = z20.object({
|
|
2924
|
+
key: visibilityCompareMetricKeySchema,
|
|
2925
|
+
/** Human label ("Named share of voice", "Cited rate", …). */
|
|
2926
|
+
label: z20.string(),
|
|
2927
|
+
/**
|
|
2928
|
+
* `true` for share of voice, which is less exposed to broad model-wide naming
|
|
2929
|
+
* propensity than an absolute rate. It does not bypass model continuity: no
|
|
2930
|
+
* metric can make a directional call when every provider is excluded.
|
|
2931
|
+
*/
|
|
2932
|
+
driftRobust: z20.boolean(),
|
|
2933
|
+
from: visibilityCompareMetricPeriodSchema,
|
|
2934
|
+
to: visibilityCompareMetricPeriodSchema,
|
|
2935
|
+
/** `to.point / from.point`; `null` when `from.point` is `0` or `null` (ratio undefined). */
|
|
2936
|
+
rateRatio: z20.number().nullable(),
|
|
2937
|
+
/** Sign of `to.point - from.point`; `null` when either point is `null`. */
|
|
2938
|
+
direction: z20.union([visibilityCompareDirectionSchema, z20.null()]),
|
|
2939
|
+
verdict: visibilityCompareVerdictSchema
|
|
2940
|
+
});
|
|
2941
|
+
var visibilityComparePeriodWindowSchema = z20.object({
|
|
2942
|
+
/** The `YYYY-MM` requested. */
|
|
2943
|
+
month: z20.string(),
|
|
2944
|
+
/** Resolved inclusive ISO bounds the month expanded to. */
|
|
2945
|
+
since: z20.string(),
|
|
2946
|
+
until: z20.string(),
|
|
2947
|
+
/** Completed/partial, non-probe answer-visibility runs in the month. */
|
|
2948
|
+
runCount: z20.number().int(),
|
|
2949
|
+
/**
|
|
2950
|
+
* `true` when `runCount` is below the reliability floor (`< 5` sweeps): the
|
|
2951
|
+
* intervals are wide and a `moved` verdict is unlikely to be reachable. A
|
|
2952
|
+
* signal to raise the sweep schedule, surfaced so the report can caveat.
|
|
2953
|
+
*/
|
|
2954
|
+
lowRunCount: z20.boolean()
|
|
2955
|
+
});
|
|
2956
|
+
var visibilityCompareBasketSchema = z20.object({
|
|
2957
|
+
/** Distinct tracked queries with at least one common provider pair — the compared universe. */
|
|
2958
|
+
queryCount: z20.number().int(),
|
|
2959
|
+
/** Queries observed only in `from` (dropped from the comparison). */
|
|
2960
|
+
excludedFromOnly: z20.number().int(),
|
|
2961
|
+
/** Queries observed only in `to`. */
|
|
2962
|
+
excludedToOnly: z20.number().int(),
|
|
2963
|
+
/**
|
|
2964
|
+
* The compared engine set: providers with ≥1 common query/provider pair.
|
|
2965
|
+
*/
|
|
2966
|
+
providers: z20.array(z20.string()),
|
|
2967
|
+
/** Providers observed in either period that did not make the basket (dropped from the comparison). */
|
|
2968
|
+
excludedProviders: z20.array(z20.string())
|
|
2969
|
+
});
|
|
2970
|
+
var visibilityCompareModelChangeSchema = z20.object({
|
|
2971
|
+
provider: z20.string(),
|
|
2972
|
+
fromModels: z20.array(z20.string()),
|
|
2973
|
+
toModels: z20.array(z20.string())
|
|
2974
|
+
});
|
|
2975
|
+
var visibilityCompareProviderContinuityStatusSchema = z20.enum([
|
|
2976
|
+
"included",
|
|
2977
|
+
"model-discontinuous",
|
|
2978
|
+
"model-unknown"
|
|
2979
|
+
]);
|
|
2980
|
+
var visibilityCompareProviderContinuitySchema = z20.object({
|
|
2981
|
+
provider: z20.string(),
|
|
2982
|
+
/** `included` only when both months carry exactly one known model id, identical across the two, and NO snapshot with an unrecorded (null) model — a null mixed alongside a known id still marks the period `model-unknown`. */
|
|
2983
|
+
status: visibilityCompareProviderContinuityStatusSchema,
|
|
2984
|
+
fromModels: z20.array(z20.string()),
|
|
2985
|
+
toModels: z20.array(z20.string())
|
|
2986
|
+
});
|
|
2987
|
+
var visibilityCompareContinuityStatusSchema = z20.enum([
|
|
2988
|
+
"comparable",
|
|
2989
|
+
"model-discontinuous",
|
|
2990
|
+
"model-unknown",
|
|
2991
|
+
"insufficient-data"
|
|
2992
|
+
]);
|
|
2993
|
+
var visibilityCompareContinuitySchema = z20.object({
|
|
2994
|
+
status: visibilityCompareContinuityStatusSchema,
|
|
2995
|
+
/** Providers retained in the directional comparison after the continuity gate. */
|
|
2996
|
+
comparedProviders: z20.array(z20.string()),
|
|
2997
|
+
/** Every provider with common query/provider pairs, including excluded ones and their model evidence. */
|
|
2998
|
+
providers: z20.array(visibilityCompareProviderContinuitySchema)
|
|
2999
|
+
});
|
|
3000
|
+
var visibilityCompareProviderRowSchema = z20.object({
|
|
3001
|
+
provider: z20.string(),
|
|
3002
|
+
from: z20.object({ checked: z20.number().int(), mentioned: z20.number().int(), cited: z20.number().int() }),
|
|
3003
|
+
to: z20.object({ checked: z20.number().int(), mentioned: z20.number().int(), cited: z20.number().int() })
|
|
3004
|
+
});
|
|
3005
|
+
var visibilityCompareQueriesMentionedSchema = z20.object({
|
|
3006
|
+
from: z20.object({ count: z20.number().int(), of: z20.number().int() }),
|
|
3007
|
+
to: z20.object({ count: z20.number().int(), of: z20.number().int() })
|
|
3008
|
+
});
|
|
3009
|
+
var visibilityCompareDtoSchema = z20.object({
|
|
3010
|
+
project: z20.string(),
|
|
3011
|
+
from: visibilityComparePeriodWindowSchema,
|
|
3012
|
+
to: visibilityComparePeriodWindowSchema,
|
|
3013
|
+
basket: visibilityCompareBasketSchema,
|
|
3014
|
+
/** Ordered: mention SoV (primary), cited SoV, mention rate (level), cited rate. */
|
|
3015
|
+
metrics: z20.array(visibilityCompareMetricSchema),
|
|
3016
|
+
queriesMentioned: visibilityCompareQueriesMentionedSchema,
|
|
3017
|
+
byProvider: z20.array(visibilityCompareProviderRowSchema),
|
|
3018
|
+
/** Providers whose configured model id set changed between the periods (empty = none detected). */
|
|
3019
|
+
modelChanges: z20.array(visibilityCompareModelChangeSchema),
|
|
3020
|
+
/** Strict model-continuity evidence and the providers that remain comparable. */
|
|
3021
|
+
continuity: visibilityCompareContinuitySchema,
|
|
3022
|
+
/** Per-competitor mention counts within each period's basket (for the SoV detail). */
|
|
3023
|
+
competitors: z20.object({
|
|
3024
|
+
from: z20.array(visibilityStatsShareCompetitorSchema),
|
|
3025
|
+
to: z20.array(visibilityStatsShareCompetitorSchema)
|
|
3026
|
+
})
|
|
3027
|
+
});
|
|
2897
3028
|
function calendarMonthBounds(month) {
|
|
2898
3029
|
const match = /^(\d{4})-(\d{2})$/.exec(month);
|
|
2899
3030
|
if (!match) throw new RangeError("month must be in YYYY-MM format");
|
|
@@ -5501,6 +5632,25 @@ function sumInfraHits(segments) {
|
|
|
5501
5632
|
return segments.sitemap + segments.robots + segments.asset;
|
|
5502
5633
|
}
|
|
5503
5634
|
|
|
5635
|
+
// ../contracts/src/statistics.ts
|
|
5636
|
+
function round(value, dp = 4) {
|
|
5637
|
+
const f = 10 ** dp;
|
|
5638
|
+
return (Math.round(value * f) + 0) / f;
|
|
5639
|
+
}
|
|
5640
|
+
function wilsonInterval(successes, n, z33 = 1.96) {
|
|
5641
|
+
if (!Number.isFinite(n) || n <= 0) return null;
|
|
5642
|
+
const s = Math.max(0, Math.min(successes, n));
|
|
5643
|
+
const p = s / n;
|
|
5644
|
+
const z210 = z33 * z33;
|
|
5645
|
+
const denom = 1 + z210 / n;
|
|
5646
|
+
const center = (p + z210 / (2 * n)) / denom;
|
|
5647
|
+
const margin = z33 / denom * Math.sqrt(p * (1 - p) / n + z210 / (4 * n * n));
|
|
5648
|
+
return {
|
|
5649
|
+
low: round(Math.max(0, center - margin)),
|
|
5650
|
+
high: round(Math.min(1, center + margin))
|
|
5651
|
+
};
|
|
5652
|
+
}
|
|
5653
|
+
|
|
5504
5654
|
// ../contracts/src/ads.ts
|
|
5505
5655
|
import { z as z32 } from "zod";
|
|
5506
5656
|
var adsConnectRequestSchema = z32.object({
|
|
@@ -5984,6 +6134,7 @@ export {
|
|
|
5984
6134
|
parseWindow,
|
|
5985
6135
|
windowCutoff,
|
|
5986
6136
|
visibilityStatsDtoSchema,
|
|
6137
|
+
visibilityCompareDtoSchema,
|
|
5987
6138
|
calendarMonthBounds,
|
|
5988
6139
|
formatRatio,
|
|
5989
6140
|
formatNumber,
|
|
@@ -6097,6 +6248,7 @@ export {
|
|
|
6097
6248
|
classifyTrafficPath,
|
|
6098
6249
|
segmentCrawlerHits,
|
|
6099
6250
|
sumInfraHits,
|
|
6251
|
+
wilsonInterval,
|
|
6100
6252
|
adsConnectRequestSchema,
|
|
6101
6253
|
adsConnectionStatusDtoSchema,
|
|
6102
6254
|
adsDisconnectResponseSchema,
|
|
@@ -25,7 +25,7 @@ import {
|
|
|
25
25
|
trafficConnectVercelRequestSchema,
|
|
26
26
|
trafficConnectWordpressRequestSchema,
|
|
27
27
|
trafficEventKindSchema
|
|
28
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-IAJ5TQ4S.js";
|
|
29
29
|
|
|
30
30
|
// src/config.ts
|
|
31
31
|
import fs from "fs";
|
|
@@ -1578,6 +1578,18 @@ var getApiV1ProjectsByNameVisibilityStats = (options) => {
|
|
|
1578
1578
|
...options
|
|
1579
1579
|
});
|
|
1580
1580
|
};
|
|
1581
|
+
var getApiV1ProjectsByNameVisibilityCompare = (options) => {
|
|
1582
|
+
return (options.client ?? client).get({
|
|
1583
|
+
security: [
|
|
1584
|
+
{
|
|
1585
|
+
scheme: "bearer",
|
|
1586
|
+
type: "http"
|
|
1587
|
+
}
|
|
1588
|
+
],
|
|
1589
|
+
url: "/api/v1/projects/{name}/visibility-compare",
|
|
1590
|
+
...options
|
|
1591
|
+
});
|
|
1592
|
+
};
|
|
1581
1593
|
var getApiV1ProjectsByNameSnapshotsDiff = (options) => {
|
|
1582
1594
|
return (options.client ?? client).get({
|
|
1583
1595
|
security: [
|
|
@@ -5171,6 +5183,15 @@ var ApiClient = class {
|
|
|
5171
5183
|
})
|
|
5172
5184
|
);
|
|
5173
5185
|
}
|
|
5186
|
+
async getVisibilityCompare(project, from, to) {
|
|
5187
|
+
return this.invoke(
|
|
5188
|
+
() => getApiV1ProjectsByNameVisibilityCompare({
|
|
5189
|
+
client: this.heyClient,
|
|
5190
|
+
path: { name: project },
|
|
5191
|
+
query: { from, to }
|
|
5192
|
+
})
|
|
5193
|
+
);
|
|
5194
|
+
}
|
|
5174
5195
|
// ── Backlinks — workspace-level ────────────────────────────────────────
|
|
5175
5196
|
async backlinksStatus() {
|
|
5176
5197
|
return this.invoke(() => getApiV1BacklinksStatus({ client: this.heyClient }));
|
|
@@ -5915,6 +5936,21 @@ var canonryMcpTools = [
|
|
|
5915
5936
|
shareOfVoice: input.shareOfVoice
|
|
5916
5937
|
})
|
|
5917
5938
|
}),
|
|
5939
|
+
defineTool({
|
|
5940
|
+
name: "canonry_visibility_compare",
|
|
5941
|
+
title: "Compare AEO visibility month over month",
|
|
5942
|
+
description: "Statistically honest month-over-month AEO comparison in ONE call \u2014 use this instead of hand-computing deltas from two visibility-stats calls. Share of voice (`mention-share-of-voice`, `driftRobust: true`) is less exposed to broad model-wide naming propensity than absolute rates, but it never overrides model continuity. The response restricts to common query/provider pairs, then includes only providers with exactly one known, identical configured model id in both months. `continuity` surfaces every provider, its model evidence, and whether it was excluded for a changed, mixed mid-month, or unknown model. When no provider remains, metrics return `model-discontinuous` or `model-unknown`, never a directional call. A silent upstream version bump under an unchanged configured id remains undetectable. `from` must be a month strictly before `to`.",
|
|
5943
|
+
access: "read",
|
|
5944
|
+
tier: "monitoring",
|
|
5945
|
+
inputSchema: z2.object({
|
|
5946
|
+
project: projectNameSchema,
|
|
5947
|
+
from: z2.string().describe('Earlier calendar month (YYYY-MM), the baseline. Must be strictly before "to".'),
|
|
5948
|
+
to: z2.string().describe('Later calendar month (YYYY-MM), compared against "from".')
|
|
5949
|
+
}),
|
|
5950
|
+
annotations: readAnnotations(),
|
|
5951
|
+
openApiOperations: ["GET /api/v1/projects/{name}/visibility-compare"],
|
|
5952
|
+
handler: (client2, input) => client2.getVisibilityCompare(input.project, input.from, input.to)
|
|
5953
|
+
}),
|
|
5918
5954
|
defineTool({
|
|
5919
5955
|
name: "canonry_content_targets",
|
|
5920
5956
|
title: "Get content targets",
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
loadConfig,
|
|
11
11
|
loadConfigRaw,
|
|
12
12
|
saveConfigPatch
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-PJATAPZW.js";
|
|
14
14
|
import {
|
|
15
15
|
CC_CACHE_DIR,
|
|
16
16
|
DUCKDB_SPEC,
|
|
@@ -115,7 +115,7 @@ import {
|
|
|
115
115
|
siteAuditPages,
|
|
116
116
|
siteAuditSnapshots,
|
|
117
117
|
usageCounters
|
|
118
|
-
} from "./chunk-
|
|
118
|
+
} from "./chunk-FVVKNMZW.js";
|
|
119
119
|
import {
|
|
120
120
|
AGENT_MEMORY_VALUE_MAX_BYTES,
|
|
121
121
|
AGENT_PROVIDER_IDS,
|
|
@@ -178,7 +178,7 @@ import {
|
|
|
178
178
|
validationError,
|
|
179
179
|
winnabilityClassLabel,
|
|
180
180
|
withRetry
|
|
181
|
-
} from "./chunk-
|
|
181
|
+
} from "./chunk-IAJ5TQ4S.js";
|
|
182
182
|
|
|
183
183
|
// src/telemetry.ts
|
|
184
184
|
import crypto from "crypto";
|
|
@@ -6515,7 +6515,7 @@ function readStoredGroundingSources(rawResponse) {
|
|
|
6515
6515
|
return result;
|
|
6516
6516
|
}
|
|
6517
6517
|
async function backfillInsightsCommand(project, opts) {
|
|
6518
|
-
const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-
|
|
6518
|
+
const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-J7G4CMI5.js");
|
|
6519
6519
|
const config = loadConfig();
|
|
6520
6520
|
const db = createClient(config.database);
|
|
6521
6521
|
migrate(db);
|
package/dist/cli.js
CHANGED
|
@@ -29,7 +29,7 @@ import {
|
|
|
29
29
|
setTelemetrySource,
|
|
30
30
|
showFirstRunNotice,
|
|
31
31
|
trackEvent
|
|
32
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-ZZEA774R.js";
|
|
33
33
|
import {
|
|
34
34
|
CliError,
|
|
35
35
|
EXIT_SYSTEM_ERROR,
|
|
@@ -46,7 +46,7 @@ import {
|
|
|
46
46
|
saveConfig,
|
|
47
47
|
saveConfigPatch,
|
|
48
48
|
usageError
|
|
49
|
-
} from "./chunk-
|
|
49
|
+
} from "./chunk-PJATAPZW.js";
|
|
50
50
|
import {
|
|
51
51
|
apiKeys,
|
|
52
52
|
createClient,
|
|
@@ -54,7 +54,7 @@ import {
|
|
|
54
54
|
projects,
|
|
55
55
|
queries,
|
|
56
56
|
renderReportHtml
|
|
57
|
-
} from "./chunk-
|
|
57
|
+
} from "./chunk-FVVKNMZW.js";
|
|
58
58
|
import {
|
|
59
59
|
BacklinkSources,
|
|
60
60
|
CcReleaseSyncStatuses,
|
|
@@ -80,7 +80,7 @@ import {
|
|
|
80
80
|
providerQuotaPolicySchema,
|
|
81
81
|
resolveProviderInput,
|
|
82
82
|
winnabilityClassSchema
|
|
83
|
-
} from "./chunk-
|
|
83
|
+
} from "./chunk-IAJ5TQ4S.js";
|
|
84
84
|
|
|
85
85
|
// src/cli.ts
|
|
86
86
|
import { pathToFileURL } from "url";
|
|
@@ -11841,6 +11841,78 @@ async function showVisibilityStats(project, opts) {
|
|
|
11841
11841
|
function pct3(rate) {
|
|
11842
11842
|
return rate === null ? "\u2014" : formatRatio(rate);
|
|
11843
11843
|
}
|
|
11844
|
+
async function showVisibilityCompare(project, opts) {
|
|
11845
|
+
if (!opts.from || !opts.to) throw new Error("visibility-compare requires --from <YYYY-MM> and --to <YYYY-MM>");
|
|
11846
|
+
const client = createApiClient();
|
|
11847
|
+
const data = await client.getVisibilityCompare(project, opts.from, opts.to);
|
|
11848
|
+
if (isMachineFormat(opts.format)) {
|
|
11849
|
+
console.log(JSON.stringify(data, null, 2));
|
|
11850
|
+
return;
|
|
11851
|
+
}
|
|
11852
|
+
printVisibilityCompare(data);
|
|
11853
|
+
}
|
|
11854
|
+
function periodCell(p) {
|
|
11855
|
+
if (p.point === null || p.ciLow === null || p.ciHigh === null) return "no data";
|
|
11856
|
+
const p1 = (v) => formatRatio(v);
|
|
11857
|
+
return `${p1(p.point)} [${p1(p.ciLow)}, ${p1(p.ciHigh)}]`;
|
|
11858
|
+
}
|
|
11859
|
+
function verdictCell(m) {
|
|
11860
|
+
switch (m.verdict) {
|
|
11861
|
+
case "within-noise":
|
|
11862
|
+
return "within noise";
|
|
11863
|
+
case "insufficient-data":
|
|
11864
|
+
return "no data";
|
|
11865
|
+
case "moved":
|
|
11866
|
+
return `moved ${m.direction === "down" ? "down" : m.direction === "up" ? "up" : ""}`.trim();
|
|
11867
|
+
case "model-discontinuous":
|
|
11868
|
+
return "model discontinuity";
|
|
11869
|
+
case "model-unknown":
|
|
11870
|
+
return "model unknown";
|
|
11871
|
+
}
|
|
11872
|
+
}
|
|
11873
|
+
function printVisibilityCompare(data) {
|
|
11874
|
+
console.log(`AEO month over month: ${data.project} ${data.from.month} -> ${data.to.month}`);
|
|
11875
|
+
const b = data.basket;
|
|
11876
|
+
const excl = [];
|
|
11877
|
+
if (b.excludedFromOnly > 0) excl.push(`${b.excludedFromOnly} only in ${data.from.month}`);
|
|
11878
|
+
if (b.excludedToOnly > 0) excl.push(`${b.excludedToOnly} only in ${data.to.month}`);
|
|
11879
|
+
if (b.excludedProviders.length > 0) excl.push(`engines dropped: ${b.excludedProviders.join(", ")}`);
|
|
11880
|
+
console.log(`Basket: ${b.queryCount} quer${b.queryCount === 1 ? "y" : "ies"}, ${b.providers.length} engine(s)${excl.length ? ` (excluded: ${excl.join("; ")})` : ""}`);
|
|
11881
|
+
const sweeps = `Sweeps: ${data.from.month} ${data.from.runCount}, ${data.to.month} ${data.to.runCount}`;
|
|
11882
|
+
const low = data.from.lowRunCount || data.to.lowRunCount;
|
|
11883
|
+
console.log(low ? `${sweeps} (below the 5-sweep floor \u2014 intervals are wide, a "moved" verdict is unlikely to be reachable)` : sweeps);
|
|
11884
|
+
if (data.continuity.status !== "comparable") {
|
|
11885
|
+
console.log(`Continuity: ${data.continuity.status.replace("-", " ")} \u2014 no directional call is made.`);
|
|
11886
|
+
}
|
|
11887
|
+
console.log("");
|
|
11888
|
+
const rows = data.metrics.map((m) => ({
|
|
11889
|
+
label: `${m.label}${m.driftRobust ? " *" : ""}`,
|
|
11890
|
+
to: periodCell(m.to),
|
|
11891
|
+
from: periodCell(m.from),
|
|
11892
|
+
verdict: verdictCell(m)
|
|
11893
|
+
}));
|
|
11894
|
+
rows.push({
|
|
11895
|
+
label: "Queries named (count)",
|
|
11896
|
+
to: `${data.queriesMentioned.to.count} of ${data.queriesMentioned.to.of}`,
|
|
11897
|
+
from: `${data.queriesMentioned.from.count} of ${data.queriesMentioned.from.of}`,
|
|
11898
|
+
verdict: ""
|
|
11899
|
+
});
|
|
11900
|
+
const w = (sel, head) => Math.max(head.length, ...rows.map((r) => sel(r).length));
|
|
11901
|
+
const lw = w((r) => r.label, "Metric");
|
|
11902
|
+
const tw = w((r) => r.to, data.to.month);
|
|
11903
|
+
const fw = w((r) => r.from, data.from.month);
|
|
11904
|
+
console.log(` ${"Metric".padEnd(lw)} ${data.to.month.padEnd(tw)} ${data.from.month.padEnd(fw)} Verdict`);
|
|
11905
|
+
for (const r of rows) {
|
|
11906
|
+
console.log(` ${r.label.padEnd(lw)} ${r.to.padEnd(tw)} ${r.from.padEnd(fw)} ${r.verdict}`);
|
|
11907
|
+
}
|
|
11908
|
+
console.log("");
|
|
11909
|
+
console.log(" * share of voice is less exposed to broad model-wide naming propensity; model continuity is still required.");
|
|
11910
|
+
for (const provider of data.continuity.providers) {
|
|
11911
|
+
if (provider.status !== "included") {
|
|
11912
|
+
console.log(` Excluded for model continuity: ${provider.provider} (${provider.fromModels.join("/") || "?"} -> ${provider.toModels.join("/") || "?"}; ${provider.status.replace("-", " ")})`);
|
|
11913
|
+
}
|
|
11914
|
+
}
|
|
11915
|
+
}
|
|
11844
11916
|
function citedCell(c) {
|
|
11845
11917
|
return `${c.cited}/${c.total}`;
|
|
11846
11918
|
}
|
|
@@ -11932,6 +12004,7 @@ function printVisibilityStats(data) {
|
|
|
11932
12004
|
|
|
11933
12005
|
// src/cli-commands/visibility-stats.ts
|
|
11934
12006
|
var USAGE4 = "canonry visibility-stats <project> [--since <iso>] [--until <iso>] [--month <YYYY-MM>] [--last-runs <n>] [--by-provider] [--share-of-voice] [--format json|jsonl]";
|
|
12007
|
+
var COMPARE_USAGE = "canonry visibility-compare <project> --from <YYYY-MM> --to <YYYY-MM> [--format json]";
|
|
11935
12008
|
var VISIBILITY_STATS_CLI_COMMANDS = [
|
|
11936
12009
|
{
|
|
11937
12010
|
path: ["visibility-stats"],
|
|
@@ -11960,6 +12033,22 @@ var VISIBILITY_STATS_CLI_COMMANDS = [
|
|
|
11960
12033
|
format: input.format
|
|
11961
12034
|
});
|
|
11962
12035
|
}
|
|
12036
|
+
},
|
|
12037
|
+
{
|
|
12038
|
+
path: ["visibility-compare"],
|
|
12039
|
+
usage: COMPARE_USAGE,
|
|
12040
|
+
options: {
|
|
12041
|
+
from: stringOption(),
|
|
12042
|
+
to: stringOption()
|
|
12043
|
+
},
|
|
12044
|
+
run: async (input) => {
|
|
12045
|
+
const project = requireProject(input, "visibility-compare", COMPARE_USAGE);
|
|
12046
|
+
await showVisibilityCompare(project, {
|
|
12047
|
+
from: getString(input.values, "from"),
|
|
12048
|
+
to: getString(input.values, "to"),
|
|
12049
|
+
format: input.format
|
|
12050
|
+
});
|
|
12051
|
+
}
|
|
11963
12052
|
}
|
|
11964
12053
|
];
|
|
11965
12054
|
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createServer
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-ZZEA774R.js";
|
|
4
4
|
import {
|
|
5
5
|
loadConfig
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
8
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-PJATAPZW.js";
|
|
7
|
+
import "./chunk-FVVKNMZW.js";
|
|
8
|
+
import "./chunk-IAJ5TQ4S.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-PJATAPZW.js";
|
|
7
7
|
import {
|
|
8
8
|
isReadOnlyKey
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-IAJ5TQ4S.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": "@ainyc/canonry",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.117.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",
|
|
@@ -65,27 +65,27 @@
|
|
|
65
65
|
"@types/node-cron": "^3.0.11",
|
|
66
66
|
"tsup": "^8.5.1",
|
|
67
67
|
"tsx": "^4.19.0",
|
|
68
|
+
"@ainyc/canonry-api-client": "0.0.0",
|
|
68
69
|
"@ainyc/canonry-api-routes": "0.0.0",
|
|
69
70
|
"@ainyc/canonry-config": "0.0.0",
|
|
70
|
-
"@ainyc/canonry-
|
|
71
|
+
"@ainyc/canonry-contracts": "0.0.0",
|
|
71
72
|
"@ainyc/canonry-db": "0.0.0",
|
|
72
73
|
"@ainyc/canonry-integration-bing": "0.0.0",
|
|
73
|
-
"@ainyc/canonry-contracts": "0.0.0",
|
|
74
74
|
"@ainyc/canonry-integration-openai-ads": "0.0.0",
|
|
75
|
+
"@ainyc/canonry-integration-commoncrawl": "0.0.0",
|
|
75
76
|
"@ainyc/canonry-integration-cloud-run": "0.0.0",
|
|
76
77
|
"@ainyc/canonry-integration-google": "0.0.0",
|
|
77
78
|
"@ainyc/canonry-integration-google-business-profile": "0.0.0",
|
|
78
|
-
"@ainyc/canonry-integration-
|
|
79
|
+
"@ainyc/canonry-integration-google-places": "0.0.0",
|
|
79
80
|
"@ainyc/canonry-integration-traffic": "0.0.0",
|
|
80
81
|
"@ainyc/canonry-integration-wordpress": "0.0.0",
|
|
81
|
-
"@ainyc/canonry-intelligence": "0.0.0",
|
|
82
82
|
"@ainyc/canonry-provider-cdp": "0.0.0",
|
|
83
|
+
"@ainyc/canonry-intelligence": "0.0.0",
|
|
83
84
|
"@ainyc/canonry-provider-claude": "0.0.0",
|
|
84
|
-
"@ainyc/canonry-integration-google-places": "0.0.0",
|
|
85
|
-
"@ainyc/canonry-provider-local": "0.0.0",
|
|
86
|
-
"@ainyc/canonry-provider-openai": "0.0.0",
|
|
87
85
|
"@ainyc/canonry-provider-gemini": "0.0.0",
|
|
88
|
-
"@ainyc/canonry-provider-
|
|
86
|
+
"@ainyc/canonry-provider-openai": "0.0.0",
|
|
87
|
+
"@ainyc/canonry-provider-perplexity": "0.0.0",
|
|
88
|
+
"@ainyc/canonry-provider-local": "0.0.0"
|
|
89
89
|
},
|
|
90
90
|
"scripts": {
|
|
91
91
|
"build": "tsx scripts/copy-agent-assets.ts && tsup && tsx build-web.ts",
|