@ainyc/canonry 4.86.0 → 4.88.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 (27) hide show
  1. package/assets/agent-workspace/skills/canonry/references/server-side-traffic.md +19 -0
  2. package/assets/assets/{BacklinksPage-BNrvc-gV.js → BacklinksPage-Dpx6ylmU.js} +1 -1
  3. package/assets/assets/{ChartPrimitives-BlIkdUdy.js → ChartPrimitives-CG5EGu62.js} +1 -1
  4. package/assets/assets/ProjectPage-B_xnYE7W.js +6 -0
  5. package/assets/assets/{RunRow-CAPnKzi7.js → RunRow-C0V4vf-u.js} +1 -1
  6. package/assets/assets/{RunsPage-idnuzKBn.js → RunsPage-9gWTjteG.js} +1 -1
  7. package/assets/assets/{SettingsPage-Bka67uJq.js → SettingsPage-kBwz4Glg.js} +1 -1
  8. package/assets/assets/{TrafficPage-C_o-rA5o.js → TrafficPage-D4adjs8S.js} +1 -1
  9. package/assets/assets/TrafficSourceDetailPage-CmURRHaU.js +1 -0
  10. package/assets/assets/{arrow-left-B-JfzARi.js → arrow-left-DJ0-oFbd.js} +1 -1
  11. package/assets/assets/{extract-error-message-BhPbjIX6.js → extract-error-message-DfBzETgi.js} +1 -1
  12. package/assets/assets/{index-uPSrDA8e.js → index-BeuGfMy8.js} +107 -107
  13. package/assets/assets/index-ClkRAeHL.css +1 -0
  14. package/assets/assets/{trash-2-BbRvn40h.js → trash-2-Bjf6mCqw.js} +1 -1
  15. package/assets/index.html +2 -2
  16. package/dist/{chunk-SELXBOAP.js → chunk-2VEFNAQ3.js} +4 -4
  17. package/dist/{chunk-23HGQV22.js → chunk-JZ67YCHT.js} +365 -0
  18. package/dist/{chunk-LLJPZKHG.js → chunk-RH3QYFX3.js} +2 -2
  19. package/dist/{chunk-DLBQU3VG.js → chunk-WMZJO56S.js} +213 -57
  20. package/dist/cli.js +23 -12
  21. package/dist/index.js +4 -4
  22. package/dist/{intelligence-service-ZHUJKZRO.js → intelligence-service-WTEEV46F.js} +2 -2
  23. package/dist/mcp.js +2 -2
  24. package/package.json +6 -6
  25. package/assets/assets/ProjectPage-CAyx_xNr.js +0 -6
  26. package/assets/assets/TrafficSourceDetailPage-D_jvoSTV.js +0 -1
  27. package/assets/assets/index-BgWgJE7S.css +0 -1
@@ -3163,6 +3163,196 @@ var ccCachedReleaseSchema = z23.object({
3163
3163
 
3164
3164
  // ../contracts/src/composites.ts
3165
3165
  import { z as z24 } from "zod";
3166
+ var metricToneSchema = z24.enum(["positive", "caution", "negative", "neutral"]);
3167
+ var scoreSummarySchema = z24.object({
3168
+ label: z24.string(),
3169
+ value: z24.string(),
3170
+ delta: z24.string(),
3171
+ tone: metricToneSchema,
3172
+ description: z24.string(),
3173
+ tooltip: z24.string().optional(),
3174
+ trend: z24.array(z24.number()),
3175
+ progress: z24.number().optional(),
3176
+ providerCoverage: z24.string().optional()
3177
+ });
3178
+ var mentionShareSchema = scoreSummarySchema.extend({
3179
+ breakdown: z24.object({
3180
+ projectMentionSnapshots: z24.number().int().nonnegative(),
3181
+ competitorMentionSnapshots: z24.number().int().nonnegative(),
3182
+ perCompetitor: z24.array(z24.object({
3183
+ domain: z24.string(),
3184
+ mentionSnapshots: z24.number().int().nonnegative(),
3185
+ shareOfCompetitiveTotal: z24.number()
3186
+ })),
3187
+ snapshotsWithAnswerText: z24.number().int().nonnegative(),
3188
+ snapshotsTotal: z24.number().int().nonnegative()
3189
+ })
3190
+ });
3191
+ var movementSummarySchema = z24.object({
3192
+ gained: z24.number().int().nonnegative(),
3193
+ lost: z24.number().int().nonnegative(),
3194
+ tone: metricToneSchema,
3195
+ hasPreviousRun: z24.boolean(),
3196
+ gainedQueries: z24.array(z24.string()).optional(),
3197
+ lostQueries: z24.array(z24.string()).optional()
3198
+ });
3199
+ var movementComparisonSchema = z24.object({
3200
+ hasPreviousRun: z24.boolean(),
3201
+ comparable: z24.boolean(),
3202
+ querySetChanged: z24.boolean(),
3203
+ previousRunAt: z24.string().nullable(),
3204
+ currentQueryCount: z24.number().int().nonnegative(),
3205
+ previousQueryCount: z24.number().int().nonnegative(),
3206
+ comparableQueryCount: z24.number().int().nonnegative(),
3207
+ addedQueryCount: z24.number().int().nonnegative(),
3208
+ removedQueryCount: z24.number().int().nonnegative(),
3209
+ addedQueries: z24.array(z24.string()),
3210
+ removedQueries: z24.array(z24.string())
3211
+ });
3212
+ var projectOverviewInsightSchema = z24.object({
3213
+ id: z24.string(),
3214
+ projectId: z24.string(),
3215
+ runId: z24.string().nullable(),
3216
+ type: z24.enum([
3217
+ "regression",
3218
+ "gain",
3219
+ "opportunity",
3220
+ "first-citation",
3221
+ "provider-pickup",
3222
+ "persistent-gap",
3223
+ "competitor-gained",
3224
+ "competitor-lost",
3225
+ "gbp-lodging-gap",
3226
+ "gbp-listing-discrepancy",
3227
+ "gbp-cta-gap",
3228
+ "gbp-metric-drop",
3229
+ "gbp-keyword-drop"
3230
+ ]),
3231
+ severity: z24.enum(["critical", "high", "medium", "low"]),
3232
+ title: z24.string(),
3233
+ query: z24.string(),
3234
+ provider: z24.string(),
3235
+ recommendation: z24.object({
3236
+ action: z24.string(),
3237
+ target: z24.string().optional(),
3238
+ reason: z24.string()
3239
+ }).optional(),
3240
+ cause: z24.object({
3241
+ cause: z24.string(),
3242
+ competitorDomain: z24.string().optional(),
3243
+ details: z24.string().optional()
3244
+ }).optional(),
3245
+ dismissed: z24.boolean(),
3246
+ createdAt: z24.string()
3247
+ });
3248
+ var projectOverviewHealthSchema = z24.object({
3249
+ id: z24.string(),
3250
+ projectId: z24.string(),
3251
+ runId: z24.string().nullable(),
3252
+ overallCitedRate: z24.number(),
3253
+ overallMentionRate: z24.number(),
3254
+ totalPairs: z24.number().int().nonnegative(),
3255
+ citedPairs: z24.number().int().nonnegative(),
3256
+ mentionedPairs: z24.number().int().nonnegative(),
3257
+ providerBreakdown: z24.record(z24.string(), z24.object({
3258
+ citedRate: z24.number(),
3259
+ mentionRate: z24.number(),
3260
+ cited: z24.number().int().nonnegative(),
3261
+ mentioned: z24.number().int().nonnegative(),
3262
+ total: z24.number().int().nonnegative()
3263
+ })),
3264
+ createdAt: z24.string(),
3265
+ status: z24.enum(["ready", "no-data"]),
3266
+ reason: z24.literal("no-runs-yet").optional()
3267
+ });
3268
+ var projectOverviewDtoSchema = z24.object({
3269
+ project: projectDtoSchema,
3270
+ latestRun: latestProjectRunDtoSchema,
3271
+ health: projectOverviewHealthSchema.nullable(),
3272
+ topInsights: z24.array(projectOverviewInsightSchema),
3273
+ queryCounts: z24.object({
3274
+ totalQueries: z24.number().int().nonnegative(),
3275
+ citedQueries: z24.number().int().nonnegative(),
3276
+ notCitedQueries: z24.number().int().nonnegative(),
3277
+ citedRate: z24.number(),
3278
+ mentionedQueries: z24.number().int().nonnegative(),
3279
+ notMentionedQueries: z24.number().int().nonnegative(),
3280
+ mentionRate: z24.number()
3281
+ }),
3282
+ providers: z24.array(z24.object({
3283
+ provider: z24.string(),
3284
+ citedRate: z24.number(),
3285
+ cited: z24.number().int().nonnegative(),
3286
+ total: z24.number().int().nonnegative()
3287
+ })),
3288
+ transitions: z24.object({
3289
+ since: z24.string().nullable(),
3290
+ gained: z24.number().int().nonnegative(),
3291
+ lost: z24.number().int().nonnegative(),
3292
+ emerging: z24.number().int().nonnegative()
3293
+ }),
3294
+ scores: z24.object({
3295
+ mention: scoreSummarySchema,
3296
+ visibility: scoreSummarySchema,
3297
+ mentionShare: mentionShareSchema,
3298
+ gapQueries: scoreSummarySchema,
3299
+ mentionGaps: scoreSummarySchema,
3300
+ indexCoverage: scoreSummarySchema,
3301
+ competitorPressure: scoreSummarySchema,
3302
+ runStatus: scoreSummarySchema
3303
+ }),
3304
+ movementSummary: movementSummarySchema,
3305
+ citationMovement: movementSummarySchema,
3306
+ mentionMovement: movementSummarySchema,
3307
+ movementComparison: movementComparisonSchema,
3308
+ competitors: z24.array(z24.object({
3309
+ id: z24.string(),
3310
+ domain: z24.string(),
3311
+ citationCount: z24.number().int().nonnegative(),
3312
+ totalQueries: z24.number().int().nonnegative(),
3313
+ pressureLabel: z24.enum(["None", "Low", "Moderate", "High"]),
3314
+ citedQueries: z24.array(z24.string())
3315
+ })),
3316
+ providerScores: z24.array(z24.object({
3317
+ provider: z24.string(),
3318
+ model: z24.string().nullable(),
3319
+ score: z24.number(),
3320
+ cited: z24.number().int().nonnegative(),
3321
+ total: z24.number().int().nonnegative(),
3322
+ trend: z24.array(z24.number()).optional()
3323
+ })),
3324
+ attentionItems: z24.array(z24.object({
3325
+ id: z24.string(),
3326
+ tone: metricToneSchema,
3327
+ title: z24.string(),
3328
+ detail: z24.string(),
3329
+ actionLabel: z24.string(),
3330
+ href: z24.string()
3331
+ })),
3332
+ runHistory: z24.array(z24.object({
3333
+ runId: z24.string(),
3334
+ createdAt: z24.string(),
3335
+ citedCount: z24.number().int().nonnegative(),
3336
+ totalCount: z24.number().int().nonnegative(),
3337
+ citationRate: z24.number(),
3338
+ mentionedCount: z24.number().int().nonnegative(),
3339
+ mentionRate: z24.number(),
3340
+ status: z24.string()
3341
+ })),
3342
+ suggestedQueries: z24.object({
3343
+ rows: z24.array(z24.object({
3344
+ query: z24.string(),
3345
+ impressions: z24.number(),
3346
+ clicks: z24.number(),
3347
+ avgPosition: z24.number(),
3348
+ reason: z24.string()
3349
+ })),
3350
+ totalCandidates: z24.number().int().nonnegative(),
3351
+ skippedAlreadyTracked: z24.number().int().nonnegative()
3352
+ }),
3353
+ dateRangeLabel: z24.string(),
3354
+ contextLabel: z24.string()
3355
+ });
3166
3356
  var searchHitKindSchema = z24.enum(["snapshot", "insight"]);
3167
3357
  var projectSearchSnapshotHitSchema = z24.object({
3168
3358
  kind: z24.literal("snapshot"),
@@ -3533,6 +3723,11 @@ function summarizeCheckResults(results) {
3533
3723
  return summary;
3534
3724
  }
3535
3725
 
3726
+ // ../contracts/src/query-normalize.ts
3727
+ function normalizeQueryText(value) {
3728
+ return value.trim().toLowerCase();
3729
+ }
3730
+
3536
3731
  // ../contracts/src/citations.ts
3537
3732
  import { z as z27 } from "zod";
3538
3733
  var citationCoverageProviderSchema = z27.object({
@@ -4360,6 +4555,20 @@ function coerceSkillManifest(parsed) {
4360
4555
 
4361
4556
  // ../contracts/src/traffic.ts
4362
4557
  import { z as z30 } from "zod";
4558
+ var trafficCrawlerSegmentsSchema = z30.object({
4559
+ content: z30.number().int().nonnegative(),
4560
+ sitemap: z30.number().int().nonnegative(),
4561
+ robots: z30.number().int().nonnegative(),
4562
+ asset: z30.number().int().nonnegative(),
4563
+ other: z30.number().int().nonnegative()
4564
+ });
4565
+ var trafficPathClassSchema = z30.enum([
4566
+ "content",
4567
+ "sitemap",
4568
+ "robots",
4569
+ "asset",
4570
+ "other"
4571
+ ]);
4363
4572
  var trafficSourceTypeSchema = z30.enum([
4364
4573
  "cloud-run",
4365
4574
  "wordpress",
@@ -4516,7 +4725,18 @@ var trafficBackfillResponseSchema = z30.object({
4516
4725
  daysApplied: z30.number().int().positive()
4517
4726
  });
4518
4727
  var trafficSourceTotalsSchema = z30.object({
4728
+ /**
4729
+ * Total classified-crawler hits in the window. UNCHANGED contract — still the
4730
+ * full count across every path class. Use `crawlerContentHits` for the
4731
+ * "content was actually crawled" signal.
4732
+ */
4519
4733
  crawlerHits: z30.number().int().nonnegative(),
4734
+ /** Crawler hits against content/document paths only (= `crawlerSegments.content`). */
4735
+ crawlerContentHits: z30.number().int().nonnegative(),
4736
+ /** Infrastructure crawler hits — sitemap + robots + asset fetches (`crawlerSegments.{sitemap,robots,asset}`). */
4737
+ crawlerInfraHits: z30.number().int().nonnegative(),
4738
+ /** Full per-class crawler-hit breakdown; the five buckets sum to `crawlerHits`. */
4739
+ crawlerSegments: trafficCrawlerSegmentsSchema,
4520
4740
  aiUserFetchHits: z30.number().int().nonnegative(),
4521
4741
  aiReferralHits: z30.number().int().nonnegative(),
4522
4742
  sampleCount: z30.number().int().nonnegative()
@@ -4547,6 +4767,8 @@ var trafficCrawlerEventEntrySchema = z30.object({
4547
4767
  operator: z30.string(),
4548
4768
  verificationStatus: z30.string(),
4549
4769
  pathNormalized: z30.string(),
4770
+ /** Coarse class of the fetched path — lets the UI split content crawls from sitemap/robots/asset polling. */
4771
+ pathClass: trafficPathClassSchema,
4550
4772
  status: z30.number().int(),
4551
4773
  hits: z30.number().int().nonnegative()
4552
4774
  });
@@ -4582,13 +4804,151 @@ var trafficEventsResponseSchema = z30.object({
4582
4804
  windowStart: z30.string(),
4583
4805
  windowEnd: z30.string(),
4584
4806
  totals: z30.object({
4807
+ /** Total classified-crawler hits across the window. UNCHANGED contract. */
4585
4808
  crawlerHits: z30.number().int().nonnegative(),
4809
+ /** Crawler hits against content/document paths only (= `crawlerSegments.content`). */
4810
+ crawlerContentHits: z30.number().int().nonnegative(),
4811
+ /** Infrastructure crawler hits — sitemap + robots + asset fetches. */
4812
+ crawlerInfraHits: z30.number().int().nonnegative(),
4813
+ /** Full per-class crawler-hit breakdown; the five buckets sum to `crawlerHits`. */
4814
+ crawlerSegments: trafficCrawlerSegmentsSchema,
4586
4815
  aiUserFetchHits: z30.number().int().nonnegative(),
4587
4816
  aiReferralHits: z30.number().int().nonnegative()
4588
4817
  }),
4589
4818
  events: z30.array(trafficEventEntrySchema)
4590
4819
  });
4591
4820
 
4821
+ // ../contracts/src/traffic-path.ts
4822
+ var TrafficPathClasses = {
4823
+ content: "content",
4824
+ sitemap: "sitemap",
4825
+ robots: "robots",
4826
+ asset: "asset",
4827
+ other: "other"
4828
+ };
4829
+ var ROBOTS_BASENAMES = /* @__PURE__ */ new Set(["robots.txt", "llms.txt", "llms-full.txt"]);
4830
+ var ASSET_EXTENSIONS = /* @__PURE__ */ new Set([
4831
+ "css",
4832
+ "js",
4833
+ "mjs",
4834
+ "cjs",
4835
+ "map",
4836
+ "json",
4837
+ "png",
4838
+ "jpg",
4839
+ "jpeg",
4840
+ "webp",
4841
+ "avif",
4842
+ "gif",
4843
+ "svg",
4844
+ "ico",
4845
+ "bmp",
4846
+ "tif",
4847
+ "tiff",
4848
+ "woff",
4849
+ "woff2",
4850
+ "ttf",
4851
+ "otf",
4852
+ "eot",
4853
+ "mp4",
4854
+ "webm",
4855
+ "mov",
4856
+ "m4v",
4857
+ "mp3",
4858
+ "wav",
4859
+ "ogg",
4860
+ "flac",
4861
+ "m4a",
4862
+ "wasm"
4863
+ ]);
4864
+ var DOCUMENT_EXTENSIONS = /* @__PURE__ */ new Set([
4865
+ "html",
4866
+ "htm",
4867
+ "xhtml",
4868
+ "shtml",
4869
+ "php",
4870
+ "php5",
4871
+ "php7",
4872
+ "asp",
4873
+ "aspx",
4874
+ "jsp",
4875
+ "jspx",
4876
+ "cfm",
4877
+ "md"
4878
+ ]);
4879
+ var DOWNLOAD_EXTENSIONS = /* @__PURE__ */ new Set([
4880
+ "pdf",
4881
+ "csv",
4882
+ "tsv",
4883
+ "txt",
4884
+ "doc",
4885
+ "docx",
4886
+ "xls",
4887
+ "xlsx",
4888
+ "ppt",
4889
+ "pptx",
4890
+ "odt",
4891
+ "ods",
4892
+ "odp",
4893
+ "rtf",
4894
+ "zip",
4895
+ "gz",
4896
+ "tgz",
4897
+ "tar",
4898
+ "rar",
4899
+ "7z",
4900
+ "bz2",
4901
+ "xz",
4902
+ "rss",
4903
+ "atom",
4904
+ "ics",
4905
+ "vcf",
4906
+ "epub",
4907
+ "mobi",
4908
+ "apk",
4909
+ "dmg",
4910
+ "exe",
4911
+ "bin",
4912
+ "iso",
4913
+ "sql"
4914
+ ]);
4915
+ var SITEMAP_BASENAME = /^sitemap(?:[-_]index)?$/;
4916
+ function classifyTrafficPath(pathNormalized) {
4917
+ const raw = (pathNormalized ?? "").trim();
4918
+ if (!raw) return TrafficPathClasses.other;
4919
+ const rawPath = raw.split(/[?#]/)[0] ?? "";
4920
+ const pathOnly = rawPath.length > 1 ? rawPath.replace(/\/+$/, "") || "/" : rawPath;
4921
+ if (!pathOnly) return TrafficPathClasses.other;
4922
+ const lower = pathOnly.toLowerCase();
4923
+ const segments = lower.split("/");
4924
+ const basename = segments[segments.length - 1] ?? "";
4925
+ if (ROBOTS_BASENAMES.has(basename)) return TrafficPathClasses.robots;
4926
+ if (lower.endsWith(".xml") || lower.endsWith(".xml.gz")) return TrafficPathClasses.sitemap;
4927
+ if (SITEMAP_BASENAME.test(basename)) return TrafficPathClasses.sitemap;
4928
+ const dot = basename.lastIndexOf(".");
4929
+ const ext = dot > 0 ? basename.slice(dot + 1) : "";
4930
+ if (ext) {
4931
+ if (ASSET_EXTENSIONS.has(ext)) return TrafficPathClasses.asset;
4932
+ if (DOCUMENT_EXTENSIONS.has(ext)) return TrafficPathClasses.content;
4933
+ if (DOWNLOAD_EXTENSIONS.has(ext)) return TrafficPathClasses.other;
4934
+ return TrafficPathClasses.content;
4935
+ }
4936
+ return TrafficPathClasses.content;
4937
+ }
4938
+ function emptyCrawlerSegments() {
4939
+ return { content: 0, sitemap: 0, robots: 0, asset: 0, other: 0 };
4940
+ }
4941
+ function segmentCrawlerHits(rows) {
4942
+ const segments = emptyCrawlerSegments();
4943
+ for (const row of rows) {
4944
+ segments[classifyTrafficPath(row.pathNormalized)] += row.hits;
4945
+ }
4946
+ return segments;
4947
+ }
4948
+ function sumInfraHits(segments) {
4949
+ return segments.sitemap + segments.robots + segments.asset;
4950
+ }
4951
+
4592
4952
  // ../contracts/src/formatting.ts
4593
4953
  function formatRatio(value) {
4594
4954
  if (!Number.isFinite(value) || value === 0) return "0%";
@@ -5029,6 +5389,7 @@ export {
5029
5389
  backlinksInstallResultDtoSchema,
5030
5390
  ccAvailableReleaseSchema,
5031
5391
  ccCachedReleaseSchema,
5392
+ projectOverviewDtoSchema,
5032
5393
  ContentActions,
5033
5394
  contentActionLabel,
5034
5395
  actionConfidenceLabel,
@@ -5052,6 +5413,7 @@ export {
5052
5413
  CheckCategories,
5053
5414
  doctorReportSchema,
5054
5415
  summarizeCheckResults,
5416
+ normalizeQueryText,
5055
5417
  citationVisibilityResponseSchema,
5056
5418
  emptyCitationVisibility,
5057
5419
  citationStateToCited,
@@ -5088,6 +5450,9 @@ export {
5088
5450
  trafficEventKindSchema,
5089
5451
  TrafficEventKinds,
5090
5452
  trafficEventsResponseSchema,
5453
+ classifyTrafficPath,
5454
+ segmentCrawlerHits,
5455
+ sumInfraHits,
5091
5456
  formatRatio,
5092
5457
  formatNumber,
5093
5458
  formatDate,
@@ -23,7 +23,7 @@ import {
23
23
  trafficConnectVercelRequestSchema,
24
24
  trafficConnectWordpressRequestSchema,
25
25
  trafficEventKindSchema
26
- } from "./chunk-23HGQV22.js";
26
+ } from "./chunk-JZ67YCHT.js";
27
27
 
28
28
  // src/config.ts
29
29
  import fs from "fs";
@@ -5597,7 +5597,7 @@ var canonryMcpTools = [
5597
5597
  defineTool({
5598
5598
  name: "canonry_project_overview",
5599
5599
  title: "Get project overview (composite)",
5600
- description: 'One-call summary for "how is project X doing?" \u2014 bundles project info, latest run, top undismissed insights, latest health snapshot, query cited rate, per-provider breakdown, gained/lost/emerging vs the previous run, the five score gauges (visibility, gap queries, index coverage, competitor pressure, run status), per-(provider, model) scores, configured competitors with pressure labels, an attention queue of critical/high insights, and a recent-runs sparkline. Filterable by location and time window. Prefer this over fanning out to separate tools.',
5600
+ description: 'One-call summary for "how is project X doing?". Returns independent mention and citation coverage, separate query-level movement for each signal, query-basket comparability with added/removed counts, latest run and health, insights, provider/model breakdowns, competitors, attention items, and recent history. Movement excludes queries not shared by both sweeps. Filterable by location and time window. Prefer this over fanning out to separate tools.',
5601
5601
  access: "read",
5602
5602
  tier: "core",
5603
5603
  inputSchema: z2.object({