@ainyc/canonry 4.80.0 → 4.82.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (25) hide show
  1. package/assets/agent-workspace/skills/canonry/references/canonry-cli.md +24 -12
  2. package/assets/assets/{BacklinksPage-dRc62jAY.js → BacklinksPage-CHclt-pq.js} +1 -1
  3. package/assets/assets/{ChartPrimitives-D2_IvTkk.js → ChartPrimitives-2Ub4vNWe.js} +1 -1
  4. package/assets/assets/ProjectPage-UPmHfuxR.js +6 -0
  5. package/assets/assets/{RunRow-C0MA3yuQ.js → RunRow-rUL1UeA3.js} +1 -1
  6. package/assets/assets/{RunsPage-4uxTYgGy.js → RunsPage-BQpHfUJf.js} +1 -1
  7. package/assets/assets/{SettingsPage-3-SLhcJ7.js → SettingsPage-DjTJlr_1.js} +1 -1
  8. package/assets/assets/{TrafficPage-DZ50qwme.js → TrafficPage-D7rv3BrH.js} +1 -1
  9. package/assets/assets/TrafficSourceDetailPage-BysyuH2H.js +1 -0
  10. package/assets/assets/{arrow-left-BaZIkAXX.js → arrow-left-CR_FGlkE.js} +1 -1
  11. package/assets/assets/{extract-error-message-cpvfuFqW.js → extract-error-message-BKkAbWNp.js} +1 -1
  12. package/assets/assets/{index-EnY_OBRd.js → index-DzzTt20n.js} +87 -87
  13. package/assets/assets/{trash-2-JpcztiS5.js → trash-2-uSttujvh.js} +1 -1
  14. package/assets/index.html +1 -1
  15. package/dist/{chunk-CXIGHPBE.js → chunk-IEUTAQUF.js} +471 -124
  16. package/dist/{chunk-2QBSRHSN.js → chunk-JLAD6CYH.js} +88 -8
  17. package/dist/{chunk-AVN6Q6LM.js → chunk-KPSFRSS7.js} +96 -3
  18. package/dist/{chunk-LCABGFYN.js → chunk-NSZ3D3MM.js} +404 -242
  19. package/dist/cli.js +145 -18
  20. package/dist/index.js +4 -4
  21. package/dist/{intelligence-service-ZWW3I3NL.js → intelligence-service-2UUJ3YGI.js} +2 -2
  22. package/dist/mcp.js +23 -4
  23. package/package.json +8 -8
  24. package/assets/assets/ProjectPage-DSuvRUIf.js +0 -6
  25. package/assets/assets/TrafficSourceDetailPage-CzK5TMFp.js +0 -1
@@ -2,6 +2,7 @@ import {
2
2
  AGENT_MEMORY_KEY_MAX_LENGTH,
3
3
  AGENT_MEMORY_VALUE_MAX_BYTES,
4
4
  DISCOVERY_MAX_PROBES_CAP,
5
+ backlinkSourceSchema,
5
6
  competitorBatchRequestSchema,
6
7
  discoveryBucketSchema,
7
8
  discoveryCompetitorTypeSchema,
@@ -22,7 +23,7 @@ import {
22
23
  trafficConnectVercelRequestSchema,
23
24
  trafficConnectWordpressRequestSchema,
24
25
  trafficEventKindSchema
25
- } from "./chunk-AVN6Q6LM.js";
26
+ } from "./chunk-KPSFRSS7.js";
26
27
 
27
28
  // src/config.ts
28
29
  import fs from "fs";
@@ -1605,6 +1606,18 @@ var postApiV1Keys = (options) => {
1605
1606
  }
1606
1607
  });
1607
1608
  };
1609
+ var getApiV1KeysSelf = (options) => {
1610
+ return (options?.client ?? client).get({
1611
+ security: [
1612
+ {
1613
+ scheme: "bearer",
1614
+ type: "http"
1615
+ }
1616
+ ],
1617
+ url: "/api/v1/keys/self",
1618
+ ...options
1619
+ });
1620
+ };
1608
1621
  var postApiV1KeysByIdRevoke = (options) => {
1609
1622
  return (options.client ?? client).post({
1610
1623
  security: [
@@ -3221,6 +3234,30 @@ var getApiV1ProjectsByNameBacklinksHistory = (options) => {
3221
3234
  ...options
3222
3235
  });
3223
3236
  };
3237
+ var getApiV1ProjectsByNameBacklinksSources = (options) => {
3238
+ return (options.client ?? client).get({
3239
+ security: [
3240
+ {
3241
+ scheme: "bearer",
3242
+ type: "http"
3243
+ }
3244
+ ],
3245
+ url: "/api/v1/projects/{name}/backlinks/sources",
3246
+ ...options
3247
+ });
3248
+ };
3249
+ var postApiV1ProjectsByNameBacklinksBingSync = (options) => {
3250
+ return (options.client ?? client).post({
3251
+ security: [
3252
+ {
3253
+ scheme: "bearer",
3254
+ type: "http"
3255
+ }
3256
+ ],
3257
+ url: "/api/v1/projects/{name}/backlinks/bing-sync",
3258
+ ...options
3259
+ });
3260
+ };
3224
3261
  var postApiV1ProjectsByNameTrafficConnectCloudRun = (options) => {
3225
3262
  return (options.client ?? client).post({
3226
3263
  security: [
@@ -4017,6 +4054,10 @@ var ApiClient = class {
4017
4054
  async listApiKeys() {
4018
4055
  return this.invoke(() => getApiV1Keys({ client: this.heyClient }));
4019
4056
  }
4057
+ /** Introspect the CURRENT key (the one this client authenticates with). */
4058
+ async getApiKeySelf() {
4059
+ return this.invoke(() => getApiV1KeysSelf({ client: this.heyClient }));
4060
+ }
4020
4061
  async createApiKey(body) {
4021
4062
  return this.invoke(() => postApiV1Keys({ client: this.heyClient, body }));
4022
4063
  }
@@ -5060,6 +5101,23 @@ var ApiClient = class {
5060
5101
  })
5061
5102
  );
5062
5103
  }
5104
+ async backlinksBingSync(project) {
5105
+ return this.invoke(
5106
+ () => postApiV1ProjectsByNameBacklinksBingSync({
5107
+ client: this.heyClient,
5108
+ path: { name: project }
5109
+ })
5110
+ );
5111
+ }
5112
+ async backlinksSources(project, opts = {}) {
5113
+ return this.invoke(
5114
+ () => getApiV1ProjectsByNameBacklinksSources({
5115
+ client: this.heyClient,
5116
+ path: { name: project },
5117
+ query: { excludeCrawlers: opts.excludeCrawlers ? "1" : void 0 }
5118
+ })
5119
+ );
5120
+ }
5063
5121
  async backlinksSummary(project, opts = {}) {
5064
5122
  return this.invoke(
5065
5123
  () => getApiV1ProjectsByNameBacklinksSummary({
@@ -5067,7 +5125,8 @@ var ApiClient = class {
5067
5125
  path: { name: project },
5068
5126
  query: {
5069
5127
  release: opts.release,
5070
- excludeCrawlers: opts.excludeCrawlers ? "1" : void 0
5128
+ excludeCrawlers: opts.excludeCrawlers ? "1" : void 0,
5129
+ source: opts.source
5071
5130
  }
5072
5131
  })
5073
5132
  );
@@ -5081,14 +5140,19 @@ var ApiClient = class {
5081
5140
  limit: opts.limit,
5082
5141
  offset: opts.offset,
5083
5142
  release: opts.release,
5084
- excludeCrawlers: opts.excludeCrawlers ? "1" : void 0
5143
+ excludeCrawlers: opts.excludeCrawlers ? "1" : void 0,
5144
+ source: opts.source
5085
5145
  }
5086
5146
  })
5087
5147
  );
5088
5148
  }
5089
- async backlinksHistory(project) {
5149
+ async backlinksHistory(project, opts = {}) {
5090
5150
  return this.invoke(
5091
- () => getApiV1ProjectsByNameBacklinksHistory({ client: this.heyClient, path: { name: project } })
5151
+ () => getApiV1ProjectsByNameBacklinksHistory({
5152
+ client: this.heyClient,
5153
+ path: { name: project },
5154
+ query: { source: opts.source }
5155
+ })
5092
5156
  );
5093
5157
  }
5094
5158
  };
@@ -5332,7 +5396,11 @@ var contentMapInputSchema = z2.object({
5332
5396
  var backlinksDomainsInputSchema = z2.object({
5333
5397
  project: projectNameSchema,
5334
5398
  limit: z2.number().int().positive().max(200).optional().describe("Max linking-domain rows. Default 50, max 200."),
5335
- release: z2.string().optional().describe("Common Crawl release id (e.g., cc-main-2026-jan-feb-mar). Omit for the most recent release with data.")
5399
+ release: z2.string().optional().describe("Window id (Common Crawl release e.g. cc-main-2026-jan-feb-mar, or Bing window e.g. bing-2026-06-15). Omit for the most recent window with data."),
5400
+ source: backlinkSourceSchema.optional().describe("Backlink source: commoncrawl (default) or bing-webmaster.")
5401
+ });
5402
+ var backlinksSourcesInputSchema = z2.object({
5403
+ project: projectNameSchema
5336
5404
  });
5337
5405
  var memoryUpsertInputSchema = z2.object({
5338
5406
  project: projectNameSchema,
@@ -5822,7 +5890,7 @@ var canonryMcpTools = [
5822
5890
  defineTool({
5823
5891
  name: "canonry_backlinks_domains",
5824
5892
  title: "List backlink domains",
5825
- description: "Backlink summary and top linking domains from the most recent ready Common Crawl release for a project. Off-site authority signal that correlates with citation likelihood. Returns null summary when no release sync has completed for this workspace.",
5893
+ description: "Source-aware backlink summary + top linking domains for a project. `source=commoncrawl` (default) reads the most recent ready Common Crawl release; `source=bing-webmaster` reads the latest live Bing Webmaster inbound-link window. Off-site authority signal that correlates with citation likelihood. Returns null summary when the source has no data yet.",
5826
5894
  access: "read",
5827
5895
  tier: "setup",
5828
5896
  inputSchema: backlinksDomainsInputSchema,
@@ -5830,9 +5898,21 @@ var canonryMcpTools = [
5830
5898
  openApiOperations: ["GET /api/v1/projects/{name}/backlinks/domains"],
5831
5899
  handler: (client2, input) => client2.backlinksDomains(input.project, {
5832
5900
  limit: input.limit ?? 50,
5833
- release: input.release
5901
+ release: input.release,
5902
+ source: input.source
5834
5903
  })
5835
5904
  }),
5905
+ defineTool({
5906
+ name: "canonry_backlinks_sources",
5907
+ title: "Backlink source availability",
5908
+ description: "Reports which backlink sources are set up for a project (commoncrawl, bing-webmaster): connected, has data, latest window, linking-domain count, and freshness. Use to decide whether to read CC vs Bing or prompt the operator to connect a source.",
5909
+ access: "read",
5910
+ tier: "setup",
5911
+ inputSchema: backlinksSourcesInputSchema,
5912
+ annotations: readAnnotations(),
5913
+ openApiOperations: ["GET /api/v1/projects/{name}/backlinks/sources"],
5914
+ handler: (client2, input) => client2.backlinksSources(input.project)
5915
+ }),
5836
5916
  defineTool({
5837
5917
  name: "canonry_settings_get",
5838
5918
  title: "Get settings",
@@ -571,6 +571,16 @@ var auditLogEntrySchema = z3.object({
571
571
  createdAt: z3.string()
572
572
  });
573
573
 
574
+ // ../contracts/src/scopes.ts
575
+ var READ_ONLY_SCOPE = "read";
576
+ var WILDCARD_SCOPE = "*";
577
+ function grantsWrite(scope) {
578
+ return scope === WILDCARD_SCOPE || scope === "write" || scope.endsWith(".write");
579
+ }
580
+ function isReadOnlyKey(scopes) {
581
+ return scopes.includes(READ_ONLY_SCOPE) && !scopes.some(grantsWrite);
582
+ }
583
+
574
584
  // ../contracts/src/api-keys.ts
575
585
  import { z as z4 } from "zod";
576
586
  var apiKeyDtoSchema = z4.object({
@@ -579,6 +589,13 @@ var apiKeyDtoSchema = z4.object({
579
589
  /** First 9 chars of the raw token (`cnry_` + 4 hex). Safe to display. */
580
590
  keyPrefix: z4.string(),
581
591
  scopes: z4.array(z4.string()),
592
+ /**
593
+ * Server-derived convenience flag: `true` when this key is read-only (carries
594
+ * the `read` scope and no write-granting scope), in which case the API rejects
595
+ * every write HTTP method for it. Derived from `scopes` via `isReadOnlyKey`
596
+ * — surfaces don't recompute it (see the UI/CLI parity rule). Additive field.
597
+ */
598
+ readOnly: z4.boolean(),
582
599
  createdAt: z4.string(),
583
600
  lastUsedAt: z4.string().nullable(),
584
601
  revokedAt: z4.string().nullable()
@@ -2501,6 +2518,22 @@ var agentMemoryDeleteRequestSchema = z21.object({
2501
2518
 
2502
2519
  // ../contracts/src/backlinks.ts
2503
2520
  import { z as z22 } from "zod";
2521
+ var backlinkSourceSchema = z22.enum(["commoncrawl", "bing-webmaster"]);
2522
+ var BacklinkSources = backlinkSourceSchema.enum;
2523
+ function computeBacklinkSummaryMetrics(rows) {
2524
+ if (rows.length === 0) {
2525
+ return { totalLinkingDomains: 0, totalHosts: 0, top10HostsShare: "0" };
2526
+ }
2527
+ const sorted = [...rows].sort((a, b) => b.numHosts - a.numHosts);
2528
+ const totalHosts = sorted.reduce((acc, r) => acc + r.numHosts, 0);
2529
+ const top10Hosts = sorted.slice(0, 10).reduce((acc, r) => acc + r.numHosts, 0);
2530
+ const share = totalHosts > 0 ? top10Hosts / totalHosts : 0;
2531
+ return {
2532
+ totalLinkingDomains: rows.length,
2533
+ totalHosts,
2534
+ top10HostsShare: share.toFixed(6)
2535
+ };
2536
+ }
2504
2537
  var ccReleaseSyncStatusSchema = z22.enum(["queued", "downloading", "querying", "ready", "failed"]);
2505
2538
  var CcReleaseSyncStatuses = ccReleaseSyncStatusSchema.enum;
2506
2539
  var ccReleaseSyncDtoSchema = z22.object({
@@ -2526,16 +2559,24 @@ var ccReleaseSyncDtoSchema = z22.object({
2526
2559
  });
2527
2560
  var backlinkDomainDtoSchema = z22.object({
2528
2561
  linkingDomain: z22.string(),
2529
- numHosts: z22.number().int()
2562
+ // For Common Crawl this is the count of distinct hosts within the linking
2563
+ // domain; for Bing Webmaster it is the count of distinct linking pages (URLs)
2564
+ // from that linking host. Read alongside `source` — the unit differs per source.
2565
+ numHosts: z22.number().int(),
2566
+ source: backlinkSourceSchema
2530
2567
  });
2531
2568
  var backlinkSummaryDtoSchema = z22.object({
2532
2569
  projectId: z22.string(),
2570
+ // Window identifier. Common Crawl uses the release slug
2571
+ // (`cc-main-YYYY-<mon>-<mon>-<mon>`); Bing Webmaster uses a synthetic
2572
+ // per-sync-day window (`bing-YYYY-MM-DD`).
2533
2573
  release: z22.string(),
2534
2574
  targetDomain: z22.string(),
2535
2575
  totalLinkingDomains: z22.number().int(),
2536
2576
  totalHosts: z22.number().int(),
2537
2577
  top10HostsShare: z22.string(),
2538
2578
  queriedAt: z22.string(),
2579
+ source: backlinkSourceSchema,
2539
2580
  // Populated when the response is filtered (e.g. ?excludeCrawlers=1).
2540
2581
  // Counts the rows omitted from totalLinkingDomains/totalHosts so callers
2541
2582
  // can show "N hidden" hints without re-deriving them.
@@ -2543,6 +2584,9 @@ var backlinkSummaryDtoSchema = z22.object({
2543
2584
  excludedHosts: z22.number().int().optional()
2544
2585
  });
2545
2586
  var backlinkListResponseSchema = z22.object({
2587
+ // The source this response was filtered to (defaults to commoncrawl when the
2588
+ // caller omits `?source`).
2589
+ source: backlinkSourceSchema,
2546
2590
  summary: backlinkSummaryDtoSchema.nullable(),
2547
2591
  total: z22.number().int(),
2548
2592
  rows: z22.array(backlinkDomainDtoSchema)
@@ -2552,7 +2596,38 @@ var backlinkHistoryEntrySchema = z22.object({
2552
2596
  totalLinkingDomains: z22.number().int(),
2553
2597
  totalHosts: z22.number().int(),
2554
2598
  top10HostsShare: z22.string(),
2555
- queriedAt: z22.string()
2599
+ queriedAt: z22.string(),
2600
+ source: backlinkSourceSchema
2601
+ });
2602
+ var backlinkSourceAvailabilityDtoSchema = z22.object({
2603
+ source: backlinkSourceSchema,
2604
+ /**
2605
+ * The source is set up for this project:
2606
+ * - commoncrawl: `autoExtractBacklinks` enabled AND a `ready` release sync exists.
2607
+ * - bing-webmaster: a Bing Webmaster connection exists for the project domain.
2608
+ */
2609
+ connected: z22.boolean(),
2610
+ /** Backlink rows exist for this project + source. */
2611
+ hasData: z22.boolean(),
2612
+ /** Latest window id with data for this source, null when none. */
2613
+ latestRelease: z22.string().nullable(),
2614
+ /**
2615
+ * Linking-domain count in the latest window. Excludes crawler/proxy hosts only
2616
+ * when the request sets `?excludeCrawlers=1` (default off, matching the summary
2617
+ * and domains endpoints); the dashboard passes it so the switcher pill matches
2618
+ * the metric card.
2619
+ */
2620
+ totalLinkingDomains: z22.number().int(),
2621
+ /** Freshness: `queriedAt` of the latest summary for this source, null when none. */
2622
+ lastSyncedAt: z22.string().nullable()
2623
+ });
2624
+ var backlinkSourcesResponseSchema = z22.object({
2625
+ projectId: z22.string(),
2626
+ targetDomain: z22.string(),
2627
+ /** Availability for every known source, in a stable order. */
2628
+ sources: z22.array(backlinkSourceAvailabilityDtoSchema),
2629
+ anyConnected: z22.boolean(),
2630
+ anyData: z22.boolean()
2556
2631
  });
2557
2632
  var backlinksInstallStatusDtoSchema = z22.object({
2558
2633
  duckdbInstalled: z22.boolean(),
@@ -3023,6 +3098,17 @@ function absolutizeProjectUrl(url, canonicalDomain) {
3023
3098
  if (trimmed.startsWith("/")) return `https://${host}${trimmed}`;
3024
3099
  return `https://${host}/${trimmed}`;
3025
3100
  }
3101
+ function hostOf(value) {
3102
+ if (value == null) return null;
3103
+ const trimmed = value.trim();
3104
+ if (!trimmed) return null;
3105
+ try {
3106
+ const url = trimmed.includes("://") ? new URL(trimmed) : new URL(`https://${trimmed}`);
3107
+ return url.hostname.replace(/^www\./, "").toLowerCase();
3108
+ } catch {
3109
+ return null;
3110
+ }
3111
+ }
3026
3112
  function normalizeUrlPath(input) {
3027
3113
  if (input == null) return null;
3028
3114
  let trimmed = input.trim();
@@ -4610,11 +4696,15 @@ export {
4610
4696
  AGENT_MEMORY_KEY_MAX_LENGTH,
4611
4697
  agentMemoryUpsertRequestSchema,
4612
4698
  agentMemoryDeleteRequestSchema,
4699
+ backlinkSourceSchema,
4700
+ BacklinkSources,
4701
+ computeBacklinkSummaryMetrics,
4613
4702
  CcReleaseSyncStatuses,
4614
4703
  ccReleaseSyncDtoSchema,
4615
4704
  backlinkSummaryDtoSchema,
4616
4705
  backlinkListResponseSchema,
4617
4706
  backlinkHistoryEntrySchema,
4707
+ backlinkSourcesResponseSchema,
4618
4708
  backlinksInstallStatusDtoSchema,
4619
4709
  backlinksInstallResultDtoSchema,
4620
4710
  ccAvailableReleaseSchema,
@@ -4643,6 +4733,7 @@ export {
4643
4733
  doctorReportSchema,
4644
4734
  summarizeCheckResults,
4645
4735
  absolutizeProjectUrl,
4736
+ hostOf,
4646
4737
  normalizeUrlPath,
4647
4738
  citationVisibilityResponseSchema,
4648
4739
  emptyCitationVisibility,
@@ -4706,5 +4797,7 @@ export {
4706
4797
  AI_ENGINE_SELF_DOMAINS,
4707
4798
  VERTEX_AI_SEARCH_PROXY_DOMAIN,
4708
4799
  AI_PROVIDER_INFRA_DOMAINS,
4709
- escapeLikePattern
4800
+ escapeLikePattern,
4801
+ READ_ONLY_SCOPE,
4802
+ isReadOnlyKey
4710
4803
  };