@ainyc/canonry 4.42.0 → 4.43.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/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-NUBexmUO.js"></script>
16
- <link rel="stylesheet" crossorigin href="./assets/index-DdOq6OIk.css">
15
+ <script type="module" crossorigin src="./assets/index-kRilKhIW.js"></script>
16
+ <link rel="stylesheet" crossorigin href="./assets/index-jvmhx0du.css">
17
17
  </head>
18
18
  <body>
19
19
  <div id="root"></div>
@@ -38,6 +38,7 @@ import {
38
38
  buildProviderScores,
39
39
  buildProviderTrends,
40
40
  buildRunHistory,
41
+ buildSuggestedQueries,
41
42
  buildVisibilityScore,
42
43
  categorizeQueryByIntent,
43
44
  ccReleaseSyncs,
@@ -78,7 +79,7 @@ import {
78
79
  schedules,
79
80
  trafficSources,
80
81
  usageCounters
81
- } from "./chunk-BPJATXCC.js";
82
+ } from "./chunk-MITJYCHG.js";
82
83
  import {
83
84
  AGENT_MEMORY_VALUE_MAX_BYTES,
84
85
  AGENT_PROVIDER_IDS,
@@ -7287,6 +7288,11 @@ async function compositeRoutes(app) {
7287
7288
  const attentionItems = buildAttentionItems(insightRows, allRuns);
7288
7289
  const sparklineRuns = visibilityRuns.slice(0, DEFAULT_RUN_HISTORY_LIMIT).map((r) => ({ id: r.id, createdAt: r.createdAt, status: r.status }));
7289
7290
  const runHistory = buildRunHistory(sparklineRuns, snapshotsByRun);
7291
+ const suggestedQueries = buildSuggestedQueriesFromGsc(
7292
+ app,
7293
+ project.id,
7294
+ projectQueries.map((q) => q.query)
7295
+ );
7290
7296
  const result = {
7291
7297
  project: formatProject2(project),
7292
7298
  latestRun,
@@ -7301,6 +7307,7 @@ async function compositeRoutes(app) {
7301
7307
  providerScores,
7302
7308
  attentionItems,
7303
7309
  runHistory,
7310
+ suggestedQueries,
7304
7311
  dateRangeLabel: "All time",
7305
7312
  contextLabel: `${project.country} / ${project.language.toUpperCase()}`
7306
7313
  };
@@ -7502,6 +7509,29 @@ function summarizeTransitionsFromSnapshots(latest, previous, since) {
7502
7509
  }
7503
7510
  return { since, gained, lost, emerging };
7504
7511
  }
7512
+ function buildSuggestedQueriesFromGsc(app, projectId, trackedQueries) {
7513
+ const cutoff = new Date(Date.now() - 28 * 24 * 60 * 60 * 1e3).toISOString().slice(0, 10);
7514
+ const rows = app.db.select({
7515
+ query: gscSearchData.query,
7516
+ impressions: sql6`COALESCE(SUM(${gscSearchData.impressions}), 0)`,
7517
+ clicks: sql6`COALESCE(SUM(${gscSearchData.clicks}), 0)`,
7518
+ // Weighted average: SUM(position * impressions) / SUM(impressions).
7519
+ // NULLIF guards the degenerate impressions=0 case (SQLite returns NULL,
7520
+ // which the JS coerces to 0 — caught by the impression floor anyway).
7521
+ avgPosition: sql6`COALESCE(SUM(${gscSearchData.position} * ${gscSearchData.impressions}) * 1.0 / NULLIF(SUM(${gscSearchData.impressions}), 0), 0)`
7522
+ }).from(gscSearchData).where(and7(
7523
+ eq15(gscSearchData.projectId, projectId),
7524
+ sql6`${gscSearchData.date} >= ${cutoff}`,
7525
+ sql6`${gscSearchData.impressions} > 0`
7526
+ )).groupBy(gscSearchData.query).orderBy(sql6`SUM(${gscSearchData.impressions}) DESC`).limit(100).all();
7527
+ const gscRows = rows.map((r) => ({
7528
+ query: r.query,
7529
+ impressions: Number(r.impressions),
7530
+ clicks: Number(r.clicks),
7531
+ avgPosition: Number(r.avgPosition)
7532
+ }));
7533
+ return buildSuggestedQueries(gscRows, { trackedQueries });
7534
+ }
7505
7535
  function buildIndexCoverageScore(app, projectId) {
7506
7536
  const tooltip = "Percentage of inspected URLs currently indexed. Google Search Console is preferred when available, otherwise Bing Webmaster Tools is used.";
7507
7537
  const empty = {
@@ -26279,7 +26309,7 @@ function readStoredGroundingSources(rawResponse) {
26279
26309
  return result;
26280
26310
  }
26281
26311
  async function backfillInsightsCommand(project, opts) {
26282
- const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-NPBBAN4Y.js");
26312
+ const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-HWWNLBZM.js");
26283
26313
  const config = loadConfig();
26284
26314
  const db = createClient(config.database);
26285
26315
  migrate(db);
@@ -3740,6 +3740,59 @@ function describe(parts) {
3740
3740
  return `${score}% of brand mentions are you. Top competitor: ${top.domain} (${top.mentionSnapshots} mentions).`;
3741
3741
  }
3742
3742
 
3743
+ // ../intelligence/src/suggested-queries.ts
3744
+ var DEFAULT_MIN_IMPRESSIONS = 10;
3745
+ var DEFAULT_LIMIT = 10;
3746
+ function buildSuggestedQueries(gscRows, options) {
3747
+ const minImpressions = options.minImpressions ?? DEFAULT_MIN_IMPRESSIONS;
3748
+ const limit = options.limit ?? DEFAULT_LIMIT;
3749
+ const trackedSet = new Set(options.trackedQueries.map(normalizeQuery));
3750
+ let skippedAlreadyTracked = 0;
3751
+ const candidates = [];
3752
+ for (const row of gscRows) {
3753
+ if (row.impressions < minImpressions) continue;
3754
+ const normalized = normalizeQuery(row.query);
3755
+ if (normalized.length === 0) continue;
3756
+ if (trackedSet.has(normalized)) {
3757
+ skippedAlreadyTracked++;
3758
+ continue;
3759
+ }
3760
+ candidates.push({
3761
+ query: row.query,
3762
+ impressions: row.impressions,
3763
+ clicks: row.clicks,
3764
+ avgPosition: row.avgPosition,
3765
+ reason: buildReason(row)
3766
+ });
3767
+ }
3768
+ candidates.sort((a, b) => b.impressions - a.impressions);
3769
+ const rows = candidates.slice(0, limit);
3770
+ return {
3771
+ rows,
3772
+ totalCandidates: candidates.length,
3773
+ skippedAlreadyTracked
3774
+ };
3775
+ }
3776
+ function normalizeQuery(value) {
3777
+ return value.trim().toLowerCase();
3778
+ }
3779
+ function buildReason(row) {
3780
+ const impressionsLabel = formatImpressions2(row.impressions);
3781
+ if (row.avgPosition <= 10) {
3782
+ return `${impressionsLabel} impressions \xB7 ranks #${Math.round(row.avgPosition)} on Google`;
3783
+ }
3784
+ if (row.avgPosition <= 20) {
3785
+ return `${impressionsLabel} impressions \xB7 ranks #${Math.round(row.avgPosition)} \u2014 close to top 10`;
3786
+ }
3787
+ return `${impressionsLabel} impressions \xB7 ranks #${Math.round(row.avgPosition)}`;
3788
+ }
3789
+ function formatImpressions2(value) {
3790
+ if (value >= 1e6) return `${(value / 1e6).toFixed(1)}M`;
3791
+ if (value >= 1e4) return `${Math.round(value / 1e3)}K`;
3792
+ if (value >= 1e3) return `${(value / 1e3).toFixed(1)}K`;
3793
+ return value.toString();
3794
+ }
3795
+
3743
3796
  // src/intelligence-service.ts
3744
3797
  import crypto from "crypto";
3745
3798
 
@@ -4269,6 +4322,7 @@ export {
4269
4322
  buildProviderTrends,
4270
4323
  providerKey,
4271
4324
  buildMentionShare,
4325
+ buildSuggestedQueries,
4272
4326
  createLogger,
4273
4327
  IntelligenceService
4274
4328
  };
package/dist/cli.js CHANGED
@@ -21,7 +21,7 @@ import {
21
21
  setTelemetrySource,
22
22
  showFirstRunNotice,
23
23
  trackEvent
24
- } from "./chunk-D37LKESQ.js";
24
+ } from "./chunk-IXP4WGLQ.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-BPJATXCC.js";
47
+ } from "./chunk-MITJYCHG.js";
48
48
  import {
49
49
  CcReleaseSyncStatuses,
50
50
  CheckScopes,
package/dist/index.js CHANGED
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  createServer
3
- } from "./chunk-D37LKESQ.js";
3
+ } from "./chunk-IXP4WGLQ.js";
4
4
  import {
5
5
  loadConfig
6
6
  } from "./chunk-JZ2VJW4U.js";
7
- import "./chunk-BPJATXCC.js";
7
+ import "./chunk-MITJYCHG.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-BPJATXCC.js";
3
+ } from "./chunk-MITJYCHG.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.42.0",
3
+ "version": "4.43.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",
@@ -61,21 +61,21 @@
61
61
  "tsup": "^8.5.1",
62
62
  "tsx": "^4.19.0",
63
63
  "@ainyc/canonry-api-routes": "0.0.0",
64
- "@ainyc/canonry-config": "0.0.0",
65
64
  "@ainyc/canonry-contracts": "0.0.0",
66
65
  "@ainyc/canonry-intelligence": "0.0.0",
67
- "@ainyc/canonry-integration-bing": "0.0.0",
66
+ "@ainyc/canonry-config": "0.0.0",
68
67
  "@ainyc/canonry-db": "0.0.0",
69
68
  "@ainyc/canonry-integration-cloud-run": "0.0.0",
70
- "@ainyc/canonry-integration-commoncrawl": "0.0.0",
71
- "@ainyc/canonry-integration-wordpress": "0.0.0",
69
+ "@ainyc/canonry-integration-bing": "0.0.0",
72
70
  "@ainyc/canonry-integration-google": "0.0.0",
73
71
  "@ainyc/canonry-integration-traffic": "0.0.0",
72
+ "@ainyc/canonry-integration-wordpress": "0.0.0",
74
73
  "@ainyc/canonry-provider-cdp": "0.0.0",
75
74
  "@ainyc/canonry-provider-claude": "0.0.0",
76
75
  "@ainyc/canonry-provider-gemini": "0.0.0",
77
- "@ainyc/canonry-provider-local": "0.0.0",
76
+ "@ainyc/canonry-integration-commoncrawl": "0.0.0",
78
77
  "@ainyc/canonry-provider-perplexity": "0.0.0",
78
+ "@ainyc/canonry-provider-local": "0.0.0",
79
79
  "@ainyc/canonry-provider-openai": "0.0.0"
80
80
  },
81
81
  "scripts": {