@ainyc/canonry 4.99.0 → 4.99.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.
Files changed (25) hide show
  1. package/assets/assets/{BacklinksPage-CuWs7I1D.js → BacklinksPage-v2RC8wlg.js} +1 -1
  2. package/assets/assets/{ChartPrimitives-bm37tprp.js → ChartPrimitives-B74e5pqn.js} +1 -1
  3. package/assets/assets/ProjectPage-BCzS7TQn.js +6 -0
  4. package/assets/assets/{RunRow-DzhQl87g.js → RunRow-BmVPjO-m.js} +1 -1
  5. package/assets/assets/{RunsPage-wOaewhbF.js → RunsPage-CK5atXvL.js} +1 -1
  6. package/assets/assets/{SettingsPage-CJdhhkkE.js → SettingsPage-DarPFUPl.js} +1 -1
  7. package/assets/assets/{TrafficPage-BJBeN5Ph.js → TrafficPage-Ddnn_WqU.js} +1 -1
  8. package/assets/assets/{TrafficSourceDetailPage-D3PmH0B1.js → TrafficSourceDetailPage-g08SKnwZ.js} +1 -1
  9. package/assets/assets/{arrow-left-BmITMI6O.js → arrow-left-D39Vxasb.js} +1 -1
  10. package/assets/assets/{extract-error-message-BGwnyAfP.js → extract-error-message-BiNWqBeh.js} +1 -1
  11. package/assets/assets/{index-BsZNCwg8.css → index-BCuWbxUj.css} +1 -1
  12. package/assets/assets/index-Dd4J1VhB.js +210 -0
  13. package/assets/assets/{trash-2-Bd2mkP_w.js → trash-2-xh6gsnap.js} +1 -1
  14. package/assets/index.html +2 -2
  15. package/dist/{chunk-CEHD33NQ.js → chunk-4Q3LBD7A.js} +251 -111
  16. package/dist/{chunk-VQN74WWA.js → chunk-IDI6LMYL.js} +1 -1
  17. package/dist/{chunk-CWFTMFEU.js → chunk-JF7EXHGA.js} +12 -3
  18. package/dist/{chunk-DJVUNURL.js → chunk-YBIT5O62.js} +36 -29
  19. package/dist/cli.js +4 -4
  20. package/dist/index.js +4 -4
  21. package/dist/{intelligence-service-QHBXW4KI.js → intelligence-service-TWCEKVKZ.js} +2 -2
  22. package/dist/mcp.js +2 -2
  23. package/package.json +8 -8
  24. package/assets/assets/ProjectPage-BksYe8FP.js +0 -6
  25. package/assets/assets/index-BSX6r6ju.js +0 -210
@@ -24,7 +24,7 @@ import {
24
24
  trafficConnectVercelRequestSchema,
25
25
  trafficConnectWordpressRequestSchema,
26
26
  trafficEventKindSchema
27
- } from "./chunk-CWFTMFEU.js";
27
+ } from "./chunk-JF7EXHGA.js";
28
28
 
29
29
  // src/config.ts
30
30
  import fs from "fs";
@@ -3998,12 +3998,15 @@ var citationScorecardSchema = z28.object({
3998
3998
  providers: z28.array(z28.string()),
3999
3999
  /** matrix[queryIndex][providerIndex] — null when no snapshot exists for the pair. */
4000
4000
  matrix: z28.array(z28.array(citationCellSchema.nullable())),
4001
- /** Per-provider citation rate (0..100). */
4001
+ /** Per-provider citation + mention rates (0..100). */
4002
4002
  providerRates: z28.array(z28.object({
4003
4003
  provider: z28.string(),
4004
4004
  citedCount: z28.number(),
4005
+ /** Number of snapshots for this provider where the answer text mentioned the project. */
4006
+ mentionedCount: z28.number(),
4005
4007
  totalCount: z28.number(),
4006
- citationRate: z28.number()
4008
+ citationRate: z28.number(),
4009
+ mentionRate: z28.number()
4007
4010
  }))
4008
4011
  });
4009
4012
  var competitorRowSchema = z28.object({
@@ -4274,7 +4277,11 @@ var citationsTrendPointSchema = z28.object({
4274
4277
  * within that provider (`cited / scanned`), so it remains comparable
4275
4278
  * between providers in the same run.
4276
4279
  */
4277
- providerRates: z28.array(z28.object({ provider: z28.string(), citationRate: z28.number() }))
4280
+ providerRates: z28.array(z28.object({
4281
+ provider: z28.string(),
4282
+ citationRate: z28.number(),
4283
+ mentionRate: z28.number()
4284
+ }))
4278
4285
  });
4279
4286
  var reportInsightSchema = z28.object({
4280
4287
  id: z28.string(),
@@ -4356,6 +4363,8 @@ var whatsChangedSectionSchema = z28.object({
4356
4363
  mentionRate: reportRateDeltaSchema.nullable(),
4357
4364
  /** Cited query count delta vs the prior completed run. Null when no prior run. */
4358
4365
  citedQueryCount: reportRateDeltaSchema.nullable(),
4366
+ /** Mentioned query count delta vs the prior completed run. Null when no prior run. */
4367
+ mentionedQueryCount: reportRateDeltaSchema.nullable(),
4359
4368
  /**
4360
4369
  * GSC clicks delta — the most recent `comparisonWindowDays` of `gsc.trend`
4361
4370
  * vs the `comparisonWindowDays` before that. Null when GSC isn't connected
@@ -263,7 +263,7 @@ import {
263
263
  wordpressSchemaDeployResultDtoSchema,
264
264
  wordpressSchemaStatusResultDtoSchema,
265
265
  wordpressStatusDtoSchema
266
- } from "./chunk-CWFTMFEU.js";
266
+ } from "./chunk-JF7EXHGA.js";
267
267
 
268
268
  // src/intelligence-service.ts
269
269
  import { eq as eq37, desc as desc18, asc as asc5, and as and27, ne as ne5, or as or5, inArray as inArray14, gte as gte7, lte as lte4 } from "drizzle-orm";
@@ -4428,19 +4428,23 @@ function buildCitationScorecard(snapshots, queryLookup) {
4428
4428
  answerMentioned: snap.answerMentioned ?? null,
4429
4429
  model: snap.model
4430
4430
  };
4431
- const counts2 = providerCounts.get(snap.provider) ?? { cited: 0, total: 0 };
4431
+ const counts2 = providerCounts.get(snap.provider) ?? { cited: 0, mentioned: 0, total: 0 };
4432
4432
  counts2.total++;
4433
4433
  if (snap.citationState === CitationStates.cited) counts2.cited++;
4434
+ if (snap.answerMentioned === true) counts2.mentioned++;
4434
4435
  providerCounts.set(snap.provider, counts2);
4435
4436
  }
4436
4437
  const providerRates = providerList.map((provider) => {
4437
- const counts2 = providerCounts.get(provider) ?? { cited: 0, total: 0 };
4438
+ const counts2 = providerCounts.get(provider) ?? { cited: 0, mentioned: 0, total: 0 };
4438
4439
  const citationRate = counts2.total > 0 ? Math.round(counts2.cited / counts2.total * 100) : 0;
4440
+ const mentionRate = counts2.total > 0 ? Math.round(counts2.mentioned / counts2.total * 100) : 0;
4439
4441
  return {
4440
4442
  provider,
4441
4443
  citedCount: counts2.cited,
4444
+ mentionedCount: counts2.mentioned,
4442
4445
  totalCount: counts2.total,
4443
- citationRate
4446
+ citationRate,
4447
+ mentionRate
4444
4448
  };
4445
4449
  });
4446
4450
  return { queries: queryList, providers: providerList, matrix, providerRates };
@@ -10221,9 +10225,9 @@ function renderWhatsChanged(report, audience) {
10221
10225
  );
10222
10226
  }
10223
10227
  const rateTiles = `<div class="metric-grid">
10224
- ${renderRateDeltaTile(isClient ? "AI links to your website" : "Citation rate", w.citationRate, "%")}
10225
- ${renderRateDeltaTile(isClient ? "AI mentions your name" : "Mention rate", w.mentionRate, "%")}
10226
- ${renderRateDeltaTile(isClient ? "Questions AI answered with you" : "Cited queries", w.citedQueryCount, "count")}
10228
+ ${renderRateDeltaTile(isClient ? "AI mentions your name" : "Citation rate", isClient ? w.mentionRate : w.citationRate, "%")}
10229
+ ${renderRateDeltaTile(isClient ? "AI links to your website" : "Mention rate", isClient ? w.citationRate : w.mentionRate, "%")}
10230
+ ${renderRateDeltaTile(isClient ? "Questions AI mentioned you in" : "Cited queries", isClient ? w.mentionedQueryCount : w.citedQueryCount, "count")}
10227
10231
  ${renderTrafficDeltaTile(isClient ? "Visitors from Google" : "GSC clicks", w.gscClicksDelta, isClient ? "visits" : "clicks", w.comparisonWindowDays)}
10228
10232
  ${renderTrafficDeltaTile(isClient ? "Visitors from AI tools" : "AI referral sessions", w.aiReferralsDelta, isClient ? "visits" : "sessions", w.comparisonWindowDays)}
10229
10233
  </div>`;
@@ -11117,9 +11121,9 @@ function renderClientSummary(report) {
11117
11121
  const s = report.executiveSummary;
11118
11122
  const sc = report.citationScorecard;
11119
11123
  const totalQ = s.totalQueryCount;
11120
- const heroNumber = totalQ > 0 ? `${s.citationRate}%` : "\u2014";
11121
- const heroSentence = totalQ > 0 ? `When customers asked AI ${totalQ} ${pluralize(totalQ, "question")} about your industry, AI linked to your website in ${s.citedQueryCount} of ${totalQ === 1 ? "them" : "those answers"}.` : "No AI check has been run yet. Run a check to see how AI tools answer customer questions about your business.";
11122
- const trend = clientTrendCopy(report.whatsChanged.citationRate);
11124
+ const heroNumber = totalQ > 0 ? `${s.mentionRate}%` : "\u2014";
11125
+ const heroSentence = totalQ > 0 ? `When customers asked AI ${totalQ} ${pluralize(totalQ, "question")} about your industry, AI mentioned you in ${s.mentionedQueryCount} of ${totalQ === 1 ? "them" : "those answers"}.` : "No AI check has been run yet. Run a check to see how AI tools answer customer questions about your business.";
11126
+ const trend = clientTrendCopy(report.whatsChanged.mentionRate);
11123
11127
  const heroTrend = trend ? `<p class="client-hero-trend tone-${trend.tone}"><span style="margin-right:6px;">${trend.arrow}</span>${escapeHtml(trend.text)}</p>` : "";
11124
11128
  const hero = `<div class="client-hero">
11125
11129
  <div class="client-hero-eyebrow">Overview</div>
@@ -11159,15 +11163,15 @@ function renderClientSummary(report) {
11159
11163
  </ol>
11160
11164
  </div>` : "";
11161
11165
  const providerBars = sc.providerRates.length > 0 ? `<div class="client-card">
11162
- <h3>How often each AI tool links to your website</h3>
11163
- <p class="card-subtitle">Higher is better. Each bar shows the share of customer questions where the AI cited your site.</p>
11166
+ <h3>How often each AI tool mentions you</h3>
11167
+ <p class="card-subtitle">Higher is better. Each bar shows the share of customer questions where the AI named you in the answer.</p>
11164
11168
  <div class="client-bar-list">
11165
11169
  ${sc.providerRates.map((r) => {
11166
- const pct = Math.max(r.citationRate, 1.5);
11170
+ const pct = Math.max(r.mentionRate, 1.5);
11167
11171
  return `<div class="client-bar-row">
11168
11172
  <span class="bar-label">${escapeHtml(providerDisplayName(r.provider))}</span>
11169
11173
  <div class="bar-track"><div class="bar-fill" style="width:${pct}%"></div></div>
11170
- <span class="bar-value">${r.citationRate}% <span class="bar-value-sub">(${r.citedCount}/${r.totalCount})</span></span>
11174
+ <span class="bar-value">${r.mentionRate}% <span class="bar-value-sub">(${r.mentionedCount}/${r.totalCount})</span></span>
11171
11175
  </div>`;
11172
11176
  }).join("")}
11173
11177
  </div>
@@ -11953,9 +11957,10 @@ function buildCitationsTrend(db, projectId, queryLookup, locationFilter) {
11953
11957
  considered++;
11954
11958
  if (snap.citationState === CitationStates.cited) citedQueryIds.add(snap.queryId);
11955
11959
  if (snap.answerMentioned) mentionedQueryIds.add(snap.queryId);
11956
- const counts2 = providerCounts.get(snap.provider) ?? { cited: 0, total: 0 };
11960
+ const counts2 = providerCounts.get(snap.provider) ?? { cited: 0, mentioned: 0, total: 0 };
11957
11961
  counts2.total++;
11958
11962
  if (snap.citationState === CitationStates.cited) counts2.cited++;
11963
+ if (snap.answerMentioned === true) counts2.mentioned++;
11959
11964
  providerCounts.set(snap.provider, counts2);
11960
11965
  }
11961
11966
  if (considered === 0) continue;
@@ -11965,7 +11970,8 @@ function buildCitationsTrend(db, projectId, queryLookup, locationFilter) {
11965
11970
  const mentionRate = totalQueries > 0 ? Math.round(mentionedQueryCount / totalQueries * 100) : 0;
11966
11971
  const providerRates = [...providerCounts.entries()].map(([provider, counts2]) => ({
11967
11972
  provider,
11968
- citationRate: counts2.total > 0 ? Math.round(counts2.cited / counts2.total * 100) : 0
11973
+ citationRate: counts2.total > 0 ? Math.round(counts2.cited / counts2.total * 100) : 0,
11974
+ mentionRate: counts2.total > 0 ? Math.round(counts2.mentioned / counts2.total * 100) : 0
11969
11975
  })).sort((a, b) => a.provider.localeCompare(b.provider));
11970
11976
  points.push({
11971
11977
  runId: run.id,
@@ -12345,23 +12351,17 @@ function buildReportActionPlan(input) {
12345
12351
  }
12346
12352
  return actions.sort((a, b) => a.priority - b.priority).slice(0, 10);
12347
12353
  }
12348
- function trendSentence(trend) {
12349
- switch (trend) {
12350
- case "up":
12351
- return "Citation coverage improved versus the prior comparable check.";
12352
- case "down":
12353
- return "Citation coverage declined versus the prior comparable check.";
12354
- case "flat":
12355
- return "Citation coverage is flat versus the prior comparable check.";
12356
- case "unknown":
12357
- return "There is not enough comparable run history yet to call a trend.";
12358
- }
12354
+ function mentionTrendSentence(delta) {
12355
+ if (!delta) return "There is not enough comparable run history yet to call a mention trend.";
12356
+ if (delta.direction === "up") return "Mention coverage improved versus the prior comparable checks.";
12357
+ if (delta.direction === "down") return "Mention coverage declined versus the prior comparable checks.";
12358
+ return "Mention coverage is flat versus the prior comparable checks.";
12359
12359
  }
12360
12360
  function buildClientSummary(reportLike) {
12361
12361
  const s = reportLike.executiveSummary;
12362
12362
  const queryNoun = s.totalQueryCount === 1 ? "query" : "queries";
12363
- const headline = s.totalQueryCount > 0 ? `${s.citedQueryCount} of ${s.totalQueryCount} tracked ${queryNoun} are cited by AI engines` : "No tracked queries have completed a check yet";
12364
- const overview = s.totalQueryCount > 0 ? `${reportLike.canonicalDomain} is cited on ${s.citationRate}% of tracked queries and mentioned on ${s.mentionRate}% of tracked queries. ${trendSentence(s.trend)}` : "At least one completed check is needed before this can summarize how the brand appears in AI answers.";
12363
+ const headline = s.totalQueryCount > 0 ? `${s.mentionedQueryCount} of ${s.totalQueryCount} tracked ${queryNoun} mention the brand in AI answers` : "No tracked queries have completed a check yet";
12364
+ const overview = s.totalQueryCount > 0 ? `${reportLike.canonicalDomain} is mentioned on ${s.mentionRate}% of tracked queries and cited on ${s.citationRate}% of tracked queries. ${mentionTrendSentence(reportLike.whatsChanged.mentionRate)}` : "At least one completed check is needed before this can summarize how the brand appears in AI answers.";
12365
12365
  const confidenceNotes = [];
12366
12366
  if (s.totalQueryCount === 0) {
12367
12367
  confidenceNotes.push("Confidence is low until the first tracked query check completes.");
@@ -12496,6 +12496,11 @@ function buildWhatsChanged(input) {
12496
12496
  ...citedQueryCountSmoothed,
12497
12497
  direction: rateDirection(citedQueryCountSmoothed.deltaAbs, COUNT_REAL_MOVEMENT_THRESHOLD)
12498
12498
  } : null;
12499
+ const mentionedQueryCountSmoothed = smoothedRunDelta(citationsTrend, (p) => p.mentionedQueryCount);
12500
+ const mentionedQueryCount = enoughHistory && mentionedQueryCountSmoothed ? {
12501
+ ...mentionedQueryCountSmoothed,
12502
+ direction: rateDirection(mentionedQueryCountSmoothed.deltaAbs, COUNT_REAL_MOVEMENT_THRESHOLD)
12503
+ } : null;
12499
12504
  const providerMovements = [];
12500
12505
  if (enoughHistory) {
12501
12506
  const priorByProvider = new Map(prior.providerRates.map((p) => [p.provider, p.citationRate]));
@@ -12531,6 +12536,7 @@ function buildWhatsChanged(input) {
12531
12536
  citationRate,
12532
12537
  mentionRate,
12533
12538
  citedQueryCount,
12539
+ mentionedQueryCount,
12534
12540
  gscClicksDelta,
12535
12541
  aiReferralsDelta,
12536
12542
  comparisonWindowDays,
@@ -12694,6 +12700,7 @@ function buildProjectReport(db, projectName, periodDays) {
12694
12700
  reportLocation,
12695
12701
  executiveSummary,
12696
12702
  citationsTrend,
12703
+ whatsChanged,
12697
12704
  gsc: gscSection,
12698
12705
  actionPlan
12699
12706
  });
package/dist/cli.js CHANGED
@@ -27,7 +27,7 @@ import {
27
27
  setTelemetrySource,
28
28
  showFirstRunNotice,
29
29
  trackEvent
30
- } from "./chunk-CEHD33NQ.js";
30
+ } from "./chunk-4Q3LBD7A.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-VQN74WWA.js";
47
+ } from "./chunk-IDI6LMYL.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-DJVUNURL.js";
55
+ } from "./chunk-YBIT5O62.js";
56
56
  import {
57
57
  BacklinkSources,
58
58
  CcReleaseSyncStatuses,
@@ -78,7 +78,7 @@ import {
78
78
  providerQuotaPolicySchema,
79
79
  resolveProviderInput,
80
80
  winnabilityClassSchema
81
- } from "./chunk-CWFTMFEU.js";
81
+ } from "./chunk-JF7EXHGA.js";
82
82
 
83
83
  // src/cli.ts
84
84
  import { pathToFileURL } from "url";
package/dist/index.js CHANGED
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  createServer
3
- } from "./chunk-CEHD33NQ.js";
3
+ } from "./chunk-4Q3LBD7A.js";
4
4
  import {
5
5
  loadConfig
6
- } from "./chunk-VQN74WWA.js";
7
- import "./chunk-DJVUNURL.js";
8
- import "./chunk-CWFTMFEU.js";
6
+ } from "./chunk-IDI6LMYL.js";
7
+ import "./chunk-YBIT5O62.js";
8
+ import "./chunk-JF7EXHGA.js";
9
9
  export {
10
10
  createServer,
11
11
  loadConfig
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  IntelligenceService
3
- } from "./chunk-DJVUNURL.js";
4
- import "./chunk-CWFTMFEU.js";
3
+ } from "./chunk-YBIT5O62.js";
4
+ import "./chunk-JF7EXHGA.js";
5
5
  export {
6
6
  IntelligenceService
7
7
  };
package/dist/mcp.js CHANGED
@@ -3,10 +3,10 @@ import {
3
3
  PACKAGE_VERSION,
4
4
  canonryMcpTools,
5
5
  createApiClient
6
- } from "./chunk-VQN74WWA.js";
6
+ } from "./chunk-IDI6LMYL.js";
7
7
  import {
8
8
  isReadOnlyKey
9
- } from "./chunk-CWFTMFEU.js";
9
+ } from "./chunk-JF7EXHGA.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.99.0",
3
+ "version": "4.99.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",
@@ -62,27 +62,27 @@
62
62
  "@types/node-cron": "^3.0.11",
63
63
  "tsup": "^8.5.1",
64
64
  "tsx": "^4.19.0",
65
- "@ainyc/canonry-api-client": "0.0.0",
66
65
  "@ainyc/canonry-api-routes": "0.0.0",
67
- "@ainyc/canonry-contracts": "0.0.0",
68
- "@ainyc/canonry-config": "0.0.0",
66
+ "@ainyc/canonry-api-client": "0.0.0",
69
67
  "@ainyc/canonry-db": "0.0.0",
70
- "@ainyc/canonry-integration-openai-ads": "0.0.0",
71
68
  "@ainyc/canonry-integration-bing": "0.0.0",
69
+ "@ainyc/canonry-integration-openai-ads": "0.0.0",
72
70
  "@ainyc/canonry-integration-cloud-run": "0.0.0",
71
+ "@ainyc/canonry-config": "0.0.0",
73
72
  "@ainyc/canonry-integration-commoncrawl": "0.0.0",
74
73
  "@ainyc/canonry-integration-google": "0.0.0",
75
74
  "@ainyc/canonry-integration-google-business-profile": "0.0.0",
75
+ "@ainyc/canonry-contracts": "0.0.0",
76
76
  "@ainyc/canonry-integration-traffic": "0.0.0",
77
77
  "@ainyc/canonry-intelligence": "0.0.0",
78
78
  "@ainyc/canonry-integration-google-places": "0.0.0",
79
+ "@ainyc/canonry-integration-wordpress": "0.0.0",
79
80
  "@ainyc/canonry-provider-cdp": "0.0.0",
80
81
  "@ainyc/canonry-provider-claude": "0.0.0",
81
82
  "@ainyc/canonry-provider-gemini": "0.0.0",
82
- "@ainyc/canonry-integration-wordpress": "0.0.0",
83
83
  "@ainyc/canonry-provider-local": "0.0.0",
84
- "@ainyc/canonry-provider-openai": "0.0.0",
85
- "@ainyc/canonry-provider-perplexity": "0.0.0"
84
+ "@ainyc/canonry-provider-perplexity": "0.0.0",
85
+ "@ainyc/canonry-provider-openai": "0.0.0"
86
86
  },
87
87
  "scripts": {
88
88
  "build": "tsx scripts/copy-agent-assets.ts && tsup && tsx build-web.ts",