@canonry/canonry 7.87.1 → 7.87.2

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 (33) hide show
  1. package/assets/agent-workspace/skills/aero/references/ai-traffic-tracking.md +6 -1
  2. package/assets/agent-workspace/skills/canonry/references/ai-traffic-tracking.md +6 -1
  3. package/assets/agent-workspace/skills/canonry/references/canonry-cli.md +3 -0
  4. package/assets/agent-workspace/skills/canonry/references/server-side-traffic.md +17 -5
  5. package/dist/{backfill-PNHBAV5N.js → backfill-6AYHWEQX.js} +5 -5
  6. package/dist/{bootstrap-AZYQXBHN.js → bootstrap-27NOBWTP.js} +1 -1
  7. package/dist/{chunk-J7ITGXCS.js → chunk-3FHBPJ5R.js} +2 -2
  8. package/dist/{chunk-W7DHXSXN.js → chunk-AI75KS7G.js} +2163 -2073
  9. package/dist/{chunk-O26FQ7RI.js → chunk-AYYZ4HKJ.js} +30 -0
  10. package/dist/{chunk-RHOIR5QY.js → chunk-BVJA3TV2.js} +3 -3
  11. package/dist/{chunk-CR54BCUP.js → chunk-IE4D47JE.js} +4 -4
  12. package/dist/{chunk-BKZ6PQAE.js → chunk-IVGVPPQT.js} +8 -8
  13. package/dist/{chunk-UXSWQAVZ.js → chunk-LYTBHEID.js} +31 -31
  14. package/dist/{chunk-VDYXB6SV.js → chunk-POMLL2OZ.js} +83 -12
  15. package/dist/{chunk-ECZGTJIQ.js → chunk-T2MGGW6Y.js} +2 -2
  16. package/dist/{chunk-RSPOFH66.js → chunk-TFB2S6TQ.js} +1 -1
  17. package/dist/{chunk-2I22IUA3.js → chunk-ZCNKGBIV.js} +2 -2
  18. package/dist/{chunk-G44S34CE.js → chunk-ZJVQ72VC.js} +1 -1
  19. package/dist/{cli-commands-62QECRBV.js → cli-commands-H7BFVUGC.js} +1 -1
  20. package/dist/cli.js +2 -2
  21. package/dist/{dashboard-4HOXCUQE.js → dashboard-KT2ACPI5.js} +3 -3
  22. package/dist/{demo-IY7Y7KR3.js → demo-LWSLULEZ.js} +1 -1
  23. package/dist/{demo-server-BLLSDILQ.js → demo-server-UENMDVMG.js} +5 -5
  24. package/dist/index.d.ts +202 -67
  25. package/dist/index.js +9 -9
  26. package/dist/{init-JY76QAOC.js → init-TF3OPCEC.js} +2 -2
  27. package/dist/{intelligence-service-GJYBEHJE.js → intelligence-service-LEH5UVIC.js} +4 -4
  28. package/dist/{serve-ZQXMTDE7.js → serve-LLIUILD2.js} +10 -10
  29. package/dist/{session-MGOUDLXN.js → session-2NQKSF2N.js} +5 -5
  30. package/dist/{src-SJYGA7NH.js → src-JQYZ2TP6.js} +3 -1
  31. package/dist/{tools-ZWFLE5UR.js → tools-UPJRW4DN.js} +4 -4
  32. package/dist/{traffic-B7Q4WPOV.js → traffic-GWBZKYR5.js} +1 -1
  33. package/package.json +1 -1
@@ -51,6 +51,7 @@ __export(schema_exports, {
51
51
  agentSessions: () => agentSessions,
52
52
  agentToolEvents: () => agentToolEvents,
53
53
  aiReferralEventsHourly: () => aiReferralEventsHourly,
54
+ aiReferralVisitors: () => aiReferralVisitors,
54
55
  aiUserFetchEventsHourly: () => aiUserFetchEventsHourly,
55
56
  aiUserFetchLikelyFakeHourly: () => aiUserFetchLikelyFakeHourly,
56
57
  aiUserFetchVerificationManifestsHourly: () => aiUserFetchVerificationManifestsHourly,
@@ -2786,6 +2787,18 @@ var agentScannerClients = sqliteTable2("agent_scanner_clients", {
2786
2787
  primaryKey2({ columns: [table.projectId, table.sourceId, table.clientKey] }),
2787
2788
  index2("idx_agent_scanner_clients_source_last").on(table.sourceId, table.lastProbeAt)
2788
2789
  ]);
2790
+ var aiReferralVisitors = sqliteTable2("ai_referral_visitors", {
2791
+ projectId: text2("project_id").notNull().references(() => projects.id, { onDelete: "cascade" }),
2792
+ sourceId: text2("source_id").notNull().references(() => trafficSources.id, { onDelete: "cascade" }),
2793
+ visitorKey: text2("visitor_key").notNull(),
2794
+ /** Oldest first, at most 50, none older than the retention window. */
2795
+ arrivals: text2("arrivals", { mode: "json" }).$type().notNull().default([]),
2796
+ lastArrivalAt: text2("last_arrival_at").notNull(),
2797
+ updatedAt: text2("updated_at").notNull()
2798
+ }, (table) => [
2799
+ primaryKey2({ columns: [table.projectId, table.sourceId, table.visitorKey] }),
2800
+ index2("idx_ai_referral_visitors_source_last").on(table.sourceId, table.lastArrivalAt)
2801
+ ]);
2789
2802
  var discoverySessions = sqliteTable2("discovery_sessions", {
2790
2803
  id: text2("id").primaryKey(),
2791
2804
  projectId: text2("project_id").notNull().references(() => projects.id, { onDelete: "cascade" }),
@@ -8609,6 +8622,22 @@ var MIGRATION_VERSIONS = [
8609
8622
  )`,
8610
8623
  `CREATE INDEX IF NOT EXISTS idx_journey_visitor_aliases_visitor ON journey_visitor_aliases(project_id, visitor_key)`
8611
8624
  ]
8625
+ },
8626
+ {
8627
+ version: 207,
8628
+ name: "ai-referral-visitors",
8629
+ statements: [
8630
+ `CREATE TABLE IF NOT EXISTS ai_referral_visitors (
8631
+ project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
8632
+ source_id TEXT NOT NULL REFERENCES traffic_sources(id) ON DELETE CASCADE,
8633
+ visitor_key TEXT NOT NULL,
8634
+ arrivals TEXT NOT NULL DEFAULT '[]',
8635
+ last_arrival_at TEXT NOT NULL,
8636
+ updated_at TEXT NOT NULL,
8637
+ PRIMARY KEY (project_id, source_id, visitor_key)
8638
+ )`,
8639
+ `CREATE INDEX IF NOT EXISTS idx_ai_referral_visitors_source_last ON ai_referral_visitors(source_id, last_arrival_at)`
8640
+ ]
8612
8641
  }
8613
8642
  ];
8614
8643
  var AERO_LEDGER_REBUILDS = [
@@ -10128,6 +10157,7 @@ export {
10128
10157
  agentJourneyEvents,
10129
10158
  agentJourneyCaptureDays,
10130
10159
  agentScannerClients,
10160
+ aiReferralVisitors,
10131
10161
  discoverySessions,
10132
10162
  researchRuns,
10133
10163
  researchRunQueries,
@@ -6,7 +6,7 @@ import {
6
6
  correctBackgroundCallJourneys,
7
7
  mergeSplitJourneyVisitors,
8
8
  writeUnrecognizedAgentBuckets
9
- } from "./chunk-W7DHXSXN.js";
9
+ } from "./chunk-AI75KS7G.js";
10
10
  import {
11
11
  AGENT_TRUST_RULES_VERSION,
12
12
  BROWSER_SHAPED_AGENT_MARKERS,
@@ -23,7 +23,7 @@ import {
23
23
  isSelfTraffic,
24
24
  normalizeTrafficPathPattern,
25
25
  unrecognizedAgentName
26
- } from "./chunk-VDYXB6SV.js";
26
+ } from "./chunk-POMLL2OZ.js";
27
27
  import {
28
28
  RawEventSampleEventTypes,
29
29
  agentJourneyCaptureDays,
@@ -36,7 +36,7 @@ import {
36
36
  rawEventSamples,
37
37
  trafficReclassificationState,
38
38
  unrecognizedAgentEventsHourly
39
- } from "./chunk-O26FQ7RI.js";
39
+ } from "./chunk-AYYZ4HKJ.js";
40
40
  import {
41
41
  AI_ENGINE_DOMAINS,
42
42
  AI_ENGINE_SELF_DOMAINS,
@@ -8,7 +8,7 @@ import {
8
8
  reparseStoredResult4,
9
9
  reparseStoredResult5,
10
10
  resolveStoredApiResponse
11
- } from "./chunk-RHOIR5QY.js";
11
+ } from "./chunk-BVJA3TV2.js";
12
12
  import {
13
13
  loadConfig
14
14
  } from "./chunk-2FJB3CSS.js";
@@ -24,7 +24,7 @@ import {
24
24
  createRunCompetitorResolver,
25
25
  readMarketCompetitorNames,
26
26
  refreshSnapshotMentionIdentity
27
- } from "./chunk-W7DHXSXN.js";
27
+ } from "./chunk-AI75KS7G.js";
28
28
  import {
29
29
  RawEventSampleEventTypes,
30
30
  auditLog,
@@ -38,7 +38,7 @@ import {
38
38
  querySnapshots,
39
39
  rawEventSamples,
40
40
  runs
41
- } from "./chunk-O26FQ7RI.js";
41
+ } from "./chunk-AYYZ4HKJ.js";
42
42
  import {
43
43
  ProviderNames,
44
44
  RetrievalContracts,
@@ -429,7 +429,7 @@ No DB writes performed. Re-run without --dry-run to apply.`);
429
429
  }
430
430
  }
431
431
  async function backfillInsightsCommand(project, opts) {
432
- const { IntelligenceService } = await import("./intelligence-service-GJYBEHJE.js");
432
+ const { IntelligenceService } = await import("./intelligence-service-LEH5UVIC.js");
433
433
  const config = loadConfig();
434
434
  const db = createClient(config.database);
435
435
  migrate(db);
@@ -27,14 +27,14 @@ import {
27
27
  resolveConfiguredAgentProvider,
28
28
  resolveSessionProviderAndModel,
29
29
  setAeroSystemPrompt
30
- } from "./chunk-ECZGTJIQ.js";
30
+ } from "./chunk-T2MGGW6Y.js";
31
31
  import {
32
32
  AeroToolProfiles,
33
33
  AeroToolScopes,
34
34
  buildAeroStateTools,
35
35
  isAeroToolProfile,
36
36
  truncateToolResult
37
- } from "./chunk-RSPOFH66.js";
37
+ } from "./chunk-TFB2S6TQ.js";
38
38
  import {
39
39
  getGoogleAuthConfig,
40
40
  getGoogleConnection,
@@ -65,7 +65,7 @@ import {
65
65
  openrouterAdapter,
66
66
  perplexityAdapter,
67
67
  startTrafficReclassification
68
- } from "./chunk-RHOIR5QY.js";
68
+ } from "./chunk-BVJA3TV2.js";
69
69
  import {
70
70
  classifyUsageSurface,
71
71
  createApiUsageTelemetry,
@@ -149,7 +149,7 @@ import {
149
149
  persistSiteCrawlGraphLayout,
150
150
  prepareSiteCrawlGraphLayout,
151
151
  recordedSharePct
152
- } from "./chunk-G44S34CE.js";
152
+ } from "./chunk-ZJVQ72VC.js";
153
153
  import {
154
154
  CanonryMcpToolNames,
155
155
  canonryMcpTools
@@ -162,7 +162,7 @@ import {
162
162
  } from "./chunk-HGMYEDAQ.js";
163
163
  import {
164
164
  IntelligenceService
165
- } from "./chunk-2I22IUA3.js";
165
+ } from "./chunk-ZCNKGBIV.js";
166
166
  import {
167
167
  computeCitedCompetitorDomains,
168
168
  determineCitationState
@@ -292,7 +292,7 @@ import {
292
292
  webhookResponseReason,
293
293
  webhookTargetRefusalReason,
294
294
  writeAuditLog
295
- } from "./chunk-W7DHXSXN.js";
295
+ } from "./chunk-AI75KS7G.js";
296
296
  import {
297
297
  OperationalLogStore,
298
298
  SentimentIdempotencyConflict,
@@ -380,7 +380,7 @@ import {
380
380
  unrecognizedAgentEventsHourly,
381
381
  unrecognizedAgentNotifyState,
382
382
  usageCounters
383
- } from "./chunk-O26FQ7RI.js";
383
+ } from "./chunk-AYYZ4HKJ.js";
384
384
  import {
385
385
  AGENT_MEMORY_VALUE_MAX_BYTES,
386
386
  AI_ENGINE_DOMAINS,
@@ -5940,7 +5940,7 @@ function nonBlank(value) {
5940
5940
  return trimmed ? trimmed : void 0;
5941
5941
  }
5942
5942
  function resolveBuildCommit(env = process.env) {
5943
- const embedded = true ? "a044e59ea7224007b8c3e85cb1c037f6aff2c6c9" : void 0;
5943
+ const embedded = true ? "3e6b78ab9a0ad676e2df968c5b36d5746d9639cf" : void 0;
5944
5944
  return nonBlank(embedded) ?? nonBlank(env.CANONRY_COMMIT);
5945
5945
  }
5946
5946
  function resolveInstanceIdentity(env = process.env) {
@@ -728,7 +728,7 @@ var DEMO_CLI_COMMANDS = [{
728
728
  options: { host: stringOption(), port: stringOption(), "trust-proxy": multiStringOption() },
729
729
  allowPositionals: false,
730
730
  run: async (input) => {
731
- const { demoCommand } = await import("./demo-IY7Y7KR3.js");
731
+ const { demoCommand } = await import("./demo-LWSLULEZ.js");
732
732
  await demoCommand({
733
733
  host: getString(input.values, "host"),
734
734
  port: getString(input.values, "port"),
@@ -749,7 +749,7 @@ var BACKFILL_CLI_COMMANDS = [
749
749
  allowPositionals: false,
750
750
  supportsDryRun: true,
751
751
  run: async (input) => {
752
- const { backfillAnswerVisibilityCommand } = await import("./backfill-PNHBAV5N.js");
752
+ const { backfillAnswerVisibilityCommand } = await import("./backfill-6AYHWEQX.js");
753
753
  await backfillAnswerVisibilityCommand({
754
754
  project: getString(input.values, "project"),
755
755
  dryRun: input.dryRun,
@@ -766,7 +766,7 @@ var BACKFILL_CLI_COMMANDS = [
766
766
  allowPositionals: false,
767
767
  supportsDryRun: true,
768
768
  run: async (input) => {
769
- const { backfillAnswerMentionsCommand } = await import("./backfill-PNHBAV5N.js");
769
+ const { backfillAnswerMentionsCommand } = await import("./backfill-6AYHWEQX.js");
770
770
  await backfillAnswerMentionsCommand({
771
771
  project: getString(input.values, "project"),
772
772
  dryRun: input.dryRun,
@@ -784,7 +784,7 @@ var BACKFILL_CLI_COMMANDS = [
784
784
  },
785
785
  supportsDryRun: true,
786
786
  run: async (input) => {
787
- const { backfillInsightsCommand } = await import("./backfill-PNHBAV5N.js");
787
+ const { backfillInsightsCommand } = await import("./backfill-6AYHWEQX.js");
788
788
  const usage = "canonry backfill insights <project> [--from-run <id>] [--to-run <id>] [--since <date>] [--dry-run] [--format json]";
789
789
  const project3 = requireProject(input, "backfill insights", usage);
790
790
  await backfillInsightsCommand(project3, {
@@ -804,7 +804,7 @@ var BACKFILL_CLI_COMMANDS = [
804
804
  },
805
805
  allowPositionals: false,
806
806
  run: async (input) => {
807
- const { backfillNormalizedPathsCommand } = await import("./backfill-PNHBAV5N.js");
807
+ const { backfillNormalizedPathsCommand } = await import("./backfill-6AYHWEQX.js");
808
808
  await backfillNormalizedPathsCommand({
809
809
  project: getString(input.values, "project"),
810
810
  format: input.format
@@ -819,7 +819,7 @@ var BACKFILL_CLI_COMMANDS = [
819
819
  },
820
820
  allowPositionals: false,
821
821
  run: async (input) => {
822
- const { backfillAiReferralPathsCommand } = await import("./backfill-PNHBAV5N.js");
822
+ const { backfillAiReferralPathsCommand } = await import("./backfill-6AYHWEQX.js");
823
823
  await backfillAiReferralPathsCommand({
824
824
  project: getString(input.values, "project"),
825
825
  format: input.format
@@ -831,7 +831,7 @@ var BACKFILL_CLI_COMMANDS = [
831
831
  usage: "canonry backfill snapshot-attribution <project> [--dry-run] [--format json]",
832
832
  supportsDryRun: true,
833
833
  run: async (input) => {
834
- const { backfillSnapshotAttributionCommand } = await import("./backfill-PNHBAV5N.js");
834
+ const { backfillSnapshotAttributionCommand } = await import("./backfill-6AYHWEQX.js");
835
835
  const usage = "canonry backfill snapshot-attribution <project> [--dry-run] [--format json]";
836
836
  const project3 = requireProject(input, "backfill snapshot-attribution", usage);
837
837
  await backfillSnapshotAttributionCommand({
@@ -850,7 +850,7 @@ var BACKFILL_CLI_COMMANDS = [
850
850
  allowPositionals: false,
851
851
  supportsDryRun: true,
852
852
  run: async (input) => {
853
- const { backfillTrafficClassificationCommand } = await import("./backfill-PNHBAV5N.js");
853
+ const { backfillTrafficClassificationCommand } = await import("./backfill-6AYHWEQX.js");
854
854
  await backfillTrafficClassificationCommand({
855
855
  project: getString(input.values, "project"),
856
856
  dryRun: input.dryRun,
@@ -1292,7 +1292,7 @@ var DASHBOARD_CLI_COMMANDS = [
1292
1292
  usage: "canonry dashboard reset-password [--format json]",
1293
1293
  help: "Clears the dashboard password from config.yaml, so the dashboard asks for a new one after a restart.\nLocal only: it edits the config file under CANONRY_CONFIG_DIR and does not call the server.",
1294
1294
  run: async (input) => {
1295
- const { resetDashboardPassword } = await import("./dashboard-4HOXCUQE.js");
1295
+ const { resetDashboardPassword } = await import("./dashboard-KT2ACPI5.js");
1296
1296
  await resetDashboardPassword({ format: input.format });
1297
1297
  }
1298
1298
  },
@@ -3286,7 +3286,7 @@ var TRAFFIC_CLI_COMMANDS = [
3286
3286
  help: "Complete stored traffic totals and breakdowns for the selected window. Project-wide for Simple and Advanced portfolios; no provider calls or sync.",
3287
3287
  options: { period: stringOption() },
3288
3288
  run: async (input) => {
3289
- const { trafficAnalytics } = await import("./traffic-B7Q4WPOV.js");
3289
+ const { trafficAnalytics } = await import("./traffic-GWBZKYR5.js");
3290
3290
  const project3 = requireProject(input, "traffic.analytics", "canonry traffic analytics <project> [--period 7|14|30|90]");
3291
3291
  await trafficAnalytics(project3, { period: getString(input.values, "window") ?? getString(input.values, "period"), format: input.format });
3292
3292
  }
@@ -3298,7 +3298,7 @@ var TRAFFIC_CLI_COMMANDS = [
3298
3298
  help: "DB-only diagnostic. Raw headlines stay unchanged. Candidate bursts are not confirmed automation; adjusted counts are estimates. Property, Target and market attribution are unavailable. The observed GA quotient has unknown comparable coverage.",
3299
3299
  options: { "start-date": stringOption(), "end-date": stringOption(), source: stringOption(), "burst-threshold": stringOption(), "ratio-threshold": stringOption(), limit: stringOption() },
3300
3300
  run: async (input) => {
3301
- const { trafficReferralAssessment } = await import("./traffic-B7Q4WPOV.js");
3301
+ const { trafficReferralAssessment } = await import("./traffic-GWBZKYR5.js");
3302
3302
  const project3 = requireProject(input, "traffic.referral-assessment", "canonry traffic referral-assessment <project> --start-date YYYY-MM-DD --end-date YYYY-MM-DD");
3303
3303
  await trafficReferralAssessment(project3, {
3304
3304
  startDate: getString(input.values, "start") ?? getString(input.values, "start-date"),
@@ -3331,7 +3331,7 @@ var TRAFFIC_CLI_COMMANDS = [
3331
3331
  "confirm-fail-open": { type: "boolean" }
3332
3332
  },
3333
3333
  run: async (input) => {
3334
- const { trafficConnectCloudflare, DEFAULT_CLOUDFLARE_QUEUE_RETENTION_SECONDS } = await import("./traffic-B7Q4WPOV.js");
3334
+ const { trafficConnectCloudflare, DEFAULT_CLOUDFLARE_QUEUE_RETENTION_SECONDS } = await import("./traffic-GWBZKYR5.js");
3335
3335
  const forwardPageViews = getBoolean(input.values, "forward-page-views");
3336
3336
  const noForwardPageViews = getBoolean(input.values, "no-forward-page-views");
3337
3337
  if (forwardPageViews && noForwardPageViews) {
@@ -3384,7 +3384,7 @@ var TRAFFIC_CLI_COMMANDS = [
3384
3384
  "display-name": stringOption()
3385
3385
  },
3386
3386
  run: async (input) => {
3387
- const { trafficConnectCloudRun } = await import("./traffic-B7Q4WPOV.js");
3387
+ const { trafficConnectCloudRun } = await import("./traffic-GWBZKYR5.js");
3388
3388
  const project3 = requireProject(
3389
3389
  input,
3390
3390
  "traffic.connect.cloud-run",
@@ -3415,7 +3415,7 @@ var TRAFFIC_CLI_COMMANDS = [
3415
3415
  "display-name": stringOption()
3416
3416
  },
3417
3417
  run: async (input) => {
3418
- const { trafficConnectWordpress } = await import("./traffic-B7Q4WPOV.js");
3418
+ const { trafficConnectWordpress } = await import("./traffic-GWBZKYR5.js");
3419
3419
  const project3 = requireProject(
3420
3420
  input,
3421
3421
  "traffic.connect.wordpress",
@@ -3447,7 +3447,7 @@ var TRAFFIC_CLI_COMMANDS = [
3447
3447
  "display-name": stringOption()
3448
3448
  },
3449
3449
  run: async (input) => {
3450
- const { trafficConnectVercel } = await import("./traffic-B7Q4WPOV.js");
3450
+ const { trafficConnectVercel } = await import("./traffic-GWBZKYR5.js");
3451
3451
  const project3 = requireProject(
3452
3452
  input,
3453
3453
  "traffic.connect.vercel",
@@ -3486,7 +3486,7 @@ var TRAFFIC_CLI_COMMANDS = [
3486
3486
  source: stringOption()
3487
3487
  },
3488
3488
  run: async (input) => {
3489
- const { trafficActivate } = await import("./traffic-B7Q4WPOV.js");
3489
+ const { trafficActivate } = await import("./traffic-GWBZKYR5.js");
3490
3490
  const project3 = requireProject(
3491
3491
  input,
3492
3492
  "traffic.activate",
@@ -3505,7 +3505,7 @@ var TRAFFIC_CLI_COMMANDS = [
3505
3505
  "since-minutes": stringOption()
3506
3506
  },
3507
3507
  run: async (input) => {
3508
- const { trafficSync } = await import("./traffic-B7Q4WPOV.js");
3508
+ const { trafficSync } = await import("./traffic-GWBZKYR5.js");
3509
3509
  const project3 = requireProject(
3510
3510
  input,
3511
3511
  "traffic.sync",
@@ -3534,7 +3534,7 @@ var TRAFFIC_CLI_COMMANDS = [
3534
3534
  wait: { type: "boolean" }
3535
3535
  },
3536
3536
  run: async (input) => {
3537
- const { trafficBackfill } = await import("./traffic-B7Q4WPOV.js");
3537
+ const { trafficBackfill } = await import("./traffic-GWBZKYR5.js");
3538
3538
  const project3 = requireProject(
3539
3539
  input,
3540
3540
  "traffic.backfill",
@@ -3563,7 +3563,7 @@ var TRAFFIC_CLI_COMMANDS = [
3563
3563
  "advance-to-now": { type: "boolean" }
3564
3564
  },
3565
3565
  run: async (input) => {
3566
- const { trafficReset } = await import("./traffic-B7Q4WPOV.js");
3566
+ const { trafficReset } = await import("./traffic-GWBZKYR5.js");
3567
3567
  const project3 = requireProject(
3568
3568
  input,
3569
3569
  "traffic.reset",
@@ -3585,7 +3585,7 @@ var TRAFFIC_CLI_COMMANDS = [
3585
3585
  source: stringOption()
3586
3586
  },
3587
3587
  run: async (input) => {
3588
- const { trafficDeclareGap } = await import("./traffic-B7Q4WPOV.js");
3588
+ const { trafficDeclareGap } = await import("./traffic-GWBZKYR5.js");
3589
3589
  const project3 = requireProject(
3590
3590
  input,
3591
3591
  "traffic.declare-gap",
@@ -3600,7 +3600,7 @@ var TRAFFIC_CLI_COMMANDS = [
3600
3600
  path: ["traffic", "sources"],
3601
3601
  usage: "canonry traffic sources <project> [--format json]",
3602
3602
  run: async (input) => {
3603
- const { trafficSources } = await import("./traffic-B7Q4WPOV.js");
3603
+ const { trafficSources } = await import("./traffic-GWBZKYR5.js");
3604
3604
  const project3 = requireProject(
3605
3605
  input,
3606
3606
  "traffic.sources",
@@ -3613,7 +3613,7 @@ var TRAFFIC_CLI_COMMANDS = [
3613
3613
  path: ["traffic", "status"],
3614
3614
  usage: "canonry traffic status <project> [--format json]",
3615
3615
  run: async (input) => {
3616
- const { trafficStatus } = await import("./traffic-B7Q4WPOV.js");
3616
+ const { trafficStatus } = await import("./traffic-GWBZKYR5.js");
3617
3617
  const project3 = requireProject(
3618
3618
  input,
3619
3619
  "traffic.status",
@@ -3628,7 +3628,7 @@ var TRAFFIC_CLI_COMMANDS = [
3628
3628
  help: "Stored sampled tail with 30-day retention, not visits. Unknown traffic is excluded by default. No provider calls.",
3629
3629
  options: { kind: stringOption(), source: stringOption(), since: stringOption(), until: stringOption(), "since-minutes": stringOption(), path: stringOption(), limit: stringOption(), offset: stringOption() },
3630
3630
  run: async (input) => {
3631
- const { trafficSamples } = await import("./traffic-B7Q4WPOV.js");
3631
+ const { trafficSamples } = await import("./traffic-GWBZKYR5.js");
3632
3632
  const project3 = requireProject(input, "traffic.samples", "canonry traffic samples <project>");
3633
3633
  const integer = (name) => parseIntegerOption(input, name, { command: "traffic.samples", usage: "canonry traffic samples <project>", message: `--${name} must be an integer` });
3634
3634
  await trafficSamples(project3, { kind: getString(input.values, "kind"), sourceId: getString(input.values, "source"), since: getString(input.values, "since"), until: getString(input.values, "until"), sinceMinutes: integer("since-minutes"), path: getString(input.values, "path"), limit: integer("limit"), offset: integer("offset"), format: input.format });
@@ -3640,7 +3640,7 @@ var TRAFFIC_CLI_COMMANDS = [
3640
3640
  help: "Bots and agents no rule recognizes yet, by the name in their user agent, busiest first. Default window: last 30 days. Stored rows only, no provider calls.",
3641
3641
  options: { source: stringOption(), since: stringOption(), until: stringOption(), limit: stringOption() },
3642
3642
  run: async (input) => {
3643
- const { trafficUnrecognized } = await import("./traffic-B7Q4WPOV.js");
3643
+ const { trafficUnrecognized } = await import("./traffic-GWBZKYR5.js");
3644
3644
  const project3 = requireProject(input, "traffic.unrecognized", "canonry traffic unrecognized <project>");
3645
3645
  const limit = parseIntegerOption(input, "limit", { command: "traffic.unrecognized", usage: "canonry traffic unrecognized <project>", message: "--limit must be an integer" });
3646
3646
  await trafficUnrecognized(project3, { sourceId: getString(input.values, "source"), since: getString(input.values, "since"), until: getString(input.values, "until"), limit, format: input.format });
@@ -3659,7 +3659,7 @@ var TRAFFIC_CLI_COMMANDS = [
3659
3659
  granularity: stringOption()
3660
3660
  },
3661
3661
  run: async (input) => {
3662
- const { trafficEvents } = await import("./traffic-B7Q4WPOV.js");
3662
+ const { trafficEvents } = await import("./traffic-GWBZKYR5.js");
3663
3663
  const project3 = requireProject(
3664
3664
  input,
3665
3665
  "traffic.events",
@@ -6931,7 +6931,7 @@ var SYSTEM_CLI_COMMANDS = [
6931
6931
  options: { access: stringOption() },
6932
6932
  run: async (input) => {
6933
6933
  if (input.positionals.length > 1) throw usageError("Expected at most one command group");
6934
- const [{ printCliCatalog }, { REGISTERED_CLI_COMMANDS: REGISTERED_CLI_COMMANDS2 }] = await Promise.all([import("./cli-catalog-CBTM3JKP.js"), import("./cli-commands-62QECRBV.js")]);
6934
+ const [{ printCliCatalog }, { REGISTERED_CLI_COMMANDS: REGISTERED_CLI_COMMANDS2 }] = await Promise.all([import("./cli-catalog-CBTM3JKP.js"), import("./cli-commands-H7BFVUGC.js")]);
6935
6935
  printCliCatalog(REGISTERED_CLI_COMMANDS2, input.format, input.positionals[0], getString(input.values, "access"));
6936
6936
  }
6937
6937
  },
@@ -6980,7 +6980,7 @@ var SYSTEM_CLI_COMMANDS = [
6980
6980
  },
6981
6981
  allowPositionals: false,
6982
6982
  run: async (input) => {
6983
- const { initCommand } = await import("./init-JY76QAOC.js");
6983
+ const { initCommand } = await import("./init-TF3OPCEC.js");
6984
6984
  await initCommand({
6985
6985
  force: getBoolean(input.values, "force"),
6986
6986
  ref: getString(input.values, "ref"),
@@ -7013,7 +7013,7 @@ var SYSTEM_CLI_COMMANDS = [
7013
7013
  },
7014
7014
  allowPositionals: false,
7015
7015
  run: async (input) => {
7016
- const { bootstrapCommand } = await import("./bootstrap-AZYQXBHN.js");
7016
+ const { bootstrapCommand } = await import("./bootstrap-27NOBWTP.js");
7017
7017
  await bootstrapCommand({
7018
7018
  format: input.format,
7019
7019
  ref: getString(input.values, "ref")
@@ -7035,7 +7035,7 @@ var SYSTEM_CLI_COMMANDS = [
7035
7035
  allowPositionals: false,
7036
7036
  run: async (input) => {
7037
7037
  applyServerEnv(input.values);
7038
- const { serveCommand } = await import("./serve-ZQXMTDE7.js");
7038
+ const { serveCommand } = await import("./serve-LLIUILD2.js");
7039
7039
  await serveCommand(input.format);
7040
7040
  }
7041
7041
  },
@@ -8404,8 +8404,8 @@ var AGENT_CLI_COMMANDS = [
8404
8404
  "timeout-ms": stringOption()
8405
8405
  },
8406
8406
  run: async (input) => {
8407
- const { coerceAgentProvider } = await import("./session-MGOUDLXN.js");
8408
- const { AERO_TOOL_PROFILES, isAeroToolProfile } = await import("./tools-ZWFLE5UR.js");
8407
+ const { coerceAgentProvider } = await import("./session-2NQKSF2N.js");
8408
+ const { AERO_TOOL_PROFILES, isAeroToolProfile } = await import("./tools-UPJRW4DN.js");
8409
8409
  const { agentAsk } = await import("./agent-ask-7VUPXTXL.js");
8410
8410
  const usage = `canonry agent ask <project> "<prompt>" [--provider ${AGENT_PROVIDER_IDS.join("|")}] [--model <id>] [--scope all|read-only] [--profile default|ads-operator] [--context <json>] [--conversation <id>] [--max-tool-calls <n>] [--timeout-ms <ms>] [--format json]`;
8411
8411
  const project3 = requireProject(input, "agent.ask", usage);
@@ -3,6 +3,8 @@ import {
3
3
  AgentTrustLevels,
4
4
  AgentTrustReasons,
5
5
  AiReferralTrafficClasses,
6
+ JOURNEY_LOOKBACK_DAYS,
7
+ JOURNEY_VISIT_IDLE_MINUTES,
6
8
  TrafficEventConfidences,
7
9
  TrafficEvidenceKinds,
8
10
  TrafficPathClasses,
@@ -11,7 +13,8 @@ import {
11
13
  classifyJourneyEntry,
12
14
  classifyTrafficPath,
13
15
  hostMatchesDomain,
14
- hostOf
16
+ hostOf,
17
+ isLocationRedirectStatus
15
18
  } from "./chunk-F643WELJ.js";
16
19
 
17
20
  // ../integration-traffic/src/agent-trust.ts
@@ -18170,6 +18173,18 @@ function isStepRefererHost(host, path) {
18170
18173
  return host === entry.slice(0, slash) && path.startsWith(entry.slice(slash));
18171
18174
  });
18172
18175
  }
18176
+ function siteDomainHosts(siteDomains = []) {
18177
+ return siteDomains.map(domainOf).filter((d) => Boolean(d));
18178
+ }
18179
+ function isStepReferer(event, siteHosts = []) {
18180
+ const refererUrl = refererUrlOf(event.referer);
18181
+ const refererBase = baseHost(refererUrl?.hostname || null);
18182
+ if (!refererBase) return false;
18183
+ const siteHost = baseHost(hostOfEvent(event));
18184
+ if (siteHost && (onDomain(refererBase, siteHost) || onDomain(siteHost, refererBase))) return true;
18185
+ if (siteHosts.some((domain) => onDomain(refererBase, domain))) return true;
18186
+ return isStepRefererHost(refererBase, refererUrl?.pathname ?? "/");
18187
+ }
18173
18188
  function isAssetPath(path) {
18174
18189
  return ASSET_PATH_PREFIXES.some((prefix) => path.startsWith(prefix)) || ASSET_EXTENSION_PATTERN.test(path);
18175
18190
  }
@@ -18194,7 +18209,7 @@ function isLikelyBrowser(userAgent) {
18194
18209
  return Boolean(ua) && /^Mozilla\//.test(ua) && !NON_BROWSER_PATTERN.test(ua);
18195
18210
  }
18196
18211
  function extractJourneyRequests(events, options = {}) {
18197
- const siteDomains = (options.siteDomains ?? []).map(domainOf).filter((d) => Boolean(d));
18212
+ const siteHosts = siteDomainHosts(options.siteDomains);
18198
18213
  const out = [];
18199
18214
  for (const event of events) {
18200
18215
  const method = event.method?.toUpperCase() ?? null;
@@ -18212,12 +18227,8 @@ function extractJourneyRequests(events, options = {}) {
18212
18227
  });
18213
18228
  const maskedPath = maskJourneyPath(rawPath);
18214
18229
  const path = (kept.length ? `${maskedPath}?${kept.join("&")}` : maskedPath).slice(0, MAX_PATH_LENGTH);
18215
- const refererUrl = refererUrlOf(event.referer);
18216
- const refererHost = refererUrl?.hostname || null;
18217
- const refererBase = baseHost(refererHost);
18218
- const siteHost = baseHost(hostOfEvent(event));
18219
- const sameSite = Boolean(refererBase && (siteHost && (onDomain(refererBase, siteHost) || onDomain(siteHost, refererBase)) || siteDomains.some((domain) => onDomain(refererBase, domain))));
18220
- const stepReferer = sameSite || Boolean(refererBase && isStepRefererHost(refererBase, refererUrl?.pathname ?? "/"));
18230
+ const refererHost = refererUrlOf(event.referer)?.hostname || null;
18231
+ const stepReferer = isStepReferer(event, siteHosts);
18221
18232
  const ai = classifyAiReferral(event);
18222
18233
  const networkClickId = Object.keys(NETWORK_CLICK_ID_PARAMETERS).find((name) => params.has(name));
18223
18234
  out.push({
@@ -18615,11 +18626,68 @@ function isLikelySubresourcePath(path) {
18615
18626
  const cleanPath = path.split("?")[0] || "/";
18616
18627
  return ASSET_PATH_PREFIXES2.some((prefix) => cleanPath.startsWith(prefix)) || ASSET_EXTENSION_PATTERN2.test(cleanPath);
18617
18628
  }
18618
- function actorKey(event) {
18629
+ function batchActorKey(event) {
18619
18630
  const remoteIp = event.remoteIp?.trim();
18620
18631
  const userAgent = event.userAgent?.trim();
18621
- if (remoteIp || userAgent) return `${remoteIp ?? "unknown-ip"} ${userAgent ?? "unknown-ua"}`;
18622
- return `event:${event.eventId}`;
18632
+ return remoteIp || userAgent ? `${remoteIp ?? "unknown-ip"} ${userAgent ?? "unknown-ua"}` : null;
18633
+ }
18634
+ function actorKey(event) {
18635
+ return batchActorKey(event) ?? `event:${event.eventId}`;
18636
+ }
18637
+ var AI_REFERRAL_LOOKBACK_MS = JOURNEY_LOOKBACK_DAYS * 24 * 60 * 6e4;
18638
+ var AI_REFERRAL_SAME_VISIT_MS = JOURNEY_VISIT_IDLE_MINUTES * 6e4;
18639
+ function findAiReferralFollowOns(events, options) {
18640
+ const lookbackMs = options.lookbackMs ?? AI_REFERRAL_LOOKBACK_MS;
18641
+ const siteHosts = siteDomainHosts(options.siteDomains);
18642
+ const candidates = [];
18643
+ for (const event of events) {
18644
+ if (isSelfTraffic(event)) continue;
18645
+ const referral = classifyAiReferral(event);
18646
+ if (!referral || isLikelySubresourcePath(resolveAiReferralLandingPath(event, referral.evidenceType))) continue;
18647
+ const at = Date.parse(event.observedAt);
18648
+ const actor = options.actorKey(event, referral.product);
18649
+ if (!Number.isFinite(at) || actor === null) continue;
18650
+ const hop = event.status !== null && isLocationRedirectStatus(event.status);
18651
+ candidates.push({ eventId: event.eventId, actor, at, step: isStepReferer(event, siteHosts), hop });
18652
+ }
18653
+ candidates.sort((a, b) => a.at - b.at || Number(a.step) - Number(b.step));
18654
+ const actors = [...new Set(candidates.map((candidate) => candidate.actor))];
18655
+ const known = actors.length > 0 && options.known ? options.known(actors) : /* @__PURE__ */ new Map();
18656
+ const eventIds = /* @__PURE__ */ new Set();
18657
+ const arrivals = /* @__PURE__ */ new Map();
18658
+ const counted = (actor, arrival) => {
18659
+ const list = arrivals.get(actor);
18660
+ if (list) list.push(arrival);
18661
+ else arrivals.set(actor, [arrival]);
18662
+ };
18663
+ for (const candidate of candidates) {
18664
+ const remembered = [...known.get(candidate.actor) ?? [], ...arrivals.get(candidate.actor) ?? []];
18665
+ if (candidate.step) {
18666
+ const covered = remembered.some((arrival) => arrival.at <= candidate.at && candidate.at - arrival.at <= lookbackMs);
18667
+ if (covered || candidate.hop) {
18668
+ eventIds.add(candidate.eventId);
18669
+ continue;
18670
+ }
18671
+ counted(candidate.actor, { at: candidate.at, standIn: true });
18672
+ continue;
18673
+ }
18674
+ if (candidate.hop) continue;
18675
+ const alreadyCounted = remembered.some((arrival) => arrival.standIn && arrival.at >= candidate.at && arrival.at - candidate.at <= AI_REFERRAL_SAME_VISIT_MS);
18676
+ if (alreadyCounted) {
18677
+ eventIds.add(candidate.eventId);
18678
+ continue;
18679
+ }
18680
+ counted(candidate.actor, { at: candidate.at, standIn: false });
18681
+ }
18682
+ return { eventIds, arrivals };
18683
+ }
18684
+ function findAiReferralFollowOnsInBatch(events) {
18685
+ return findAiReferralFollowOns(events, {
18686
+ actorKey: (event, product) => {
18687
+ const actor = batchActorKey(event);
18688
+ return actor === null ? null : `${actor} ${product}`;
18689
+ }
18690
+ }).eventIds;
18623
18691
  }
18624
18692
  function aiReferralSessionKey(event, aiReferral, landingPathNormalized, windowMs) {
18625
18693
  return [
@@ -18679,6 +18747,7 @@ function buildTrafficProbeReport(events, options = {}) {
18679
18747
  const includedEvents = events.filter((event) => !isSelfTraffic(event));
18680
18748
  const selfTrafficExcluded = events.length - includedEvents.length;
18681
18749
  const scannerBursts = options.scannerBurstEventIds ?? findScannerBurstsInBatch(includedEvents);
18750
+ const aiReferralFollowOns = options.aiReferralFollowOnEventIds ?? findAiReferralFollowOnsInBatch(includedEvents);
18682
18751
  let crawlerHits = 0;
18683
18752
  let aiUserFetchHits = 0;
18684
18753
  let aiUserFetchLikelyFakeHits = 0;
@@ -18770,7 +18839,7 @@ function buildTrafficProbeReport(events, options = {}) {
18770
18839
  if (aiReferral) {
18771
18840
  aiReferralHits += 1;
18772
18841
  const landingPathNormalized = resolveAiReferralLandingPath(event, aiReferral.evidenceType);
18773
- if (!isLikelySubresourcePath(landingPathNormalized)) {
18842
+ if (!aiReferralFollowOns.has(event.eventId) && !isLikelySubresourcePath(landingPathNormalized)) {
18774
18843
  const session = {
18775
18844
  tsHour,
18776
18845
  operator: aiReferral.operator,
@@ -19549,6 +19618,8 @@ export {
19549
19618
  UNRECOGNIZED_AGENT_NAMING_VERSION,
19550
19619
  unrecognizedAgentName,
19551
19620
  normalizeTrafficPathPattern,
19621
+ AI_REFERRAL_LOOKBACK_MS,
19622
+ findAiReferralFollowOns,
19552
19623
  buildTrafficProbeReport,
19553
19624
  normalizeCloudflareWorkerEvent,
19554
19625
  CLOUDFLARE_WORKER_BINDINGS,
@@ -5,7 +5,7 @@ import {
5
5
  isStoredPageReadTool,
6
6
  isStoredReadTool,
7
7
  truncateToolResult
8
- } from "./chunk-RSPOFH66.js";
8
+ } from "./chunk-TFB2S6TQ.js";
9
9
  import {
10
10
  CANONRY_MCP_TOOLKITS,
11
11
  resolveAeroSkillDir
@@ -34,7 +34,7 @@ import {
34
34
  import {
35
35
  agentToolEvents,
36
36
  llmUsageEvents
37
- } from "./chunk-O26FQ7RI.js";
37
+ } from "./chunk-AYYZ4HKJ.js";
38
38
  import {
39
39
  MeasurementPortfolioLists,
40
40
  SeoCapabilities,
@@ -10,7 +10,7 @@ import {
10
10
  } from "./chunk-HGMYEDAQ.js";
11
11
  import {
12
12
  buildOpenApiDocument
13
- } from "./chunk-W7DHXSXN.js";
13
+ } from "./chunk-AI75KS7G.js";
14
14
  import {
15
15
  DEFAULT_COMPETITOR_AUTO_ALIAS_MODE,
16
16
  MeasurementPortfolioLists,
@@ -17,7 +17,7 @@ import {
17
17
  mergeGscQueryTotalsWithFallback,
18
18
  readGscQueryDailyRows,
19
19
  readLatestGscDataDate
20
- } from "./chunk-W7DHXSXN.js";
20
+ } from "./chunk-AI75KS7G.js";
21
21
  import {
22
22
  competitors,
23
23
  gbpDailyMetrics,
@@ -35,7 +35,7 @@ import {
35
35
  queries,
36
36
  querySnapshots,
37
37
  runs
38
- } from "./chunk-O26FQ7RI.js";
38
+ } from "./chunk-AYYZ4HKJ.js";
39
39
  import {
40
40
  CitationStates,
41
41
  RunKinds,