@canonry/canonry 7.77.1 → 7.78.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 (139) hide show
  1. package/assets/agent-workspace/skills/aero/references/seo-analysis.md +13 -2
  2. package/assets/agent-workspace/skills/canonry/references/canonry-cli.md +4 -2
  3. package/assets/assets/{AgentSetupPage-BZXWC3x6.js → AgentSetupPage-BGdvyQFL.js} +4 -4
  4. package/assets/assets/{AuditHistoryPanel-DcrUuwRu.js → AuditHistoryPanel-Bb5wq-Bk.js} +1 -1
  5. package/assets/assets/{BacklinksPage-BSpHJBiy.js → BacklinksPage-i1cfxTDj.js} +1 -1
  6. package/assets/assets/{HistoryPage-0a0CK9zF.js → HistoryPage-C2NRdNrn.js} +1 -1
  7. package/assets/assets/MeasurementPropertyPage-CwPuJMBy.js +4 -0
  8. package/assets/assets/ProjectPage-Bbnbg7c9.js +11 -0
  9. package/assets/assets/{RunsPage-D0vbz1Ho.js → RunsPage-CJHJ7kHk.js} +1 -1
  10. package/assets/assets/{SettingsPage-DjRm5cmn.js → SettingsPage-r8VrtFyJ.js} +1 -1
  11. package/assets/assets/SiteHealthSection-D1oSuo9O.js +2 -0
  12. package/assets/assets/ToneBadge-CUe-WrzN.js +60 -0
  13. package/assets/assets/{TrafficPage-Z8Z_z0k9.js → TrafficPage-DY2ykwH1.js} +1 -1
  14. package/assets/assets/TrafficSourceDetailPage-D3KHgRvF.js +1 -0
  15. package/assets/assets/{account-context-zaSxLBst.js → account-context-B50QqDEA.js} +1 -1
  16. package/assets/assets/{card-COqALGzB.js → card-BE2fqwVq.js} +1 -1
  17. package/assets/assets/{extract-error-message-DKve0SNr.js → extract-error-message-xuN_xeRJ.js} +1 -1
  18. package/assets/assets/{format-helpers-DKrHlaV7.js → format-helpers-CiC6gALY.js} +1 -1
  19. package/assets/assets/{index-CKZK95pI.css → index-CHHZDc6d.css} +1 -1
  20. package/assets/assets/{index-fzqtwr6m.js → index-Dfm8z5cG.js} +23 -23
  21. package/assets/assets/{query-client-COM9uzxL.js → query-client-C5GhDMY7.js} +1 -1
  22. package/assets/assets/react-query-CmHyfYFq.js +1 -0
  23. package/assets/assets/{react-sigma_core.esm.min-e91U3Myi.js → react-sigma_core.esm.min-Bjdtl0TQ.js} +1 -1
  24. package/assets/assets/{service-BgFTYqJA.js → service-B2i_ZzWP.js} +1 -1
  25. package/assets/index.html +8 -8
  26. package/dist/{ads-M6IAQDG7.js → ads-MIR5MCHL.js} +3 -3
  27. package/dist/{agent-X2T5X5K3.js → agent-IXRL5RBI.js} +7 -7
  28. package/dist/{agent-ask-55LQH4TI.js → agent-ask-K42H6H2T.js} +3 -3
  29. package/dist/{agent-conversations-O6WC2NPV.js → agent-conversations-2T3W4DHO.js} +3 -3
  30. package/dist/{agent-memory-6DWFMB4I.js → agent-memory-LJBNSTSP.js} +3 -3
  31. package/dist/{agent-providers-Q4YDVQX3.js → agent-providers-QR4LY3AP.js} +3 -3
  32. package/dist/{agent-transcript-SJKCP2AO.js → agent-transcript-JIHJWHV6.js} +3 -3
  33. package/dist/{analytics-4JOQMWH7.js → analytics-JRV7DBBU.js} +3 -3
  34. package/dist/{apply-EAKKKIZD.js → apply-ZFWDSAV4.js} +3 -3
  35. package/dist/{backfill-PASKIVGP.js → backfill-LU2AQIPY.js} +9 -9
  36. package/dist/{backlinks-TICPC323.js → backlinks-NAC2373F.js} +3 -3
  37. package/dist/{bing-MC7TSL4E.js → bing-L3LDBJOC.js} +3 -3
  38. package/dist/{bootstrap-X2BW64W7.js → bootstrap-I6DA4KWB.js} +10 -10
  39. package/dist/{cdp-TCJKITCR.js → cdp-4F74XLTH.js} +7 -7
  40. package/dist/{chunk-CCNPBUQ5.js → chunk-367K6XVX.js} +2 -2
  41. package/dist/{chunk-JPOIDGGF.js → chunk-3MGM3U6V.js} +1 -1
  42. package/dist/{chunk-2BDWXHYF.js → chunk-45RGH7XI.js} +3 -3
  43. package/dist/{chunk-RPJJOBKN.js → chunk-6ACWXQNZ.js} +3 -1
  44. package/dist/{chunk-B7JHQ3FW.js → chunk-6P6YBNKN.js} +7 -7
  45. package/dist/{chunk-YMOQSEO3.js → chunk-6PRFVLIK.js} +15 -4
  46. package/dist/{chunk-D5XPB7MM.js → chunk-6VBLPCCX.js} +1 -1
  47. package/dist/{chunk-5QR7D4RQ.js → chunk-7HB6QLX4.js} +1 -1
  48. package/dist/{chunk-7UVCZZQJ.js → chunk-AI44ZCMK.js} +1 -1
  49. package/dist/{chunk-X7UC755Q.js → chunk-C5WSQXP5.js} +26 -2
  50. package/dist/{chunk-CQMNWC5K.js → chunk-EFMZSYRD.js} +160 -26
  51. package/dist/{chunk-FXIZBJZ4.js → chunk-EHXNYXAS.js} +3 -3
  52. package/dist/{chunk-2WBT6TEJ.js → chunk-FCYGY4FT.js} +1 -1
  53. package/dist/{chunk-XYYWKCJQ.js → chunk-JERATA5R.js} +1 -1
  54. package/dist/{chunk-P3BWUKJL.js → chunk-JEUL5QZP.js} +4 -4
  55. package/dist/{chunk-PSNTEGNY.js → chunk-KZB6HLFT.js} +1 -1
  56. package/dist/{chunk-UGNNR7EO.js → chunk-L2KMR7CM.js} +2 -2
  57. package/dist/{chunk-H4ANN32B.js → chunk-L6F2HOQH.js} +8 -8
  58. package/dist/{chunk-GDKMVOZI.js → chunk-M3BUP6XD.js} +104 -13
  59. package/dist/{chunk-4QHTXT4A.js → chunk-MUYTDD35.js} +40 -4
  60. package/dist/{chunk-TESDUMVK.js → chunk-O4WBYEGV.js} +1 -1
  61. package/dist/{chunk-FCGYYZHL.js → chunk-PM2DB3HE.js} +164 -10
  62. package/dist/{chunk-TRW4XLQK.js → chunk-QXSOXDUR.js} +2 -2
  63. package/dist/{chunk-2SCPPWRW.js → chunk-RSVANBNW.js} +4 -4
  64. package/dist/{chunk-UB65XBH2.js → chunk-SAHH2FXO.js} +3 -3
  65. package/dist/{chunk-46KV7CZU.js → chunk-SOQVI7EZ.js} +2 -2
  66. package/dist/{chunk-Z2FY6AGZ.js → chunk-TZRYVW75.js} +2 -2
  67. package/dist/{chunk-C3UFOS7J.js → chunk-UH44UCRM.js} +2 -2
  68. package/dist/{chunk-TJYS2XCI.js → chunk-UQOC5ZQE.js} +4 -4
  69. package/dist/{chunk-2BRVGCVU.js → chunk-VLOCDWCS.js} +7 -1
  70. package/dist/{chunk-6EZQHF67.js → chunk-WCFANFR2.js} +371 -340
  71. package/dist/{chunk-ZXYCPRNY.js → chunk-WSWHLKKJ.js} +1 -1
  72. package/dist/{chunk-NDTU7FGL.js → chunk-WVCDUKJ2.js} +1 -1
  73. package/dist/{chunk-JZT3ZRD3.js → chunk-WXIL2EFM.js} +4 -4
  74. package/dist/{chunk-JSCO223C.js → chunk-ZHFE6J3A.js} +1 -1
  75. package/dist/{chunk-HD2VVIPD.js → chunk-ZUC7CJVD.js} +5 -5
  76. package/dist/{citations-IA3OCV53.js → citations-2XELMCCV.js} +3 -3
  77. package/dist/{cli-catalog-ZVFLJXID.js → cli-catalog-KC6JYHSW.js} +3 -3
  78. package/dist/{cli-commands-O7BYY3W5.js → cli-commands-WCOAB6XU.js} +7 -7
  79. package/dist/cli.js +13 -13
  80. package/dist/{competitor-4FVAZAQZ.js → competitor-IK4GYTZO.js} +3 -3
  81. package/dist/{content-OVBF6U7Z.js → content-SMQPJXPC.js} +3 -3
  82. package/dist/{dashboard-UGZSSIWK.js → dashboard-EE24ROVG.js} +6 -6
  83. package/dist/{demo-5CU3JDHC.js → demo-7XH2N65A.js} +1 -1
  84. package/dist/{demo-server-43QV3UKM.js → demo-server-CVB65UYW.js} +12 -12
  85. package/dist/{discover-R5BYAPOU.js → discover-3KHUCVE7.js} +3 -3
  86. package/dist/{discover-eval-3FA4BR2L.js → discover-eval-DOEP4ZQ7.js} +3 -3
  87. package/dist/{doctor-2Q5LVV2P.js → doctor-3T6RKSE7.js} +3 -3
  88. package/dist/{evidence-LMGRT5IO.js → evidence-4NFL5KM3.js} +3 -3
  89. package/dist/{export-cmd-LBLZ273Z.js → export-cmd-BQC6XLJ7.js} +3 -3
  90. package/dist/{ga-PBIWRU67.js → ga-HBRA4UUK.js} +3 -3
  91. package/dist/{gbp-NYG7SW6P.js → gbp-2WMBTDJV.js} +3 -3
  92. package/dist/{google-57XEYVOU.js → google-JFUE4BNJ.js} +4 -4
  93. package/dist/{google-marketing-XPE6CVQI.js → google-marketing-5ROIKBC7.js} +1 -1
  94. package/dist/{health-cmd-SJVYQZQL.js → health-cmd-7BMVCCG2.js} +3 -3
  95. package/dist/{history-5XYZNWGP.js → history-QA4ZXCVH.js} +3 -3
  96. package/dist/index.d.ts +216 -23
  97. package/dist/index.js +26 -26
  98. package/dist/{init-KXR6PJEQ.js → init-O4G2MDMC.js} +12 -12
  99. package/dist/{insights-L7OOH34I.js → insights-K4UX2PSI.js} +3 -3
  100. package/dist/intelligence-service-D7DS4UKT.js +16 -0
  101. package/dist/{journeys-VXBGDFBO.js → journeys-UWEWJXGT.js} +3 -3
  102. package/dist/{keys-YMB5HAAG.js → keys-CL5YYE7Q.js} +3 -3
  103. package/dist/{keyword-RZEMKH3K.js → keyword-IFCC5IZT.js} +3 -3
  104. package/dist/{logs-ONZWSYXS.js → logs-2A3HBUBK.js} +3 -3
  105. package/dist/{mcp-KK6EFHAZ.js → mcp-B6L7PKZ4.js} +4 -4
  106. package/dist/mcp.js +10 -10
  107. package/dist/{measurement-plan-LE7INWW6.js → measurement-plan-GYSO6CXX.js} +5 -5
  108. package/dist/{notify-T6T5LYRR.js → notify-XM23I2B3.js} +3 -3
  109. package/dist/{organic-evidence-P2GZ766W.js → organic-evidence-U7HZMXKP.js} +3 -3
  110. package/dist/{overview-P2AILIWJ.js → overview-TSAK5DQP.js} +4 -4
  111. package/dist/{project-7MHQSOJD.js → project-L7DLDEPI.js} +3 -3
  112. package/dist/{query-EUDMU6L7.js → query-FM5HDHO4.js} +3 -3
  113. package/dist/{research-4DASCVGY.js → research-7G5JU44N.js} +3 -3
  114. package/dist/{results-export-GKXHX55L.js → results-export-JJDGG6ZP.js} +3 -3
  115. package/dist/{run-6LJGMJ5S.js → run-ZVIQVG23.js} +4 -4
  116. package/dist/{schedule-D74P2BO5.js → schedule-TV7LWSYI.js} +3 -3
  117. package/dist/{search-W7AOYWRM.js → search-7KRZLZ6S.js} +3 -3
  118. package/dist/{serve-UNVCQSRC.js → serve-WSOG525W.js} +27 -27
  119. package/dist/{session-6NGNVCKP.js → session-OUGQSGVV.js} +14 -14
  120. package/dist/{settings-LGD64PFE.js → settings-AOXQJOHN.js} +3 -3
  121. package/dist/{skills-CYHWYN42.js → skills-DWXA55QA.js} +2 -2
  122. package/dist/{snapshot-PDYGSZZH.js → snapshot-B44CXKFU.js} +3 -3
  123. package/dist/{src-SXB3MOP3.js → src-IBGSUYEG.js} +2 -2
  124. package/dist/{status-UZ4SE7ZP.js → status-RNBSFZ6Q.js} +4 -4
  125. package/dist/{technical-aeo-BNH7NV44.js → technical-aeo-UAOKK5QH.js} +3 -3
  126. package/dist/{telemetry-UWDS7QNJ.js → telemetry-55PUOMA7.js} +4 -4
  127. package/dist/{tools-EDPBQCI2.js → tools-HRGP4FXN.js} +11 -11
  128. package/dist/{traffic-NI6ACQO4.js → traffic-M4OHG5JW.js} +5 -5
  129. package/dist/{users-XTZ65NLC.js → users-GU7MULRM.js} +3 -3
  130. package/dist/{visibility-stats-EPF6MHYQ.js → visibility-stats-4IDTDXDC.js} +3 -3
  131. package/dist/{wordpress-ZACJ3H5M.js → wordpress-CYXB4R5Y.js} +3 -3
  132. package/package.json +1 -1
  133. package/assets/assets/MeasurementPropertyPage-DbfTFN3F.js +0 -4
  134. package/assets/assets/ProjectPage-D0m-Xpp3.js +0 -9
  135. package/assets/assets/SiteHealthSection-BCdPVFEJ.js +0 -2
  136. package/assets/assets/ToneBadge-DSJSzqI6.js +0 -60
  137. package/assets/assets/TrafficSourceDetailPage-DJyDO527.js +0 -1
  138. package/assets/assets/react-query-BVRWpXWq.js +0 -1
  139. package/dist/intelligence-service-NXZYQJBH.js +0 -16
@@ -3,7 +3,7 @@ import {
3
3
  resolveCliAccess,
4
4
  resolveCliAccessForInvocation,
5
5
  windowOptions
6
- } from "./chunk-RPJJOBKN.js";
6
+ } from "./chunk-6ACWXQNZ.js";
7
7
  import {
8
8
  emitJsonl
9
9
  } from "./chunk-Z7IUAJOF.js";
@@ -14,7 +14,7 @@ import {
14
14
  } from "./chunk-HGMYEDAQ.js";
15
15
  import {
16
16
  OperationAccesses
17
- } from "./chunk-FCGYYZHL.js";
17
+ } from "./chunk-PM2DB3HE.js";
18
18
 
19
19
  // src/cli-catalog.ts
20
20
  import { createRequire } from "module";
@@ -111,7 +111,7 @@ async function dispatchRegisteredCommand(args, fallbackFormat, specs) {
111
111
  const accessValue = accessFilterFromArgs(argsWithoutHelp);
112
112
  validateAccessFilter(accessValue);
113
113
  if (fallbackFormat !== "text") {
114
- const { printCliCatalog: printCliCatalog2 } = await import("./cli-catalog-ZVFLJXID.js");
114
+ const { printCliCatalog: printCliCatalog2 } = await import("./cli-catalog-KC6JYHSW.js");
115
115
  const group2 = argsWithoutHelp.find((arg) => !arg.startsWith("--"));
116
116
  printCliCatalog2(specs, fallbackFormat, group2, accessValue);
117
117
  return true;
@@ -5,7 +5,7 @@ import {
5
5
  AppError,
6
6
  parseWindowIn,
7
7
  resolveDateRange
8
- } from "./chunk-FCGYYZHL.js";
8
+ } from "./chunk-PM2DB3HE.js";
9
9
 
10
10
  // src/cli-access.ts
11
11
  var CLI_ACCESS_BY_ID = Object.freeze({
@@ -329,8 +329,10 @@ var CLI_ACCESS_BY_ID = Object.freeze({
329
329
  "sentiment.job": "stored",
330
330
  "sentiment.jobs": "stored",
331
331
  "sentiment.settings": "stored",
332
+ "seo.competitors": "stored",
332
333
  "seo.context": "stored",
333
334
  "seo.domain-intelligence": "stored",
335
+ "seo.keyword-gaps": "stored",
334
336
  "seo.keyword-metrics": "stored",
335
337
  "seo.market-rankings": "stored",
336
338
  "seo.market-summary": "stored",
@@ -5,10 +5,10 @@ import {
5
5
  isStoredPageReadTool,
6
6
  isStoredReadTool,
7
7
  truncateToolResult
8
- } from "./chunk-JZT3ZRD3.js";
8
+ } from "./chunk-WXIL2EFM.js";
9
9
  import {
10
10
  CANONRY_MCP_TOOLKITS
11
- } from "./chunk-NDTU7FGL.js";
11
+ } from "./chunk-WVCDUKJ2.js";
12
12
  import {
13
13
  AGENT_REASONING_LEVELS,
14
14
  aeroStreamFn,
@@ -22,18 +22,18 @@ import {
22
22
  resolveApiKeyFor,
23
23
  resolveModelForProvider,
24
24
  validateAgentProviderRegistry
25
- } from "./chunk-2BRVGCVU.js";
25
+ } from "./chunk-VLOCDWCS.js";
26
26
  import {
27
27
  CanonryMcpToolNames,
28
28
  canonryMcpTools
29
- } from "./chunk-4QHTXT4A.js";
29
+ } from "./chunk-MUYTDD35.js";
30
30
  import {
31
31
  createLogger
32
- } from "./chunk-Z2FY6AGZ.js";
32
+ } from "./chunk-TZRYVW75.js";
33
33
  import {
34
34
  agentToolEvents,
35
35
  llmUsageEvents
36
- } from "./chunk-D5XPB7MM.js";
36
+ } from "./chunk-6VBLPCCX.js";
37
37
  import {
38
38
  MeasurementPortfolioLists,
39
39
  SeoCapabilities,
@@ -42,7 +42,7 @@ import {
42
42
  describeError,
43
43
  validationError,
44
44
  visibilityReportRequestSchema
45
- } from "./chunk-FCGYYZHL.js";
45
+ } from "./chunk-PM2DB3HE.js";
46
46
 
47
47
  // src/agent/session.ts
48
48
  import fs3 from "fs";
@@ -5,7 +5,7 @@ import {
5
5
  loadConfig,
6
6
  loadConfigRaw,
7
7
  saveConfigPatch
8
- } from "./chunk-2BRVGCVU.js";
8
+ } from "./chunk-VLOCDWCS.js";
9
9
  import {
10
10
  CANONRY_NPM_PACKAGE_URL,
11
11
  compareSemver,
@@ -18,7 +18,7 @@ import {
18
18
  updateCheckEnvOptOut,
19
19
  upgradeCaveatFor,
20
20
  upgradeCommandFor
21
- } from "./chunk-FCGYYZHL.js";
21
+ } from "./chunk-PM2DB3HE.js";
22
22
 
23
23
  // src/runtime-context.ts
24
24
  function cliRuntimeContext(env = process.env, stdio = process) {
@@ -389,11 +389,11 @@ function getOrCreateAnonymousId() {
389
389
  try {
390
390
  const config = loadConfig();
391
391
  if (config.anonymousId) return config.anonymousId;
392
+ if (anonymousIdWriteHolds > 0) return getDeterministicAnonymousId();
392
393
  const carried = preConfigAnonymousId?.configPath === getConfigPath() ? preConfigAnonymousId.id : void 0;
393
394
  const id = carried ?? crypto.randomUUID();
394
- config.anonymousId = id;
395
395
  try {
396
- saveConfigPatch(config);
396
+ saveConfigPatch({ anonymousId: id });
397
397
  } catch {
398
398
  return getDeterministicAnonymousId();
399
399
  }
@@ -407,6 +407,16 @@ function getOrCreateAnonymousId() {
407
407
  return fallback;
408
408
  }
409
409
  var preConfigAnonymousId;
410
+ var anonymousIdWriteHolds = 0;
411
+ function holdAnonymousIdWrites() {
412
+ anonymousIdWriteHolds += 1;
413
+ let held = true;
414
+ return () => {
415
+ if (!held) return;
416
+ held = false;
417
+ anonymousIdWriteHolds -= 1;
418
+ };
419
+ }
410
420
  function readEnvAnonymousId() {
411
421
  const raw = process.env[ANON_ID_ENV_VAR]?.trim();
412
422
  if (!raw) return void 0;
@@ -600,6 +610,7 @@ export {
600
610
  getTelemetryStatus,
601
611
  isTelemetryEnabled,
602
612
  getOrCreateAnonymousId,
613
+ holdAnonymousIdWrites,
603
614
  isFirstRun,
604
615
  showFirstRunNotice,
605
616
  detectAndTrackUpgrade,
@@ -20,7 +20,7 @@ import {
20
20
  templateLinkRatio,
21
21
  templateLinkUbiquityAvailable,
22
22
  validationError
23
- } from "./chunk-FCGYYZHL.js";
23
+ } from "./chunk-PM2DB3HE.js";
24
24
  import {
25
25
  __export
26
26
  } from "./chunk-MLKGABMK.js";
@@ -23,7 +23,7 @@ import {
23
23
  measurementDraftUpsertGroupRequestSchema,
24
24
  measurementDraftUpsertMarketRequestSchema,
25
25
  measurementDraftUpsertTargetRequestSchema
26
- } from "./chunk-FCGYYZHL.js";
26
+ } from "./chunk-PM2DB3HE.js";
27
27
 
28
28
  // src/measurement-draft-actions.ts
29
29
  import { z } from "zod";
@@ -15,7 +15,7 @@ import {
15
15
  formatCanonryPluginUpdateHint,
16
16
  formatCanonryPluginVersionMismatch,
17
17
  skillsClientSchema
18
- } from "./chunk-FCGYYZHL.js";
18
+ } from "./chunk-PM2DB3HE.js";
19
19
 
20
20
  // src/commands/skills.ts
21
21
  import crypto from "crypto";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  loadConfig
3
- } from "./chunk-2BRVGCVU.js";
3
+ } from "./chunk-VLOCDWCS.js";
4
4
  import {
5
5
  PACKAGE_VERSION
6
6
  } from "./chunk-AOJU5LKX.js";
@@ -36,7 +36,7 @@ import {
36
36
  sentimentSettingsReadSchema,
37
37
  sentimentSummaryReadSchema,
38
38
  upgradeCommandFor
39
- } from "./chunk-FCGYYZHL.js";
39
+ } from "./chunk-PM2DB3HE.js";
40
40
 
41
41
  // ../api-client-generated/src/generated/core/bodySerializer.gen.ts
42
42
  var jsonBodySerializer = {
@@ -900,6 +900,16 @@ var getApiV1ProjectsByNameSeoRankedKeywords = (options) => (options.client ?? cl
900
900
  url: "/api/v1/projects/{name}/seo/ranked-keywords",
901
901
  ...options
902
902
  });
903
+ var getApiV1ProjectsByNameSeoCompetitors = (options) => (options.client ?? client).get({
904
+ security: [{ scheme: "bearer", type: "http" }],
905
+ url: "/api/v1/projects/{name}/seo/competitors",
906
+ ...options
907
+ });
908
+ var getApiV1ProjectsByNameSeoKeywordGaps = (options) => (options.client ?? client).get({
909
+ security: [{ scheme: "bearer", type: "http" }],
910
+ url: "/api/v1/projects/{name}/seo/keyword-gaps",
911
+ ...options
912
+ });
903
913
  var getApiV1ProjectsByNameSeoMarketRankings = (options) => (options.client ?? client).get({
904
914
  security: [{ scheme: "bearer", type: "http" }],
905
915
  url: "/api/v1/projects/{name}/seo/market-rankings",
@@ -6220,6 +6230,20 @@ var ApiClient = class {
6220
6230
  query
6221
6231
  }));
6222
6232
  }
6233
+ async getSeoCompetitors(project, query) {
6234
+ return this.invoke(() => getApiV1ProjectsByNameSeoCompetitors({
6235
+ client: this.heyClient,
6236
+ path: { name: project },
6237
+ query
6238
+ }));
6239
+ }
6240
+ async getSeoKeywordGaps(project, query) {
6241
+ return this.invoke(() => getApiV1ProjectsByNameSeoKeywordGaps({
6242
+ client: this.heyClient,
6243
+ path: { name: project },
6244
+ query
6245
+ }));
6246
+ }
6223
6247
  async getSeoMarketRankings(project, query) {
6224
6248
  return this.invoke(() => getApiV1ProjectsByNameSeoMarketRankings({
6225
6249
  client: this.heyClient,
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  answerServiceAdapters,
3
3
  answerServiceDescriptors
4
- } from "./chunk-ZXYCPRNY.js";
4
+ } from "./chunk-WSWHLKKJ.js";
5
5
  import {
6
6
  AeroLlmUsageFeatures,
7
7
  aeroTurnStatus,
@@ -27,14 +27,14 @@ import {
27
27
  resolveConfiguredAgentProvider,
28
28
  resolveSessionProviderAndModel,
29
29
  setAeroSystemPrompt
30
- } from "./chunk-B7JHQ3FW.js";
30
+ } from "./chunk-6P6YBNKN.js";
31
31
  import {
32
32
  AeroToolProfiles,
33
33
  AeroToolScopes,
34
34
  buildAeroStateTools,
35
35
  isAeroToolProfile,
36
36
  truncateToolResult
37
- } from "./chunk-JZT3ZRD3.js";
37
+ } from "./chunk-WXIL2EFM.js";
38
38
  import {
39
39
  getGoogleAuthConfig,
40
40
  getGoogleConnection,
@@ -53,7 +53,7 @@ import {
53
53
  removeCloudflareTrafficConnection,
54
54
  removeCloudflareTrafficConnectionBySourceId,
55
55
  upsertCloudflareTrafficConnection
56
- } from "./chunk-PSNTEGNY.js";
56
+ } from "./chunk-KZB6HLFT.js";
57
57
  import {
58
58
  claudeAdapter,
59
59
  embedQueries,
@@ -64,7 +64,7 @@ import {
64
64
  openaiAdapter,
65
65
  openrouterAdapter,
66
66
  perplexityAdapter
67
- } from "./chunk-C3UFOS7J.js";
67
+ } from "./chunk-UH44UCRM.js";
68
68
  import {
69
69
  classifyUsageSurface,
70
70
  createApiUsageTelemetry,
@@ -76,7 +76,7 @@ import {
76
76
  startOutcomeTimer,
77
77
  trackFeatureCompleted,
78
78
  trackInstallState
79
- } from "./chunk-TJYS2XCI.js";
79
+ } from "./chunk-UQOC5ZQE.js";
80
80
  import {
81
81
  isLoopbackBindHost
82
82
  } from "./chunk-TSENU4GG.js";
@@ -84,28 +84,29 @@ import {
84
84
  isApiProviderRegistrable,
85
85
  isCdpProviderRegistrable,
86
86
  registeredProviderNames
87
- } from "./chunk-2WBT6TEJ.js";
87
+ } from "./chunk-FCYGY4FT.js";
88
88
  import {
89
89
  checkLatestVersionForServer,
90
90
  getOrCreateAnonymousId,
91
91
  getServerUpdateStatus,
92
92
  getTelemetryStatus,
93
+ holdAnonymousIdWrites,
93
94
  installAttribution,
94
95
  isTelemetryEnabled,
95
96
  recordDashboardEvent,
96
97
  setTelemetryPreference,
97
98
  trackEvent
98
- } from "./chunk-YMOQSEO3.js";
99
+ } from "./chunk-6PRFVLIK.js";
99
100
  import {
100
101
  createCanonryMcpServer
101
- } from "./chunk-2SCPPWRW.js";
102
+ } from "./chunk-RSVANBNW.js";
102
103
  import {
103
104
  CANONRY_MCP_TIERS,
104
105
  CANONRY_MCP_TOOLKIT_NAMES
105
- } from "./chunk-NDTU7FGL.js";
106
+ } from "./chunk-WVCDUKJ2.js";
106
107
  import {
107
108
  ApiClient
108
- } from "./chunk-X7UC755Q.js";
109
+ } from "./chunk-C5WSQXP5.js";
109
110
  import {
110
111
  AGENT_PROVIDERS,
111
112
  adapterSupportsBatch,
@@ -124,6 +125,7 @@ import {
124
125
  isAgentModelUnchecked,
125
126
  loadConfig,
126
127
  loadConfigRaw,
128
+ loadedConfigPath,
127
129
  openRouterModels,
128
130
  providerConfigFromEntry,
129
131
  providersWithUnsupportedBatch,
@@ -136,21 +138,21 @@ import {
136
138
  saveConfigPatch,
137
139
  sentimentInstallReadiness,
138
140
  updateSharedProviderExecutionGate
139
- } from "./chunk-2BRVGCVU.js";
141
+ } from "./chunk-VLOCDWCS.js";
140
142
  import {
141
143
  getBundledSkillSnapshots
142
- } from "./chunk-7UVCZZQJ.js";
144
+ } from "./chunk-AI44ZCMK.js";
143
145
  import {
144
146
  computeFactorAverages,
145
147
  deleteSiteCrawlGraphLayout,
146
148
  persistSiteCrawlGraphLayout,
147
149
  prepareSiteCrawlGraphLayout,
148
150
  recordedSharePct
149
- } from "./chunk-46KV7CZU.js";
151
+ } from "./chunk-SOQVI7EZ.js";
150
152
  import {
151
153
  CanonryMcpToolNames,
152
154
  canonryMcpTools
153
- } from "./chunk-4QHTXT4A.js";
155
+ } from "./chunk-MUYTDD35.js";
154
156
  import {
155
157
  PACKAGE_VERSION
156
158
  } from "./chunk-AOJU5LKX.js";
@@ -159,16 +161,16 @@ import {
159
161
  } from "./chunk-HGMYEDAQ.js";
160
162
  import {
161
163
  IntelligenceService
162
- } from "./chunk-HD2VVIPD.js";
164
+ } from "./chunk-ZUC7CJVD.js";
163
165
  import {
164
166
  addLogListener,
165
167
  createFastifyLogger,
166
168
  createLogger
167
- } from "./chunk-Z2FY6AGZ.js";
169
+ } from "./chunk-TZRYVW75.js";
168
170
  import {
169
171
  computeCitedCompetitorDomains,
170
172
  determineCitationState
171
- } from "./chunk-XYYWKCJQ.js";
173
+ } from "./chunk-JERATA5R.js";
172
174
  import {
173
175
  BingApiError,
174
176
  CC_CACHE_DIR,
@@ -289,7 +291,7 @@ import {
289
291
  webhookResponseReason,
290
292
  webhookTargetRefusalReason,
291
293
  writeAuditLog
292
- } from "./chunk-GDKMVOZI.js";
294
+ } from "./chunk-M3BUP6XD.js";
293
295
  import {
294
296
  OperationalLogStore,
295
297
  SentimentIdempotencyConflict,
@@ -375,7 +377,7 @@ import {
375
377
  siteLivenessState,
376
378
  trafficSources,
377
379
  usageCounters
378
- } from "./chunk-D5XPB7MM.js";
380
+ } from "./chunk-6VBLPCCX.js";
379
381
  import {
380
382
  AGENT_MEMORY_VALUE_MAX_BYTES,
381
383
  AI_ENGINE_DOMAINS,
@@ -455,6 +457,7 @@ import {
455
457
  SentimentOutcomes,
456
458
  SeoAdapterOutcomes,
457
459
  SeoCapabilities,
460
+ SeoKeywordGapModes,
458
461
  SeoMarketRankingSearchStatuses,
459
462
  SeoProviders,
460
463
  SeoRunStatuses,
@@ -574,6 +577,7 @@ import {
574
577
  normalizeIdTokens,
575
578
  normalizeMeasurementExecutionQueryText,
576
579
  normalizeProjectDomain,
580
+ normalizeQueryText,
577
581
  normalizeServedModel,
578
582
  normalizeSiteAuditRunRequest,
579
583
  normalizeUrlPath,
@@ -604,6 +608,8 @@ import {
604
608
  sentimentEvaluatorProvider,
605
609
  sentimentSelectionSchema,
606
610
  seoDeviceSchema,
611
+ seoKeywordGapComparison,
612
+ seoKeywordGapModeSchema,
607
613
  seoProfileInputSchema,
608
614
  seoRankingSettingsSchema,
609
615
  serializeForInlineScript,
@@ -627,7 +633,7 @@ import {
627
633
  winnabilityClassLabel,
628
634
  withRetry,
629
635
  withSkippedProviders
630
- } from "./chunk-FCGYYZHL.js";
636
+ } from "./chunk-PM2DB3HE.js";
631
637
 
632
638
  // src/google-marketing-runtime.ts
633
639
  import crypto2 from "crypto";
@@ -3457,8 +3463,27 @@ var resultSchema = z2.object({
3457
3463
  location_code: z2.number().int(),
3458
3464
  language_code: z2.string(),
3459
3465
  target: z2.string().optional(),
3466
+ target1: z2.string().optional(),
3467
+ target2: z2.string().optional(),
3460
3468
  items: z2.array(z2.unknown()).nullable()
3461
3469
  });
3470
+ var competitorItemSchema = z2.object({
3471
+ domain: z2.string(),
3472
+ intersections: count,
3473
+ avg_position: amount,
3474
+ full_domain_metrics: z2.object({ organic: z2.object({ count, etv: amount }).nullish() }).nullish()
3475
+ });
3476
+ var comparisonSerpSchema = z2.object({
3477
+ type: z2.literal("organic"),
3478
+ domain: z2.string(),
3479
+ url: z2.string().nullish(),
3480
+ rank_group: z2.number().int().positive()
3481
+ });
3482
+ var gapItemSchema = z2.object({
3483
+ keyword_data: keywordDataSchema,
3484
+ first_domain_serp_element: comparisonSerpSchema,
3485
+ second_domain_serp_element: comparisonSerpSchema.nullish()
3486
+ });
3462
3487
  var serpResultSchema = z2.object({
3463
3488
  keyword: z2.string(),
3464
3489
  location_code: z2.number().int(),
@@ -3568,11 +3593,75 @@ function normalizeDataForSeoResults(rawResults, request, collectedAt, options =
3568
3593
  throw new Error("SEO provider returned a different market.");
3569
3594
  }
3570
3595
  const providerTarget = request.target?.kind === SeoTargetKinds.host ? registrableDomain(request.target.value) : request.target?.value.toLowerCase();
3571
- if (request.target && result.target?.toLowerCase() !== providerTarget) {
3596
+ if (request.capability === SeoCapabilities["keyword-gaps"]) {
3597
+ if (result.target1?.toLowerCase() !== request.comparison?.competitor.value.toLowerCase() || result.target2?.toLowerCase() !== providerTarget) {
3598
+ throw new Error("SEO provider returned a different comparison pair.");
3599
+ }
3600
+ } else if (request.target && result.target?.toLowerCase() !== providerTarget) {
3572
3601
  throw new Error("SEO provider returned a different target.");
3573
3602
  }
3574
3603
  const items = result.items ?? [];
3575
3604
  switch (request.capability) {
3605
+ case SeoCapabilities["competitor-discovery"]: {
3606
+ if (!request.target) throw new Error("SEO target is required.");
3607
+ const seen = /* @__PURE__ */ new Set();
3608
+ for (const rawItem of items) {
3609
+ const item = competitorItemSchema.parse(rawItem);
3610
+ const domain = normalizeHostname(item.domain);
3611
+ if (!domain || !registrableDomain(domain)) throw new Error("SEO provider returned an invalid competitor domain.");
3612
+ if (registrableDomain(domain) === request.target.value.toLowerCase() || seen.has(domain)) continue;
3613
+ seen.add(domain);
3614
+ output.competitors.push({
3615
+ target: request.target,
3616
+ domain,
3617
+ sharedKeywords: item.intersections ?? null,
3618
+ averagePosition: item.avg_position ?? null,
3619
+ organicKeywords: item.full_domain_metrics?.organic?.count ?? null,
3620
+ estimatedOrganicTraffic: item.full_domain_metrics?.organic?.etv ?? null,
3621
+ // The endpoint does not return its weekly dataset timestamp.
3622
+ provenance: provenance(request, collectedAt, null)
3623
+ });
3624
+ }
3625
+ break;
3626
+ }
3627
+ case SeoCapabilities["keyword-gaps"]: {
3628
+ if (!request.target || !request.comparison) throw new Error("SEO comparison is required.");
3629
+ const { competitor, mode } = request.comparison;
3630
+ const seen = /* @__PURE__ */ new Set();
3631
+ for (const rawItem of items) {
3632
+ const item = gapItemSchema.parse(rawItem);
3633
+ const rival = item.first_domain_serp_element;
3634
+ const own = item.second_domain_serp_element;
3635
+ const rivalHost = normalizeHostname(rival.domain);
3636
+ const ownHost = own ? normalizeHostname(own.domain) : null;
3637
+ if (!rivalHost || !hostBelongsTo(rivalHost, competitor) || own && (!ownHost || !hostBelongsTo(ownHost, request.target))) {
3638
+ throw new Error("SEO provider returned rankings outside the comparison pair.");
3639
+ }
3640
+ if (mode === SeoKeywordGapModes.shared && !own || mode === SeoKeywordGapModes.missing && own) {
3641
+ throw new Error("SEO provider returned a different comparison population.");
3642
+ }
3643
+ const key = normalizeQueryText(item.keyword_data.keyword);
3644
+ if (seen.has(key)) continue;
3645
+ seen.add(key);
3646
+ const metric = keywordMetrics(item.keyword_data, request, collectedAt);
3647
+ const targetRankOrganic = own?.rank_group ?? null;
3648
+ output.keywordGaps.push({
3649
+ target: request.target,
3650
+ competitor,
3651
+ keyword: metric.keyword,
3652
+ targetRankOrganic,
3653
+ competitorRankOrganic: rival.rank_group,
3654
+ targetUrl: own?.url ?? null,
3655
+ competitorUrl: rival.url ?? null,
3656
+ searchVolume: metric.searchVolume,
3657
+ keywordDifficulty: metric.keywordDifficulty,
3658
+ cpcUsd: metric.cpcUsd,
3659
+ ...seoKeywordGapComparison(targetRankOrganic, rival.rank_group),
3660
+ provenance: provenance(request, collectedAt, item.keyword_data.serp_info?.last_updated_time ?? null)
3661
+ });
3662
+ }
3663
+ break;
3664
+ }
3576
3665
  case SeoCapabilities["keyword-metrics"]: {
3577
3666
  const requested = new Map(request.keywords.map((keyword) => [keyword.toLowerCase(), keyword]));
3578
3667
  for (const rawItem of items) {
@@ -3641,7 +3730,9 @@ var ENDPOINTS = {
3641
3730
  [SeoCapabilities["keyword-metrics"]]: "dataforseo_labs/google/keyword_overview/live",
3642
3731
  [SeoCapabilities["domain-intelligence"]]: "dataforseo_labs/google/domain_rank_overview/live",
3643
3732
  [SeoCapabilities["ranked-keywords"]]: "dataforseo_labs/google/ranked_keywords/live",
3644
- [SeoCapabilities["market-rankings"]]: "serp/google/organic/live/advanced"
3733
+ [SeoCapabilities["market-rankings"]]: "serp/google/organic/live/advanced",
3734
+ [SeoCapabilities["competitor-discovery"]]: "dataforseo_labs/google/competitors_domain/live",
3735
+ [SeoCapabilities["keyword-gaps"]]: "dataforseo_labs/google/domain_intersection/live"
3645
3736
  };
3646
3737
  var MAX_SEARCH_TEXT_LENGTH = 700;
3647
3738
  var SURCHARGED_OPERATORS = [
@@ -3732,6 +3823,40 @@ function taskPayload(request) {
3732
3823
  const host = targetHost(target);
3733
3824
  const domain = registrableDomain(host);
3734
3825
  switch (request.capability) {
3826
+ case SeoCapabilities["competitor-discovery"]:
3827
+ if (target.kind !== SeoTargetKinds.domain) throw validationError("Competitor discovery requires a whole-domain scope.");
3828
+ return {
3829
+ ...common,
3830
+ target: host,
3831
+ limit: request.limit,
3832
+ offset: 0,
3833
+ item_types: ["organic"],
3834
+ include_clickstream_data: false,
3835
+ ignore_synonyms: false,
3836
+ exclude_domains: [host],
3837
+ order_by: ["intersections,desc"]
3838
+ };
3839
+ case SeoCapabilities["keyword-gaps"]: {
3840
+ const comparison = request.comparison;
3841
+ if (target.kind !== SeoTargetKinds.domain || !comparison || comparison.competitor.kind !== SeoTargetKinds.domain) {
3842
+ throw validationError("Keyword gaps require a whole-domain target and comparison domain.");
3843
+ }
3844
+ if (!seoKeywordGapModeSchema.safeParse(comparison.mode).success) throw validationError("Choose shared or missing searches for keyword gaps.");
3845
+ const competitor = targetHost(comparison.competitor);
3846
+ if (competitor === host) throw validationError("Choose a comparison domain different from the target.");
3847
+ return {
3848
+ ...common,
3849
+ target1: competitor,
3850
+ target2: host,
3851
+ intersections: comparison.mode === SeoKeywordGapModes.shared,
3852
+ limit: request.limit,
3853
+ offset: 0,
3854
+ item_types: ["organic"],
3855
+ include_serp_info: true,
3856
+ include_clickstream_data: false,
3857
+ order_by: ["keyword_data.keyword_info.search_volume,desc"]
3858
+ };
3859
+ }
3735
3860
  case SeoCapabilities["domain-intelligence"]:
3736
3861
  if (target.kind !== SeoTargetKinds.domain) throw validationError("Domain intelligence requires a whole-domain scope.");
3737
3862
  return { ...common, target: host, limit: 1, ignore_synonyms: false };
@@ -3766,6 +3891,8 @@ function appendResults(target, source) {
3766
3891
  target.domainIntelligence.push(...source.domainIntelligence);
3767
3892
  target.rankedKeywords.push(...source.rankedKeywords);
3768
3893
  target.marketRankings.push(...source.marketRankings);
3894
+ target.competitors.push(...source.competitors);
3895
+ target.keywordGaps.push(...source.keywordGaps);
3769
3896
  }
3770
3897
  function createDataForSeoAdapter(credentials) {
3771
3898
  const auth = { login: credentials.login.trim(), password: credentials.password };
@@ -5810,7 +5937,7 @@ function nonBlank(value) {
5810
5937
  return trimmed ? trimmed : void 0;
5811
5938
  }
5812
5939
  function resolveBuildCommit(env = process.env) {
5813
- const embedded = true ? "68e116717d6c9f8e51f1909b38f184f264855ffe" : void 0;
5940
+ const embedded = true ? "d072bd75fd700d80034392e01808c70cb509c189" : void 0;
5814
5941
  return nonBlank(embedded) ?? nonBlank(env.CANONRY_COMMIT);
5815
5942
  }
5816
5943
  function resolveInstanceIdentity(env = process.env) {
@@ -19533,9 +19660,10 @@ function createGoogleMarketingConfigCredentialStore(input) {
19533
19660
  };
19534
19661
  }
19535
19662
  async function createServer(opts) {
19536
- const runtimeConfigPath = path5.resolve(opts.configPath ?? getConfigPath());
19663
+ const configSourcePath = opts.configPath ?? loadedConfigPath(opts.config);
19664
+ const runtimeConfigPath = path5.resolve(configSourcePath ?? getConfigPath());
19537
19665
  const runtimeConfigIdentity = runtimePathIdentity(runtimeConfigPath);
19538
- const persistedConfigPath = opts.configPath === void 0 ? void 0 : runtimeConfigPath;
19666
+ const persistedConfigPath = configSourcePath === void 0 ? void 0 : runtimeConfigPath;
19539
19667
  const persistConfigPatch = (patch, options = {}) => {
19540
19668
  if (persistedConfigPath !== void 0) saveConfigPatch(patch, { ...options, configPath: persistedConfigPath });
19541
19669
  };
@@ -19558,6 +19686,12 @@ async function createServer(opts) {
19558
19686
  genReqId: () => crypto26.randomUUID(),
19559
19687
  trustProxy
19560
19688
  });
19689
+ if (!ownsDefaultConfig) {
19690
+ const releaseAnonymousIdWrites = holdAnonymousIdWrites();
19691
+ app.addHook("onClose", async () => {
19692
+ releaseAnonymousIdWrites();
19693
+ });
19694
+ }
19561
19695
  const allowedHosts = buildAllowedHosts(opts.host, opts.config.apiUrl, opts.config.publicUrl);
19562
19696
  const embedAllowedOrigins = new Set(
19563
19697
  (embed.allowedOrigins ?? []).map((o) => {
@@ -2,18 +2,18 @@ import {
2
2
  configExists,
3
3
  loadConfigRaw,
4
4
  saveConfigPatch
5
- } from "./chunk-2BRVGCVU.js";
5
+ } from "./chunk-VLOCDWCS.js";
6
6
  import {
7
7
  BUNDLED_SKILL_NAMES,
8
8
  installSkills
9
- } from "./chunk-7UVCZZQJ.js";
9
+ } from "./chunk-AI44ZCMK.js";
10
10
  import {
11
11
  PACKAGE_VERSION
12
12
  } from "./chunk-AOJU5LKX.js";
13
13
  import {
14
14
  SKILL_MANIFEST_FILENAME,
15
15
  SkillsClients
16
- } from "./chunk-FCGYYZHL.js";
16
+ } from "./chunk-PM2DB3HE.js";
17
17
 
18
18
  // src/skills-autosync.ts
19
19
  import fs from "fs";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  API_PROVIDER_NAMES,
3
3
  ProviderNames
4
- } from "./chunk-FCGYYZHL.js";
4
+ } from "./chunk-PM2DB3HE.js";
5
5
 
6
6
  // src/provider-registration.ts
7
7
  function isApiProviderRegistrable(name, entry) {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  hostMatchesDomain
3
- } from "./chunk-FCGYYZHL.js";
3
+ } from "./chunk-PM2DB3HE.js";
4
4
 
5
5
  // src/citation-utils.ts
6
6
  function pickProjectCitedDomain(citedDomains, projectDomains) {