@ainyc/canonry 4.193.2 → 4.195.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 (29) hide show
  1. package/README.md +1 -1
  2. package/assets/agent-workspace/skills/canonry/SKILL.md +81 -1
  3. package/assets/agent-workspace/skills/canonry/references/canonry-cli.md +41 -0
  4. package/assets/assets/{AuditHistoryPanel-BBXiKuD1.js → AuditHistoryPanel-vWUtVXOI.js} +1 -1
  5. package/assets/assets/{BacklinksPage-CE_-DKWO.js → BacklinksPage-CSzuMEuv.js} +1 -1
  6. package/assets/assets/{HistoryPage-D-l4jMt5.js → HistoryPage-DtCTQ7CQ.js} +1 -1
  7. package/assets/assets/{MeasurementPropertyPage-fCJm3sW6.js → MeasurementPropertyPage-B7gTMWNs.js} +1 -1
  8. package/assets/assets/{ProjectPage-Cxrd8lZM.js → ProjectPage-Bsm0_jUY.js} +1 -1
  9. package/assets/assets/{RunRow-C2kmB04V.js → RunRow-D5k4Rdo4.js} +1 -1
  10. package/assets/assets/{RunsPage-B73hjh_l.js → RunsPage-DIXBB2Om.js} +1 -1
  11. package/assets/assets/{SettingsPage-Ba30Jfnn.js → SettingsPage-wYhBm6Az.js} +1 -1
  12. package/assets/assets/{SiteHealthSection-mjpxy6N9.js → SiteHealthSection-YebzsgDh.js} +3 -3
  13. package/assets/assets/{TrafficPage-BZ8H_c8u.js → TrafficPage-DtnSRFO8.js} +1 -1
  14. package/assets/assets/{TrafficSourceDetailPage-sCUyzPpH.js → TrafficSourceDetailPage-DYQ6mpYq.js} +1 -1
  15. package/assets/assets/{extract-error-message-G-MvSIBA.js → extract-error-message-BdChrkmo.js} +1 -1
  16. package/assets/assets/{index-CSktlkUv.js → index-C_E2NRYY.js} +26 -26
  17. package/assets/assets/{react-sigma_core.esm.min-CgN2Dnvk.js → react-sigma_core.esm.min-sKWUk_tG.js} +1 -1
  18. package/assets/assets/{v2-overview-adapter-OmeP2l8O.js → v2-overview-adapter-CkPt-sRK.js} +1 -1
  19. package/assets/index.html +1 -1
  20. package/dist/{chunk-5CXUV3ZX.js → chunk-3WODA4JF.js} +288 -7
  21. package/dist/{chunk-24JHDZ7H.js → chunk-B2XM6AQ6.js} +318 -33
  22. package/dist/{chunk-KJJMIWVD.js → chunk-H3RVNMOO.js} +91 -38
  23. package/dist/{chunk-LIMWYFHS.js → chunk-LJKAB4CX.js} +2 -2
  24. package/dist/{chunk-Q5KGSOT7.js → chunk-UMU3IBXM.js} +1231 -484
  25. package/dist/cli.js +252 -156
  26. package/dist/index.js +4 -4
  27. package/dist/{intelligence-service-6ORSU2M6.js → intelligence-service-MGQRJW4V.js} +2 -2
  28. package/dist/mcp.js +4 -4
  29. package/package.json +10 -10
@@ -4,6 +4,7 @@ import {
4
4
  CANONRY_MCP_TOOLKIT_NAMES,
5
5
  CanonryMcpToolNames,
6
6
  CliError,
7
+ PACKAGE_VERSION,
7
8
  canonryMcpTools,
8
9
  configExists,
9
10
  createCanonryMcpServer,
@@ -14,7 +15,7 @@ import {
14
15
  loadConfig,
15
16
  loadConfigRaw,
16
17
  saveConfigPatch
17
- } from "./chunk-24JHDZ7H.js";
18
+ } from "./chunk-B2XM6AQ6.js";
18
19
  import {
19
20
  CC_CACHE_DIR,
20
21
  DUCKDB_SPEC,
@@ -22,8 +23,10 @@ import {
22
23
  GSC_DATA_LAG_DAYS,
23
24
  GSC_REPORTING_TIME_ZONE,
24
25
  IntelligenceService,
26
+ OperationalLogStore,
25
27
  PLUGIN_DIR,
26
28
  USER_SESSION_COOKIE_NAME,
29
+ addLogListener,
27
30
  adsAdGroups,
28
31
  adsAds,
29
32
  adsCampaigns,
@@ -56,6 +59,7 @@ import {
56
59
  crawlerEventsHourly,
57
60
  createClient,
58
61
  createCredentialChecker,
62
+ createFastifyLogger,
59
63
  createLogger,
60
64
  createUserSession,
61
65
  deliverWebhook,
@@ -162,7 +166,7 @@ import {
162
166
  siteCrawlSnapshots,
163
167
  toAlertView,
164
168
  usageCounters
165
- } from "./chunk-Q5KGSOT7.js";
169
+ } from "./chunk-UMU3IBXM.js";
166
170
  import {
167
171
  AGENT_MEMORY_VALUE_MAX_BYTES,
168
172
  AGENT_PROVIDER_IDS,
@@ -204,6 +208,7 @@ import {
204
208
  SITE_CRAWL_GRAPH_MAX_NODES,
205
209
  SchedulableRunKinds,
206
210
  SiteHealthLinkClassificationSources,
211
+ SnapshotProviderModes,
207
212
  TEMPLATE_LINK_RATIO_THRESHOLD,
208
213
  TrafficEventConfidences,
209
214
  TrafficEventKinds,
@@ -275,6 +280,7 @@ import {
275
280
  isSelfLink,
276
281
  isVertexGroundingRedirect,
277
282
  mapWithConcurrency,
283
+ maskTelemetryAnonymousId,
278
284
  nextScheduleUpdatedAt,
279
285
  normalizeIdTokens,
280
286
  normalizeMeasurementExecutionQueryText,
@@ -305,7 +311,7 @@ import {
305
311
  validationError,
306
312
  winnabilityClassLabel,
307
313
  withRetry
308
- } from "./chunk-5CXUV3ZX.js";
314
+ } from "./chunk-3WODA4JF.js";
309
315
 
310
316
  // src/telemetry.ts
311
317
  import crypto from "crypto";
@@ -359,18 +365,51 @@ function envSourceOverride() {
359
365
  function setTelemetrySource(source) {
360
366
  CURRENT_SOURCE = source;
361
367
  }
362
- function isTelemetryEnabled() {
363
- if (process.env.CANONRY_TELEMETRY_DISABLED === "1") return false;
364
- if (process.env.DO_NOT_TRACK === "1") return false;
365
- if (process.env.CI) return false;
366
- if (!configExists()) return true;
368
+ function resolveTelemetryStatus(input) {
369
+ const base = {
370
+ configuredEnabled: input.configuredEnabled,
371
+ ...input.anonymousId ? { anonymousId: maskAnonymousId(input.anonymousId) } : {},
372
+ target: "local"
373
+ };
374
+ if (input.canonryTelemetryDisabled === "1") {
375
+ return { ...base, enabled: false, reason: "CANONRY_TELEMETRY_DISABLED" };
376
+ }
377
+ if (input.doNotTrack === "1") {
378
+ return { ...base, enabled: false, reason: "DO_NOT_TRACK" };
379
+ }
380
+ if (input.ci) return { ...base, enabled: false, reason: "CI" };
381
+ if (!input.configuredEnabled) return { ...base, enabled: false, reason: "configured_disabled" };
382
+ if (input.configState === "absent") return { ...base, enabled: true, reason: "NO_CONFIG" };
383
+ if (input.configState === "unavailable") return { ...base, enabled: true, reason: "CONFIG_UNAVAILABLE" };
384
+ return { ...base, enabled: true, reason: "enabled" };
385
+ }
386
+ function maskAnonymousId(value) {
387
+ return maskTelemetryAnonymousId(value);
388
+ }
389
+ function getTelemetryStatus() {
390
+ const env = {
391
+ canonryTelemetryDisabled: process.env.CANONRY_TELEMETRY_DISABLED,
392
+ doNotTrack: process.env.DO_NOT_TRACK,
393
+ ci: process.env.CI
394
+ };
395
+ if (!configExists()) {
396
+ return resolveTelemetryStatus({ ...env, configuredEnabled: true, configState: "absent" });
397
+ }
367
398
  try {
368
399
  const config = loadConfig();
369
- return config.telemetry !== false;
400
+ return resolveTelemetryStatus({
401
+ ...env,
402
+ configuredEnabled: config.telemetry !== false,
403
+ configState: "present",
404
+ anonymousId: config.anonymousId
405
+ });
370
406
  } catch {
371
- return true;
407
+ return resolveTelemetryStatus({ ...env, configuredEnabled: true, configState: "unavailable" });
372
408
  }
373
409
  }
410
+ function isTelemetryEnabled() {
411
+ return getTelemetryStatus().enabled;
412
+ }
374
413
  function getOrCreateAnonymousId() {
375
414
  const fromEnv = readEnvAnonymousId();
376
415
  if (fromEnv) return fromEnv;
@@ -6246,7 +6285,7 @@ function nonBlank(value) {
6246
6285
  return trimmed ? trimmed : void 0;
6247
6286
  }
6248
6287
  function resolveBuildCommit(env = process.env) {
6249
- const embedded = true ? "89d578914ed6cd982efa0707ac03ebc985659656" : void 0;
6288
+ const embedded = true ? "9cc37abc3436114b63ddd6722b5bfb1af0f85c02" : void 0;
6250
6289
  return nonBlank(embedded) ?? nonBlank(env.CANONRY_COMMIT);
6251
6290
  }
6252
6291
  function resolveInstanceIdentity(env = process.env) {
@@ -12057,7 +12096,7 @@ function readStoredGroundingSources(rawResponse) {
12057
12096
  return result;
12058
12097
  }
12059
12098
  async function backfillInsightsCommand(project, opts) {
12060
- const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-6ORSU2M6.js");
12099
+ const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-MGQRJW4V.js");
12061
12100
  const config = loadConfig();
12062
12101
  const db = createClient(config.database);
12063
12102
  migrate(db);
@@ -15811,7 +15850,12 @@ function registerMcpHttpRoutes(scope, opts) {
15811
15850
  if (!request.apiKey && request.principal?.kind === "user") {
15812
15851
  sessionKey = mintSessionKey(opts.db, scopes, request.principal.id);
15813
15852
  }
15814
- const client = new ApiClient(opts.selfApiUrl, sessionKey?.raw ?? bearer, { skipProbe: true });
15853
+ const client = new ApiClient(opts.selfApiUrl, sessionKey?.raw ?? bearer, {
15854
+ skipProbe: true,
15855
+ clientName: `canonry-mcp/${PACKAGE_VERSION}`,
15856
+ // Correlation only: this is never accepted as caller identity or authority.
15857
+ actorSession: crypto26.randomUUID()
15858
+ });
15815
15859
  let server;
15816
15860
  try {
15817
15861
  server = createCanonryMcpServer({
@@ -16402,11 +16446,26 @@ var SnapshotService = class {
16402
16446
  const domain = hostOf(input.domain) ?? input.domain.trim();
16403
16447
  const manualQueries = normalizeStringList(resolveSnapshotRequestQueries(input));
16404
16448
  const manualCompetitors = normalizeStringList(input.competitors ?? []);
16405
- const providers = this.registry.getAll();
16449
+ const requestedNames = input.providers === void 0 ? void 0 : [...new Set(input.providers)];
16450
+ const mode = input.providerMode ?? SnapshotProviderModes.all;
16451
+ const providers = requestedNames === void 0 ? this.registry.getAll().filter((provider) => mode === SnapshotProviderModes.all || provider.adapter.mode === mode) : requestedNames.map((name) => {
16452
+ const provider = this.registry.get(name);
16453
+ if (!provider) throw validationError(`Snapshot provider "${name}" is not configured`);
16454
+ if (mode !== SnapshotProviderModes.all && provider.adapter.mode !== mode) {
16455
+ throw validationError(`Snapshot provider "${name}" does not match providerMode "${mode}"`);
16456
+ }
16457
+ return provider;
16458
+ });
16406
16459
  if (providers.length === 0) {
16460
+ if (input.providers !== void 0 || input.providerMode !== void 0) {
16461
+ throw validationError(`No configured snapshot providers match the selection (providerMode: ${mode})`);
16462
+ }
16407
16463
  throw new Error("No providers configured. Add at least one provider API key before running canonry snapshot.");
16408
16464
  }
16409
- const analysisProvider = pickAnalysisProvider(this.registry.getApiProviders());
16465
+ const analysisProvider = pickAnalysisProvider(providers.filter((provider) => provider.adapter.mode === SnapshotProviderModes.api));
16466
+ if (!analysisProvider && manualQueries.length === 0) {
16467
+ throw validationError("Automatic category-query generation requires a selected API provider. Include an API provider or pass manual queries via --queries.");
16468
+ }
16410
16469
  const homepageUrl = `https://${domain}`;
16411
16470
  const [siteText, audit] = await Promise.all([
16412
16471
  fetchSiteText(domain),
@@ -17641,20 +17700,14 @@ function createGoogleMarketingConfigCredentialStore(input) {
17641
17700
  }
17642
17701
  async function createServer(opts) {
17643
17702
  const dashboardManagedRunKinds = resolveDashboardManagedRunKinds(process.env, opts.config);
17644
- const logger = opts.logger === false ? false : process.stdout.isTTY ? {
17645
- transport: {
17646
- target: "pino-pretty",
17647
- options: {
17648
- colorize: true,
17649
- translateTime: "HH:MM:ss",
17650
- ignore: "pid,hostname,reqId",
17651
- messageFormat: "{msg} {req.method} {req.url}"
17652
- }
17653
- }
17654
- } : true;
17703
+ const operationalLogs = new OperationalLogStore(opts.db, {
17704
+ retention: opts.config.database === ":memory:" ? "process" : "durable"
17705
+ });
17706
+ const logger = createFastifyLogger({ enabled: opts.logger !== false, module: "Server" });
17655
17707
  const trustProxy = resolveTrustProxy(process.env.CANONRY_TRUST_PROXY);
17656
17708
  const app = Fastify({
17657
- logger,
17709
+ loggerInstance: logger,
17710
+ genReqId: () => crypto27.randomUUID(),
17658
17711
  trustProxy
17659
17712
  });
17660
17713
  const registry = new ProviderRegistry();
@@ -19112,7 +19165,7 @@ async function createServer(opts) {
19112
19165
  },
19113
19166
  getRunnableProviderNames: () => registry.getAll().map((provider) => provider.adapter.name),
19114
19167
  getEffectiveProviderModels: () => effectiveProviderModels(registry),
19115
- onProviderUpdate: (providerName, apiKey, model, baseUrl, incomingQuota) => {
19168
+ onProviderUpdate: (providerName, apiKey, model, baseUrl, incomingQuota, auditContext) => {
19116
19169
  const name = providerName;
19117
19170
  if (!adapterMap[name]) return null;
19118
19171
  if (!opts.config.providers) opts.config.providers = {};
@@ -19172,7 +19225,11 @@ async function createServer(opts) {
19172
19225
  targetProjectIds.map((projectId) => ({
19173
19226
  id: crypto27.randomUUID(),
19174
19227
  projectId,
19175
- actor: "api",
19228
+ actor: auditContext?.actor ?? "api",
19229
+ userAgent: auditContext?.userAgent ?? null,
19230
+ actorSession: auditContext?.actorSession ?? null,
19231
+ credentialId: auditContext?.credentialId ?? null,
19232
+ requestId: auditContext?.requestId ?? null,
19176
19233
  action: existing ? "provider.updated" : "provider.created",
19177
19234
  entityType: "provider",
19178
19235
  entityId: name,
@@ -19248,15 +19305,8 @@ async function createServer(opts) {
19248
19305
  }
19249
19306
  });
19250
19307
  },
19251
- getTelemetryStatus: () => {
19252
- const enabled = isTelemetryEnabled();
19253
- return {
19254
- enabled,
19255
- // Only read/create the anonymous ID if telemetry is enabled.
19256
- // Don't mutate config for opted-out users.
19257
- anonymousId: enabled ? getOrCreateAnonymousId() : void 0
19258
- };
19259
- },
19308
+ listOperationalLogs: (query) => operationalLogs.list(query),
19309
+ getTelemetryStatus,
19260
19310
  setTelemetryEnabled: (enabled) => {
19261
19311
  const config = loadConfig();
19262
19312
  config.telemetry = enabled;
@@ -19527,7 +19577,9 @@ async function createServer(opts) {
19527
19577
  rejectRuntimeStartup(error);
19528
19578
  }
19529
19579
  });
19580
+ const stopLogCapture = addLogListener((entry) => operationalLogs.append(entry));
19530
19581
  app.addHook("onClose", async () => {
19582
+ stopLogCapture();
19531
19583
  scheduler.stop();
19532
19584
  });
19533
19585
  return app;
@@ -19592,6 +19644,7 @@ function parseQueryResponse(raw, count2) {
19592
19644
  export {
19593
19645
  trackCliCommandFinished,
19594
19646
  setTelemetrySource,
19647
+ getTelemetryStatus,
19595
19648
  isTelemetryEnabled,
19596
19649
  getOrCreateAnonymousId,
19597
19650
  isFirstRun,
@@ -5,11 +5,11 @@ import {
5
5
  installSkills,
6
6
  loadConfigRaw,
7
7
  saveConfigPatch
8
- } from "./chunk-24JHDZ7H.js";
8
+ } from "./chunk-B2XM6AQ6.js";
9
9
  import {
10
10
  SKILL_MANIFEST_FILENAME,
11
11
  SkillsClients
12
- } from "./chunk-5CXUV3ZX.js";
12
+ } from "./chunk-3WODA4JF.js";
13
13
 
14
14
  // src/skills-autosync.ts
15
15
  import fs from "fs";