@canonry/canonry 4.134.1 → 4.135.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.
Files changed (25) hide show
  1. package/assets/agent-workspace/skills/canonry/references/canonry-cli.md +20 -3
  2. package/assets/assets/{AuditHistoryPanel-BW7LVMSZ.js → AuditHistoryPanel-BS0dmlrQ.js} +1 -1
  3. package/assets/assets/{BacklinksPage-DU65axM1.js → BacklinksPage-CPpWLVfa.js} +1 -1
  4. package/assets/assets/{ChartPrimitives-CUZJ7nUb.js → ChartPrimitives-Dv--2i87.js} +1 -1
  5. package/assets/assets/{HistoryPage-BswdEXC5.js → HistoryPage-BO4Fv-9q.js} +1 -1
  6. package/assets/assets/{ProjectPage-CttTuKKo.js → ProjectPage-Di_nDqtH.js} +6 -6
  7. package/assets/assets/{RunRow-CBxbfubI.js → RunRow-BE8zdGJ8.js} +1 -1
  8. package/assets/assets/{RunsPage-BQxA05ua.js → RunsPage-CbGanhaz.js} +1 -1
  9. package/assets/assets/{SettingsPage-krEusjc9.js → SettingsPage-odOpsOuf.js} +1 -1
  10. package/assets/assets/{TrafficPage-DMhcA9lg.js → TrafficPage-DK7oc0DK.js} +1 -1
  11. package/assets/assets/{TrafficSourceDetailPage-Dm0Gj0HS.js → TrafficSourceDetailPage-CEFjQVuF.js} +1 -1
  12. package/assets/assets/{arrow-left-_1YaUPbl.js → arrow-left-DgzLEzZB.js} +1 -1
  13. package/assets/assets/{extract-error-message-D4XKG37U.js → extract-error-message-vlMjpZb2.js} +1 -1
  14. package/assets/assets/{index-V1C3c7nO.js → index-BMlTgq7D.js} +53 -53
  15. package/assets/assets/{trash-2-D3LWIGDJ.js → trash-2-DX33Ys-K.js} +1 -1
  16. package/assets/index.html +1 -1
  17. package/dist/{chunk-NWVPRV7A.js → chunk-3PFRVEWP.js} +99 -31
  18. package/dist/{chunk-BSU2MI3Y.js → chunk-PAR6P5H6.js} +1 -1
  19. package/dist/{chunk-CF5WTWXI.js → chunk-PXEEWJRV.js} +50 -20
  20. package/dist/{chunk-DVJGFY3J.js → chunk-TPVMHYHD.js} +45 -71
  21. package/dist/cli.js +18 -25
  22. package/dist/index.js +4 -4
  23. package/dist/{intelligence-service-NO4FJUYD.js → intelligence-service-BMEJ5GFZ.js} +2 -2
  24. package/dist/mcp.js +2 -2
  25. package/package.json +9 -9
@@ -365,7 +365,7 @@ import {
365
365
  wordpressSchemaDeployResultDtoSchema,
366
366
  wordpressSchemaStatusResultDtoSchema,
367
367
  wordpressStatusDtoSchema
368
- } from "./chunk-CF5WTWXI.js";
368
+ } from "./chunk-PXEEWJRV.js";
369
369
 
370
370
  // src/intelligence-service.ts
371
371
  import { eq as eq44, desc as desc21, asc as asc9, and as and35, ne as ne6, or as or10, inArray as inArray15, gte as gte12, lte as lte8 } from "drizzle-orm";
@@ -28725,11 +28725,17 @@ function storedSnapshotProvenance(input) {
28725
28725
  sourceSync
28726
28726
  };
28727
28727
  }
28728
- function historicalCampaignRollups(rows) {
28728
+ function adsAccountToday(timezone, nowIso) {
28729
+ return formatIsoDateInTimeZone(nowIso, timezone ?? "UTC");
28730
+ }
28731
+ function inProgressWindowDate(newestDate, accountToday) {
28732
+ return newestDate !== null && newestDate === accountToday ? accountToday : null;
28733
+ }
28734
+ function historicalCampaignRollups(rows, accountToday) {
28729
28735
  if (rows.length === 0) {
28730
28736
  return {
28731
28737
  status: AdsHistoricalCampaignRollupStatuses.unavailable,
28732
- window: { from: null, to: null },
28738
+ window: { from: null, to: null, inProgressDate: null },
28733
28739
  totals: null
28734
28740
  };
28735
28741
  }
@@ -28749,7 +28755,7 @@ function historicalCampaignRollups(rows) {
28749
28755
  }
28750
28756
  return {
28751
28757
  status: AdsHistoricalCampaignRollupStatuses.reported,
28752
- window: { from: fromDate, to: toDate },
28758
+ window: { from: fromDate, to: toDate, inProgressDate: inProgressWindowDate(toDate, accountToday) },
28753
28759
  totals: {
28754
28760
  impressions,
28755
28761
  clicks,
@@ -30506,6 +30512,8 @@ async function adsRoutes(app, opts) {
30506
30512
  if (from) conditions.push(gte8(adsInsightsDaily.date, from));
30507
30513
  if (to) conditions.push(lte6(adsInsightsDaily.date, to));
30508
30514
  const rows = app.db.select().from(adsInsightsDaily).where(and22(...conditions)).orderBy(asc6(adsInsightsDaily.date)).all();
30515
+ const conn = app.db.select().from(adsConnections).where(eq28(adsConnections.projectId, project.id)).get();
30516
+ const accountToday = adsAccountToday(conn?.timezone, (/* @__PURE__ */ new Date()).toISOString());
30509
30517
  const dtoRows = rows.map((row) => ({
30510
30518
  level: row.level,
30511
30519
  entityId: row.entityId,
@@ -30515,9 +30523,9 @@ async function adsRoutes(app, opts) {
30515
30523
  spendMicros: row.spendMicros,
30516
30524
  conversions: row.conversions,
30517
30525
  ctr: adsCtr(row.clicks, row.impressions),
30518
- cpcMicros: adsCpcMicros(row.spendMicros, row.clicks)
30526
+ cpcMicros: adsCpcMicros(row.spendMicros, row.clicks),
30527
+ inProgress: row.date === accountToday
30519
30528
  }));
30520
- const conn = app.db.select().from(adsConnections).where(eq28(adsConnections.projectId, project.id)).get();
30521
30529
  const response = { rows: dtoRows, currencyCode: conn?.currencyCode ?? null };
30522
30530
  return response;
30523
30531
  });
@@ -30547,7 +30555,7 @@ async function adsRoutes(app, opts) {
30547
30555
  sourceSync,
30548
30556
  latestAdsSync
30549
30557
  });
30550
- const rollups = historicalCampaignRollups(app.db.select({
30558
+ const rollupRows = app.db.select({
30551
30559
  date: adsInsightsDaily.date,
30552
30560
  impressions: adsInsightsDaily.impressions,
30553
30561
  clicks: adsInsightsDaily.clicks,
@@ -30556,7 +30564,11 @@ async function adsRoutes(app, opts) {
30556
30564
  }).from(adsInsightsDaily).where(and22(
30557
30565
  eq28(adsInsightsDaily.projectId, project.id),
30558
30566
  eq28(adsInsightsDaily.level, AdsInsightLevels.campaign)
30559
- )).all());
30567
+ )).all();
30568
+ const rollups = historicalCampaignRollups(
30569
+ rollupRows,
30570
+ adsAccountToday(connection?.timezone, (/* @__PURE__ */ new Date()).toISOString())
30571
+ );
30560
30572
  const adsByGroup = /* @__PURE__ */ new Map();
30561
30573
  for (const ad of adRows) {
30562
30574
  const list = adsByGroup.get(ad.adGroupId) ?? [];
@@ -30862,7 +30874,9 @@ async function adsRoutes(app, opts) {
30862
30874
  maxReaderCalls: ADS_LIVE_MAX_READER_CALLS,
30863
30875
  readerCalls,
30864
30876
  maxPagesPerReaderCall: liveDeliveryMaxPagesPerReaderCall,
30865
- maxUpstreamHttpRequests: ADS_LIVE_MAX_READER_CALLS * liveDeliveryMaxPagesPerReaderCall,
30877
+ // The +1 is the single-page in-progress-day request an insight
30878
+ // reader call makes alongside its paginating ranged walk.
30879
+ maxUpstreamHttpRequests: ADS_LIVE_MAX_READER_CALLS * (liveDeliveryMaxPagesPerReaderCall + 1),
30866
30880
  truncated
30867
30881
  },
30868
30882
  entities,
@@ -30906,7 +30920,14 @@ async function adsRoutes(app, opts) {
30906
30920
  campaignCount,
30907
30921
  adGroupCount,
30908
30922
  adCount,
30909
- window: { from: fromDate, to: toDate },
30923
+ window: {
30924
+ from: fromDate,
30925
+ to: toDate,
30926
+ inProgressDate: inProgressWindowDate(
30927
+ toDate,
30928
+ adsAccountToday(row?.timezone, (/* @__PURE__ */ new Date()).toISOString())
30929
+ )
30930
+ },
30910
30931
  totals: {
30911
30932
  impressions,
30912
30933
  clicks,
@@ -31823,7 +31844,7 @@ function normalizeAiTrafficClass(value) {
31823
31844
  return value === AiReferralTrafficClasses.paid ? AiReferralTrafficClasses.paid : AiReferralTrafficClasses.organic;
31824
31845
  }
31825
31846
  function emptyAiCounts() {
31826
- return { sessions: 0, users: 0 };
31847
+ return { sessions: 0 };
31827
31848
  }
31828
31849
  function resolveWinningDimensions(rows) {
31829
31850
  const groups = /* @__PURE__ */ new Map();
@@ -31860,37 +31881,6 @@ function resolveWinningDimensions(rows) {
31860
31881
  }
31861
31882
  return winners;
31862
31883
  }
31863
- function resolveLegacyWinningUsers(rows) {
31864
- const groups = /* @__PURE__ */ new Map();
31865
- for (const row of rows) {
31866
- const key = `${row.date}\0${row.source}\0${row.medium}`;
31867
- let byDimension = groups.get(key);
31868
- if (!byDimension) {
31869
- byDimension = /* @__PURE__ */ new Map();
31870
- groups.set(key, byDimension);
31871
- }
31872
- let dim = byDimension.get(row.sourceDimension);
31873
- if (!dim) {
31874
- dim = { paidUsers: 0, organicUsers: 0 };
31875
- byDimension.set(row.sourceDimension, dim);
31876
- }
31877
- const users = row.users ?? 0;
31878
- if (normalizeAiTrafficClass(row.trafficClass) === AiReferralTrafficClasses.paid) {
31879
- dim.paidUsers += users;
31880
- } else {
31881
- dim.organicUsers += users;
31882
- }
31883
- }
31884
- let paidUsers = 0;
31885
- let organicUsers = 0;
31886
- for (const byDimension of groups.values()) {
31887
- const dims = [...byDimension.values()];
31888
- const best = dims.reduce((winner, d) => d.paidUsers + d.organicUsers > winner.paidUsers + winner.organicUsers ? d : winner);
31889
- paidUsers += best.paidUsers;
31890
- organicUsers += best.organicUsers;
31891
- }
31892
- return { paidUsers, organicUsers };
31893
- }
31894
31884
  function summarizeAiReferralCounts(rows) {
31895
31885
  const paidDeduped = emptyAiCounts();
31896
31886
  const organicDeduped = emptyAiCounts();
@@ -31901,20 +31891,15 @@ function summarizeAiReferralCounts(rows) {
31901
31891
  paidDeduped.sessions += winner.paidSessions;
31902
31892
  organicDeduped.sessions += winner.organicSessions;
31903
31893
  }
31904
- const legacyUsers = resolveLegacyWinningUsers(rows);
31905
- paidDeduped.users = legacyUsers.paidUsers;
31906
- organicDeduped.users = legacyUsers.organicUsers;
31907
31894
  for (const row of rows) {
31908
31895
  if (row.sourceDimension !== "session") continue;
31909
31896
  const sessions = row.sessions ?? 0;
31910
- const users = row.users ?? 0;
31911
31897
  bySessionChannelGroup.set(
31912
31898
  row.channelGroup,
31913
31899
  (bySessionChannelGroup.get(row.channelGroup) ?? 0) + sessions
31914
31900
  );
31915
31901
  const bucket = normalizeAiTrafficClass(row.trafficClass) === AiReferralTrafficClasses.paid ? paidBySession : organicBySession;
31916
31902
  bucket.sessions += sessions;
31917
- bucket.users += users;
31918
31903
  }
31919
31904
  return {
31920
31905
  paidDeduped,
@@ -31922,14 +31907,8 @@ function summarizeAiReferralCounts(rows) {
31922
31907
  paidBySession,
31923
31908
  organicBySession,
31924
31909
  bySessionChannelGroup,
31925
- deduped: {
31926
- sessions: paidDeduped.sessions + organicDeduped.sessions,
31927
- users: paidDeduped.users + organicDeduped.users
31928
- },
31929
- bySession: {
31930
- sessions: paidBySession.sessions + organicBySession.sessions,
31931
- users: paidBySession.users + organicBySession.users
31932
- }
31910
+ deduped: { sessions: paidDeduped.sessions + organicDeduped.sessions },
31911
+ bySession: { sessions: paidBySession.sessions + organicBySession.sessions }
31933
31912
  };
31934
31913
  }
31935
31914
  function buildAiReferralDailySeries(rows) {
@@ -32690,8 +32669,7 @@ async function ga4Routes(app, opts) {
32690
32669
  medium: gaAiReferrals.medium,
32691
32670
  trafficClass: gaAiReferrals.trafficClass,
32692
32671
  sourceDimension: gaAiReferrals.sourceDimension,
32693
- sessions: sql15`SUM(${gaAiReferrals.sessions})`,
32694
- users: sql15`SUM(${gaAiReferrals.users})`
32672
+ sessions: sql15`SUM(${gaAiReferrals.sessions})`
32695
32673
  }).from(gaAiReferrals).where(and25(...aiConditions)).groupBy(gaAiReferrals.source, gaAiReferrals.medium, gaAiReferrals.trafficClass, gaAiReferrals.sourceDimension).all();
32696
32674
  const aiReferralLandingPageRows = app.db.select({
32697
32675
  source: gaAiReferrals.source,
@@ -32699,8 +32677,7 @@ async function ga4Routes(app, opts) {
32699
32677
  trafficClass: gaAiReferrals.trafficClass,
32700
32678
  sourceDimension: gaAiReferrals.sourceDimension,
32701
32679
  landingPage: sql15`COALESCE(${gaAiReferrals.landingPageNormalized}, ${gaAiReferrals.landingPage})`,
32702
- sessions: sql15`SUM(${gaAiReferrals.sessions})`,
32703
- users: sql15`SUM(${gaAiReferrals.users})`
32680
+ sessions: sql15`SUM(${gaAiReferrals.sessions})`
32704
32681
  }).from(gaAiReferrals).where(and25(...aiConditions)).groupBy(
32705
32682
  gaAiReferrals.source,
32706
32683
  gaAiReferrals.medium,
@@ -32715,8 +32692,7 @@ async function ga4Routes(app, opts) {
32715
32692
  trafficClass: gaAiReferrals.trafficClass,
32716
32693
  sourceDimension: gaAiReferrals.sourceDimension,
32717
32694
  channelGroup: gaAiReferrals.channelGroup,
32718
- sessions: gaAiReferrals.sessions,
32719
- users: gaAiReferrals.users
32695
+ sessions: gaAiReferrals.sessions
32720
32696
  }).from(gaAiReferrals).where(and25(...aiConditions)).all();
32721
32697
  const aiReferrals = pickWinningDimension(
32722
32698
  aiReferralRows,
@@ -32762,13 +32738,18 @@ async function ga4Routes(app, opts) {
32762
32738
  directSessions: r.directSessions ?? 0,
32763
32739
  users: r.users ?? 0
32764
32740
  })),
32741
+ // No `users` on either referral row type, and no `ai*Users*` totals: GA
32742
+ // reports users as a COUNT DISTINCT at the grain requested, so summing
32743
+ // the stored column across landing pages (and, for these rows, across
32744
+ // every date in the window) counted one visitor once per row. Withdrawn
32745
+ // in 4.135.0; see `ga-ai-referral-aggregation.ts` for why no correct
32746
+ // figure can be computed or fetched.
32765
32747
  aiReferrals: aiReferrals.map((r) => ({
32766
32748
  source: r.source,
32767
32749
  medium: r.medium,
32768
32750
  trafficClass: normalizeAiTrafficClass(r.trafficClass),
32769
32751
  sourceDimension: r.sourceDimension,
32770
- sessions: r.sessions ?? 0,
32771
- users: r.users ?? 0
32752
+ sessions: r.sessions ?? 0
32772
32753
  })),
32773
32754
  aiReferralLandingPages: aiReferralLandingPages.map((r) => ({
32774
32755
  source: r.source,
@@ -32776,21 +32757,14 @@ async function ga4Routes(app, opts) {
32776
32757
  trafficClass: normalizeAiTrafficClass(r.trafficClass),
32777
32758
  sourceDimension: r.sourceDimension,
32778
32759
  landingPage: r.landingPage,
32779
- sessions: r.sessions ?? 0,
32780
- users: r.users ?? 0
32760
+ sessions: r.sessions ?? 0
32781
32761
  })),
32782
32762
  aiSessionsDeduped: aiSummary.deduped.sessions,
32783
- aiUsersDeduped: aiSummary.deduped.users,
32784
32763
  paidAiSessionsDeduped: aiSummary.paidDeduped.sessions,
32785
- paidAiUsersDeduped: aiSummary.paidDeduped.users,
32786
32764
  organicAiSessionsDeduped: aiSummary.organicDeduped.sessions,
32787
- organicAiUsersDeduped: aiSummary.organicDeduped.users,
32788
32765
  aiSessionsBySession: aiSummary.bySession.sessions,
32789
- aiUsersBySession: aiSummary.bySession.users,
32790
32766
  paidAiSessionsBySession: aiSummary.paidBySession.sessions,
32791
- paidAiUsersBySession: aiSummary.paidBySession.users,
32792
32767
  organicAiSessionsBySession: aiSummary.organicBySession.sessions,
32793
- organicAiUsersBySession: aiSummary.organicBySession.users,
32794
32768
  socialReferrals: socialReferrals.map((r) => ({
32795
32769
  source: r.source,
32796
32770
  medium: r.medium,
package/dist/cli.js CHANGED
@@ -29,7 +29,7 @@ import {
29
29
  setTelemetrySource,
30
30
  showFirstRunNotice,
31
31
  trackEvent
32
- } from "./chunk-NWVPRV7A.js";
32
+ } from "./chunk-3PFRVEWP.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-BSU2MI3Y.js";
49
+ } from "./chunk-PAR6P5H6.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-DVJGFY3J.js";
57
+ } from "./chunk-TPVMHYHD.js";
58
58
  import {
59
59
  AdsDeliverySnapshotStatuses,
60
60
  AdsHistoricalCampaignRollupStatuses,
@@ -100,7 +100,7 @@ import {
100
100
  providerQuotaPolicySchema,
101
101
  resolveProviderInput,
102
102
  winnabilityClassSchema
103
- } from "./chunk-CF5WTWXI.js";
103
+ } from "./chunk-PXEEWJRV.js";
104
104
 
105
105
  // src/cli.ts
106
106
  import { pathToFileURL } from "url";
@@ -3012,6 +3012,9 @@ function readRequest(inputPath, schema) {
3012
3012
  });
3013
3013
  }
3014
3014
  }
3015
+ function partialDayNote(inProgressDate) {
3016
+ return inProgressDate === null ? "" : ` (${inProgressDate} still filling)`;
3017
+ }
3015
3018
  function printOperationDetails(operation) {
3016
3019
  console.log(`Operation: ${operation.operationKey}`);
3017
3020
  if (operation.entityId) console.log(`Entity: ${operation.entityType ?? "unknown"} ${operation.entityId}`);
@@ -3366,8 +3369,9 @@ async function adsInsights(project, opts) {
3366
3369
  console.log("DATE LEVEL ENTITY IMPR CLICKS SPEND CPC");
3367
3370
  for (const row of result.rows) {
3368
3371
  const cpc = row.cpcMicros != null ? formatMicros(row.cpcMicros, currency) : "\u2014";
3372
+ const partial = row.inProgress ? " (still filling)" : "";
3369
3373
  console.log(
3370
- `${row.date} ${row.level.padEnd(9)} ${row.entityId.padEnd(36).slice(0, 36)} ${String(row.impressions).padStart(6)} ${String(row.clicks).padStart(6)} ${formatMicros(row.spendMicros, currency).padStart(9)} ${cpc}`
3374
+ `${row.date} ${row.level.padEnd(9)} ${row.entityId.padEnd(36).slice(0, 36)} ${String(row.impressions).padStart(6)} ${String(row.clicks).padStart(6)} ${formatMicros(row.spendMicros, currency).padStart(9)} ${cpc}${partial}`
3371
3375
  );
3372
3376
  }
3373
3377
  }
@@ -3384,7 +3388,7 @@ async function adsSummary(project, opts) {
3384
3388
  }
3385
3389
  console.log(`Account: ${result.displayName ?? "unknown"} (${result.currencyCode ?? "?"})`);
3386
3390
  console.log(`Structure: ${result.campaignCount} campaigns / ${result.adGroupCount} ad groups / ${result.adCount} ads`);
3387
- console.log(`Window: ${result.window.from ?? "\u2014"} \u2192 ${result.window.to ?? "\u2014"}`);
3391
+ console.log(`Window: ${result.window.from ?? "\u2014"} \u2192 ${result.window.to ?? "\u2014"}${partialDayNote(result.window.inProgressDate)}`);
3388
3392
  console.log(`Impressions: ${result.totals.impressions}`);
3389
3393
  console.log(`Clicks: ${result.totals.clicks}${result.totals.ctr != null ? ` (CTR ${(result.totals.ctr * 100).toFixed(2)}%)` : ""}`);
3390
3394
  console.log(`Spend: ${formatMicros(result.totals.spendMicros, result.currencyCode ?? "USD")}${result.totals.cpcMicros != null ? ` (CPC ${formatMicros(result.totals.cpcMicros, result.currencyCode ?? "USD")})` : ""}`);
@@ -3402,7 +3406,8 @@ async function adsDeliveryDiagnostics(project, opts) {
3402
3406
  console.log(`Last synced: ${result.snapshot.lastSyncedAt ?? "never"}`);
3403
3407
  console.log(`Activity: ${result.assessment.state}`);
3404
3408
  if (result.historicalCampaignRollups.status === AdsHistoricalCampaignRollupStatuses.reported && result.historicalCampaignRollups.totals !== null) {
3405
- console.log(`Historical: ${result.historicalCampaignRollups.totals.impressions} impressions / ${result.historicalCampaignRollups.totals.clicks} clicks (${result.historicalCampaignRollups.window.from} \u2192 ${result.historicalCampaignRollups.window.to})`);
3409
+ const rollupWindow = result.historicalCampaignRollups.window;
3410
+ console.log(`Historical: ${result.historicalCampaignRollups.totals.impressions} impressions / ${result.historicalCampaignRollups.totals.clicks} clicks (${rollupWindow.from} \u2192 ${rollupWindow.to})${partialDayNote(rollupWindow.inProgressDate)}`);
3406
3411
  } else {
3407
3412
  console.log("Historical: no stored campaign rollups");
3408
3413
  }
@@ -3982,13 +3987,13 @@ async function gaTraffic(project, opts) {
3982
3987
  const attrWidth = 12;
3983
3988
  const classWidth = 8;
3984
3989
  console.log(" AI REFERRAL SOURCES");
3985
- console.log(` ${"SOURCE".padEnd(25)} ${"MEDIUM".padEnd(15)} ${"CLASS".padEnd(classWidth)} ${"ATTRIBUTION".padEnd(attrWidth)} ${"SESSIONS".padEnd(10)}${"USERS".padEnd(8)}`);
3986
- console.log(` ${"\u2500".repeat(25)} ${"\u2500".repeat(15)} ${"\u2500".repeat(classWidth)} ${"\u2500".repeat(attrWidth)} ${"\u2500".repeat(10)}${"\u2500".repeat(8)}`);
3990
+ console.log(` ${"SOURCE".padEnd(25)} ${"MEDIUM".padEnd(15)} ${"CLASS".padEnd(classWidth)} ${"ATTRIBUTION".padEnd(attrWidth)} ${"SESSIONS".padEnd(10)}`);
3991
+ console.log(` ${"\u2500".repeat(25)} ${"\u2500".repeat(15)} ${"\u2500".repeat(classWidth)} ${"\u2500".repeat(attrWidth)} ${"\u2500".repeat(10)}`);
3987
3992
  for (const ref of result.aiReferrals) {
3988
3993
  const dimLabel = ref.sourceDimension === "first_user" ? "first-visit" : ref.sourceDimension === "manual_utm" ? "utm" : "session";
3989
3994
  const classLabel = ref.trafficClass === "paid" ? "paid" : "organic";
3990
3995
  console.log(
3991
- ` ${ref.source.padEnd(25)} ${ref.medium.padEnd(15)} ${classLabel.padEnd(classWidth)} ${dimLabel.padEnd(attrWidth)} ${String(ref.sessions).padEnd(10)}${String(ref.users).padEnd(8)}`
3996
+ ` ${ref.source.padEnd(25)} ${ref.medium.padEnd(15)} ${classLabel.padEnd(classWidth)} ${dimLabel.padEnd(attrWidth)} ${String(ref.sessions).padEnd(10)}`
3992
3997
  );
3993
3998
  }
3994
3999
  console.log();
@@ -3996,14 +4001,14 @@ async function gaTraffic(project, opts) {
3996
4001
  if (result.aiReferralLandingPages.length > 0) {
3997
4002
  const attrWidth = 12;
3998
4003
  console.log(" AI REFERRAL LANDING PAGES");
3999
- console.log(` ${"LANDING PAGE".padEnd(30)} ${"SOURCE".padEnd(25)} ${"ATTRIBUTION".padEnd(attrWidth)} ${"SESSIONS".padEnd(10)}${"USERS".padEnd(8)}`);
4000
- console.log(` ${"\u2500".repeat(30)} ${"\u2500".repeat(25)} ${"\u2500".repeat(attrWidth)} ${"\u2500".repeat(10)}${"\u2500".repeat(8)}`);
4004
+ console.log(` ${"LANDING PAGE".padEnd(30)} ${"SOURCE".padEnd(25)} ${"ATTRIBUTION".padEnd(attrWidth)} ${"SESSIONS".padEnd(10)}`);
4005
+ console.log(` ${"\u2500".repeat(30)} ${"\u2500".repeat(25)} ${"\u2500".repeat(attrWidth)} ${"\u2500".repeat(10)}`);
4001
4006
  for (const row of result.aiReferralLandingPages) {
4002
4007
  const dimLabel = row.sourceDimension === "first_user" ? "first-visit" : row.sourceDimension === "manual_utm" ? "utm" : "session";
4003
4008
  const page = row.landingPage.length > 30 ? row.landingPage.slice(0, 27) + "..." : row.landingPage;
4004
4009
  const source = row.source.length > 25 ? row.source.slice(0, 22) + "..." : row.source;
4005
4010
  console.log(
4006
- ` ${page.padEnd(30)} ${source.padEnd(25)} ${dimLabel.padEnd(attrWidth)} ${String(row.sessions).padEnd(10)}${String(row.users).padEnd(8)}`
4011
+ ` ${page.padEnd(30)} ${source.padEnd(25)} ${dimLabel.padEnd(attrWidth)} ${String(row.sessions).padEnd(10)}`
4007
4012
  );
4008
4013
  }
4009
4014
  console.log();
@@ -4299,17 +4304,11 @@ async function gaAttribution(project, opts) {
4299
4304
  totalUsers: traffic.totalUsers,
4300
4305
  organicSessions: traffic.totalOrganicSessions,
4301
4306
  aiSessions: traffic.aiSessionsDeduped,
4302
- aiUsers: traffic.aiUsersDeduped,
4303
4307
  paidAiSessions: traffic.paidAiSessionsDeduped,
4304
- paidAiUsers: traffic.paidAiUsersDeduped,
4305
4308
  organicAiSessions: traffic.organicAiSessionsDeduped,
4306
- organicAiUsers: traffic.organicAiUsersDeduped,
4307
4309
  aiSessionsBySession: traffic.aiSessionsBySession,
4308
- aiUsersBySession: traffic.aiUsersBySession,
4309
4310
  paidAiSessionsBySession: traffic.paidAiSessionsBySession,
4310
- paidAiUsersBySession: traffic.paidAiUsersBySession,
4311
4311
  organicAiSessionsBySession: traffic.organicAiSessionsBySession,
4312
- organicAiUsersBySession: traffic.organicAiUsersBySession,
4313
4312
  socialSessions: traffic.socialSessions,
4314
4313
  socialUsers: traffic.socialUsers,
4315
4314
  directSessions: traffic.totalDirectSessions,
@@ -4386,17 +4385,11 @@ async function gaAttribution(project, opts) {
4386
4385
  totalUsers: traffic.totalUsers,
4387
4386
  organicSessions: traffic.totalOrganicSessions,
4388
4387
  aiSessions: traffic.aiSessionsDeduped,
4389
- aiUsers: traffic.aiUsersDeduped,
4390
4388
  paidAiSessions: traffic.paidAiSessionsDeduped,
4391
- paidAiUsers: traffic.paidAiUsersDeduped,
4392
4389
  organicAiSessions: traffic.organicAiSessionsDeduped,
4393
- organicAiUsers: traffic.organicAiUsersDeduped,
4394
4390
  aiSessionsBySession: traffic.aiSessionsBySession,
4395
- aiUsersBySession: traffic.aiUsersBySession,
4396
4391
  paidAiSessionsBySession: traffic.paidAiSessionsBySession,
4397
- paidAiUsersBySession: traffic.paidAiUsersBySession,
4398
4392
  organicAiSessionsBySession: traffic.organicAiSessionsBySession,
4399
- organicAiUsersBySession: traffic.organicAiUsersBySession,
4400
4393
  socialSessions: traffic.socialSessions,
4401
4394
  socialUsers: traffic.socialUsers,
4402
4395
  directSessions: traffic.totalDirectSessions,
package/dist/index.js CHANGED
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  createServer
3
- } from "./chunk-NWVPRV7A.js";
3
+ } from "./chunk-3PFRVEWP.js";
4
4
  import {
5
5
  loadConfig
6
- } from "./chunk-BSU2MI3Y.js";
7
- import "./chunk-DVJGFY3J.js";
8
- import "./chunk-CF5WTWXI.js";
6
+ } from "./chunk-PAR6P5H6.js";
7
+ import "./chunk-TPVMHYHD.js";
8
+ import "./chunk-PXEEWJRV.js";
9
9
  export {
10
10
  createServer,
11
11
  loadConfig
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  IntelligenceService
3
- } from "./chunk-DVJGFY3J.js";
4
- import "./chunk-CF5WTWXI.js";
3
+ } from "./chunk-TPVMHYHD.js";
4
+ import "./chunk-PXEEWJRV.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-BSU2MI3Y.js";
6
+ } from "./chunk-PAR6P5H6.js";
7
7
  import {
8
8
  isReadOnlyKey
9
- } from "./chunk-CF5WTWXI.js";
9
+ } from "./chunk-PXEEWJRV.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": "@canonry/canonry",
3
- "version": "4.134.1",
3
+ "version": "4.135.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,26 +65,26 @@
65
65
  "@types/node-cron": "^3.0.11",
66
66
  "tsup": "^8.5.1",
67
67
  "tsx": "^4.19.0",
68
+ "@ainyc/canonry-config": "0.0.0",
68
69
  "@ainyc/canonry-api-client": "0.0.0",
70
+ "@ainyc/canonry-contracts": "0.0.0",
69
71
  "@ainyc/canonry-api-routes": "0.0.0",
70
- "@ainyc/canonry-config": "0.0.0",
71
72
  "@ainyc/canonry-db": "0.0.0",
72
- "@ainyc/canonry-contracts": "0.0.0",
73
73
  "@ainyc/canonry-integration-bing": "0.0.0",
74
- "@ainyc/canonry-integration-commoncrawl": "0.0.0",
75
- "@ainyc/canonry-integration-openai-ads": "0.0.0",
76
- "@ainyc/canonry-integration-google-places": "0.0.0",
77
74
  "@ainyc/canonry-integration-cloud-run": "0.0.0",
75
+ "@ainyc/canonry-integration-openai-ads": "0.0.0",
76
+ "@ainyc/canonry-integration-commoncrawl": "0.0.0",
78
77
  "@ainyc/canonry-integration-google": "0.0.0",
79
78
  "@ainyc/canonry-integration-google-business-profile": "0.0.0",
80
- "@ainyc/canonry-integration-traffic": "0.0.0",
79
+ "@ainyc/canonry-integration-wordpress": "0.0.0",
80
+ "@ainyc/canonry-integration-google-places": "0.0.0",
81
81
  "@ainyc/canonry-intelligence": "0.0.0",
82
82
  "@ainyc/canonry-provider-cdp": "0.0.0",
83
- "@ainyc/canonry-provider-gemini": "0.0.0",
84
83
  "@ainyc/canonry-provider-claude": "0.0.0",
85
- "@ainyc/canonry-integration-wordpress": "0.0.0",
84
+ "@ainyc/canonry-provider-gemini": "0.0.0",
86
85
  "@ainyc/canonry-provider-openai": "0.0.0",
87
86
  "@ainyc/canonry-provider-local": "0.0.0",
87
+ "@ainyc/canonry-integration-traffic": "0.0.0",
88
88
  "@ainyc/canonry-provider-perplexity": "0.0.0"
89
89
  },
90
90
  "scripts": {