@ainyc/canonry 4.15.0 → 4.17.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -20,7 +20,7 @@ import {
20
20
  setTelemetrySource,
21
21
  showFirstRunNotice,
22
22
  trackEvent
23
- } from "./chunk-DLSQXNUN.js";
23
+ } from "./chunk-ZGHD3IAV.js";
24
24
  import {
25
25
  CliError,
26
26
  EXIT_SYSTEM_ERROR,
@@ -36,7 +36,7 @@ import {
36
36
  saveConfig,
37
37
  saveConfigPatch,
38
38
  usageError
39
- } from "./chunk-C32VL5BB.js";
39
+ } from "./chunk-6TWKC3DP.js";
40
40
  import {
41
41
  apiKeys,
42
42
  competitors,
@@ -49,7 +49,7 @@ import {
49
49
  queries,
50
50
  querySnapshots,
51
51
  runs
52
- } from "./chunk-7HBZCGRL.js";
52
+ } from "./chunk-PAZCY4FF.js";
53
53
  import {
54
54
  CcReleaseSyncStatuses,
55
55
  CheckScopes,
@@ -60,6 +60,7 @@ import {
60
60
  RunKinds,
61
61
  RunStatuses,
62
62
  SkillsClients,
63
+ TrafficEventKinds,
63
64
  determineAnswerMentioned,
64
65
  effectiveDomains,
65
66
  formatRunErrorOneLine,
@@ -68,7 +69,7 @@ import {
68
69
  providerQuotaPolicySchema,
69
70
  resolveProviderInput,
70
71
  skillsClientSchema
71
- } from "./chunk-6QTH5NS5.js";
72
+ } from "./chunk-Q2OED5JQ.js";
72
73
 
73
74
  // src/cli.ts
74
75
  import { pathToFileURL } from "url";
@@ -620,7 +621,7 @@ function readStoredGroundingSources(rawResponse) {
620
621
  return result;
621
622
  }
622
623
  async function backfillInsightsCommand(project, opts) {
623
- const { IntelligenceService } = await import("./intelligence-service-BCKXIKIL.js");
624
+ const { IntelligenceService } = await import("./intelligence-service-X3PQLBUV.js");
624
625
  const config = loadConfig();
625
626
  const db = createClient(config.database);
626
627
  migrate(db);
@@ -2801,6 +2802,128 @@ async function trafficSync(project, opts) {
2801
2802
  console.log(` Sample rows: ${result.sampleRows}`);
2802
2803
  console.log(` Synced at: ${result.syncedAt}`);
2803
2804
  }
2805
+ function formatSourceLine(source) {
2806
+ const parts = [
2807
+ source.id,
2808
+ source.sourceType,
2809
+ source.status,
2810
+ source.lastSyncedAt ?? "never synced",
2811
+ source.displayName
2812
+ ];
2813
+ return parts.join(" ");
2814
+ }
2815
+ async function trafficSources(project, opts) {
2816
+ const client = createApiClient();
2817
+ const result = await client.trafficListSources(project);
2818
+ if (opts.format === "json") {
2819
+ console.log(JSON.stringify(result, null, 2));
2820
+ return;
2821
+ }
2822
+ if (result.sources.length === 0) {
2823
+ console.log(`No traffic sources connected for project "${project}".`);
2824
+ console.log("Run: canonry traffic connect cloud-run <project> --gcp-project <id> --service-account-key <path>");
2825
+ return;
2826
+ }
2827
+ console.log(`Traffic sources for "${project}":`);
2828
+ console.log(" ID TYPE STATUS LAST_SYNCED DISPLAY_NAME");
2829
+ for (const source of result.sources) {
2830
+ console.log(` ${formatSourceLine(source)}`);
2831
+ }
2832
+ }
2833
+ async function trafficStatus(project, opts) {
2834
+ const client = createApiClient();
2835
+ const result = await client.trafficStatus(project);
2836
+ const details = result.sources;
2837
+ if (opts.format === "json") {
2838
+ console.log(JSON.stringify(result, null, 2));
2839
+ return;
2840
+ }
2841
+ if (details.length === 0) {
2842
+ console.log(`No traffic sources connected for project "${project}".`);
2843
+ console.log("Run: canonry traffic connect cloud-run <project> --gcp-project <id> --service-account-key <path>");
2844
+ return;
2845
+ }
2846
+ for (const d of details) {
2847
+ console.log(`Source ${d.id} (${d.sourceType})`);
2848
+ console.log(` Display name: ${d.displayName}`);
2849
+ console.log(` Status: ${d.status}`);
2850
+ console.log(` Last synced: ${d.lastSyncedAt ?? "never"}`);
2851
+ if (d.lastError) console.log(` Last error: ${d.lastError}`);
2852
+ console.log(` 24h crawler: ${d.totals24h.crawlerHits} hits`);
2853
+ console.log(` 24h AI referral: ${d.totals24h.aiReferralHits} hits`);
2854
+ console.log(` 24h samples: ${d.totals24h.sampleCount}`);
2855
+ if (d.latestRun) {
2856
+ console.log(` Latest run: ${d.latestRun.runId} (${d.latestRun.status})`);
2857
+ console.log(` Started: ${d.latestRun.startedAt}`);
2858
+ if (d.latestRun.finishedAt) console.log(` Finished: ${d.latestRun.finishedAt}`);
2859
+ if (d.latestRun.error) console.log(` Error: ${d.latestRun.error}`);
2860
+ } else {
2861
+ console.log(` Latest run: (none)`);
2862
+ }
2863
+ console.log("");
2864
+ }
2865
+ }
2866
+ function formatEventLine(event) {
2867
+ if (event.kind === TrafficEventKinds.crawler) {
2868
+ return [
2869
+ event.tsHour,
2870
+ "crawler",
2871
+ event.botId,
2872
+ event.verificationStatus,
2873
+ String(event.status),
2874
+ event.pathNormalized,
2875
+ `${event.hits} hits`
2876
+ ].join(" ");
2877
+ }
2878
+ return [
2879
+ event.tsHour,
2880
+ "ai-referral",
2881
+ event.product,
2882
+ event.evidenceType,
2883
+ event.sourceDomain,
2884
+ event.landingPathNormalized,
2885
+ `${event.hits} hits`
2886
+ ].join(" ");
2887
+ }
2888
+ async function trafficEvents(project, opts) {
2889
+ if (opts.kind && opts.kind !== "all" && opts.kind !== TrafficEventKinds.crawler && opts.kind !== TrafficEventKinds["ai-referral"]) {
2890
+ throw new CliError({
2891
+ code: "TRAFFIC_INVALID_KIND",
2892
+ message: `--kind must be one of: all, ${TrafficEventKinds.crawler}, ${TrafficEventKinds["ai-referral"]}`,
2893
+ displayMessage: `Error: --kind must be "all", "${TrafficEventKinds.crawler}", or "${TrafficEventKinds["ai-referral"]}"`,
2894
+ details: { project, kind: opts.kind }
2895
+ });
2896
+ }
2897
+ const params = {};
2898
+ if (opts.kind && opts.kind !== "all") params.kind = opts.kind;
2899
+ if (opts.source) params.sourceId = opts.source;
2900
+ if (opts.limit !== void 0) params.limit = opts.limit;
2901
+ if (opts.sinceMinutes !== void 0) {
2902
+ const since = new Date(Date.now() - opts.sinceMinutes * 6e4).toISOString();
2903
+ params.since = since;
2904
+ } else if (opts.since) {
2905
+ params.since = opts.since;
2906
+ }
2907
+ if (opts.until) params.until = opts.until;
2908
+ const client = createApiClient();
2909
+ const result = await client.trafficListEvents(project, params);
2910
+ if (opts.format === "json") {
2911
+ console.log(JSON.stringify(result, null, 2));
2912
+ return;
2913
+ }
2914
+ console.log(`Traffic events for "${project}" ${result.windowStart} \u2192 ${result.windowEnd}`);
2915
+ console.log(` Crawler hits (window): ${result.totals.crawlerHits}`);
2916
+ console.log(` AI referral hits (window): ${result.totals.aiReferralHits}`);
2917
+ console.log("");
2918
+ if (result.events.length === 0) {
2919
+ console.log("No events in this window.");
2920
+ return;
2921
+ }
2922
+ console.log(" TS_HOUR KIND IDENTITY EVIDENCE/STATUS PATH HITS");
2923
+ for (const event of result.events) {
2924
+ console.log(` ${formatEventLine(event)}`);
2925
+ }
2926
+ }
2804
2927
 
2805
2928
  // src/cli-commands/traffic.ts
2806
2929
  var TRAFFIC_CLI_COMMANDS = [
@@ -2847,7 +2970,7 @@ var TRAFFIC_CLI_COMMANDS = [
2847
2970
  },
2848
2971
  {
2849
2972
  path: ["traffic", "sync"],
2850
- usage: "canonry traffic sync <project> --source <id> [--since-minutes 60] [--format json]",
2973
+ usage: "canonry traffic sync <project> --source <id> [--since-minutes 43200] [--format json]",
2851
2974
  options: {
2852
2975
  source: stringOption(),
2853
2976
  "since-minutes": stringOption()
@@ -2856,12 +2979,15 @@ var TRAFFIC_CLI_COMMANDS = [
2856
2979
  const project = requireProject(
2857
2980
  input,
2858
2981
  "traffic.sync",
2859
- "canonry traffic sync <project> --source <id> [--since-minutes 60]"
2982
+ "canonry traffic sync <project> --source <id> [--since-minutes 43200]"
2860
2983
  );
2861
2984
  const source = getString(input.values, "source");
2862
2985
  if (!source) throw new Error("--source <id> is required");
2863
- const sinceStr = getString(input.values, "since-minutes");
2864
- const sinceMinutes = sinceStr ? parseInt(sinceStr, 10) : void 0;
2986
+ const sinceMinutes = parseIntegerOption(input, "since-minutes", {
2987
+ command: "traffic.sync",
2988
+ usage: "canonry traffic sync <project> --source <id> [--since-minutes 43200]",
2989
+ message: "--since-minutes must be an integer"
2990
+ });
2865
2991
  await trafficSync(project, {
2866
2992
  source,
2867
2993
  sinceMinutes,
@@ -2869,6 +2995,68 @@ var TRAFFIC_CLI_COMMANDS = [
2869
2995
  });
2870
2996
  }
2871
2997
  },
2998
+ {
2999
+ path: ["traffic", "sources"],
3000
+ usage: "canonry traffic sources <project> [--format json]",
3001
+ run: async (input) => {
3002
+ const project = requireProject(
3003
+ input,
3004
+ "traffic.sources",
3005
+ "canonry traffic sources <project>"
3006
+ );
3007
+ await trafficSources(project, { format: input.format });
3008
+ }
3009
+ },
3010
+ {
3011
+ path: ["traffic", "status"],
3012
+ usage: "canonry traffic status <project> [--format json]",
3013
+ run: async (input) => {
3014
+ const project = requireProject(
3015
+ input,
3016
+ "traffic.status",
3017
+ "canonry traffic status <project>"
3018
+ );
3019
+ await trafficStatus(project, { format: input.format });
3020
+ }
3021
+ },
3022
+ {
3023
+ path: ["traffic", "events"],
3024
+ usage: "canonry traffic events <project> [--kind crawler|ai-referral|all] [--source <id>] [--since-minutes 1440] [--since <iso>] [--until <iso>] [--limit 500] [--format json]",
3025
+ options: {
3026
+ kind: stringOption(),
3027
+ source: stringOption(),
3028
+ "since-minutes": stringOption(),
3029
+ since: stringOption(),
3030
+ until: stringOption(),
3031
+ limit: stringOption()
3032
+ },
3033
+ run: async (input) => {
3034
+ const project = requireProject(
3035
+ input,
3036
+ "traffic.events",
3037
+ "canonry traffic events <project>"
3038
+ );
3039
+ const sinceMinutes = parseIntegerOption(input, "since-minutes", {
3040
+ command: "traffic.events",
3041
+ usage: "canonry traffic events <project> [--since-minutes 1440]",
3042
+ message: "--since-minutes must be an integer"
3043
+ });
3044
+ const limit = parseIntegerOption(input, "limit", {
3045
+ command: "traffic.events",
3046
+ usage: "canonry traffic events <project> [--limit 500]",
3047
+ message: "--limit must be an integer"
3048
+ });
3049
+ await trafficEvents(project, {
3050
+ kind: getString(input.values, "kind"),
3051
+ source: getString(input.values, "source"),
3052
+ sinceMinutes,
3053
+ since: getString(input.values, "since"),
3054
+ until: getString(input.values, "until"),
3055
+ limit,
3056
+ format: input.format
3057
+ });
3058
+ }
3059
+ },
2872
3060
  {
2873
3061
  path: ["traffic"],
2874
3062
  usage: "canonry traffic <subcommand> <project> [args]",
@@ -2876,7 +3064,7 @@ var TRAFFIC_CLI_COMMANDS = [
2876
3064
  unknownSubcommand(input.positionals[0], {
2877
3065
  command: "traffic",
2878
3066
  usage: "canonry traffic <subcommand> <project> [args]",
2879
- available: ["connect", "sync"]
3067
+ available: ["connect", "sync", "status", "sources", "events"]
2880
3068
  });
2881
3069
  }
2882
3070
  }
@@ -6072,6 +6260,8 @@ function getClient17() {
6072
6260
  async function setSchedule(project, opts) {
6073
6261
  const client = getClient17();
6074
6262
  const body = {};
6263
+ if (opts.kind) body.kind = opts.kind;
6264
+ if (opts.sourceId) body.sourceId = opts.sourceId;
6075
6265
  if (opts.preset) body.preset = opts.preset;
6076
6266
  if (opts.cron) body.cron = opts.cron;
6077
6267
  if (opts.timezone) body.timezone = opts.timezone;
@@ -6081,61 +6271,68 @@ async function setSchedule(project, opts) {
6081
6271
  console.log(JSON.stringify(result, null, 2));
6082
6272
  return;
6083
6273
  }
6084
- console.log(`Schedule set for "${project}":`);
6274
+ console.log(`Schedule set for "${project}" (kind: ${result.kind}):`);
6085
6275
  printSchedule(result);
6086
6276
  }
6087
- async function showSchedule(project, format) {
6277
+ async function showSchedule(project, format, kind) {
6088
6278
  const client = getClient17();
6089
- const result = await client.getSchedule(project);
6279
+ const result = await client.getSchedule(project, kind);
6090
6280
  if (format === "json") {
6091
6281
  console.log(JSON.stringify(result, null, 2));
6092
6282
  return;
6093
6283
  }
6094
6284
  printSchedule(result);
6095
6285
  }
6096
- async function enableSchedule(project, format) {
6286
+ async function enableSchedule(project, format, kind) {
6097
6287
  const client = getClient17();
6098
- const current = await client.getSchedule(project);
6099
- const body = { timezone: current.timezone, enabled: true };
6288
+ const current = await client.getSchedule(project, kind);
6289
+ const body = { kind: current.kind, timezone: current.timezone, enabled: true };
6100
6290
  if (current.preset) body.preset = current.preset;
6101
6291
  else body.cron = current.cronExpr;
6102
6292
  if (current.providers.length) body.providers = current.providers;
6293
+ if (current.sourceId) body.sourceId = current.sourceId;
6103
6294
  const result = await client.putSchedule(project, body);
6104
6295
  if (format === "json") {
6105
6296
  console.log(JSON.stringify(result, null, 2));
6106
6297
  return;
6107
6298
  }
6108
- console.log(`Schedule enabled for "${project}"`);
6299
+ console.log(`Schedule enabled for "${project}" (kind: ${result.kind})`);
6109
6300
  }
6110
- async function disableSchedule(project, format) {
6301
+ async function disableSchedule(project, format, kind) {
6111
6302
  const client = getClient17();
6112
- const current = await client.getSchedule(project);
6113
- const body = { timezone: current.timezone, enabled: false };
6303
+ const current = await client.getSchedule(project, kind);
6304
+ const body = { kind: current.kind, timezone: current.timezone, enabled: false };
6114
6305
  if (current.preset) body.preset = current.preset;
6115
6306
  else body.cron = current.cronExpr;
6116
6307
  if (current.providers.length) body.providers = current.providers;
6308
+ if (current.sourceId) body.sourceId = current.sourceId;
6117
6309
  const result = await client.putSchedule(project, body);
6118
6310
  if (format === "json") {
6119
6311
  console.log(JSON.stringify(result, null, 2));
6120
6312
  return;
6121
6313
  }
6122
- console.log(`Schedule disabled for "${project}"`);
6314
+ console.log(`Schedule disabled for "${project}" (kind: ${result.kind})`);
6123
6315
  }
6124
- async function removeSchedule(project, format) {
6316
+ async function removeSchedule(project, format, kind) {
6125
6317
  const client = getClient17();
6126
- await client.deleteSchedule(project);
6318
+ await client.deleteSchedule(project, kind);
6319
+ const resolvedKind = kind ?? "answer-visibility";
6127
6320
  if (format === "json") {
6128
- console.log(JSON.stringify({ project, removed: true }, null, 2));
6321
+ console.log(JSON.stringify({ project, kind: resolvedKind, removed: true }, null, 2));
6129
6322
  return;
6130
6323
  }
6131
- console.log(`Schedule removed for "${project}"`);
6324
+ console.log(`Schedule removed for "${project}" (kind: ${resolvedKind})`);
6132
6325
  }
6133
6326
  function printSchedule(s) {
6134
6327
  const label = s.preset ?? s.cronExpr;
6328
+ console.log(` Kind: ${s.kind}`);
6135
6329
  console.log(` Schedule: ${label}`);
6136
6330
  console.log(` Cron: ${s.cronExpr}`);
6137
6331
  console.log(` Timezone: ${s.timezone}`);
6138
6332
  console.log(` Enabled: ${s.enabled ? "yes" : "no"}`);
6333
+ if (s.kind === "traffic-sync" && s.sourceId) {
6334
+ console.log(` Source: ${s.sourceId}`);
6335
+ }
6139
6336
  if (s.providers.length) {
6140
6337
  console.log(` Providers: ${s.providers.join(", ")}`);
6141
6338
  }
@@ -6151,30 +6348,31 @@ function printSchedule(s) {
6151
6348
  var SCHEDULE_CLI_COMMANDS = [
6152
6349
  {
6153
6350
  path: ["schedule", "set"],
6154
- usage: "canonry schedule set <project> (--preset <preset> | --cron <expr>) [--timezone <tz>] [--provider <name>...] [--format json]",
6351
+ usage: "canonry schedule set <project> (--preset <preset> | --cron <expr>) [--kind answer-visibility|traffic-sync] [--source <id>] [--timezone <tz>] [--provider <name>...] [--format json]",
6155
6352
  options: {
6156
6353
  preset: stringOption(),
6157
6354
  cron: stringOption(),
6355
+ kind: stringOption(),
6356
+ source: stringOption(),
6158
6357
  timezone: stringOption(),
6159
6358
  provider: multiStringOption()
6160
6359
  },
6161
6360
  run: async (input) => {
6162
- const project = requireProject(
6163
- input,
6164
- "schedule.set",
6165
- "canonry schedule set <project> (--preset <preset> | --cron <expr>) [--timezone <tz>] [--provider <name>...] [--format json]"
6166
- );
6361
+ const usage = "canonry schedule set <project> (--preset <preset> | --cron <expr>) [--kind answer-visibility|traffic-sync] [--source <id>] [--timezone <tz>] [--provider <name>...] [--format json]";
6362
+ const project = requireProject(input, "schedule.set", usage);
6167
6363
  if (!getString(input.values, "preset") && !getString(input.values, "cron")) {
6168
6364
  throw usageError("Error: --preset or --cron is required", {
6169
6365
  message: "schedule preset or cron is required",
6170
6366
  details: {
6171
6367
  command: "schedule.set",
6172
- usage: "canonry schedule set <project> (--preset <preset> | --cron <expr>) [--timezone <tz>] [--provider <name>...] [--format json]",
6368
+ usage,
6173
6369
  required: ["preset | cron"]
6174
6370
  }
6175
6371
  });
6176
6372
  }
6177
6373
  await setSchedule(project, {
6374
+ kind: getString(input.values, "kind"),
6375
+ sourceId: getString(input.values, "source"),
6178
6376
  preset: getString(input.values, "preset"),
6179
6377
  cron: getString(input.values, "cron"),
6180
6378
  timezone: getString(input.values, "timezone"),
@@ -6185,34 +6383,38 @@ var SCHEDULE_CLI_COMMANDS = [
6185
6383
  },
6186
6384
  {
6187
6385
  path: ["schedule", "show"],
6188
- usage: "canonry schedule show <project> [--format json]",
6386
+ usage: "canonry schedule show <project> [--kind answer-visibility|traffic-sync] [--format json]",
6387
+ options: { kind: stringOption() },
6189
6388
  run: async (input) => {
6190
- const project = requireProject(input, "schedule.show", "canonry schedule show <project> [--format json]");
6191
- await showSchedule(project, input.format);
6389
+ const project = requireProject(input, "schedule.show", "canonry schedule show <project> [--kind ...]");
6390
+ await showSchedule(project, input.format, getString(input.values, "kind"));
6192
6391
  }
6193
6392
  },
6194
6393
  {
6195
6394
  path: ["schedule", "enable"],
6196
- usage: "canonry schedule enable <project> [--format json]",
6395
+ usage: "canonry schedule enable <project> [--kind answer-visibility|traffic-sync] [--format json]",
6396
+ options: { kind: stringOption() },
6197
6397
  run: async (input) => {
6198
- const project = requireProject(input, "schedule.enable", "canonry schedule enable <project> [--format json]");
6199
- await enableSchedule(project, input.format);
6398
+ const project = requireProject(input, "schedule.enable", "canonry schedule enable <project> [--kind ...]");
6399
+ await enableSchedule(project, input.format, getString(input.values, "kind"));
6200
6400
  }
6201
6401
  },
6202
6402
  {
6203
6403
  path: ["schedule", "disable"],
6204
- usage: "canonry schedule disable <project> [--format json]",
6404
+ usage: "canonry schedule disable <project> [--kind answer-visibility|traffic-sync] [--format json]",
6405
+ options: { kind: stringOption() },
6205
6406
  run: async (input) => {
6206
- const project = requireProject(input, "schedule.disable", "canonry schedule disable <project> [--format json]");
6207
- await disableSchedule(project, input.format);
6407
+ const project = requireProject(input, "schedule.disable", "canonry schedule disable <project> [--kind ...]");
6408
+ await disableSchedule(project, input.format, getString(input.values, "kind"));
6208
6409
  }
6209
6410
  },
6210
6411
  {
6211
6412
  path: ["schedule", "remove"],
6212
- usage: "canonry schedule remove <project> [--format json]",
6413
+ usage: "canonry schedule remove <project> [--kind answer-visibility|traffic-sync] [--format json]",
6414
+ options: { kind: stringOption() },
6213
6415
  run: async (input) => {
6214
- const project = requireProject(input, "schedule.remove", "canonry schedule remove <project> [--format json]");
6215
- await removeSchedule(project, input.format);
6416
+ const project = requireProject(input, "schedule.remove", "canonry schedule remove <project> [--kind ...]");
6417
+ await removeSchedule(project, input.format, getString(input.values, "kind"));
6216
6418
  }
6217
6419
  },
6218
6420
  {
@@ -10451,6 +10653,7 @@ Integrations:
10451
10653
  google Google Search Console / Analytics
10452
10654
  bing Bing Webmaster Tools
10453
10655
  wordpress WordPress REST API
10656
+ traffic Server-side traffic ingestion (Cloud Run)
10454
10657
 
10455
10658
  Automation:
10456
10659
  schedule Manage scheduled runs
@@ -10492,7 +10695,7 @@ async function runCli(args = process.argv.slice(2)) {
10492
10695
  showFirstRunNotice();
10493
10696
  getOrCreateAnonymousId();
10494
10697
  }
10495
- const SUBCOMMAND_COMMANDS = /* @__PURE__ */ new Set(["backfill", "project", "query", "keyword", "competitor", "schedule", "notify", "settings", "telemetry", "google", "bing", "wordpress", "cdp"]);
10698
+ const SUBCOMMAND_COMMANDS = /* @__PURE__ */ new Set(["backfill", "project", "query", "keyword", "competitor", "schedule", "notify", "settings", "telemetry", "google", "bing", "wordpress", "cdp", "traffic"]);
10496
10699
  const MIXED_SUBCOMMANDS = {
10497
10700
  insights: /* @__PURE__ */ new Set(["dismiss"]),
10498
10701
  run: /* @__PURE__ */ new Set(["show", "cancel"])
package/dist/index.js CHANGED
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  createServer
3
- } from "./chunk-DLSQXNUN.js";
3
+ } from "./chunk-ZGHD3IAV.js";
4
4
  import {
5
5
  loadConfig
6
- } from "./chunk-C32VL5BB.js";
7
- import "./chunk-7HBZCGRL.js";
8
- import "./chunk-6QTH5NS5.js";
6
+ } from "./chunk-6TWKC3DP.js";
7
+ import "./chunk-PAZCY4FF.js";
8
+ import "./chunk-Q2OED5JQ.js";
9
9
  export {
10
10
  createServer,
11
11
  loadConfig
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  IntelligenceService
3
- } from "./chunk-7HBZCGRL.js";
4
- import "./chunk-6QTH5NS5.js";
3
+ } from "./chunk-PAZCY4FF.js";
4
+ import "./chunk-Q2OED5JQ.js";
5
5
  export {
6
6
  IntelligenceService
7
7
  };
package/dist/mcp.js CHANGED
@@ -2,8 +2,8 @@ import {
2
2
  CliError,
3
3
  canonryMcpTools,
4
4
  createApiClient
5
- } from "./chunk-C32VL5BB.js";
6
- import "./chunk-6QTH5NS5.js";
5
+ } from "./chunk-6TWKC3DP.js";
6
+ import "./chunk-Q2OED5JQ.js";
7
7
 
8
8
  // src/mcp/cli.ts
9
9
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
@@ -107,7 +107,7 @@ function zodErrorMessage(error) {
107
107
  }
108
108
 
109
109
  // src/mcp/toolkits.ts
110
- var CANONRY_MCP_TOOLKIT_NAMES = ["monitoring", "setup", "gsc", "ga", "agent"];
110
+ var CANONRY_MCP_TOOLKIT_NAMES = ["monitoring", "setup", "gsc", "ga", "traffic", "agent"];
111
111
  var CANONRY_MCP_TOOLKITS = [
112
112
  {
113
113
  name: "monitoring",
@@ -133,6 +133,12 @@ var CANONRY_MCP_TOOLKITS = [
133
133
  description: "Read GA traffic, AI/social referral history, attribution trend, and session history.",
134
134
  whenToLoad: "Load when you need traffic, referral, or attribution data from Google Analytics 4."
135
135
  },
136
+ {
137
+ name: "traffic",
138
+ title: "Server-side traffic ingestion",
139
+ description: "Connect Cloud Run traffic sources, trigger syncs, and read crawler / AI-referral hourly rollups straight from server logs (no GA dependency).",
140
+ whenToLoad: "Load when you need server-log evidence of crawler hits or AI-referral arrivals (e.g. confirming GPTBot or ChatGPT-User on a page), or when wiring up / syncing a Cloud Run traffic source."
141
+ },
136
142
  {
137
143
  name: "agent",
138
144
  title: "Aero agent lifecycle and memory",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ainyc/canonry",
3
- "version": "4.15.0",
3
+ "version": "4.17.1",
4
4
  "type": "module",
5
5
  "description": "Agent-first open-source AEO operating platform - track how answer engines cite your domain",
6
6
  "license": "FSL-1.1-ALv2",
@@ -60,21 +60,21 @@
60
60
  "tsup": "^8.5.1",
61
61
  "tsx": "^4.19.0",
62
62
  "@ainyc/canonry-api-routes": "0.0.0",
63
- "@ainyc/canonry-config": "0.0.0",
64
63
  "@ainyc/canonry-db": "0.0.0",
65
- "@ainyc/canonry-integration-bing": "0.0.0",
64
+ "@ainyc/canonry-config": "0.0.0",
66
65
  "@ainyc/canonry-intelligence": "0.0.0",
67
- "@ainyc/canonry-integration-cloud-run": "0.0.0",
68
66
  "@ainyc/canonry-contracts": "0.0.0",
69
- "@ainyc/canonry-integration-commoncrawl": "0.0.0",
67
+ "@ainyc/canonry-integration-bing": "0.0.0",
68
+ "@ainyc/canonry-integration-cloud-run": "0.0.0",
70
69
  "@ainyc/canonry-integration-google": "0.0.0",
71
- "@ainyc/canonry-integration-traffic": "0.0.0",
72
70
  "@ainyc/canonry-integration-wordpress": "0.0.0",
71
+ "@ainyc/canonry-integration-commoncrawl": "0.0.0",
73
72
  "@ainyc/canonry-provider-cdp": "0.0.0",
74
- "@ainyc/canonry-provider-claude": "0.0.0",
73
+ "@ainyc/canonry-integration-traffic": "0.0.0",
75
74
  "@ainyc/canonry-provider-gemini": "0.0.0",
76
75
  "@ainyc/canonry-provider-local": "0.0.0",
77
76
  "@ainyc/canonry-provider-openai": "0.0.0",
77
+ "@ainyc/canonry-provider-claude": "0.0.0",
78
78
  "@ainyc/canonry-provider-perplexity": "0.0.0"
79
79
  },
80
80
  "scripts": {