@canonry/canonry 4.178.3 → 4.179.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 (28) hide show
  1. package/assets/assets/{AuditHistoryPanel-BCtMrEMF.js → AuditHistoryPanel-lD6Q5KaA.js} +1 -1
  2. package/assets/assets/{BacklinksPage-CIo2hA0i.js → BacklinksPage-ClN1xbOa.js} +1 -1
  3. package/assets/assets/{ChartPrimitives-B_LDVvTy.js → ChartPrimitives-DG35TyhH.js} +1 -1
  4. package/assets/assets/{HistoryPage-D24U8cUG.js → HistoryPage-CXKCPfG7.js} +1 -1
  5. package/assets/assets/{MeasurementPropertyPage-BKDdv-jJ.js → MeasurementPropertyPage-CiJsa0If.js} +1 -1
  6. package/assets/assets/ProjectPage-CD0QbHPd.js +9 -0
  7. package/assets/assets/{RunRow-B39IK7hK.js → RunRow-DkFcHvDU.js} +1 -1
  8. package/assets/assets/{RunsPage-R4W1kD0B.js → RunsPage-CLzUDwTj.js} +1 -1
  9. package/assets/assets/{SettingsPage-BAOGyt1F.js → SettingsPage-0PRgB0gI.js} +1 -1
  10. package/assets/assets/{SiteHealthSection-Bx7yVNMQ.js → SiteHealthSection-BXAMjVeD.js} +3 -3
  11. package/assets/assets/{TrafficPage-DL8RvM2R.js → TrafficPage-CP4qsn82.js} +1 -1
  12. package/assets/assets/{TrafficSourceDetailPage-COzjakZa.js → TrafficSourceDetailPage-DoaIZ_ix.js} +1 -1
  13. package/assets/assets/{extract-error-message-B3TERCQ-.js → extract-error-message-Cn74-t3z.js} +1 -1
  14. package/assets/assets/{index-D0GbiVhZ.css → index-BD8hYPvq.css} +1 -1
  15. package/assets/assets/{index-xtxQtZRo.js → index-BR9BgNb3.js} +22 -22
  16. package/assets/assets/{react-sigma_core.esm.min-CbXAujub.js → react-sigma_core.esm.min-CZrBq6qL.js} +1 -1
  17. package/assets/index.html +2 -2
  18. package/dist/{chunk-BNYDRPKC.js → chunk-A2AB7UK5.js} +40 -3
  19. package/dist/{chunk-GHO4574A.js → chunk-JFGP2U52.js} +8 -47
  20. package/dist/{chunk-2ZWW62T3.js → chunk-RDCTWBPF.js} +134 -46
  21. package/dist/{chunk-2UKCBT7D.js → chunk-T7QWSNIE.js} +1 -1
  22. package/dist/{chunk-XLVNLY2I.js → chunk-ZCNQGO3J.js} +2 -2
  23. package/dist/cli.js +5 -5
  24. package/dist/index.js +4 -4
  25. package/dist/{intelligence-service-LSQGK34A.js → intelligence-service-VBLTZGHS.js} +2 -2
  26. package/dist/mcp.js +3 -3
  27. package/package.json +14 -14
  28. package/assets/assets/ProjectPage-DrIs_ZuR.js +0 -9
@@ -113,6 +113,7 @@ import {
113
113
  TrafficEventConfidences,
114
114
  TrafficEventKinds,
115
115
  TrafficEvidenceKinds,
116
+ TrafficPathClasses,
116
117
  TrafficSeriesGranularities,
117
118
  TrafficSourceAuthModes,
118
119
  TrafficSourceStatuses,
@@ -638,10 +639,10 @@ import {
638
639
  wordpressSchemaDeployResultDtoSchema,
639
640
  wordpressSchemaStatusResultDtoSchema,
640
641
  wordpressStatusDtoSchema
641
- } from "./chunk-BNYDRPKC.js";
642
+ } from "./chunk-A2AB7UK5.js";
642
643
 
643
644
  // src/intelligence-service.ts
644
- import { eq as eq62, desc as desc27, asc as asc11, and as and51, ne as ne8, or as or14, inArray as inArray21, gte as gte14, lte as lte12, isNull as isNull9, sql as sql25, exists } from "drizzle-orm";
645
+ import { eq as eq62, desc as desc27, asc as asc11, and as and51, ne as ne8, or as or14, inArray as inArray22, gte as gte14, lte as lte12, isNull as isNull9, sql as sql25, exists } from "drizzle-orm";
645
646
 
646
647
  // ../db/src/client.ts
647
648
  import { mkdirSync } from "fs";
@@ -52687,7 +52688,7 @@ import crypto43 from "crypto";
52687
52688
  import { isIP } from "net";
52688
52689
  import { isDeepStrictEqual } from "util";
52689
52690
  import { Agent as UndiciAgent } from "undici";
52690
- import { and as and44, desc as desc23, eq as eq51, gte as gte11, lte as lte11, sql as sql22 } from "drizzle-orm";
52691
+ import { and as and44, desc as desc23, eq as eq51, gte as gte11, inArray as inArray18, lte as lte11, sql as sql22 } from "drizzle-orm";
52691
52692
 
52692
52693
  // ../api-routes/src/cloudflare-worker-version.ts
52693
52694
  var CURRENT_CLOUDFLARE_WORKER_VERSION = "1.0.1";
@@ -69817,7 +69818,7 @@ function assertCloudflareIngestUrlOutsideWorkerRoute(ingestUrl, workerRouteHost)
69817
69818
  }
69818
69819
  }
69819
69820
  function emptyTrafficSeriesPoint(bucket) {
69820
- return { bucket, crawlerHits: 0, aiUserFetchHits: 0, aiReferralHits: 0, aiReferralLandedHits: 0 };
69821
+ return { bucket, crawlerHits: 0, aiUserFetchHits: 0, aiReferralHits: 0, aiReferralLandedHits: 0, crawlerContentHits: 0, measured: true };
69821
69822
  }
69822
69823
  function completeTrafficSeries(windowStart, windowEnd, granularity, pointsByBucket) {
69823
69824
  const cursor = new Date(windowStart);
@@ -72467,6 +72468,11 @@ async function trafficRoutes(app, opts) {
72467
72468
  const project = resolveProject(app.db, request.params.name);
72468
72469
  const now = /* @__PURE__ */ new Date();
72469
72470
  const defaultSince = new Date(now.getTime() - 24 * 60 * 6e4);
72471
+ if (request.query?.sinceMinutes !== void 0) {
72472
+ throw validationError(
72473
+ '"sinceMinutes" is not a query parameter on this route. Use "since" (and optionally "until") with an ISO-8601 timestamp.'
72474
+ );
72475
+ }
72470
72476
  const sinceParam = request.query?.since;
72471
72477
  const untilParam = request.query?.until;
72472
72478
  const since = sinceParam ? new Date(sinceParam) : defaultSince;
@@ -72540,12 +72546,43 @@ async function trafficRoutes(app, opts) {
72540
72546
  crawlerTotal = crawlerSegments.content + crawlerSegments.sitemap + crawlerSegments.robots + crawlerSegments.asset + crawlerSegments.other;
72541
72547
  totalEventRows += pathTotals.reduce((sum, row) => sum + Number(row.rows), 0);
72542
72548
  const crawlerSeriesBucket = granularity === TrafficSeriesGranularities.day ? sql22`substr(${crawlerEventsHourly.tsHour}, 1, 10)` : crawlerEventsHourly.tsHour;
72543
- const crawlerSeries = app.db.select({
72544
- bucket: crawlerSeriesBucket,
72545
- hits: sql22`COALESCE(SUM(${crawlerEventsHourly.hits}), 0)`
72546
- }).from(crawlerEventsHourly).where(crawlerWhere).groupBy(crawlerSeriesBucket).all();
72547
- for (const row of crawlerSeries) {
72548
- trafficSeriesPoint(seriesByBucket, row.bucket).crawlerHits = Number(row.hits);
72549
+ const distinctPaths = pathTotals.map((r) => ({ pathNormalized: r.pathNormalized }));
72550
+ const contentPaths = [];
72551
+ const infraPaths = [];
72552
+ for (const { pathNormalized } of distinctPaths) {
72553
+ if (classifyTrafficPath(pathNormalized) === TrafficPathClasses.content) contentPaths.push(pathNormalized);
72554
+ else infraPaths.push(pathNormalized);
72555
+ }
72556
+ const useContentList = contentPaths.length <= infraPaths.length;
72557
+ const listed = useContentList ? contentPaths : infraPaths;
72558
+ const IN_LIST_CAP = 2e4;
72559
+ const listFitsInSql = listed.length <= IN_LIST_CAP;
72560
+ const contentExpr = listed.length === 0 ? useContentList ? sql22`0` : sql22`${crawlerEventsHourly.hits}` : useContentList ? sql22`CASE WHEN ${inArray18(crawlerEventsHourly.pathNormalized, listed)} THEN ${crawlerEventsHourly.hits} ELSE 0 END` : sql22`CASE WHEN ${inArray18(crawlerEventsHourly.pathNormalized, listed)} THEN 0 ELSE ${crawlerEventsHourly.hits} END`;
72561
+ if (listFitsInSql) {
72562
+ const crawlerSeries = app.db.select({
72563
+ bucket: crawlerSeriesBucket,
72564
+ hits: sql22`COALESCE(SUM(${crawlerEventsHourly.hits}), 0)`,
72565
+ content: sql22`COALESCE(SUM(${contentExpr}), 0)`
72566
+ }).from(crawlerEventsHourly).where(crawlerWhere).groupBy(crawlerSeriesBucket).all();
72567
+ for (const row of crawlerSeries) {
72568
+ const point = trafficSeriesPoint(seriesByBucket, String(row.bucket));
72569
+ point.crawlerHits = Number(row.hits);
72570
+ point.crawlerContentHits = Number(row.content);
72571
+ }
72572
+ } else {
72573
+ const contentSet = new Set(useContentList ? contentPaths : infraPaths);
72574
+ const grouped = app.db.select({
72575
+ bucket: crawlerSeriesBucket,
72576
+ pathNormalized: crawlerEventsHourly.pathNormalized,
72577
+ hits: sql22`COALESCE(SUM(${crawlerEventsHourly.hits}), 0)`
72578
+ }).from(crawlerEventsHourly).where(crawlerWhere).groupBy(crawlerSeriesBucket, crawlerEventsHourly.pathNormalized).all();
72579
+ for (const row of grouped) {
72580
+ const point = trafficSeriesPoint(seriesByBucket, String(row.bucket));
72581
+ const hits = Number(row.hits);
72582
+ point.crawlerHits += hits;
72583
+ const inList = contentSet.has(row.pathNormalized);
72584
+ if (useContentList ? inList : !inList) point.crawlerContentHits += hits;
72585
+ }
72549
72586
  }
72550
72587
  const rows = app.db.select().from(crawlerEventsHourly).where(crawlerWhere).orderBy(desc23(crawlerEventsHourly.tsHour)).limit(limit).all();
72551
72588
  for (const r of rows) {
@@ -72684,10 +72721,61 @@ async function trafficRoutes(app, opts) {
72684
72721
  const response = {
72685
72722
  windowStart: sinceIso,
72686
72723
  windowEnd: untilIso,
72687
- series: {
72688
- granularity,
72689
- points: completeTrafficSeries(since, until, granularity, seriesByBucket)
72690
- },
72724
+ series: (() => {
72725
+ const points = completeTrafficSeries(since, until, granularity, seriesByBucket);
72726
+ const coverageScope = (col, srcCol) => sourceIdParam ? and44(eq51(col, project.id), eq51(srcCol, sourceIdParam)) : eq51(col, project.id);
72727
+ const firsts = [
72728
+ app.db.select({ v: sql22`MIN(${crawlerEventsHourly.tsHour})` }).from(crawlerEventsHourly).where(coverageScope(crawlerEventsHourly.projectId, crawlerEventsHourly.sourceId)).get()?.v,
72729
+ app.db.select({ v: sql22`MIN(${aiUserFetchEventsHourly.tsHour})` }).from(aiUserFetchEventsHourly).where(coverageScope(aiUserFetchEventsHourly.projectId, aiUserFetchEventsHourly.sourceId)).get()?.v,
72730
+ app.db.select({ v: sql22`MIN(${aiReferralEventsHourly.tsHour})` }).from(aiReferralEventsHourly).where(coverageScope(aiReferralEventsHourly.projectId, aiReferralEventsHourly.sourceId)).get()?.v
72731
+ ].filter((v) => typeof v === "string" && v.length > 0);
72732
+ const coverageStart = firsts.length ? firsts.slice().sort()[0] : null;
72733
+ const bucketStartMs = (bucket) => Date.parse(
72734
+ granularity === TrafficSeriesGranularities.day ? `${bucket}T00:00:00.000Z` : bucket
72735
+ );
72736
+ const bucketMs = granularity === TrafficSeriesGranularities.day ? 864e5 : 36e5;
72737
+ const lastBucket = points.length ? points[points.length - 1].bucket : null;
72738
+ const lastBucketStartMs = lastBucket === null ? null : bucketStartMs(lastBucket);
72739
+ const trailingBucketIsPartial = lastBucketStartMs !== null && Number.isFinite(lastBucketStartMs) && until.getTime() < lastBucketStartMs + bucketMs;
72740
+ const coverageKey = coverageStart === null ? null : granularity === TrafficSeriesGranularities.day ? coverageStart.slice(0, 10) : coverageStart.slice(0, 13);
72741
+ for (const pt of points) {
72742
+ pt.measured = coverageKey === null ? false : (granularity === TrafficSeriesGranularities.day ? pt.bucket.slice(0, 10) : pt.bucket.slice(0, 13)) >= coverageKey;
72743
+ }
72744
+ const firstMeasuredIdx = points.findIndex((pt) => pt.measured);
72745
+ const coverageStartMs = coverageStart === null ? null : Date.parse(coverageStart);
72746
+ const leadingBucketIsPartial = firstMeasuredIdx >= 0 && coverageStartMs !== null && Number.isFinite(coverageStartMs) && coverageStartMs > bucketStartMs(points[firstMeasuredIdx].bucket);
72747
+ return {
72748
+ granularity,
72749
+ points,
72750
+ coverageStart,
72751
+ // Two edges are excluded from the fit, both for the same reason: a
72752
+ // bucket that is not a full reading must not be treated as one.
72753
+ //
72754
+ // Leading: unmeasured buckets predate recording, so they are the
72755
+ // ABSENCE of a reading, not a reading of zero. The first MEASURED
72756
+ // bucket goes too when recording began inside it, since a fraction of
72757
+ // a bucket read as a whole one slopes the fit up out of nothing.
72758
+ //
72759
+ // Trailing: `until` defaults to now, so the newest bucket holds only
72760
+ // the elapsed fraction of the current period. A site flat at 500/day
72761
+ // read at 02:00 UTC gives [...500, 500, 40] and the fit returns a
72762
+ // confident decline for a site that is not declining. Same class of
72763
+ // error as the leading edge, and the one the leading guard alone
72764
+ // would have left in place.
72765
+ //
72766
+ // linearTrend skips nulls while surviving points keep their true
72767
+ // index, so dropping an edge does not compress the x-axis.
72768
+ trends: (() => {
72769
+ const usable = (pt, i) => pt.measured && !(i === firstMeasuredIdx && leadingBucketIsPartial) && !(i === points.length - 1 && trailingBucketIsPartial);
72770
+ const series = (pick) => linearTrend(points.map((pt, i) => usable(pt, i) ? pick(pt) : null));
72771
+ return {
72772
+ crawlerContentHits: series((pt) => pt.crawlerContentHits),
72773
+ aiUserFetchHits: series((pt) => pt.aiUserFetchHits),
72774
+ aiReferralLandedHits: series((pt) => pt.aiReferralLandedHits)
72775
+ };
72776
+ })()
72777
+ };
72778
+ })(),
72691
72779
  totals: {
72692
72780
  crawlerHits: crawlerTotal,
72693
72781
  crawlerContentHits: crawlerSegments.content,
@@ -74445,7 +74533,7 @@ var RUNTIME_STATE_CHECKS = [
74445
74533
  ];
74446
74534
 
74447
74535
  // ../api-routes/src/doctor/checks/traffic-source.ts
74448
- import { and as and47, eq as eq57, gte as gte12, inArray as inArray18, ne as ne7, sql as sql23 } from "drizzle-orm";
74536
+ import { and as and47, eq as eq57, gte as gte12, inArray as inArray19, ne as ne7, sql as sql23 } from "drizzle-orm";
74449
74537
  var RECENT_DATA_WARN_DAYS = 7;
74450
74538
  var RECENT_DATA_FAIL_DAYS = 30;
74451
74539
  function isCloudflareDirectPush(source) {
@@ -74593,7 +74681,7 @@ var recentDataCheck = {
74593
74681
  ctx.db.select({ total: sql23`COALESCE(SUM(${crawlerEventsHourly.hits}), 0)` }).from(crawlerEventsHourly).where(
74594
74682
  and47(
74595
74683
  eq57(crawlerEventsHourly.projectId, ctx.project.id),
74596
- inArray18(crawlerEventsHourly.sourceId, activeSourceIds),
74684
+ inArray19(crawlerEventsHourly.sourceId, activeSourceIds),
74597
74685
  gte12(crawlerEventsHourly.tsHour, warnCutoff)
74598
74686
  )
74599
74687
  ).get()?.total ?? 0
@@ -74602,7 +74690,7 @@ var recentDataCheck = {
74602
74690
  ctx.db.select({ total: sql23`COALESCE(SUM(${aiReferralEventsHourly.sessionsOrHits}), 0)` }).from(aiReferralEventsHourly).where(
74603
74691
  and47(
74604
74692
  eq57(aiReferralEventsHourly.projectId, ctx.project.id),
74605
- inArray18(aiReferralEventsHourly.sourceId, activeSourceIds),
74693
+ inArray19(aiReferralEventsHourly.sourceId, activeSourceIds),
74606
74694
  gte12(aiReferralEventsHourly.tsHour, warnCutoff)
74607
74695
  )
74608
74696
  ).get()?.total ?? 0
@@ -74611,7 +74699,7 @@ var recentDataCheck = {
74611
74699
  ctx.db.select({ total: sql23`COALESCE(SUM(${aiUserFetchEventsHourly.hits}), 0)` }).from(aiUserFetchEventsHourly).where(
74612
74700
  and47(
74613
74701
  eq57(aiUserFetchEventsHourly.projectId, ctx.project.id),
74614
- inArray18(aiUserFetchEventsHourly.sourceId, activeSourceIds),
74702
+ inArray19(aiUserFetchEventsHourly.sourceId, activeSourceIds),
74615
74703
  gte12(aiUserFetchEventsHourly.tsHour, warnCutoff)
74616
74704
  )
74617
74705
  ).get()?.total ?? 0
@@ -74637,7 +74725,7 @@ var recentDataCheck = {
74637
74725
  ctx.db.select({ total: sql23`COALESCE(SUM(${crawlerEventsHourly.hits}), 0)` }).from(crawlerEventsHourly).where(
74638
74726
  and47(
74639
74727
  eq57(crawlerEventsHourly.projectId, ctx.project.id),
74640
- inArray18(crawlerEventsHourly.sourceId, activeSourceIds),
74728
+ inArray19(crawlerEventsHourly.sourceId, activeSourceIds),
74641
74729
  gte12(crawlerEventsHourly.tsHour, failCutoff)
74642
74730
  )
74643
74731
  ).get()?.total ?? 0
@@ -74646,7 +74734,7 @@ var recentDataCheck = {
74646
74734
  ctx.db.select({ total: sql23`COALESCE(SUM(${aiReferralEventsHourly.sessionsOrHits}), 0)` }).from(aiReferralEventsHourly).where(
74647
74735
  and47(
74648
74736
  eq57(aiReferralEventsHourly.projectId, ctx.project.id),
74649
- inArray18(aiReferralEventsHourly.sourceId, activeSourceIds),
74737
+ inArray19(aiReferralEventsHourly.sourceId, activeSourceIds),
74650
74738
  gte12(aiReferralEventsHourly.tsHour, failCutoff)
74651
74739
  )
74652
74740
  ).get()?.total ?? 0
@@ -74655,7 +74743,7 @@ var recentDataCheck = {
74655
74743
  ctx.db.select({ total: sql23`COALESCE(SUM(${aiUserFetchEventsHourly.hits}), 0)` }).from(aiUserFetchEventsHourly).where(
74656
74744
  and47(
74657
74745
  eq57(aiUserFetchEventsHourly.projectId, ctx.project.id),
74658
- inArray18(aiUserFetchEventsHourly.sourceId, activeSourceIds),
74746
+ inArray19(aiUserFetchEventsHourly.sourceId, activeSourceIds),
74659
74747
  gte12(aiUserFetchEventsHourly.tsHour, failCutoff)
74660
74748
  )
74661
74749
  ).get()?.total ?? 0
@@ -75571,7 +75659,7 @@ async function doctorRoutes(app, opts) {
75571
75659
 
75572
75660
  // ../api-routes/src/discovery/routes.ts
75573
75661
  import crypto45 from "crypto";
75574
- import { and as and48, desc as desc24, eq as eq58, gte as gte13, inArray as inArray19, isNull as isNull7, or as or12 } from "drizzle-orm";
75662
+ import { and as and48, desc as desc24, eq as eq58, gte as gte13, inArray as inArray20, isNull as isNull7, or as or12 } from "drizzle-orm";
75575
75663
  var MAX_INFLIGHT_DISCOVERY_AGE_MS = 2 * 60 * 60 * 1e3;
75576
75664
  async function discoveryRoutes(app, opts) {
75577
75665
  app.post("/projects/:name/discover/run", async (request, reply) => {
@@ -75626,7 +75714,7 @@ async function discoveryRoutes(app, opts) {
75626
75714
  // must never reuse another set's session. Null (= Gemini-only
75627
75715
  // default, including explicit ['gemini']) matches legacy rows.
75628
75716
  seedProviders == null ? isNull7(discoverySessions.seedProviders) : eq58(discoverySessions.seedProviders, seedProviders),
75629
- inArray19(discoverySessions.status, [
75717
+ inArray20(discoverySessions.status, [
75630
75718
  DiscoverySessionStatuses.queued,
75631
75719
  DiscoverySessionStatuses.seeding,
75632
75720
  DiscoverySessionStatuses.probing
@@ -76251,7 +76339,7 @@ function dedupeStrings(input) {
76251
76339
 
76252
76340
  // ../api-routes/src/technical-aeo.ts
76253
76341
  import crypto47 from "crypto";
76254
- import { and as and49, asc as asc10, count, desc as desc25, eq as eq60, inArray as inArray20, isNotNull as isNotNull3, isNull as isNull8, lt as lt11, or as or13, sql as sql24 } from "drizzle-orm";
76342
+ import { and as and49, asc as asc10, count, desc as desc25, eq as eq60, inArray as inArray21, isNotNull as isNotNull3, isNull as isNull8, lt as lt11, or as or13, sql as sql24 } from "drizzle-orm";
76255
76343
  import { alias } from "drizzle-orm/sqlite-core";
76256
76344
  var FETCHED_SITE_CRAWL_STATES = /* @__PURE__ */ new Set([
76257
76345
  ...SiteCrawlFetchedStates,
@@ -76573,7 +76661,7 @@ async function technicalAeoRoutes(app, opts) {
76573
76661
  eq60(siteCrawlSnapshots.projectId, projectId),
76574
76662
  eq60(runs.projectId, projectId),
76575
76663
  eq60(runs.kind, RunKinds["site-audit"]),
76576
- inArray20(runs.status, SURFACEABLE_STATUSES),
76664
+ inArray21(runs.status, SURFACEABLE_STATUSES),
76577
76665
  notProbeRun()
76578
76666
  ];
76579
76667
  if (runId) {
@@ -76603,7 +76691,7 @@ async function technicalAeoRoutes(app, opts) {
76603
76691
  eq60(runs.id, runId),
76604
76692
  eq60(runs.projectId, projectId),
76605
76693
  eq60(runs.kind, RunKinds["site-audit"]),
76606
- inArray20(runs.status, SURFACEABLE_STATUSES),
76694
+ inArray21(runs.status, SURFACEABLE_STATUSES),
76607
76695
  notProbeRun()
76608
76696
  )).limit(1).get());
76609
76697
  const assertKnownAuditRun = (projectId, runId) => {
@@ -76613,7 +76701,7 @@ async function technicalAeoRoutes(app, opts) {
76613
76701
  eq60(siteAuditSnapshots.projectId, projectId),
76614
76702
  eq60(runs.projectId, projectId),
76615
76703
  eq60(runs.kind, RunKinds["site-audit"]),
76616
- inArray20(runs.status, SURFACEABLE_STATUSES),
76704
+ inArray21(runs.status, SURFACEABLE_STATUSES),
76617
76705
  notProbeRun()
76618
76706
  )).limit(1).get());
76619
76707
  const emptyCrawlSummary = (projectName, legacyAuditAvailable) => ({
@@ -76637,7 +76725,7 @@ async function technicalAeoRoutes(app, opts) {
76637
76725
  eq60(siteAuditSnapshots.projectId, project.id),
76638
76726
  eq60(runs.projectId, project.id),
76639
76727
  eq60(runs.kind, RunKinds["site-audit"]),
76640
- inArray20(runs.status, SURFACEABLE_STATUSES),
76728
+ inArray21(runs.status, SURFACEABLE_STATUSES),
76641
76729
  notProbeRun()
76642
76730
  ];
76643
76731
  const targetFilters = request.query.runId ? [...baseFilters, eq60(siteAuditSnapshots.runId, request.query.runId)] : baseFilters;
@@ -76677,7 +76765,7 @@ async function technicalAeoRoutes(app, opts) {
76677
76765
  eq60(siteAuditSnapshots.projectId, project.id),
76678
76766
  eq60(runs.projectId, project.id),
76679
76767
  eq60(runs.kind, RunKinds["site-audit"]),
76680
- inArray20(runs.status, SURFACEABLE_STATUSES),
76768
+ inArray21(runs.status, SURFACEABLE_STATUSES),
76681
76769
  notProbeRun()
76682
76770
  ];
76683
76771
  if (request.query.runId) targetFilters.push(eq60(siteAuditSnapshots.runId, request.query.runId));
@@ -76719,7 +76807,7 @@ async function technicalAeoRoutes(app, opts) {
76719
76807
  eq60(siteAuditSnapshots.projectId, project.id),
76720
76808
  eq60(runs.projectId, project.id),
76721
76809
  eq60(runs.kind, RunKinds["site-audit"]),
76722
- inArray20(runs.status, SURFACEABLE_STATUSES),
76810
+ inArray21(runs.status, SURFACEABLE_STATUSES),
76723
76811
  notProbeRun()
76724
76812
  )).orderBy(desc25(siteAuditSnapshots.createdAt)).limit(limit).all();
76725
76813
  return { project: project.name, points: rows.reverse() };
@@ -77022,8 +77110,8 @@ async function technicalAeoRoutes(app, opts) {
77022
77110
  eq60(siteCrawlEdges.internal, true),
77023
77111
  isNotNull3(siteCrawlEdges.targetNodeKey),
77024
77112
  or13(
77025
- inArray20(siteCrawlEdges.sourceNodeKey, frontier),
77026
- inArray20(siteCrawlEdges.targetNodeKey, frontier)
77113
+ inArray21(siteCrawlEdges.sourceNodeKey, frontier),
77114
+ inArray21(siteCrawlEdges.targetNodeKey, frontier)
77027
77115
  )
77028
77116
  )).orderBy(asc10(siteCrawlEdges.edgeKey)).limit(maxEdges + maxNodes + 1).all();
77029
77117
  if (candidates.length > maxEdges + maxNodes) queryTruncated = true;
@@ -77060,7 +77148,7 @@ async function technicalAeoRoutes(app, opts) {
77060
77148
  eq60(siteCrawlPages.projectId, scope.projectId),
77061
77149
  eq60(siteCrawlPages.runId, scope.runId),
77062
77150
  eq60(siteCrawlPages.attemptId, scope.attemptId),
77063
- inArray20(siteCrawlPages.nodeKey, nodeKeys)
77151
+ inArray21(siteCrawlPages.nodeKey, nodeKeys)
77064
77152
  )).all();
77065
77153
  const persistedNodeKeys = new Set(pageRows.map((row) => row.nodeKey));
77066
77154
  const outermostNodeKeys = pageRows.filter((row) => distances.get(row.nodeKey) === hops).map((row) => row.nodeKey);
@@ -77070,8 +77158,8 @@ async function technicalAeoRoutes(app, opts) {
77070
77158
  eq60(siteCrawlEdges.attemptId, scope.attemptId),
77071
77159
  eq60(siteCrawlEdges.internal, true),
77072
77160
  isNotNull3(siteCrawlEdges.targetNodeKey),
77073
- inArray20(siteCrawlEdges.sourceNodeKey, outermostNodeKeys),
77074
- inArray20(siteCrawlEdges.targetNodeKey, outermostNodeKeys)
77161
+ inArray21(siteCrawlEdges.sourceNodeKey, outermostNodeKeys),
77162
+ inArray21(siteCrawlEdges.targetNodeKey, outermostNodeKeys)
77075
77163
  )).limit(1).get();
77076
77164
  if (omittedOutermostEdge && !seenEdgeKeys.has(omittedOutermostEdge.edgeKey)) {
77077
77165
  omittedEdgeKeys.add(omittedOutermostEdge.edgeKey);
@@ -77174,7 +77262,7 @@ async function technicalAeoRoutes(app, opts) {
77174
77262
  eq60(siteCrawlEdges.followable, true),
77175
77263
  eq60(siteCrawlEdges.relation, "anchor"),
77176
77264
  isNotNull3(siteCrawlEdges.targetNodeKey),
77177
- inArray20(siteCrawlEdges.sourceNodeKey, frontier)
77265
+ inArray21(siteCrawlEdges.sourceNodeKey, frontier)
77178
77266
  )).orderBy(asc10(siteCrawlEdges.edgeKey)).limit(SITE_HEALTH_PATH_MAX_VISITED_NODES + 1).all();
77179
77267
  if (candidates.length > SITE_HEALTH_PATH_MAX_VISITED_NODES) truncated = true;
77180
77268
  const candidateTargetKeys = [...new Set(candidates.map((edge) => edge.targetNodeKey).filter((nodeKey) => nodeKey != null))];
@@ -77182,7 +77270,7 @@ async function technicalAeoRoutes(app, opts) {
77182
77270
  eq60(siteCrawlPages.projectId, scope.projectId),
77183
77271
  eq60(siteCrawlPages.runId, scope.runId),
77184
77272
  eq60(siteCrawlPages.attemptId, scope.attemptId),
77185
- inArray20(siteCrawlPages.nodeKey, candidateTargetKeys)
77273
+ inArray21(siteCrawlPages.nodeKey, candidateTargetKeys)
77186
77274
  )).all().map((row) => row.nodeKey));
77187
77275
  const next = /* @__PURE__ */ new Set();
77188
77276
  for (const edge of candidates.slice(0, SITE_HEALTH_PATH_MAX_VISITED_NODES)) {
@@ -77228,7 +77316,7 @@ async function technicalAeoRoutes(app, opts) {
77228
77316
  eq60(siteCrawlPages.projectId, scope.projectId),
77229
77317
  eq60(siteCrawlPages.runId, scope.runId),
77230
77318
  eq60(siteCrawlPages.attemptId, scope.attemptId),
77231
- inArray20(siteCrawlPages.nodeKey, pathKeys)
77319
+ inArray21(siteCrawlPages.nodeKey, pathKeys)
77232
77320
  )).all();
77233
77321
  const pageByKey = new Map(pathRows.map((row) => [row.nodeKey, row]));
77234
77322
  const pathDetection = templateDetectionOf(snapshot.templateDetection);
@@ -77510,14 +77598,14 @@ async function technicalAeoRoutes(app, opts) {
77510
77598
  eq60(siteCrawlPages.projectId, scope.projectId),
77511
77599
  eq60(siteCrawlPages.runId, scope.runId),
77512
77600
  eq60(siteCrawlPages.attemptId, scope.attemptId),
77513
- inArray20(siteCrawlPages.nodeKey, pageKeys)
77601
+ inArray21(siteCrawlPages.nodeKey, pageKeys)
77514
77602
  )).all();
77515
77603
  const edgeRowsFor = (scope) => linkKeys.length === 0 ? [] : app.db.select().from(siteCrawlEdges).where(and49(
77516
77604
  eq60(siteCrawlEdges.projectId, scope.projectId),
77517
77605
  eq60(siteCrawlEdges.runId, scope.runId),
77518
77606
  eq60(siteCrawlEdges.attemptId, scope.attemptId),
77519
77607
  eq60(siteCrawlEdges.internal, true),
77520
- inArray20(siteCrawlEdges.edgeKey, linkKeys)
77608
+ inArray21(siteCrawlEdges.edgeKey, linkKeys)
77521
77609
  )).all();
77522
77610
  const beforePages = new Map(pageRowsFor(beforeScope).map((row) => [row.nodeKey, mapCrawlPage(row)]));
77523
77611
  const afterPages = new Map(pageRowsFor(afterScope).map((row) => [row.nodeKey, mapCrawlPage(row)]));
@@ -77965,9 +78053,9 @@ async function technicalAeoRoutes(app, opts) {
77965
78053
  eq60(siteCrawlSnapshots.projectId, project.id),
77966
78054
  eq60(runs.projectId, project.id),
77967
78055
  eq60(runs.kind, RunKinds["site-audit"]),
77968
- inArray20(runs.status, SURFACEABLE_STATUSES),
78056
+ inArray21(runs.status, SURFACEABLE_STATUSES),
77969
78057
  notProbeRun(),
77970
- inArray20(siteCrawlSnapshots.runId, runIds)
78058
+ inArray21(siteCrawlSnapshots.runId, runIds)
77971
78059
  )).all().map((row) => row.runId));
77972
78060
  return {
77973
78061
  project: project.name,
@@ -78107,7 +78195,7 @@ async function technicalAeoRoutes(app, opts) {
78107
78195
  )).where(and49(
78108
78196
  eq60(runs.projectId, project.id),
78109
78197
  eq60(runs.kind, RunKinds["site-audit"]),
78110
- inArray20(runs.status, [RunStatuses.queued, RunStatuses.running])
78198
+ inArray21(runs.status, [RunStatuses.queued, RunStatuses.running])
78111
78199
  )).get();
78112
78200
  if (existing) {
78113
78201
  if (existing.identityKey === identityKey) {
@@ -79311,7 +79399,7 @@ var IntelligenceService = class {
79311
79399
  let wouldDeleteTotal = 0;
79312
79400
  const existingByRunId = /* @__PURE__ */ new Map();
79313
79401
  if (isDryRun && targetRuns.length > 0) {
79314
- const rows = this.db.select({ runId: insights.runId }).from(insights).where(inArray21(insights.runId, targetRuns.map((r) => r.id))).all();
79402
+ const rows = this.db.select({ runId: insights.runId }).from(insights).where(inArray22(insights.runId, targetRuns.map((r) => r.id))).all();
79315
79403
  for (const r of rows) {
79316
79404
  if (r.runId == null) continue;
79317
79405
  existingByRunId.set(r.runId, (existingByRunId.get(r.runId) ?? 0) + 1);
@@ -79366,7 +79454,7 @@ var IntelligenceService = class {
79366
79454
  */
79367
79455
  runIdsWithSnapshots(runIds) {
79368
79456
  if (runIds.length === 0) return /* @__PURE__ */ new Set();
79369
- const rows = this.db.select({ runId: querySnapshots.runId }).from(querySnapshots).where(inArray21(querySnapshots.runId, [...runIds])).groupBy(querySnapshots.runId).all();
79457
+ const rows = this.db.select({ runId: querySnapshots.runId }).from(querySnapshots).where(inArray22(querySnapshots.runId, [...runIds])).groupBy(querySnapshots.runId).all();
79370
79458
  return new Set(rows.map((r) => r.runId));
79371
79459
  }
79372
79460
  /**
@@ -79486,7 +79574,7 @@ var IntelligenceService = class {
79486
79574
  const haveHistory = recentRunIds.length > 0;
79487
79575
  const priorRegressionsByPair = /* @__PURE__ */ new Map();
79488
79576
  if (haveHistory) {
79489
- const priorRows = this.db.select({ query: insights.query, provider: insights.provider, runId: insights.runId }).from(insights).where(and51(eq62(insights.type, "regression"), inArray21(insights.runId, recentRunIds))).all();
79577
+ const priorRows = this.db.select({ query: insights.query, provider: insights.provider, runId: insights.runId }).from(insights).where(and51(eq62(insights.type, "regression"), inArray22(insights.runId, recentRunIds))).all();
79490
79578
  const regressionGroups = /* @__PURE__ */ new Map();
79491
79579
  for (const row of priorRows) {
79492
79580
  if (!row.runId) continue;
@@ -92,7 +92,7 @@ import {
92
92
  trafficConnectWordpressRequestSchema,
93
93
  trafficEventKindSchema,
94
94
  trafficSeriesGranularitySchema
95
- } from "./chunk-BNYDRPKC.js";
95
+ } from "./chunk-A2AB7UK5.js";
96
96
 
97
97
  // src/config.ts
98
98
  import fs from "fs";
@@ -5,11 +5,11 @@ import {
5
5
  installSkills,
6
6
  loadConfigRaw,
7
7
  saveConfigPatch
8
- } from "./chunk-2UKCBT7D.js";
8
+ } from "./chunk-T7QWSNIE.js";
9
9
  import {
10
10
  SKILL_MANIFEST_FILENAME,
11
11
  SkillsClients
12
- } from "./chunk-BNYDRPKC.js";
12
+ } from "./chunk-A2AB7UK5.js";
13
13
 
14
14
  // src/skills-autosync.ts
15
15
  import fs from "fs";
package/dist/cli.js CHANGED
@@ -26,11 +26,11 @@ import {
26
26
  showFirstRunNotice,
27
27
  trackCliCommandFinished,
28
28
  trackEvent
29
- } from "./chunk-GHO4574A.js";
29
+ } from "./chunk-JFGP2U52.js";
30
30
  import {
31
31
  autoSyncSkills,
32
32
  formatAutoSyncNotice
33
- } from "./chunk-XLVNLY2I.js";
33
+ } from "./chunk-ZCNQGO3J.js";
34
34
  import {
35
35
  CliError,
36
36
  EXIT_SYSTEM_ERROR,
@@ -55,7 +55,7 @@ import {
55
55
  saveConfigPatch,
56
56
  systemError,
57
57
  usageError
58
- } from "./chunk-2UKCBT7D.js";
58
+ } from "./chunk-T7QWSNIE.js";
59
59
  import {
60
60
  CLOUDFLARE_WORKER_BINDINGS,
61
61
  CLOUDFLARE_WORKER_GENERATED_MARKER,
@@ -69,7 +69,7 @@ import {
69
69
  projects,
70
70
  queries,
71
71
  renderReportHtml
72
- } from "./chunk-2ZWW62T3.js";
72
+ } from "./chunk-RDCTWBPF.js";
73
73
  import {
74
74
  AdsDeliverySnapshotStatuses,
75
75
  AdsHistoricalCampaignRollupStatuses,
@@ -138,7 +138,7 @@ import {
138
138
  providerQuotaPolicySchema,
139
139
  resolveProviderInput,
140
140
  winnabilityClassSchema
141
- } from "./chunk-BNYDRPKC.js";
141
+ } from "./chunk-A2AB7UK5.js";
142
142
 
143
143
  // src/cli.ts
144
144
  import { pathToFileURL } from "url";
package/dist/index.js CHANGED
@@ -3,12 +3,12 @@ import {
3
3
  createGoogleMarketingCredentialStore,
4
4
  createGoogleMarketingRuntime,
5
5
  createServer
6
- } from "./chunk-GHO4574A.js";
6
+ } from "./chunk-JFGP2U52.js";
7
7
  import {
8
8
  loadConfig
9
- } from "./chunk-2UKCBT7D.js";
10
- import "./chunk-2ZWW62T3.js";
11
- import "./chunk-BNYDRPKC.js";
9
+ } from "./chunk-T7QWSNIE.js";
10
+ import "./chunk-RDCTWBPF.js";
11
+ import "./chunk-A2AB7UK5.js";
12
12
  export {
13
13
  GoogleMarketingRuntimeError,
14
14
  createGoogleMarketingCredentialStore,
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  IntelligenceService
3
- } from "./chunk-2ZWW62T3.js";
4
- import "./chunk-BNYDRPKC.js";
3
+ } from "./chunk-RDCTWBPF.js";
4
+ import "./chunk-A2AB7UK5.js";
5
5
  export {
6
6
  IntelligenceService
7
7
  };
package/dist/mcp.js CHANGED
@@ -1,13 +1,13 @@
1
1
  import {
2
2
  autoSyncSkills
3
- } from "./chunk-XLVNLY2I.js";
3
+ } from "./chunk-ZCNQGO3J.js";
4
4
  import {
5
5
  createApiClient,
6
6
  createCanonryMcpServer
7
- } from "./chunk-2UKCBT7D.js";
7
+ } from "./chunk-T7QWSNIE.js";
8
8
  import {
9
9
  isReadOnlyKey
10
- } from "./chunk-BNYDRPKC.js";
10
+ } from "./chunk-A2AB7UK5.js";
11
11
 
12
12
  // src/mcp/cli.ts
13
13
  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.178.3",
3
+ "version": "4.179.0",
4
4
  "type": "module",
5
5
  "description": "Self-hosted AI visibility (AEO) platform: track how ChatGPT, Claude, Gemini, and Perplexity cite your domain, join it with Search Console, GA4, server-side traffic, and paid media, and fix what you find through agent tools (CLI, REST, MCP). Local SQLite.",
6
6
  "license": "FSL-1.1-ALv2",
@@ -41,7 +41,7 @@
41
41
  },
42
42
  "dependencies": {
43
43
  "@anthropic-ai/sdk": "^0.91.1",
44
- "@canonry/aeo-audit": "4.7.0",
44
+ "@canonry/aeo-audit": "7.1.0",
45
45
  "@fastify/rate-limit": "^11.2.0",
46
46
  "@fastify/static": "^9.1.1",
47
47
  "@google/genai": "^1.46.0",
@@ -70,31 +70,31 @@
70
70
  "@types/node-cron": "^3.0.11",
71
71
  "tsup": "^8.5.1",
72
72
  "tsx": "^4.19.0",
73
- "@ainyc/canonry-config": "0.0.0",
74
- "@ainyc/canonry-api-routes": "0.0.0",
75
- "@ainyc/canonry-db": "0.0.0",
76
- "@ainyc/canonry-contracts": "0.0.0",
77
73
  "@ainyc/canonry-api-client": "0.0.0",
78
- "@ainyc/canonry-integration-cloud-run": "0.0.0",
74
+ "@ainyc/canonry-api-routes": "0.0.0",
75
+ "@ainyc/canonry-config": "0.0.0",
79
76
  "@ainyc/canonry-integration-bing": "0.0.0",
77
+ "@ainyc/canonry-contracts": "0.0.0",
78
+ "@ainyc/canonry-db": "0.0.0",
80
79
  "@ainyc/canonry-integration-cloudflare-queue": "0.0.0",
80
+ "@ainyc/canonry-integration-cloud-run": "0.0.0",
81
81
  "@ainyc/canonry-integration-commoncrawl": "0.0.0",
82
- "@ainyc/canonry-integration-google": "0.0.0",
83
82
  "@ainyc/canonry-integration-cloudflare-worker": "0.0.0",
83
+ "@ainyc/canonry-integration-google": "0.0.0",
84
84
  "@ainyc/canonry-integration-google-ads": "0.0.0",
85
- "@ainyc/canonry-integration-google-places": "0.0.0",
85
+ "@ainyc/canonry-integration-google-business-profile": "0.0.0",
86
86
  "@ainyc/canonry-integration-google-tag-manager": "0.0.0",
87
+ "@ainyc/canonry-integration-google-places": "0.0.0",
87
88
  "@ainyc/canonry-integration-openai-ads": "0.0.0",
88
- "@ainyc/canonry-integration-google-business-profile": "0.0.0",
89
- "@ainyc/canonry-integration-traffic": "0.0.0",
90
89
  "@ainyc/canonry-integration-wordpress": "0.0.0",
91
90
  "@ainyc/canonry-intelligence": "0.0.0",
91
+ "@ainyc/canonry-integration-traffic": "0.0.0",
92
92
  "@ainyc/canonry-provider-cdp": "0.0.0",
93
- "@ainyc/canonry-provider-gemini": "0.0.0",
94
93
  "@ainyc/canonry-provider-claude": "0.0.0",
94
+ "@ainyc/canonry-provider-gemini": "0.0.0",
95
95
  "@ainyc/canonry-provider-local": "0.0.0",
96
- "@ainyc/canonry-provider-openai": "0.0.0",
97
- "@ainyc/canonry-provider-perplexity": "0.0.0"
96
+ "@ainyc/canonry-provider-perplexity": "0.0.0",
97
+ "@ainyc/canonry-provider-openai": "0.0.0"
98
98
  },
99
99
  "scripts": {
100
100
  "build": "tsx scripts/copy-agent-assets.ts && tsup && tsx build-web.ts",