@canonry/canonry 5.19.1 → 5.20.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 (30) hide show
  1. package/assets/agent-workspace/skills/canonry/references/canonry-cli.md +3 -1
  2. package/assets/assets/{AuditHistoryPanel-ddq5tdlB.js → AuditHistoryPanel-BSh3Oezj.js} +1 -1
  3. package/assets/assets/{BacklinksPage-g57_xzTX.js → BacklinksPage-DQ59dhCx.js} +1 -1
  4. package/assets/assets/{HistoryPage-C-TdCUQ2.js → HistoryPage-BBvgid3o.js} +1 -1
  5. package/assets/assets/{MeasurementPropertyPage-CAADmNfw.js → MeasurementPropertyPage-Dmb18JbT.js} +1 -1
  6. package/assets/assets/{ProjectPage-CoBwpHmA.js → ProjectPage-CPg0q2Dy.js} +1 -1
  7. package/assets/assets/{RunRow-BpG0Zy-x.js → RunRow-BK8sZCID.js} +1 -1
  8. package/assets/assets/{RunsPage-DK3pb1LH.js → RunsPage-CIcVBTdP.js} +1 -1
  9. package/assets/assets/{SettingsPage-BruiY8Zh.js → SettingsPage-Bc3aR-gz.js} +1 -1
  10. package/assets/assets/{SiteHealthSection-De4U11Gv.js → SiteHealthSection-FF14aIXT.js} +3 -3
  11. package/assets/assets/{TrafficPage-BVolLXT2.js → TrafficPage-C_qoeGDl.js} +1 -1
  12. package/assets/assets/{TrafficSourceDetailPage-CFDb6lPD.js → TrafficSourceDetailPage-B3i_B2MI.js} +1 -1
  13. package/assets/assets/{extract-error-message-Bk1RTjzo.js → extract-error-message-BisUn6nN.js} +1 -1
  14. package/assets/assets/{index-B--AA1mG.js → index-Dht7JNX5.js} +3 -3
  15. package/assets/assets/{react-sigma_core.esm.min--QXVK1JS.js → react-sigma_core.esm.min-tWhS09SS.js} +1 -1
  16. package/assets/assets/{v2-overview-adapter-CpjJPZsC.js → v2-overview-adapter-CAoeWKQJ.js} +1 -1
  17. package/assets/index.html +1 -1
  18. package/dist/{chunk-PGOID3LE.js → chunk-4PENJKRN.js} +2 -2
  19. package/dist/{chunk-EJXDABGU.js → chunk-5FKR2K76.js} +4 -3
  20. package/dist/{chunk-EJZFTNZG.js → chunk-DRZWMFRV.js} +195 -90
  21. package/dist/{chunk-SOCYTKTF.js → chunk-QF7SY7AF.js} +27 -6
  22. package/dist/{chunk-J3JXJIST.js → chunk-TSFKNQ5X.js} +3 -3
  23. package/dist/{chunk-3IAIW5KH.js → chunk-WL27HO5C.js} +36 -8
  24. package/dist/{chunk-4WROKFN6.js → chunk-XBGPHZKA.js} +1 -1
  25. package/dist/cli.js +9 -9
  26. package/dist/{demo-server-BLDYKCFS.js → demo-server-OCBV5OMS.js} +4 -4
  27. package/dist/index.js +6 -6
  28. package/dist/{intelligence-service-3MHYLKMS.js → intelligence-service-MKHINDHN.js} +2 -2
  29. package/dist/mcp.js +4 -4
  30. package/package.json +13 -13
@@ -13,19 +13,19 @@ import {
13
13
  resolveOperatorApiKeyIds,
14
14
  runWithUsageTags,
15
15
  saveConfigPatch
16
- } from "./chunk-EJXDABGU.js";
16
+ } from "./chunk-5FKR2K76.js";
17
17
  import {
18
18
  deleteSiteCrawlGraphLayout,
19
19
  persistSiteCrawlGraphLayout,
20
20
  prepareSiteCrawlGraphLayout
21
- } from "./chunk-PGOID3LE.js";
21
+ } from "./chunk-4PENJKRN.js";
22
22
  import {
23
23
  CanonryMcpToolNames,
24
24
  CliError,
25
25
  PACKAGE_VERSION,
26
26
  canonryMcpTools,
27
27
  isMachineFormat
28
- } from "./chunk-4WROKFN6.js";
28
+ } from "./chunk-XBGPHZKA.js";
29
29
  import {
30
30
  CC_CACHE_DIR,
31
31
  DUCKDB_SPEC,
@@ -186,7 +186,7 @@ import {
186
186
  siteLivenessState,
187
187
  toAlertView,
188
188
  usageCounters
189
- } from "./chunk-3IAIW5KH.js";
189
+ } from "./chunk-WL27HO5C.js";
190
190
  import {
191
191
  AGENT_MEMORY_VALUE_MAX_BYTES,
192
192
  AGENT_NONE,
@@ -329,6 +329,7 @@ import {
329
329
  providerError,
330
330
  providerSupportsLocationContext,
331
331
  registrableDomain,
332
+ resolveProviderModel,
332
333
  resolveSnapshotRequestQueries,
333
334
  retryAfterDelayMs,
334
335
  serializeForInlineScript,
@@ -350,7 +351,7 @@ import {
350
351
  visibilityReportRequestSchema,
351
352
  winnabilityClassLabel,
352
353
  withRetry
353
- } from "./chunk-SOCYTKTF.js";
354
+ } from "./chunk-QF7SY7AF.js";
354
355
 
355
356
  // src/runtime-context.ts
356
357
  function cliRuntimeContext(env = process.env, stdio = process) {
@@ -5716,8 +5717,36 @@ async function withRetry6(fn, options = {}) {
5716
5717
  }
5717
5718
 
5718
5719
  // ../provider-perplexity/src/normalize.ts
5719
- var DEFAULT_MODEL5 = "sonar";
5720
- var BASE_URL = "https://api.perplexity.ai";
5720
+ var DEFAULT_MODEL5 = "fast";
5721
+ var BASE_URL = "https://api.perplexity.ai/v1";
5722
+ var AGENT_PATH = "/agent";
5723
+ var PERPLEXITY_RETRIEVAL_CONTRACT = "search-required-v1";
5724
+ var RETRIEVAL_OUTPUT_TYPES = /* @__PURE__ */ new Set(["search_results", "fetch_url_results"]);
5725
+ function resolveModel3(model) {
5726
+ const trimmed = model?.trim();
5727
+ return resolveProviderModel("perplexity", trimmed ? trimmed : DEFAULT_MODEL5);
5728
+ }
5729
+ var ANTHROPIC_MAX_OUTPUT_TOKENS = 4096;
5730
+ function agentSelection(model) {
5731
+ if (!model.includes("/")) return { preset: model };
5732
+ return model.startsWith("anthropic/") ? { model, max_output_tokens: ANTHROPIC_MAX_OUTPUT_TOKENS } : { model };
5733
+ }
5734
+ function buildAgentRequest(query, model, location) {
5735
+ const webSearch = { type: "web_search" };
5736
+ if (location) {
5737
+ webSearch.user_location = {
5738
+ city: location.city,
5739
+ region: location.region,
5740
+ country: location.country
5741
+ };
5742
+ }
5743
+ return {
5744
+ ...agentSelection(model),
5745
+ input: query,
5746
+ tools: [webSearch],
5747
+ tool_choice: { type: "web_search" }
5748
+ };
5749
+ }
5721
5750
  function validateConfig5(config) {
5722
5751
  if (!config.apiKey || config.apiKey.length === 0) {
5723
5752
  return { ok: false, provider: "perplexity", message: "missing api key" };
@@ -5726,48 +5755,42 @@ function validateConfig5(config) {
5726
5755
  ok: true,
5727
5756
  provider: "perplexity",
5728
5757
  message: "config valid",
5729
- model: config.model ?? DEFAULT_MODEL5
5758
+ model: resolveModel3(config.model)
5730
5759
  };
5731
5760
  }
5732
5761
  async function healthcheck5(config) {
5733
5762
  const validation = validateConfig5(config);
5734
5763
  if (!validation.ok) return validation;
5764
+ const model = resolveModel3(config.model);
5735
5765
  try {
5736
- const client = new OpenAI4({ apiKey: config.apiKey, baseURL: BASE_URL });
5766
+ const client = createClient4(config.apiKey);
5737
5767
  const response = await withRetry6(
5738
- () => client.chat.completions.create({
5739
- model: config.model ?? DEFAULT_MODEL5,
5740
- messages: [{ role: "user", content: 'Say "ok"' }]
5741
- })
5768
+ () => postAgent(client, { ...agentSelection(model), input: 'Say "ok"' })
5742
5769
  );
5743
- const text = response.choices[0]?.message?.content ?? "";
5770
+ assertUsableResponse(response);
5771
+ const text = extractAgentAnswerText(response);
5744
5772
  return {
5745
5773
  ok: text.length > 0,
5746
5774
  provider: "perplexity",
5747
5775
  message: text.length > 0 ? "perplexity api key verified" : "empty response from perplexity",
5748
- model: config.model ?? DEFAULT_MODEL5
5776
+ model
5749
5777
  };
5750
5778
  } catch (err) {
5751
5779
  return {
5752
5780
  ok: false,
5753
5781
  provider: "perplexity",
5754
5782
  message: describeError(err),
5755
- model: config.model ?? DEFAULT_MODEL5
5783
+ model
5756
5784
  };
5757
5785
  }
5758
5786
  }
5759
5787
  async function executeTrackedQuery5(input) {
5760
- const model = input.config.model ?? DEFAULT_MODEL5;
5761
- const client = new OpenAI4({ apiKey: input.config.apiKey, baseURL: BASE_URL });
5762
- const prompt = buildPrompt4(input.query, input.location);
5788
+ const model = resolveModel3(input.config.model);
5789
+ const client = createClient4(input.config.apiKey);
5790
+ const request = buildAgentRequest(input.query, model, input.location);
5763
5791
  try {
5764
- const response = await withRetry6(
5765
- () => client.chat.completions.create({
5766
- model,
5767
- messages: [{ role: "user", content: prompt }]
5768
- })
5769
- );
5770
- const rawResponse = responseToRecord5(response);
5792
+ const rawResponse = await withRetry6(() => postAgent(client, request));
5793
+ assertUsableResponse(rawResponse);
5771
5794
  const parsed = reparseStoredResult4(rawResponse);
5772
5795
  return {
5773
5796
  provider: "perplexity",
@@ -5775,7 +5798,8 @@ async function executeTrackedQuery5(input) {
5775
5798
  model,
5776
5799
  servedModel: extractServedModel5(rawResponse),
5777
5800
  groundingSources: parsed.groundingSources,
5778
- searchQueries: parsed.searchQueries
5801
+ searchQueries: parsed.searchQueries,
5802
+ retrievalStatus: parsed.retrievalStatus
5779
5803
  };
5780
5804
  } catch (err) {
5781
5805
  const msg = describeError(err);
@@ -5793,10 +5817,13 @@ function normalizeResult6(raw) {
5793
5817
  answerText: parsed.answerText,
5794
5818
  citedDomains,
5795
5819
  groundingSources,
5796
- searchQueries
5820
+ searchQueries,
5821
+ retrievalStatus: useParsed ? parsed.retrievalStatus : raw.retrievalStatus ?? "unknown"
5797
5822
  };
5798
5823
  }
5799
5824
  function hasParsedResponseContent4(rawResponse) {
5825
+ const agent = agentResponseOf(rawResponse);
5826
+ if (agent) return agentOutput(agent).length > 0;
5800
5827
  if (Array.isArray(rawResponse.choices) && rawResponse.choices.length > 0) return true;
5801
5828
  if (Array.isArray(rawResponse.search_results) && rawResponse.search_results.length > 0) return true;
5802
5829
  if (Array.isArray(rawResponse.citations) && rawResponse.citations.length > 0) return true;
@@ -5808,24 +5835,113 @@ function extractServedModel5(rawResponse) {
5808
5835
  return normalizeServedModel(rawResponse.model);
5809
5836
  }
5810
5837
  function reparseStoredResult4(rawResponse) {
5838
+ const agent = agentResponseOf(rawResponse);
5839
+ if (agent) return parseAgentResponse(agent);
5840
+ return parseSonarResponse(rawResponse);
5841
+ }
5842
+ function createClient4(apiKey) {
5843
+ return new OpenAI4({ apiKey, baseURL: BASE_URL });
5844
+ }
5845
+ function postAgent(client, body) {
5846
+ return client.post(AGENT_PATH, { body });
5847
+ }
5848
+ function assertUsableResponse(response) {
5849
+ const status = response.status;
5850
+ if (status === void 0 || status === "completed") return;
5851
+ if (status === "incomplete") {
5852
+ if (extractAgentAnswerText(response).trim().length > 0) return;
5853
+ const details = isRecord(response.incomplete_details) ? response.incomplete_details : void 0;
5854
+ const reason = typeof details?.reason === "string" && details.reason.length > 0 ? details.reason : "no reason given";
5855
+ throw new Error(`agent response incomplete with no answer: ${reason}`);
5856
+ }
5857
+ const error = isRecord(response.error) ? response.error : void 0;
5858
+ const message = typeof error?.message === "string" && error.message.length > 0 ? error.message : "no error detail";
5859
+ const type = typeof error?.type === "string" && error.type.length > 0 ? ` (${error.type})` : "";
5860
+ throw new Error(`agent response ${typeof status === "string" ? status : describeError(status)}: ${message}${type}`);
5861
+ }
5862
+ function agentResponseOf(rawResponse) {
5863
+ if (Array.isArray(rawResponse.output)) return rawResponse;
5864
+ const nested = extractNestedApiResponse(rawResponse);
5865
+ return nested && Array.isArray(nested.output) ? nested : null;
5866
+ }
5867
+ function agentOutput(response) {
5868
+ return Array.isArray(response.output) ? response.output.filter(isRecord) : [];
5869
+ }
5870
+ function parseAgentResponse(response) {
5871
+ const groundingSources = extractAgentGroundingSources(response);
5872
+ return {
5873
+ provider: "perplexity",
5874
+ answerText: extractAgentAnswerText(response),
5875
+ citedDomains: extractCitedDomains2(groundingSources),
5876
+ groundingSources,
5877
+ searchQueries: extractAgentSearchQueries(response),
5878
+ retrievalStatus: extractAgentRetrievalStatus(response)
5879
+ };
5880
+ }
5881
+ function extractAgentAnswerText(response) {
5882
+ const parts = [];
5883
+ for (const item of agentOutput(response)) {
5884
+ if (item.type !== "message" || !Array.isArray(item.content)) continue;
5885
+ for (const part of item.content) {
5886
+ if (isRecord(part) && part.type === "output_text" && typeof part.text === "string") parts.push(part.text);
5887
+ }
5888
+ }
5889
+ return parts.join("");
5890
+ }
5891
+ function extractAgentGroundingSources(response) {
5892
+ const sources = [];
5893
+ const seen = /* @__PURE__ */ new Set();
5894
+ const add = (entry) => {
5895
+ if (!isRecord(entry) || typeof entry.url !== "string" || entry.url.length === 0) return;
5896
+ if (seen.has(entry.url)) return;
5897
+ seen.add(entry.url);
5898
+ sources.push({ uri: entry.url, title: typeof entry.title === "string" ? entry.title : "" });
5899
+ };
5900
+ for (const item of agentOutput(response)) {
5901
+ if (item.type === "search_results" && Array.isArray(item.results)) {
5902
+ item.results.forEach(add);
5903
+ } else if (item.type === "fetch_url_results" && Array.isArray(item.contents)) {
5904
+ item.contents.forEach(add);
5905
+ } else if (item.type === "message" && Array.isArray(item.content)) {
5906
+ for (const part of item.content) {
5907
+ if (isRecord(part) && Array.isArray(part.annotations)) part.annotations.forEach(add);
5908
+ }
5909
+ }
5910
+ }
5911
+ return sources;
5912
+ }
5913
+ function extractAgentSearchQueries(response) {
5914
+ const queries2 = /* @__PURE__ */ new Set();
5915
+ for (const item of agentOutput(response)) {
5916
+ if (item.type !== "search_results" || !Array.isArray(item.queries)) continue;
5917
+ for (const query of item.queries) {
5918
+ if (typeof query === "string" && query.trim().length > 0) queries2.add(query);
5919
+ }
5920
+ }
5921
+ return [...queries2];
5922
+ }
5923
+ function extractAgentRetrievalStatus(response) {
5924
+ const output = agentOutput(response);
5925
+ if (output.some((item) => typeof item.type === "string" && RETRIEVAL_OUTPUT_TYPES.has(item.type))) return "used";
5926
+ if (output.some((item) => item.type === "message")) return "not-used";
5927
+ return "unknown";
5928
+ }
5929
+ function parseSonarResponse(rawResponse) {
5811
5930
  const groundingSources = extractGroundingSources(rawResponse);
5812
5931
  return {
5813
5932
  provider: "perplexity",
5814
5933
  answerText: extractAnswerText3(rawResponse),
5815
5934
  citedDomains: extractCitedDomains2(groundingSources),
5816
5935
  groundingSources,
5817
- // Perplexity documents `search_results` and `citations` on the response structure but
5818
- // does not document returned search-query telemetry, so Canonry does not synthesize it.
5936
+ // Sonar documented `search_results` and `citations` on the response but no
5937
+ // returned search-query telemetry, so Canonry does not synthesize it.
5819
5938
  // Docs: https://docs.perplexity.ai/docs/sonar/openai-compatibility
5820
- searchQueries: []
5939
+ searchQueries: [],
5940
+ // Sonar's only retrieval marker was present on every stored row, so it
5941
+ // never discriminated a non-retrieving answer. `unknown` is what we know.
5942
+ retrievalStatus: "unknown"
5821
5943
  };
5822
5944
  }
5823
- function buildPrompt4(query, location) {
5824
- if (location) {
5825
- return `${query} (searching from ${location.city}, ${location.region}, ${location.country})`;
5826
- }
5827
- return query;
5828
- }
5829
5945
  function extractCitations(rawResponse) {
5830
5946
  if (Array.isArray(rawResponse.citations)) {
5831
5947
  return rawResponse.citations.filter((c) => typeof c === "string");
@@ -5868,9 +5984,7 @@ function extractSearchResults(rawResponse) {
5868
5984
  function parseSearchResultsArray(value) {
5869
5985
  if (!Array.isArray(value)) return [];
5870
5986
  return value.flatMap((result2) => {
5871
- if (result2 === null || typeof result2 !== "object" || Array.isArray(result2)) {
5872
- return [];
5873
- }
5987
+ if (!isRecord(result2)) return [];
5874
5988
  const url = result2.url;
5875
5989
  if (typeof url !== "string" || url.length === 0) {
5876
5990
  return [];
@@ -5897,11 +6011,10 @@ function extractAnswerText3(rawResponse) {
5897
6011
  }
5898
6012
  }
5899
6013
  function extractNestedApiResponse(rawResponse) {
5900
- const apiResponse = rawResponse.apiResponse;
5901
- if (apiResponse !== null && typeof apiResponse === "object" && !Array.isArray(apiResponse)) {
5902
- return apiResponse;
5903
- }
5904
- return null;
6014
+ return isRecord(rawResponse.apiResponse) ? rawResponse.apiResponse : null;
6015
+ }
6016
+ function isRecord(value) {
6017
+ return value !== null && typeof value === "object" && !Array.isArray(value);
5905
6018
  }
5906
6019
  function extractCitedDomains2(groundingSources) {
5907
6020
  const domains = /* @__PURE__ */ new Set();
@@ -5917,22 +6030,11 @@ function extractDomainFromUri4(uri) {
5917
6030
  return hostname;
5918
6031
  }
5919
6032
  async function generateText5(prompt, config) {
5920
- const model = config.model ?? DEFAULT_MODEL5;
5921
- const client = new OpenAI4({ apiKey: config.apiKey, baseURL: BASE_URL });
5922
- const response = await withRetry6(
5923
- () => client.chat.completions.create({
5924
- model,
5925
- messages: [{ role: "user", content: prompt }]
5926
- })
5927
- );
5928
- return response.choices[0]?.message?.content ?? "";
5929
- }
5930
- function responseToRecord5(response) {
5931
- try {
5932
- return JSON.parse(JSON.stringify(response));
5933
- } catch {
5934
- return { error: "failed to serialize response" };
5935
- }
6033
+ const model = resolveModel3(config.model);
6034
+ const client = createClient4(config.apiKey);
6035
+ const response = await withRetry6(() => postAgent(client, { ...agentSelection(model), input: prompt }));
6036
+ assertUsableResponse(response);
6037
+ return extractAgentAnswerText(response);
5936
6038
  }
5937
6039
 
5938
6040
  // ../provider-perplexity/src/adapter.ts
@@ -5947,19 +6049,22 @@ var perplexityAdapter = {
5947
6049
  name: "perplexity",
5948
6050
  displayName: "Perplexity",
5949
6051
  mode: "api",
5950
- // normalize.ts folds the location into the prompt the model receives.
6052
+ // normalize.ts sends the location as `user_location` on the web_search tool.
5951
6053
  supportsLocationContext: true,
5952
6054
  keyUrl: "https://www.perplexity.ai/settings/api",
5953
- // Upstream model list: https://docs.perplexity.ai/guides/model-cards
6055
+ // Agent API presets: https://docs.perplexity.ai/docs/agent-api/presets
6056
+ // Model slugs (GET https://api.perplexity.ai/v1/models): provider-prefixed, e.g. perplexity/sonar.
5954
6057
  modelRegistry: {
5955
- defaultModel: "sonar",
5956
- validationPattern: /^sonar/,
5957
- validationHint: "expected a sonar model (e.g. sonar, sonar-pro, sonar-reasoning)",
6058
+ defaultModel: DEFAULT_MODEL5,
6059
+ // Presets, `vendor/model` slugs, and the retired Sonar names and previous
6060
+ // preset names that PROVIDER_MODEL_ALIASES resolves (`sonar` → `fast`).
6061
+ validationPattern: /^(?:fast|low|medium|high|xhigh|fast-search|pro-search|deep-research|advanced-deep-research|sonar(?:-pro|-reasoning|-reasoning-pro|-deep-research)?|[a-z0-9][a-z0-9-]*\/[A-Za-z0-9][\w.:-]*)$/,
6062
+ validationHint: "expected an Agent API preset (fast, low, medium, high, xhigh) or a provider/model slug (e.g. perplexity/sonar)",
5958
6063
  knownModels: [
5959
- { id: "sonar", displayName: "Sonar", tier: "standard" },
5960
- { id: "sonar-pro", displayName: "Sonar Pro", tier: "flagship" },
5961
- { id: "sonar-reasoning", displayName: "Sonar Reasoning", tier: "flagship" },
5962
- { id: "sonar-reasoning-pro", displayName: "Sonar Reasoning Pro", tier: "flagship" }
6064
+ { id: "fast", displayName: "Fast preset", tier: "standard" },
6065
+ { id: "low", displayName: "Low preset (pro search)", tier: "flagship" },
6066
+ { id: "medium", displayName: "Medium preset (deep research)", tier: "flagship" },
6067
+ { id: "perplexity/sonar", displayName: "Sonar model + web search", tier: "fast" }
5963
6068
  ]
5964
6069
  },
5965
6070
  validateConfig(config) {
@@ -5995,13 +6100,10 @@ var perplexityAdapter = {
5995
6100
  servedModel: raw.servedModel,
5996
6101
  groundingSources: raw.groundingSources,
5997
6102
  searchQueries: raw.searchQueries,
5998
- // Retrieval detection is not implemented for this provider. Its candidate
5999
- // marker is present on 100% of stored rows, so it has never been shown to
6000
- // discriminate a non-retrieving answer and wiring it up would hardcode
6001
- // `used`. `unknown` states what we actually know. The contract is a
6002
- // declaration about how we build the request, so it is always knowable.
6003
- retrievalStatus: "unknown",
6004
- retrievalContract: "native-auto-v1"
6103
+ // Read off the Agent API output: a `search_results` item is the retrieval
6104
+ // call. The contract is how we built the request, so it is always known.
6105
+ retrievalStatus: raw.retrievalStatus ?? "unknown",
6106
+ retrievalContract: PERPLEXITY_RETRIEVAL_CONTRACT
6005
6107
  };
6006
6108
  },
6007
6109
  normalizeResult(raw) {
@@ -6010,7 +6112,8 @@ var perplexityAdapter = {
6010
6112
  rawResponse: raw.rawResponse,
6011
6113
  model: raw.model,
6012
6114
  groundingSources: raw.groundingSources,
6013
- searchQueries: raw.searchQueries
6115
+ searchQueries: raw.searchQueries,
6116
+ retrievalStatus: raw.retrievalStatus
6014
6117
  };
6015
6118
  const normalized = normalizeResult6(perplexityRaw);
6016
6119
  return {
@@ -6019,7 +6122,7 @@ var perplexityAdapter = {
6019
6122
  citedDomains: normalized.citedDomains,
6020
6123
  groundingSources: normalized.groundingSources,
6021
6124
  searchQueries: normalized.searchQueries,
6022
- retrievalStatus: "unknown"
6125
+ retrievalStatus: normalized.retrievalStatus
6023
6126
  };
6024
6127
  },
6025
6128
  async generateText(prompt, config) {
@@ -6501,7 +6604,7 @@ function nonBlank(value) {
6501
6604
  return trimmed ? trimmed : void 0;
6502
6605
  }
6503
6606
  function resolveBuildCommit(env = process.env) {
6504
- const embedded = true ? "38f4809c78aa8ea4e0b4ab4eb9dbe5e3894ca3ac" : void 0;
6607
+ const embedded = true ? "b5366056cfff6f0e275fe651252cfa1961bf40a9" : void 0;
6505
6608
  return nonBlank(embedded) ?? nonBlank(env.CANONRY_COMMIT);
6506
6609
  }
6507
6610
  function resolveInstanceIdentity(env = process.env) {
@@ -6967,7 +7070,8 @@ var JobRunner = class {
6967
7070
  } else {
6968
7071
  const projectProviders = providerOverride ?? project.providers;
6969
7072
  activeProviders = this.registry.getForProject(projectProviders).map((entry) => {
6970
- const model = project.providerModels[entry.adapter.name];
7073
+ const override = project.providerModels[entry.adapter.name];
7074
+ const model = override === void 0 ? void 0 : resolveProviderModel(entry.adapter.name, override);
6971
7075
  return model === void 0 ? entry : { ...entry, config: { ...entry.config, model } };
6972
7076
  });
6973
7077
  }
@@ -8474,11 +8578,11 @@ function validateGeoSearchLimit(limit) {
8474
8578
  );
8475
8579
  }
8476
8580
  }
8477
- function isRecord(value) {
8581
+ function isRecord2(value) {
8478
8582
  return typeof value === "object" && value !== null && !Array.isArray(value);
8479
8583
  }
8480
8584
  function validateRequestObject(value, label) {
8481
- if (!isRecord(value)) {
8585
+ if (!isRecord2(value)) {
8482
8586
  throw new OpenAiAdsApiError(`${label} must be a JSON object`, 400);
8483
8587
  }
8484
8588
  }
@@ -8637,7 +8741,7 @@ function validateLandingPageConfiguration(value, label) {
8637
8741
  }
8638
8742
  }
8639
8743
  function parseLandingPageQueryStringTemplate(value) {
8640
- if (!isRecord(value)) return null;
8744
+ if (!isRecord2(value)) return null;
8641
8745
  const template = value.query_string_template;
8642
8746
  return typeof template === "string" && template.trim().length > 0 ? template : null;
8643
8747
  }
@@ -12077,7 +12181,7 @@ function readStoredGroundingSources(rawResponse) {
12077
12181
  return result2;
12078
12182
  }
12079
12183
  async function backfillInsightsCommand(project, opts) {
12080
- const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-3MHYLKMS.js");
12184
+ const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-MKHINDHN.js");
12081
12185
  const config = loadConfig();
12082
12186
  const db = createClient(config.database);
12083
12187
  migrate(db);
@@ -12605,7 +12709,8 @@ No DB writes performed. Re-run without --dry-run to apply.`);
12605
12709
  var ProviderRegistry = class {
12606
12710
  providers = /* @__PURE__ */ new Map();
12607
12711
  register(adapter, config) {
12608
- this.providers.set(adapter.name, { adapter, config });
12712
+ const resolved = config.model === void 0 ? config : { ...config, model: resolveProviderModel(adapter.name, config.model) };
12713
+ this.providers.set(adapter.name, { adapter, config: resolved });
12609
12714
  }
12610
12715
  get(name) {
12611
12716
  return this.providers.get(name);
@@ -15013,11 +15118,11 @@ function recordLlmUsageEvent(args) {
15013
15118
  var AERO_MEMORY_SEPARATOR = "\n\n---\n\n";
15014
15119
  var AERO_MEMORY_BLOCK_PREFIX = `${AERO_MEMORY_SEPARATOR}<memory>
15015
15120
  `;
15016
- function isRecord2(value) {
15121
+ function isRecord3(value) {
15017
15122
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
15018
15123
  }
15019
15124
  function isTextSystemBlock(value) {
15020
- return isRecord2(value) && value.type === "text" && typeof value.text === "string";
15125
+ return isRecord3(value) && value.type === "text" && typeof value.text === "string";
15021
15126
  }
15022
15127
  function splitAeroHydratedSystemPrompt(systemPrompt) {
15023
15128
  const idx = systemPrompt.lastIndexOf(AERO_MEMORY_BLOCK_PREFIX);
@@ -15029,7 +15134,7 @@ function splitAeroHydratedSystemPrompt(systemPrompt) {
15029
15134
  }
15030
15135
  function splitAeroAnthropicSystemCachePayload(payload, model) {
15031
15136
  if (model.api !== "anthropic-messages") return void 0;
15032
- if (!isRecord2(payload) || !Array.isArray(payload.system)) return void 0;
15137
+ if (!isRecord3(payload) || !Array.isArray(payload.system)) return void 0;
15033
15138
  let changed = false;
15034
15139
  const nextSystem = [];
15035
15140
  for (const block of payload.system) {
@@ -20312,7 +20417,7 @@ async function createServer(opts) {
20312
20417
  const entry = providerSummary.find((p) => p.name === name);
20313
20418
  if (entry) {
20314
20419
  entry.configured = true;
20315
- entry.model = model || registry.get(name)?.config.model;
20420
+ entry.model = registry.get(name)?.config.model;
20316
20421
  entry.quota = quota;
20317
20422
  if (name === "gemini") {
20318
20423
  entry.vertexConfigured = !!opts.config.providers?.[name]?.vertexProject;
@@ -248,11 +248,6 @@ var PROVIDER_LOCATION_HANDLING = {
248
248
  supportsLocationContext: true,
249
249
  description: "Location appended to the query text the Gemini model receives."
250
250
  },
251
- perplexity: {
252
- treatment: "prompt",
253
- supportsLocationContext: true,
254
- description: "Location appended to the query text the Perplexity model receives."
255
- },
256
251
  local: {
257
252
  treatment: "prompt",
258
253
  supportsLocationContext: true,
@@ -268,6 +263,11 @@ var PROVIDER_LOCATION_HANDLING = {
268
263
  supportsLocationContext: true,
269
264
  description: "Location sent as a structured `user_location` field on Anthropic\u2019s web_search_20250305 tool."
270
265
  },
266
+ perplexity: {
267
+ treatment: "request-param",
268
+ supportsLocationContext: true,
269
+ description: "Location sent as a structured `user_location` field on Perplexity\u2019s web_search tool."
270
+ },
271
271
  "cdp:chatgpt": {
272
272
  treatment: "browser-geo",
273
273
  supportsLocationContext: false,
@@ -4383,6 +4383,25 @@ var measurementPropertyEvidenceQuerySchema = z6.object({
4383
4383
  limit: z6.number().int().positive().max(MEASUREMENT_PAGE_MAX_LIMIT).optional()
4384
4384
  }).strict();
4385
4385
 
4386
+ // ../contracts/src/models.ts
4387
+ var PROVIDER_MODEL_ALIASES = {
4388
+ perplexity: {
4389
+ sonar: "fast",
4390
+ "sonar-pro": "low",
4391
+ "sonar-reasoning": "low",
4392
+ "sonar-reasoning-pro": "low",
4393
+ "sonar-deep-research": "medium",
4394
+ "fast-search": "fast",
4395
+ "pro-search": "low",
4396
+ "deep-research": "medium",
4397
+ "advanced-deep-research": "high"
4398
+ }
4399
+ };
4400
+ function resolveProviderModel(provider, model) {
4401
+ const aliases = PROVIDER_MODEL_ALIASES[provider];
4402
+ return aliases !== void 0 && Object.hasOwn(aliases, model) ? aliases[model] : model;
4403
+ }
4404
+
4386
4405
  // ../contracts/src/measurement-plan.ts
4387
4406
  var MEASUREMENT_PLAN_SCHEMA_VERSION = 1;
4388
4407
  var measurementPlanRevisionSchema = z7.number().int().positive();
@@ -4762,7 +4781,7 @@ function normalizeExecutionIdentity(input) {
4762
4781
  const models = {};
4763
4782
  for (const provider of providers) {
4764
4783
  const model = input.models[provider];
4765
- if (model && model.trim()) models[provider] = model.trim();
4784
+ if (model && model.trim()) models[provider] = resolveProviderModel(provider, model.trim());
4766
4785
  }
4767
4786
  return { providers, models };
4768
4787
  }
@@ -11007,6 +11026,7 @@ var runFillRefusalCodeSchema = z33.enum([
11007
11026
  "plan_revision_changed",
11008
11027
  "manifest_unreadable",
11009
11028
  "model_not_frozen",
11029
+ "model_retired",
11010
11030
  "provider_not_in_plan",
11011
11031
  "provider_nothing_missing",
11012
11032
  "provider_not_configured",
@@ -19642,6 +19662,7 @@ export {
19642
19662
  effectiveBrandNames,
19643
19663
  projectConfigSchema,
19644
19664
  resolveConfigSpecQueries,
19665
+ resolveProviderModel,
19645
19666
  queryClassFilterSchema,
19646
19667
  compileQueryClassifier,
19647
19668
  MEASUREMENT_PLAN_V2_SCHEMA_VERSION,
@@ -4,14 +4,14 @@ import {
4
4
  installSkills,
5
5
  loadConfigRaw,
6
6
  saveConfigPatch
7
- } from "./chunk-EJXDABGU.js";
7
+ } from "./chunk-5FKR2K76.js";
8
8
  import {
9
9
  PACKAGE_VERSION
10
- } from "./chunk-4WROKFN6.js";
10
+ } from "./chunk-XBGPHZKA.js";
11
11
  import {
12
12
  SKILL_MANIFEST_FILENAME,
13
13
  SkillsClients
14
- } from "./chunk-SOCYTKTF.js";
14
+ } from "./chunk-QF7SY7AF.js";
15
15
 
16
16
  // src/skills-autosync.ts
17
17
  import fs from "fs";