@canonry/canonry 7.0.0 → 7.2.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 (36) hide show
  1. package/assets/agent-workspace/skills/canonry/references/aeo-analysis.md +5 -3
  2. package/assets/agent-workspace/skills/canonry/references/canonry-cli.md +19 -2
  3. package/assets/assets/AuditHistoryPanel-Duvyi8vx.js +1 -0
  4. package/assets/assets/{BacklinksPage-HIM0fmV7.js → BacklinksPage-CY5AllQu.js} +1 -1
  5. package/assets/assets/{HistoryPage-BjEVp-fk.js → HistoryPage-C0Gr0gcj.js} +1 -1
  6. package/assets/assets/{MeasurementPropertyPage-BnVDR2y_.js → MeasurementPropertyPage-DrAB6VKX.js} +1 -1
  7. package/assets/assets/ProjectPage-DSxvvnAd.js +8 -0
  8. package/assets/assets/{RunsPage-fJQe2qJc.js → RunsPage-DMxOrtfl.js} +1 -1
  9. package/assets/assets/{SettingsPage-1yam5tl6.js → SettingsPage-sxiUNt2A.js} +1 -1
  10. package/assets/assets/SiteHealthSection--6tZe3hM.js +4 -0
  11. package/assets/assets/{TrafficPage-BdNEscz8.js → TrafficPage-CvSQDNTi.js} +2 -2
  12. package/assets/assets/{TrafficSourceDetailPage-CMEgr4Aw.js → TrafficSourceDetailPage-BaYeIBmc.js} +1 -1
  13. package/assets/assets/{extract-error-message-D2dhaJaW.js → extract-error-message-76IWhqQF.js} +1 -1
  14. package/assets/assets/index-BlrH2zRW.js +86 -0
  15. package/assets/assets/index-HWSQgVum.css +1 -0
  16. package/assets/assets/{react-sigma_core.esm.min-oP23IWpt.js → react-sigma_core.esm.min-CkAcKW2k.js} +1 -1
  17. package/assets/assets/{v2-overview-adapter-DYatWs7N.js → v2-overview-adapter-DnEE4E9w.js} +1 -1
  18. package/assets/index.html +2 -2
  19. package/dist/{chunk-TUHQ5BBQ.js → chunk-BYSSJEL7.js} +9 -8
  20. package/dist/{chunk-LXWY4NKP.js → chunk-EQBYK77W.js} +3 -3
  21. package/dist/{chunk-HQJ25LI7.js → chunk-FDBQOQLP.js} +2 -2
  22. package/dist/{chunk-EZ54X4XH.js → chunk-RCQJI3UX.js} +125 -86
  23. package/dist/{chunk-RRIZ5AKI.js → chunk-SVTVBPIT.js} +2 -2
  24. package/dist/{chunk-OOUDIVIU.js → chunk-TY3CJKKR.js} +458 -184
  25. package/dist/{chunk-A5PALGQD.js → chunk-UIDHHZH3.js} +94 -190
  26. package/dist/cli.js +32 -16
  27. package/dist/{demo-server-LHHDVXQW.js → demo-server-GWRYDPJC.js} +4 -4
  28. package/dist/index.js +6 -6
  29. package/dist/{intelligence-service-ZVKZLLKL.js → intelligence-service-3L2665AK.js} +2 -2
  30. package/dist/mcp.js +4 -4
  31. package/package.json +12 -12
  32. package/assets/assets/AuditHistoryPanel-DBYsgVsn.js +0 -1
  33. package/assets/assets/ProjectPage-BhCM47KA.js +0 -8
  34. package/assets/assets/SiteHealthSection-DysU2M6C.js +0 -4
  35. package/assets/assets/index-CgT2Btdn.css +0 -1
  36. package/assets/assets/index-D9ODLKpH.js +0 -86
@@ -17,23 +17,24 @@ import {
17
17
  resolveOperatorApiKeyIds,
18
18
  resolveSentimentInstallConfig,
19
19
  runWithUsageTags,
20
+ saveConfig,
20
21
  saveConfigPatch,
21
22
  sentimentInstallReadiness
22
- } from "./chunk-HQJ25LI7.js";
23
+ } from "./chunk-FDBQOQLP.js";
23
24
  import {
24
25
  computeFactorAverages,
25
26
  deleteSiteCrawlGraphLayout,
26
27
  persistSiteCrawlGraphLayout,
27
28
  prepareSiteCrawlGraphLayout,
28
29
  recordedSharePct
29
- } from "./chunk-RRIZ5AKI.js";
30
+ } from "./chunk-SVTVBPIT.js";
30
31
  import {
31
32
  CanonryMcpToolNames,
32
33
  CliError,
33
34
  PACKAGE_VERSION,
34
35
  canonryMcpTools,
35
36
  isMachineFormat
36
- } from "./chunk-TUHQ5BBQ.js";
37
+ } from "./chunk-BYSSJEL7.js";
37
38
  import {
38
39
  CC_CACHE_DIR,
39
40
  DUCKDB_SPEC,
@@ -161,6 +162,7 @@ import {
161
162
  newerFullSweep,
162
163
  nextRunFromCron,
163
164
  nextRunFromSchedule,
165
+ notProbeRun,
164
166
  notifications,
165
167
  parseCookieHeader,
166
168
  parseJsonColumn,
@@ -214,7 +216,7 @@ import {
214
216
  siteLivenessState,
215
217
  toAlertView,
216
218
  usageCounters
217
- } from "./chunk-EZ54X4XH.js";
219
+ } from "./chunk-RCQJI3UX.js";
218
220
  import {
219
221
  AGENT_MEMORY_VALUE_MAX_BYTES,
220
222
  AGENT_NONE,
@@ -376,6 +378,7 @@ import {
376
378
  normalizeAgentSlug,
377
379
  normalizeIdTokens,
378
380
  normalizeMeasurementExecutionQueryText,
381
+ normalizeProjectDomain,
379
382
  normalizeServedModel,
380
383
  normalizeSiteAuditRunRequest,
381
384
  normalizeUrlPath,
@@ -421,7 +424,7 @@ import {
421
424
  visibilityReportRequestSchema,
422
425
  winnabilityClassLabel,
423
426
  withRetry
424
- } from "./chunk-OOUDIVIU.js";
427
+ } from "./chunk-TY3CJKKR.js";
425
428
 
426
429
  // src/runtime-context.ts
427
430
  function cliRuntimeContext(env = process.env, stdio = process) {
@@ -441,9 +444,6 @@ var TELEMETRY_ENDPOINT = "https://canonry.ai/api/telemetry";
441
444
  var TIMEOUT_MS = 3e3;
442
445
  var ANON_ID_ENV_VAR = "CANONRY_ANONYMOUS_ID";
443
446
  var ANON_ID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
444
- function shouldDropTelemetryEvent(event, properties) {
445
- return isGhostTelemetryEvent(event, properties);
446
- }
447
447
  function bucketCliCommandDuration(durationMs) {
448
448
  const duration = Number.isFinite(durationMs) ? Math.max(0, durationMs) : 0;
449
449
  if (duration < 1e3) return "under_1s";
@@ -487,7 +487,7 @@ function setTelemetrySource(source) {
487
487
  function resolveTelemetryStatus(input) {
488
488
  const base = {
489
489
  configuredEnabled: input.configuredEnabled,
490
- ...input.anonymousId ? { anonymousId: maskAnonymousId(input.anonymousId) } : {},
490
+ ...input.anonymousId ? { anonymousId: maskTelemetryAnonymousId(input.anonymousId) } : {},
491
491
  target: "local"
492
492
  };
493
493
  if (input.canonryTelemetryDisabled === "1") {
@@ -502,9 +502,6 @@ function resolveTelemetryStatus(input) {
502
502
  if (input.configState === "unavailable") return { ...base, enabled: true, reason: "CONFIG_UNAVAILABLE" };
503
503
  return { ...base, enabled: true, reason: "enabled" };
504
504
  }
505
- function maskAnonymousId(value) {
506
- return maskTelemetryAnonymousId(value);
507
- }
508
505
  function getTelemetryStatus() {
509
506
  const env = {
510
507
  canonryTelemetryDisabled: process.env.CANONRY_TELEMETRY_DISABLED,
@@ -630,6 +627,10 @@ function detectAndTrackUpgrade() {
630
627
  function trackEvent(event, properties, options) {
631
628
  void deliverEvent(event, properties, options);
632
629
  }
630
+ function recordDashboardEvent(event) {
631
+ const { event: eventName, eventId, ...properties } = event;
632
+ trackEvent(eventName, properties, { source: "dashboard", eventId: String(eventId) });
633
+ }
633
634
  function setTelemetryPreference(enabled, method) {
634
635
  loadConfig();
635
636
  const announce = !enabled && isTelemetryEnabled();
@@ -638,7 +639,7 @@ function setTelemetryPreference(enabled, method) {
638
639
  }
639
640
  function deliverEvent(event, properties, options, delivery = {}) {
640
641
  if (!delivery.preferenceChecked && !isTelemetryEnabled()) return Promise.resolve();
641
- if (shouldDropTelemetryEvent(event, properties)) return Promise.resolve();
642
+ if (isGhostTelemetryEvent(event, properties)) return Promise.resolve();
642
643
  const anonymousId = getOrCreateAnonymousId();
643
644
  if (!anonymousId) return Promise.resolve();
644
645
  const payload = {
@@ -891,92 +892,6 @@ var GOOGLE_ADS_MAX_CUSTOMER_CLIENTS = 1e3;
891
892
  var GOOGLE_ADS_DEFAULT_CUSTOMER_CLIENT_DEPTH = 1;
892
893
  var GOOGLE_ADS_MAX_CUSTOMER_CLIENT_DEPTH = 10;
893
894
 
894
- // ../integration-google-ads/src/goal-semantics.ts
895
- function addInclusion(included, action, inclusion) {
896
- const existing = included.get(action.resourceName);
897
- if (existing) {
898
- existing.includedBy.push(inclusion);
899
- return;
900
- }
901
- included.set(action.resourceName, { conversionAction: action, includedBy: [inclusion] });
902
- }
903
- function resolveEffectiveCampaignGoalInputs(inputs) {
904
- const actions = inputs.conversionActions.map((row) => row.conversionAction);
905
- const actionsByResource = new Map(actions.map((action) => [action.resourceName, action]));
906
- const customGoalsByResource = new Map(
907
- inputs.customGoals.map((row) => [row.customConversionGoal.resourceName, row.customConversionGoal])
908
- );
909
- return inputs.campaignConfigs.map((row) => {
910
- const config = row.conversionGoalCampaignConfig;
911
- let categoryGoalSource = "UNKNOWN";
912
- let categoryOriginGoals = [];
913
- if (config.goalConfigLevel === "CUSTOMER") {
914
- categoryGoalSource = "CUSTOMER";
915
- categoryOriginGoals = inputs.customerGoals.map(({ customerConversionGoal: goal }) => ({
916
- resourceName: goal.resourceName,
917
- source: "CUSTOMER",
918
- category: goal.category,
919
- origin: goal.origin,
920
- biddable: goal.biddable === true
921
- }));
922
- } else if (config.goalConfigLevel === "CAMPAIGN") {
923
- categoryGoalSource = "CAMPAIGN";
924
- categoryOriginGoals = inputs.campaignGoals.filter(({ campaignConversionGoal: goal }) => goal.campaign === config.campaign).map(({ campaignConversionGoal: goal }) => ({
925
- resourceName: goal.resourceName,
926
- source: "CAMPAIGN",
927
- category: goal.category,
928
- origin: goal.origin,
929
- biddable: goal.biddable === true
930
- }));
931
- }
932
- const included = /* @__PURE__ */ new Map();
933
- for (const goal of categoryOriginGoals) {
934
- if (!goal.biddable) continue;
935
- for (const action of actions) {
936
- if (action.primaryForGoal !== false && action.category === goal.category && action.origin === goal.origin) {
937
- addInclusion(included, action, {
938
- source: goal.source === "CUSTOMER" ? "CUSTOMER_GOAL" : "CAMPAIGN_GOAL",
939
- goalResourceName: goal.resourceName,
940
- category: goal.category,
941
- origin: goal.origin
942
- });
943
- }
944
- }
945
- }
946
- let customGoal = null;
947
- let missingCustomGoalResourceName;
948
- const missingConversionActionResourceNames = [];
949
- if (config.goalConfigLevel === "CAMPAIGN" && config.customConversionGoal) {
950
- customGoal = customGoalsByResource.get(config.customConversionGoal) ?? null;
951
- if (!customGoal) {
952
- missingCustomGoalResourceName = config.customConversionGoal;
953
- } else {
954
- for (const resourceName of customGoal.conversionActions ?? []) {
955
- const action = actionsByResource.get(resourceName);
956
- if (!action) {
957
- missingConversionActionResourceNames.push(resourceName);
958
- continue;
959
- }
960
- addInclusion(included, action, {
961
- source: "CUSTOM_GOAL",
962
- goalResourceName: customGoal.resourceName
963
- });
964
- }
965
- }
966
- }
967
- return {
968
- campaign: row.campaign,
969
- config,
970
- categoryGoalSource,
971
- categoryOriginGoals,
972
- customGoal,
973
- conversionActions: [...included.values()],
974
- ...missingCustomGoalResourceName ? { missingCustomGoalResourceName } : {},
975
- missingConversionActionResourceNames
976
- };
977
- });
978
- }
979
-
980
895
  // ../integration-google-ads/src/types.ts
981
896
  var GoogleAdsApiError = class extends Error {
982
897
  constructor(message, status, providerStatus, requestId, retryAfter) {
@@ -1577,8 +1492,7 @@ var GoogleAdsClient = class {
1577
1492
  ...raw,
1578
1493
  // A result exactly at the cap may have more rows upstream. Treat it
1579
1494
  // as incomplete rather than silently deriving absent campaign goals.
1580
- campaignGoalsComplete: campaignGoals.data.length < GOOGLE_ADS_MAX_RESULT_ROWS,
1581
- effectiveCampaignGoalInputs: resolveEffectiveCampaignGoalInputs(raw)
1495
+ campaignGoalsComplete: campaignGoals.data.length < GOOGLE_ADS_MAX_RESULT_ROWS
1582
1496
  },
1583
1497
  metadata: {
1584
1498
  apiVersion: GOOGLE_ADS_API_VERSION,
@@ -4238,7 +4152,7 @@ function parseTrackedQueryResponse(body, model) {
4238
4152
  provider: "gemini",
4239
4153
  rawResponse,
4240
4154
  model,
4241
- servedModel: extractServedModel(rawResponse),
4155
+ servedModel: normalizeServedModel(rawResponse.modelVersion),
4242
4156
  groundingSources: parsed.groundingSources,
4243
4157
  searchQueries: parsed.searchQueries,
4244
4158
  usage: extractUsageFromRaw(rawResponse),
@@ -4262,9 +4176,6 @@ function normalizeResult(raw) {
4262
4176
  function hasParsedResponseContent(rawResponse) {
4263
4177
  return Array.isArray(rawResponse.candidates) && rawResponse.candidates.length > 0;
4264
4178
  }
4265
- function extractServedModel(rawResponse) {
4266
- return normalizeServedModel(rawResponse.modelVersion);
4267
- }
4268
4179
  function reparseStoredResult(rawResponse) {
4269
4180
  const groundingSources = extractGroundingMetadataFromRaw(rawResponse);
4270
4181
  const searchQueries = extractSearchQueriesFromRaw(rawResponse);
@@ -4448,49 +4359,25 @@ var DEFAULT_OUTPUT_DIMENSIONALITY = 768;
4448
4359
  var CLUSTERING_TASK_TYPE = "CLUSTERING";
4449
4360
  async function embedQueries(queries2, options) {
4450
4361
  if (queries2.length === 0) return [];
4451
- if (!options.apiKey && !options.client) {
4452
- throw new Error("embedQueries: missing apiKey");
4453
- }
4454
- const client = options.client ?? createGeminiEmbedClient(options.apiKey, options.baseUrl);
4455
- return client.embedBatch(queries2, {
4362
+ if (!options.apiKey) throw new Error("embedQueries: missing apiKey");
4363
+ const genai = new GoogleGenAI2({ apiKey: options.apiKey, ...options.baseUrl ? { httpOptions: { baseUrl: options.baseUrl } } : {} });
4364
+ const response = await genai.models.embedContent({
4456
4365
  model: options.model ?? DEFAULT_EMBED_MODEL,
4457
- taskType: CLUSTERING_TASK_TYPE,
4458
- outputDimensionality: options.outputDimensionality ?? DEFAULT_OUTPUT_DIMENSIONALITY
4366
+ contents: queries2,
4367
+ config: { taskType: CLUSTERING_TASK_TYPE, outputDimensionality: options.outputDimensionality ?? DEFAULT_OUTPUT_DIMENSIONALITY }
4459
4368
  });
4369
+ return extractEmbeddingVectors(response, queries2.length);
4460
4370
  }
4461
4371
  function extractEmbeddingVectors(response, expectedLength) {
4462
4372
  const embeddings = response?.embeddings ?? [];
4463
4373
  if (embeddings.length !== expectedLength) {
4464
- throw new Error(
4465
- `embedQueries: expected ${expectedLength} embeddings, got ${embeddings.length}`
4466
- );
4374
+ throw new Error(`embedQueries: expected ${expectedLength} embeddings, got ${embeddings.length}`);
4467
4375
  }
4468
4376
  return embeddings.map((e, i) => {
4469
- if (!e.values || e.values.length === 0) {
4470
- throw new Error(`embedQueries: missing values for query at index ${i}`);
4471
- }
4377
+ if (!e.values || e.values.length === 0) throw new Error(`embedQueries: missing values for query at index ${i}`);
4472
4378
  return e.values;
4473
4379
  });
4474
4380
  }
4475
- function createEmbedGenAI(apiKey, baseUrl) {
4476
- return new GoogleGenAI2({ apiKey, ...baseUrl ? { httpOptions: { baseUrl } } : {} });
4477
- }
4478
- function createGeminiEmbedClient(apiKey, baseUrl) {
4479
- const genai = createEmbedGenAI(apiKey, baseUrl);
4480
- return {
4481
- async embedBatch(queries2, opts) {
4482
- const response = await genai.models.embedContent({
4483
- model: opts.model,
4484
- contents: queries2,
4485
- config: {
4486
- taskType: opts.taskType,
4487
- outputDimensionality: opts.outputDimensionality
4488
- }
4489
- });
4490
- return extractEmbeddingVectors(response, queries2.length);
4491
- }
4492
- };
4493
- }
4494
4381
 
4495
4382
  // ../provider-gemini/src/list-models.ts
4496
4383
  function listModels(config, signal) {
@@ -4728,7 +4615,7 @@ function buildTrackedQueryRequest2(input) {
4728
4615
  // search-required-v1: web_search is the only tool, so requiring a tool
4729
4616
  // call requires a search. See OPENAI_RETRIEVAL_CONTRACT.
4730
4617
  tool_choice: "required",
4731
- input: buildPrompt2(input.query)
4618
+ input: input.query
4732
4619
  };
4733
4620
  return { endpoint: OPENAI_RESPONSES_ENDPOINT, body };
4734
4621
  }
@@ -4752,7 +4639,7 @@ function parseTrackedQueryResponse2(body, model) {
4752
4639
  provider: "openai",
4753
4640
  rawResponse,
4754
4641
  model,
4755
- servedModel: extractServedModel2(rawResponse),
4642
+ servedModel: normalizeServedModel(rawResponse.model),
4756
4643
  groundingSources: parsed.groundingSources,
4757
4644
  searchQueries: parsed.searchQueries,
4758
4645
  retrievalStatus: parsed.retrievalStatus,
@@ -4779,9 +4666,6 @@ function normalizeResult2(raw) {
4779
4666
  function hasParsedResponseContent2(rawResponse) {
4780
4667
  return Array.isArray(rawResponse.output) && rawResponse.output.length > 0;
4781
4668
  }
4782
- function extractServedModel2(rawResponse) {
4783
- return normalizeServedModel(rawResponse.model);
4784
- }
4785
4669
  function reparseStoredResult2(rawResponse) {
4786
4670
  const groundingSources = extractGroundingSourcesFromRaw(rawResponse);
4787
4671
  const searchQueries = extractSearchQueriesFromRaw2(rawResponse);
@@ -4806,9 +4690,6 @@ function extractRetrievalStatusFromRaw(rawResponse) {
4806
4690
  }
4807
4691
  return RetrievalStatuses["not-used"];
4808
4692
  }
4809
- function buildPrompt2(query) {
4810
- return query;
4811
- }
4812
4693
  function extractResponseText(response) {
4813
4694
  try {
4814
4695
  const parts = [];
@@ -5236,7 +5117,7 @@ function parseTrackedQueryResponse3(body, model) {
5236
5117
  provider: "claude",
5237
5118
  rawResponse,
5238
5119
  model,
5239
- servedModel: extractServedModel3(rawResponse),
5120
+ servedModel: extractServedModel(rawResponse),
5240
5121
  groundingSources: parsed.groundingSources,
5241
5122
  searchQueries: parsed.searchQueries,
5242
5123
  retrievalStatus: parsed.retrievalStatus,
@@ -5265,7 +5146,7 @@ function normalizeResult3(raw) {
5265
5146
  function hasParsedResponseContent3(rawResponse) {
5266
5147
  return Array.isArray(rawResponse.content) && rawResponse.content.length > 0;
5267
5148
  }
5268
- function extractServedModel3(rawResponse) {
5149
+ function extractServedModel(rawResponse) {
5269
5150
  return normalizeServedModel(rawResponse.model);
5270
5151
  }
5271
5152
  function reparseStoredResult3(rawResponse) {
@@ -5803,7 +5684,7 @@ function buildTrackedQueryRequest4(input) {
5803
5684
  },
5804
5685
  {
5805
5686
  role: "user",
5806
- content: buildPrompt3(input.query, input.location)
5687
+ content: buildPrompt2(input.query, input.location)
5807
5688
  }
5808
5689
  ]
5809
5690
  };
@@ -5831,7 +5712,7 @@ function parseTrackedQueryResponse4(body, model) {
5831
5712
  provider: "local",
5832
5713
  rawResponse,
5833
5714
  model,
5834
- servedModel: extractServedModel4(rawResponse),
5715
+ servedModel: normalizeServedModel(rawResponse.model),
5835
5716
  groundingSources: [],
5836
5717
  searchQueries: [],
5837
5718
  usage: extractUsageFromRaw4(rawResponse),
@@ -5852,7 +5733,7 @@ function normalizeResult4(raw) {
5852
5733
  searchQueries: raw.searchQueries
5853
5734
  };
5854
5735
  }
5855
- function buildPrompt3(query, location) {
5736
+ function buildPrompt2(query, location) {
5856
5737
  const locationContext = location ? ` The user is searching from ${location.city}, ${location.region}, ${location.country}.` : "";
5857
5738
  return `Based on your training knowledge, what websites, services, or organizations are commonly associated with "${query}"?${locationContext} List the most relevant ones and include their domain names (e.g. example.com) where you know them.`;
5858
5739
  }
@@ -5879,9 +5760,6 @@ async function generateText4(prompt, config) {
5879
5760
  );
5880
5761
  return response.choices[0]?.message?.content ?? "";
5881
5762
  }
5882
- function extractServedModel4(rawResponse) {
5883
- return normalizeServedModel(rawResponse.model);
5884
- }
5885
5763
  function extractUsageFromRaw4(rawResponse) {
5886
5764
  const usage = rawResponse.usage;
5887
5765
  if (usage === null || typeof usage !== "object") return void 0;
@@ -6724,7 +6602,7 @@ function parseTrackedQueryResponse5(body, model) {
6724
6602
  provider: "perplexity",
6725
6603
  rawResponse: body,
6726
6604
  model: resolveModel3(model),
6727
- servedModel: extractServedModel5(body),
6605
+ servedModel: normalizeServedModel(body.model),
6728
6606
  groundingSources: parsed.groundingSources,
6729
6607
  searchQueries: parsed.searchQueries,
6730
6608
  retrievalStatus: parsed.retrievalStatus,
@@ -6757,9 +6635,6 @@ function hasParsedResponseContent4(rawResponse) {
6757
6635
  if (!nestedResponse) return false;
6758
6636
  return Array.isArray(nestedResponse.choices) && nestedResponse.choices.length > 0 || Array.isArray(nestedResponse.search_results) && nestedResponse.search_results.length > 0 || Array.isArray(nestedResponse.citations) && nestedResponse.citations.length > 0;
6759
6637
  }
6760
- function extractServedModel5(rawResponse) {
6761
- return normalizeServedModel(rawResponse.model);
6762
- }
6763
6638
  function reparseStoredResult4(rawResponse) {
6764
6639
  const agent = agentResponseOf(rawResponse);
6765
6640
  if (agent) return parseAgentResponse(agent);
@@ -7198,7 +7073,7 @@ async function executeTrackedQuery6(input) {
7198
7073
  provider: "muse",
7199
7074
  rawResponse,
7200
7075
  model,
7201
- servedModel: extractServedModel6(rawResponse),
7076
+ servedModel: normalizeServedModel(rawResponse.model),
7202
7077
  groundingSources: parsed.groundingSources,
7203
7078
  searchQueries: parsed.searchQueries,
7204
7079
  retrievalStatus: parsed.retrievalStatus,
@@ -7209,9 +7084,6 @@ async function executeTrackedQuery6(input) {
7209
7084
  throw new Error(`[provider-muse] ${describeError(err)}`);
7210
7085
  }
7211
7086
  }
7212
- function extractServedModel6(rawResponse) {
7213
- return normalizeServedModel(rawResponse.model);
7214
- }
7215
7087
  function extractUsage(rawResponse) {
7216
7088
  const usage = asRecord(rawResponse.usage);
7217
7089
  if (!usage) return void 0;
@@ -7979,13 +7851,38 @@ function fitToByteBudget(payload) {
7979
7851
  return JSON.stringify(current);
7980
7852
  }
7981
7853
 
7854
+ // src/ui-telemetry-gate.ts
7855
+ var UI_EVENT_MINUTE_CAPACITY = 60;
7856
+ var UI_EVENT_HOUR_CAPACITY = 600;
7857
+ function createUiTelemetryGate(options = {}) {
7858
+ const now = options.now ?? Date.now;
7859
+ const enabled = options.enabled ?? isTelemetryEnabled;
7860
+ const record2 = options.record ?? recordDashboardEvent;
7861
+ const buckets = [
7862
+ { capacity: UI_EVENT_MINUTE_CAPACITY, perMs: UI_EVENT_MINUTE_CAPACITY / 6e4, tokens: UI_EVENT_MINUTE_CAPACITY },
7863
+ { capacity: UI_EVENT_HOUR_CAPACITY, perMs: UI_EVENT_HOUR_CAPACITY / 36e5, tokens: UI_EVENT_HOUR_CAPACITY }
7864
+ ];
7865
+ let refilledAt = now();
7866
+ return (event) => {
7867
+ if (!enabled()) return false;
7868
+ const at = now();
7869
+ const elapsed = Math.max(0, at - refilledAt);
7870
+ refilledAt = at;
7871
+ for (const bucket of buckets) bucket.tokens = Math.min(bucket.capacity, bucket.tokens + elapsed * bucket.perMs);
7872
+ if (buckets.some((bucket) => bucket.tokens < 1)) return false;
7873
+ for (const bucket of buckets) bucket.tokens -= 1;
7874
+ record2(event);
7875
+ return true;
7876
+ };
7877
+ }
7878
+
7982
7879
  // src/instance-identity.ts
7983
7880
  function nonBlank(value) {
7984
7881
  const trimmed = value?.trim();
7985
7882
  return trimmed ? trimmed : void 0;
7986
7883
  }
7987
7884
  function resolveBuildCommit(env = process.env) {
7988
- const embedded = true ? "49491274532e363f77adf0d73eccaac7a5359a4c" : void 0;
7885
+ const embedded = true ? "fd79321b46c7ef7c816bf08e424f67b869e07a0b" : void 0;
7989
7886
  return nonBlank(embedded) ?? nonBlank(env.CANONRY_COMMIT);
7990
7887
  }
7991
7888
  function resolveInstanceIdentity(env = process.env) {
@@ -12952,18 +12849,17 @@ function withAttemptTimeout(promise, timeoutMs, label) {
12952
12849
  );
12953
12850
  });
12954
12851
  }
12955
- async function embedWithRetry(fn, opts = {}) {
12956
- const attemptTimeoutMs = opts.attemptTimeoutMs ?? EMBED_ATTEMPT_TIMEOUT_MS;
12852
+ async function embedWithRetry(fn) {
12853
+ const attemptTimeoutMs = EMBED_ATTEMPT_TIMEOUT_MS;
12957
12854
  return withRetry(
12958
12855
  () => withAttemptTimeout(fn(), attemptTimeoutMs, "Discovery embedding call"),
12959
12856
  {
12960
- maxRetries: opts.maxRetries ?? EMBED_RETRY_MAX_RETRIES,
12857
+ maxRetries: EMBED_RETRY_MAX_RETRIES,
12961
12858
  isRetryable: isRetryableHttpError,
12962
12859
  maxDelayMs: EMBED_RETRY_MAX_DELAY_MS,
12963
- sleep: opts.sleep,
12964
- onRetry: opts.onRetry ?? (({ attempt, delayMs }) => {
12860
+ onRetry: ({ attempt, delayMs }) => {
12965
12861
  log13.warn("discovery.embed.retry", { attempt, delayMs });
12966
- })
12862
+ }
12967
12863
  }
12968
12864
  );
12969
12865
  }
@@ -12978,7 +12874,7 @@ async function executeDiscoveryRun(opts) {
12978
12874
  const canonicalDomains = effectiveDomains({
12979
12875
  canonicalDomain: projectRow.canonicalDomain,
12980
12876
  ownedDomains: projectRow.ownedDomains
12981
- });
12877
+ }).map(normalizeProjectDomain);
12982
12878
  const brandNames = effectiveBrandNames({
12983
12879
  displayName: projectRow.displayName,
12984
12880
  aliases: projectRow.aliases
@@ -12990,7 +12886,7 @@ async function executeDiscoveryRun(opts) {
12990
12886
  canonicalDomains,
12991
12887
  competitorDomains: projectCompetitors
12992
12888
  };
12993
- const deps = opts.deps ?? buildDefaultDeps(opts.registry);
12889
+ const deps = buildDefaultDeps(opts.registry);
12994
12890
  const result2 = await executeDiscovery({
12995
12891
  db: opts.db,
12996
12892
  runId: opts.runId,
@@ -13052,8 +12948,8 @@ function buildDefaultDeps(registry) {
13052
12948
  async seed(input) {
13053
12949
  const prompt = buildSeedPrompt(input);
13054
12950
  const providerNames = input.seedProviders && input.seedProviders.length > 0 ? [...input.seedProviders] : ["gemini"];
13055
- const perProvider = await Promise.all(providerNames.map(async (name) => {
13056
- const seedProvider = seedProviderFor(name);
12951
+ const admittedProviders = providerNames.map((name) => ({ name, seedProvider: seedProviderFor(name) }));
12952
+ const perProvider = await Promise.all(admittedProviders.map(async ({ name, seedProvider }) => {
13057
12953
  const raw = await seedProvider.adapter.executeTrackedQuery(
13058
12954
  {
13059
12955
  query: prompt,
@@ -14798,7 +14694,7 @@ function readStoredGroundingSources(rawResponse) {
14798
14694
  return result2;
14799
14695
  }
14800
14696
  async function backfillInsightsCommand(project, opts) {
14801
- const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-ZVKZLLKL.js");
14697
+ const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-3L2665AK.js");
14802
14698
  const config = loadConfig();
14803
14699
  const db = createClient(config.database);
14804
14700
  migrate(db);
@@ -16557,8 +16453,9 @@ var Notifier = class {
16557
16453
  })),
16558
16454
  dashboardUrl: `${this.serverUrl}/projects/${project.name}`
16559
16455
  };
16560
- await this.sendWebhook(config.url, payload, notif.id, projectId, notif.webhookSecret ?? null);
16561
- for (const insight of relevantInsights) this.rememberInsightNotified(projectId, insight);
16456
+ if (await this.sendWebhook(config.url, payload, notif.id, projectId, notif.webhookSecret ?? null)) {
16457
+ for (const insight of relevantInsights) this.rememberInsightNotified(projectId, insight);
16458
+ }
16562
16459
  }
16563
16460
  }
16564
16461
  }
@@ -16728,7 +16625,8 @@ var Notifier = class {
16728
16625
  const groupSiblings = this.db.select().from(runs).where(and18(
16729
16626
  eq20(runs.projectId, projectId),
16730
16627
  eq20(runs.kind, thisRun.kind),
16731
- eq20(runs.createdAt, thisRun.createdAt)
16628
+ eq20(runs.createdAt, thisRun.createdAt),
16629
+ notProbeRun()
16732
16630
  )).all();
16733
16631
  const stillPending = groupSiblings.some((r) => r.status === "queued" || r.status === "running");
16734
16632
  if (stillPending) return [];
@@ -16754,7 +16652,8 @@ var Notifier = class {
16754
16652
  and18(
16755
16653
  eq20(runs.projectId, projectId),
16756
16654
  eq20(runs.kind, thisRun.kind),
16757
- or(eq20(runs.status, "completed"), eq20(runs.status, "partial"))
16655
+ or(eq20(runs.status, "completed"), eq20(runs.status, "partial")),
16656
+ notProbeRun()
16758
16657
  )
16759
16658
  ).orderBy(desc9(runs.createdAt), desc9(runs.id)).limit(RECENT_FETCH_LIMIT).all();
16760
16659
  const groups = groupRunsByCreatedAt(recentRuns);
@@ -19239,11 +19138,12 @@ function truncateToByteLimit(text, maxBytes) {
19239
19138
  if (Buffer.byteLength(text, "utf8") <= maxBytes) return text;
19240
19139
  const suffix = "\u2026[truncated]";
19241
19140
  const budget = maxBytes - Buffer.byteLength(suffix, "utf8");
19242
- let buf = Buffer.from(text, "utf8").subarray(0, budget);
19243
- while (buf.length > 0 && (buf[buf.length - 1] & 192) === 128) {
19244
- buf = buf.subarray(0, buf.length - 1);
19141
+ const buf = Buffer.from(text, "utf8");
19142
+ let end = budget;
19143
+ while (end > 0 && (buf[end] & 192) === 128) {
19144
+ end -= 1;
19245
19145
  }
19246
- return buf.toString("utf8") + suffix;
19146
+ return buf.subarray(0, end).toString("utf8") + suffix;
19247
19147
  }
19248
19148
  async function runSummaryLlm(args) {
19249
19149
  const context = {
@@ -19264,8 +19164,7 @@ async function compactMessages(args) {
19264
19164
  if (split === 0) return null;
19265
19165
  const chunk = messages.slice(0, split);
19266
19166
  const suffix = messages.slice(split);
19267
- const summarize = args.summarize ?? runSummaryLlm;
19268
- const rawSummary = await summarize({ model: args.model, chunk, getApiKey: args.getApiKey });
19167
+ const rawSummary = await runSummaryLlm({ model: args.model, chunk, getApiKey: args.getApiKey });
19269
19168
  const summary = truncateToByteLimit(rawSummary, AGENT_MEMORY_VALUE_MAX_BYTES);
19270
19169
  writeCompactionNote(args.db, {
19271
19170
  projectId: args.projectId,
@@ -23212,14 +23111,19 @@ async function createServer(opts) {
23212
23111
  password,
23213
23112
  opts.config.dashboardPasswordHash
23214
23113
  );
23215
- if (!verification.ok) {
23114
+ const onDisk = verification.ok && verification.needsRehash ? loadConfigRaw() : null;
23115
+ if (!verification.ok || onDisk && onDisk.dashboardPasswordHash !== opts.config.dashboardPasswordHash) {
23216
23116
  return reply.status(401).send({
23217
23117
  error: { code: "AUTH_INVALID", message: "Incorrect password" }
23218
23118
  });
23219
23119
  }
23220
23120
  if (verification.needsRehash) {
23221
- opts.config.dashboardPasswordHash = hashDashboardPassword(password);
23222
- saveConfigPatch(opts.config);
23121
+ if (fs9.existsSync(getConfigPath()) && (!onDisk || typeof onDisk !== "object" || Array.isArray(onDisk) || !onDisk.apiUrl || !onDisk.database || !onDisk.apiKey)) {
23122
+ throw new Error("Cannot migrate dashboard password: config.yaml is unreadable or invalid");
23123
+ }
23124
+ const migratedHash = hashDashboardPassword(password);
23125
+ saveConfig({ ...onDisk ?? opts.config, dashboardPasswordHash: migratedHash });
23126
+ opts.config.dashboardPasswordHash = migratedHash;
23223
23127
  }
23224
23128
  if (!createPasswordSession(reply)) {
23225
23129
  return reply.status(401).send({
@@ -23902,10 +23806,10 @@ async function createServer(opts) {
23902
23806
  void setTelemetryPreference(enabled, "api");
23903
23807
  opts.config.telemetry = enabled;
23904
23808
  },
23905
- recordOnboardingEvent: (event) => {
23906
- const { event: eventName, eventId, ...properties } = event;
23907
- trackEvent(eventName, properties, { source: "dashboard", eventId });
23908
- },
23809
+ recordOnboardingEvent: (event) => recordDashboardEvent(event),
23810
+ // Answers false while telemetry is off or the per-process cap is spent, so
23811
+ // the dashboard stops sending for the session.
23812
+ recordUiEvent: createUiTelemetryGate(),
23909
23813
  submitFeedback: (submission, context) => sendFeedback(submission, context),
23910
23814
  onCdpConfigure: async (host, port2) => {
23911
23815
  if (!opts.config.cdp) opts.config.cdp = {};