@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.
- package/assets/agent-workspace/skills/canonry/references/aeo-analysis.md +5 -3
- package/assets/agent-workspace/skills/canonry/references/canonry-cli.md +19 -2
- package/assets/assets/AuditHistoryPanel-Duvyi8vx.js +1 -0
- package/assets/assets/{BacklinksPage-HIM0fmV7.js → BacklinksPage-CY5AllQu.js} +1 -1
- package/assets/assets/{HistoryPage-BjEVp-fk.js → HistoryPage-C0Gr0gcj.js} +1 -1
- package/assets/assets/{MeasurementPropertyPage-BnVDR2y_.js → MeasurementPropertyPage-DrAB6VKX.js} +1 -1
- package/assets/assets/ProjectPage-DSxvvnAd.js +8 -0
- package/assets/assets/{RunsPage-fJQe2qJc.js → RunsPage-DMxOrtfl.js} +1 -1
- package/assets/assets/{SettingsPage-1yam5tl6.js → SettingsPage-sxiUNt2A.js} +1 -1
- package/assets/assets/SiteHealthSection--6tZe3hM.js +4 -0
- package/assets/assets/{TrafficPage-BdNEscz8.js → TrafficPage-CvSQDNTi.js} +2 -2
- package/assets/assets/{TrafficSourceDetailPage-CMEgr4Aw.js → TrafficSourceDetailPage-BaYeIBmc.js} +1 -1
- package/assets/assets/{extract-error-message-D2dhaJaW.js → extract-error-message-76IWhqQF.js} +1 -1
- package/assets/assets/index-BlrH2zRW.js +86 -0
- package/assets/assets/index-HWSQgVum.css +1 -0
- package/assets/assets/{react-sigma_core.esm.min-oP23IWpt.js → react-sigma_core.esm.min-CkAcKW2k.js} +1 -1
- package/assets/assets/{v2-overview-adapter-DYatWs7N.js → v2-overview-adapter-DnEE4E9w.js} +1 -1
- package/assets/index.html +2 -2
- package/dist/{chunk-TUHQ5BBQ.js → chunk-BYSSJEL7.js} +9 -8
- package/dist/{chunk-LXWY4NKP.js → chunk-EQBYK77W.js} +3 -3
- package/dist/{chunk-HQJ25LI7.js → chunk-FDBQOQLP.js} +2 -2
- package/dist/{chunk-EZ54X4XH.js → chunk-RCQJI3UX.js} +125 -86
- package/dist/{chunk-RRIZ5AKI.js → chunk-SVTVBPIT.js} +2 -2
- package/dist/{chunk-OOUDIVIU.js → chunk-TY3CJKKR.js} +458 -184
- package/dist/{chunk-A5PALGQD.js → chunk-UIDHHZH3.js} +94 -190
- package/dist/cli.js +32 -16
- package/dist/{demo-server-LHHDVXQW.js → demo-server-GWRYDPJC.js} +4 -4
- package/dist/index.js +6 -6
- package/dist/{intelligence-service-ZVKZLLKL.js → intelligence-service-3L2665AK.js} +2 -2
- package/dist/mcp.js +4 -4
- package/package.json +12 -12
- package/assets/assets/AuditHistoryPanel-DBYsgVsn.js +0 -1
- package/assets/assets/ProjectPage-BhCM47KA.js +0 -8
- package/assets/assets/SiteHealthSection-DysU2M6C.js +0 -4
- package/assets/assets/index-CgT2Btdn.css +0 -1
- 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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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:
|
|
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 (
|
|
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:
|
|
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
|
|
4452
|
-
|
|
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
|
-
|
|
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:
|
|
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:
|
|
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:
|
|
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
|
|
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:
|
|
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:
|
|
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
|
|
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:
|
|
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:
|
|
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 ? "
|
|
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
|
|
12956
|
-
const attemptTimeoutMs =
|
|
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:
|
|
12857
|
+
maxRetries: EMBED_RETRY_MAX_RETRIES,
|
|
12961
12858
|
isRetryable: isRetryableHttpError,
|
|
12962
12859
|
maxDelayMs: EMBED_RETRY_MAX_DELAY_MS,
|
|
12963
|
-
|
|
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 =
|
|
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
|
|
13056
|
-
|
|
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-
|
|
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
|
-
|
|
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
|
-
|
|
19243
|
-
|
|
19244
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
23222
|
-
|
|
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
|
-
|
|
23907
|
-
|
|
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 = {};
|