@ainyc/canonry 4.43.0 → 4.44.1

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/index.html CHANGED
@@ -12,8 +12,8 @@
12
12
  <link rel="icon" type="image/png" sizes="32x32" href="./favicon-32.png" />
13
13
  <link rel="apple-touch-icon" href="./apple-touch-icon.png" />
14
14
  <title>Canonry</title>
15
- <script type="module" crossorigin src="./assets/index-kRilKhIW.js"></script>
16
- <link rel="stylesheet" crossorigin href="./assets/index-jvmhx0du.css">
15
+ <script type="module" crossorigin src="./assets/index-ObgzOp7B.js"></script>
16
+ <link rel="stylesheet" crossorigin href="./assets/index-PWkDKYPZ.css">
17
17
  </head>
18
18
  <body>
19
19
  <div id="root"></div>
@@ -77,9 +77,10 @@ import {
77
77
  rawEventSamples,
78
78
  runs,
79
79
  schedules,
80
+ smoothedRunDelta,
80
81
  trafficSources,
81
82
  usageCounters
82
- } from "./chunk-MITJYCHG.js";
83
+ } from "./chunk-TBADB57G.js";
83
84
  import {
84
85
  AGENT_MEMORY_VALUE_MAX_BYTES,
85
86
  AGENT_PROVIDER_IDS,
@@ -3150,12 +3151,16 @@ function clientConfidenceLabel(confidence) {
3150
3151
  function clientTrendCopy(delta) {
3151
3152
  if (!delta) return null;
3152
3153
  if (delta.direction === "up") {
3153
- return { text: `Up ${delta.deltaAbs.toFixed(1)} points since last check (was ${delta.prior}%)`, tone: "positive", arrow: "\u2191" };
3154
+ return { text: `Up ${delta.deltaAbs.toFixed(1)} points ${compareCopy(delta)}`, tone: "positive", arrow: "\u2191" };
3154
3155
  }
3155
3156
  if (delta.direction === "down") {
3156
- return { text: `Down ${Math.abs(delta.deltaAbs).toFixed(1)} points since last check (was ${delta.prior}%)`, tone: "negative", arrow: "\u2193" };
3157
+ return { text: `Down ${Math.abs(delta.deltaAbs).toFixed(1)} points ${compareCopy(delta)}`, tone: "negative", arrow: "\u2193" };
3157
3158
  }
3158
- return { text: `Holding steady since last check (was ${delta.prior}%)`, tone: "neutral", arrow: "\u2192" };
3159
+ return { text: `Holding steady ${compareCopy(delta)}`, tone: "neutral", arrow: "\u2192" };
3160
+ }
3161
+ function compareCopy(delta) {
3162
+ const window = delta.window ?? 1;
3163
+ return window >= 2 ? `vs prior ${window} checks (avg ${delta.prior}%)` : `since last check (was ${delta.prior}%)`;
3159
3164
  }
3160
3165
  function compactInlineList(items, limit = 3) {
3161
3166
  const visible = items.slice(0, limit);
@@ -4331,7 +4336,7 @@ function renderCompetitorLandscape(report) {
4331
4336
  </tr>`;
4332
4337
  }).join("");
4333
4338
  const table = competitors2.length > 0 ? `<table class="report-table">
4334
- <thead><tr><th>Domain</th><th>Pressure</th><th>Citations</th><th class="numeric">Mentions</th><th class="numeric">SOV</th><th>Cited queries</th></tr></thead>
4339
+ <thead><tr><th>Domain</th><th>Pressure</th><th>Citations</th><th class="numeric">Mentions</th><th class="numeric" title="Citation share \u2014 % of cited-source slots that went to this competitor across tracked queries. Distinct from Mention Share.">Citation share</th><th>Cited queries</th></tr></thead>
4335
4340
  <tbody>${rows}</tbody>
4336
4341
  </table>` : renderEmpty("No competitors configured.");
4337
4342
  const citationBars = renderCompetitorBars(report.competitorLandscape, report.meta.project.canonicalDomain);
@@ -6688,6 +6693,8 @@ function buildAgencyDiagnostics(input) {
6688
6693
  }
6689
6694
  var WHATS_CHANGED_PERIOD_DAYS2 = 14;
6690
6695
  var WHATS_CHANGED_MIN_TREND_POINTS = WHATS_CHANGED_PERIOD_DAYS2 * 2;
6696
+ var RATE_REAL_MOVEMENT_THRESHOLD_PP = 3;
6697
+ var COUNT_REAL_MOVEMENT_THRESHOLD = 0.5;
6691
6698
  var WIN_REGRESSION_LIMIT = 5;
6692
6699
  function rateDirection(delta, threshold = 0.5) {
6693
6700
  if (delta > threshold) return "up";
@@ -6716,7 +6723,8 @@ function buildWhatsChangedHeadline(citation, gscClicks, aiReferrals, enoughHisto
6716
6723
  if (citation) {
6717
6724
  const arrow = citation.direction === "up" ? "\u2191" : citation.direction === "down" ? "\u2193" : "\u2192";
6718
6725
  const verb = citation.direction === "up" ? "rose" : citation.direction === "down" ? "fell" : "held";
6719
- parts.push(`Citation rate ${verb} ${citation.prior}% ${arrow} ${citation.current}%`);
6726
+ const smoothingHint = citation.window && citation.window >= 2 ? ` (avg of last ${citation.window} checks)` : "";
6727
+ parts.push(`Citation rate ${verb} ${citation.prior}% ${arrow} ${citation.current}%${smoothingHint}`);
6720
6728
  }
6721
6729
  if (aiReferrals && aiReferrals.direction !== "flat") {
6722
6730
  const arrow = aiReferrals.direction === "up" ? "\u2191" : "\u2193";
@@ -6733,23 +6741,20 @@ function buildWhatsChanged(input) {
6733
6741
  const latest = citationsTrend.at(-1);
6734
6742
  const prior = citationsTrend.length >= 2 ? citationsTrend.at(-2) : null;
6735
6743
  const enoughHistory = !baseline && latest !== void 0 && prior !== void 0;
6736
- const citationRate = enoughHistory ? {
6737
- current: latest.citationRate,
6738
- prior: prior.citationRate,
6739
- deltaAbs: latest.citationRate - prior.citationRate,
6740
- direction: rateDirection(latest.citationRate - prior.citationRate)
6744
+ const citationRateSmoothed = smoothedRunDelta(citationsTrend, (p) => p.citationRate);
6745
+ const citationRate = enoughHistory && citationRateSmoothed ? {
6746
+ ...citationRateSmoothed,
6747
+ direction: rateDirection(citationRateSmoothed.deltaAbs, RATE_REAL_MOVEMENT_THRESHOLD_PP)
6741
6748
  } : null;
6742
- const mentionRate = enoughHistory ? {
6743
- current: latest.mentionRate,
6744
- prior: prior.mentionRate,
6745
- deltaAbs: latest.mentionRate - prior.mentionRate,
6746
- direction: rateDirection(latest.mentionRate - prior.mentionRate)
6749
+ const mentionRateSmoothed = smoothedRunDelta(citationsTrend, (p) => p.mentionRate);
6750
+ const mentionRate = enoughHistory && mentionRateSmoothed ? {
6751
+ ...mentionRateSmoothed,
6752
+ direction: rateDirection(mentionRateSmoothed.deltaAbs, RATE_REAL_MOVEMENT_THRESHOLD_PP)
6747
6753
  } : null;
6748
- const citedQueryCount = enoughHistory ? {
6749
- current: latest.citedQueryCount,
6750
- prior: prior.citedQueryCount,
6751
- deltaAbs: latest.citedQueryCount - prior.citedQueryCount,
6752
- direction: rateDirection(latest.citedQueryCount - prior.citedQueryCount, 0)
6754
+ const citedQueryCountSmoothed = smoothedRunDelta(citationsTrend, (p) => p.citedQueryCount);
6755
+ const citedQueryCount = enoughHistory && citedQueryCountSmoothed ? {
6756
+ ...citedQueryCountSmoothed,
6757
+ direction: rateDirection(citedQueryCountSmoothed.deltaAbs, COUNT_REAL_MOVEMENT_THRESHOLD)
6753
6758
  } : null;
6754
6759
  const providerMovements = [];
6755
6760
  if (enoughHistory) {
@@ -13499,7 +13504,7 @@ async function bingRoutes(app, opts) {
13499
13504
  connected: true,
13500
13505
  domain: project.canonicalDomain,
13501
13506
  siteUrl: existing?.siteUrl ?? null,
13502
- availableSites: sites.map((s) => ({ url: s.Url, verified: s.Verified ?? false }))
13507
+ availableSites: sites.map((s) => ({ url: s.Url, verified: s.IsVerified ?? false }))
13503
13508
  };
13504
13509
  });
13505
13510
  app.delete("/projects/:name/bing/disconnect", async (request, reply) => {
@@ -13535,7 +13540,7 @@ async function bingRoutes(app, opts) {
13535
13540
  const project = resolveProject(app.db, request.params.name);
13536
13541
  const conn = requireConnection(store, project.canonicalDomain);
13537
13542
  const sites = await getSites(conn.apiKey);
13538
- return { sites: sites.map((s) => ({ url: s.Url, verified: s.Verified ?? false })) };
13543
+ return { sites: sites.map((s) => ({ url: s.Url, verified: s.IsVerified ?? false })) };
13539
13544
  });
13540
13545
  app.post("/projects/:name/bing/set-site", async (request) => {
13541
13546
  const store = requireConnectionStore();
@@ -19607,7 +19612,7 @@ var BING_AUTH_CHECKS = [
19607
19612
  }
19608
19613
  };
19609
19614
  }
19610
- if (!match.Verified) {
19615
+ if (!match.IsVerified) {
19611
19616
  return {
19612
19617
  status: CheckStatuses.fail,
19613
19618
  code: "bing.auth.site-not-verified",
@@ -26309,7 +26314,7 @@ function readStoredGroundingSources(rawResponse) {
26309
26314
  return result;
26310
26315
  }
26311
26316
  async function backfillInsightsCommand(project, opts) {
26312
- const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-HWWNLBZM.js");
26317
+ const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-YFBVWCK2.js");
26313
26318
  const config = loadConfig();
26314
26319
  const db = createClient(config.database);
26315
26320
  migrate(db);
@@ -3793,6 +3793,27 @@ function formatImpressions2(value) {
3793
3793
  return value.toString();
3794
3794
  }
3795
3795
 
3796
+ // ../intelligence/src/smoothed-delta.ts
3797
+ var SMOOTHED_RUN_DELTA_MAX_WINDOW = 3;
3798
+ function smoothedRunDelta(points, valueFn, maxWindow = SMOOTHED_RUN_DELTA_MAX_WINDOW) {
3799
+ if (points.length < 2) return null;
3800
+ const window = Math.min(maxWindow, Math.floor(points.length / 2));
3801
+ const tail = points.slice(-window);
3802
+ const prior = points.slice(-window * 2, -window);
3803
+ const sum = (arr) => arr.reduce((s, p) => s + valueFn(p), 0);
3804
+ const currentAvg = sum(tail) / tail.length;
3805
+ const priorAvg = sum(prior) / prior.length;
3806
+ return {
3807
+ current: roundTo1Decimal(currentAvg),
3808
+ prior: roundTo1Decimal(priorAvg),
3809
+ deltaAbs: currentAvg - priorAvg,
3810
+ window
3811
+ };
3812
+ }
3813
+ function roundTo1Decimal(value) {
3814
+ return Math.round(value * 10) / 10;
3815
+ }
3816
+
3796
3817
  // src/intelligence-service.ts
3797
3818
  import crypto from "crypto";
3798
3819
 
@@ -4323,6 +4344,7 @@ export {
4323
4344
  providerKey,
4324
4345
  buildMentionShare,
4325
4346
  buildSuggestedQueries,
4347
+ smoothedRunDelta,
4326
4348
  createLogger,
4327
4349
  IntelligenceService
4328
4350
  };
package/dist/cli.js CHANGED
@@ -21,7 +21,7 @@ import {
21
21
  setTelemetrySource,
22
22
  showFirstRunNotice,
23
23
  trackEvent
24
- } from "./chunk-IXP4WGLQ.js";
24
+ } from "./chunk-5FQBPF72.js";
25
25
  import {
26
26
  CliError,
27
27
  EXIT_SYSTEM_ERROR,
@@ -44,7 +44,7 @@ import {
44
44
  migrate,
45
45
  projects,
46
46
  queries
47
- } from "./chunk-MITJYCHG.js";
47
+ } from "./chunk-TBADB57G.js";
48
48
  import {
49
49
  CcReleaseSyncStatuses,
50
50
  CheckScopes,
@@ -8081,6 +8081,7 @@ function renderHuman(overview) {
8081
8081
  providerScores,
8082
8082
  attentionItems,
8083
8083
  runHistory,
8084
+ suggestedQueries,
8084
8085
  dateRangeLabel,
8085
8086
  contextLabel
8086
8087
  } = overview;
@@ -8096,7 +8097,11 @@ function renderHuman(overview) {
8096
8097
  console.log("\n No runs yet.");
8097
8098
  }
8098
8099
  console.log("\nScores:");
8100
+ printScore("Mention ", scores.mention);
8099
8101
  printScore("Visibility ", scores.visibility);
8102
+ printScore("Mention share ", scores.mentionShare);
8103
+ printMentionShareBreakdown(scores.mentionShare);
8104
+ printScore("Mention gaps ", scores.mentionGaps);
8100
8105
  printScore("Gap queries ", scores.gapQueries);
8101
8106
  printScore("Index coverage ", scores.indexCoverage);
8102
8107
  printScore("Competitor press.", scores.competitorPressure);
@@ -8156,12 +8161,37 @@ function renderHuman(overview) {
8156
8161
  console.log(` ${point.createdAt.slice(0, 10)} ${String(point.citationRate).padStart(3)}% ${bar}`);
8157
8162
  }
8158
8163
  }
8164
+ if (suggestedQueries.rows.length > 0) {
8165
+ const moreLabel = suggestedQueries.totalCandidates > suggestedQueries.rows.length ? ` (showing ${suggestedQueries.rows.length} of ${suggestedQueries.totalCandidates})` : "";
8166
+ console.log(`
8167
+ Suggested queries to track${moreLabel}:`);
8168
+ for (const s of suggestedQueries.rows) {
8169
+ console.log(` + ${s.query}`);
8170
+ console.log(` ${s.reason}`);
8171
+ }
8172
+ console.log(` (add via: canonry query add ${meta.name} "<query>")`);
8173
+ }
8159
8174
  }
8160
8175
  function printScore(prefix, score) {
8161
8176
  const tone = `[${score.tone}]`.padEnd(11);
8162
8177
  const value = score.value.padEnd(8);
8163
8178
  console.log(` ${prefix} ${tone} ${value} ${score.delta}`);
8164
8179
  }
8180
+ function printMentionShareBreakdown(mentionShare) {
8181
+ const { breakdown } = mentionShare;
8182
+ if (breakdown.perCompetitor.length === 0) return;
8183
+ const total = breakdown.projectMentionSnapshots + breakdown.competitorMentionSnapshots;
8184
+ if (total === 0) return;
8185
+ const youPct = (breakdown.projectMentionSnapshots / total * 100).toFixed(1);
8186
+ console.log(` you${" ".repeat(28)} ${breakdown.projectMentionSnapshots} mentions (${youPct}% of combined)`);
8187
+ for (const row of breakdown.perCompetitor.slice(0, 3)) {
8188
+ const pct2 = (row.mentionSnapshots / total * 100).toFixed(1);
8189
+ console.log(` ${row.domain.padEnd(30)} ${row.mentionSnapshots} mentions (${pct2}% of combined)`);
8190
+ }
8191
+ if (breakdown.perCompetitor.length > 3) {
8192
+ console.log(` + ${breakdown.perCompetitor.length - 3} more competitor${breakdown.perCompetitor.length - 3 === 1 ? "" : "s"} (--format json for full breakdown)`);
8193
+ }
8194
+ }
8165
8195
  function pct(value) {
8166
8196
  return `${(value * 100).toFixed(1)}%`;
8167
8197
  }
package/dist/index.js CHANGED
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  createServer
3
- } from "./chunk-IXP4WGLQ.js";
3
+ } from "./chunk-5FQBPF72.js";
4
4
  import {
5
5
  loadConfig
6
6
  } from "./chunk-JZ2VJW4U.js";
7
- import "./chunk-MITJYCHG.js";
7
+ import "./chunk-TBADB57G.js";
8
8
  import "./chunk-Q7XFJO2V.js";
9
9
  export {
10
10
  createServer,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  IntelligenceService
3
- } from "./chunk-MITJYCHG.js";
3
+ } from "./chunk-TBADB57G.js";
4
4
  import "./chunk-Q7XFJO2V.js";
5
5
  export {
6
6
  IntelligenceService
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ainyc/canonry",
3
- "version": "4.43.0",
3
+ "version": "4.44.1",
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",
@@ -61,22 +61,22 @@
61
61
  "tsup": "^8.5.1",
62
62
  "tsx": "^4.19.0",
63
63
  "@ainyc/canonry-api-routes": "0.0.0",
64
- "@ainyc/canonry-contracts": "0.0.0",
64
+ "@ainyc/canonry-db": "0.0.0",
65
65
  "@ainyc/canonry-intelligence": "0.0.0",
66
66
  "@ainyc/canonry-config": "0.0.0",
67
- "@ainyc/canonry-db": "0.0.0",
68
- "@ainyc/canonry-integration-cloud-run": "0.0.0",
67
+ "@ainyc/canonry-contracts": "0.0.0",
69
68
  "@ainyc/canonry-integration-bing": "0.0.0",
69
+ "@ainyc/canonry-integration-cloud-run": "0.0.0",
70
+ "@ainyc/canonry-integration-commoncrawl": "0.0.0",
70
71
  "@ainyc/canonry-integration-google": "0.0.0",
71
72
  "@ainyc/canonry-integration-traffic": "0.0.0",
72
73
  "@ainyc/canonry-integration-wordpress": "0.0.0",
73
74
  "@ainyc/canonry-provider-cdp": "0.0.0",
74
75
  "@ainyc/canonry-provider-claude": "0.0.0",
75
- "@ainyc/canonry-provider-gemini": "0.0.0",
76
- "@ainyc/canonry-integration-commoncrawl": "0.0.0",
77
- "@ainyc/canonry-provider-perplexity": "0.0.0",
78
76
  "@ainyc/canonry-provider-local": "0.0.0",
79
- "@ainyc/canonry-provider-openai": "0.0.0"
77
+ "@ainyc/canonry-provider-gemini": "0.0.0",
78
+ "@ainyc/canonry-provider-openai": "0.0.0",
79
+ "@ainyc/canonry-provider-perplexity": "0.0.0"
80
80
  },
81
81
  "scripts": {
82
82
  "build": "tsx scripts/copy-agent-assets.ts && tsup && tsx build-web.ts",