@ainyc/canonry 1.32.0 → 1.33.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/index.html CHANGED
@@ -12,8 +12,8 @@
12
12
  <link rel="icon" type="image/png" sizes="32x32" href="./favicon-32.png" />
13
13
  <link rel="apple-touch-icon" href="./apple-touch-icon.png" />
14
14
  <title>Canonry</title>
15
- <script type="module" crossorigin src="./assets/index-BuSiyI7z.js"></script>
16
- <link rel="stylesheet" crossorigin href="./assets/index-r6biprHB.css">
15
+ <script type="module" crossorigin src="./assets/index-BiIPqZJb.js"></script>
16
+ <link rel="stylesheet" crossorigin href="./assets/index-B5Cg2H9M.css">
17
17
  </head>
18
18
  <body>
19
19
  <div id="root"></div>
@@ -816,6 +816,7 @@ var querySnapshotDtoSchema = z8.object({
816
816
  citedDomains: z8.array(z8.string()).default([]),
817
817
  competitorOverlap: z8.array(z8.string()).default([]),
818
818
  recommendedCompetitors: z8.array(z8.string()).default([]),
819
+ matchedTerms: z8.array(z8.string()).default([]),
819
820
  groundingSources: z8.array(groundingSourceSchema).default([]),
820
821
  searchQueries: z8.array(z8.string()).default([]),
821
822
  model: z8.string().nullable().optional(),
@@ -1093,30 +1094,39 @@ var GENERIC_TOKENS = /* @__PURE__ */ new Set([
1093
1094
  "systems",
1094
1095
  "tech"
1095
1096
  ]);
1096
- function determineAnswerMentioned(answerText, displayName, domains) {
1097
- if (!answerText) return false;
1097
+ function extractAnswerMentions(answerText, displayName, domains) {
1098
+ if (!answerText) return { mentioned: false, matchedTerms: [] };
1099
+ const matchedTerms = [];
1098
1100
  const lowerAnswer = answerText.toLowerCase();
1099
1101
  for (const domain of domains) {
1100
1102
  const normalizedDomain = normalizeProjectDomain(domain);
1101
1103
  if (!normalizedDomain || !normalizedDomain.includes(".")) continue;
1102
- if (domainMentioned(lowerAnswer, normalizedDomain)) return true;
1104
+ if (domainMentioned(lowerAnswer, normalizedDomain)) {
1105
+ matchedTerms.push(normalizedDomain);
1106
+ }
1103
1107
  }
1104
1108
  const normalizedDisplayName = normalizeText(displayName);
1105
1109
  if (normalizedDisplayName && normalizeText(answerText).includes(normalizedDisplayName)) {
1106
- return true;
1110
+ matchedTerms.push(displayName);
1107
1111
  }
1108
1112
  const tokens = collectDistinctiveTokens(displayName, domains);
1109
- if (tokens.length === 0) return false;
1110
- let matches = 0;
1113
+ let tokenMatches = 0;
1114
+ const matchedTokens = [];
1111
1115
  for (const token of tokens) {
1112
1116
  if (new RegExp(`\\b${escapeRegExp(token)}\\b`).test(lowerAnswer)) {
1113
- matches++;
1117
+ tokenMatches++;
1118
+ matchedTokens.push(token);
1114
1119
  }
1115
1120
  }
1116
- if (tokens.length === 1) {
1117
- return matches >= 1;
1121
+ const tokenThresholdMet = tokens.length > 0 && (tokens.length === 1 && tokenMatches >= 1 || tokenMatches >= Math.min(2, tokens.length));
1122
+ if (tokenThresholdMet) {
1123
+ matchedTerms.push(...matchedTokens);
1118
1124
  }
1119
- return matches >= Math.min(2, tokens.length);
1125
+ const unique = [...new Set(matchedTerms)];
1126
+ return { mentioned: unique.length > 0, matchedTerms: unique };
1127
+ }
1128
+ function determineAnswerMentioned(answerText, displayName, domains) {
1129
+ return extractAnswerMentions(answerText, displayName, domains).mentioned;
1120
1130
  }
1121
1131
  function visibilityStateFromAnswerMentioned(answerMentioned) {
1122
1132
  return answerMentioned ? "visible" : "not-visible";
@@ -1930,17 +1940,27 @@ function writeAuditLog(db, entry) {
1930
1940
  createdAt: now
1931
1941
  }).run();
1932
1942
  }
1933
- function resolveSnapshotAnswerMentioned(snapshot, project) {
1943
+ function resolveSnapshotMentionResult(snapshot, project) {
1944
+ if (snapshot.answerText) {
1945
+ const domains = effectiveDomains({
1946
+ canonicalDomain: project.canonicalDomain,
1947
+ ownedDomains: normalizeOwnedDomains(project.ownedDomains)
1948
+ });
1949
+ return extractAnswerMentions(snapshot.answerText, project.displayName, domains);
1950
+ }
1934
1951
  if (typeof snapshot.answerMentioned === "boolean") {
1935
- return snapshot.answerMentioned;
1952
+ return { mentioned: snapshot.answerMentioned, matchedTerms: [] };
1936
1953
  }
1937
- return determineAnswerMentioned(snapshot.answerText, project.displayName, effectiveDomains({
1938
- canonicalDomain: project.canonicalDomain,
1939
- ownedDomains: normalizeOwnedDomains(project.ownedDomains)
1940
- }));
1954
+ return { mentioned: false, matchedTerms: [] };
1955
+ }
1956
+ function resolveSnapshotAnswerMentioned(snapshot, project) {
1957
+ return resolveSnapshotMentionResult(snapshot, project).mentioned;
1941
1958
  }
1942
1959
  function resolveSnapshotVisibilityState(snapshot, project) {
1943
- return visibilityStateFromAnswerMentioned(resolveSnapshotAnswerMentioned(snapshot, project));
1960
+ return visibilityStateFromAnswerMentioned(resolveSnapshotMentionResult(snapshot, project).mentioned);
1961
+ }
1962
+ function resolveSnapshotMatchedTerms(snapshot, project) {
1963
+ return resolveSnapshotMentionResult(snapshot, project).matchedTerms;
1944
1964
  }
1945
1965
  function normalizeOwnedDomains(value) {
1946
1966
  if (Array.isArray(value)) return value.filter((item) => typeof item === "string");
@@ -2645,6 +2665,7 @@ async function runRoutes(app, opts) {
2645
2665
  citedDomains: parseJsonColumn(s.citedDomains, []),
2646
2666
  competitorOverlap: parseJsonColumn(s.competitorOverlap, []),
2647
2667
  recommendedCompetitors: parseJsonColumn(s.recommendedCompetitors, []),
2668
+ matchedTerms: project ? resolveSnapshotMatchedTerms(s, project) : [],
2648
2669
  model: s.model ?? rawParsed.model,
2649
2670
  location: s.location,
2650
2671
  groundingSources: rawParsed.groundingSources,
@@ -11280,7 +11301,7 @@ var CDPConnectionManager = class {
11280
11301
  await sleep(1500);
11281
11302
  } catch (err) {
11282
11303
  throw new CDPProviderError(
11283
- "CDP_CONNECTION_REFUSED",
11304
+ "CDP_TARGET_SELECTOR_FAILED",
11284
11305
  `Failed to navigate to ${target.newConversationUrl}: ${err instanceof Error ? err.message : String(err)}`
11285
11306
  );
11286
11307
  }
@@ -11769,10 +11790,11 @@ async function healthcheck5(config) {
11769
11790
  async function executeTrackedQuery5(input) {
11770
11791
  const model = input.config.model ?? DEFAULT_MODEL5;
11771
11792
  const client = new OpenAI3({ apiKey: input.config.apiKey, baseURL: BASE_URL });
11793
+ const prompt = buildPrompt4(input.keyword, input.location);
11772
11794
  const response = await client.chat.completions.create({
11773
11795
  model,
11774
11796
  messages: [
11775
- { role: "user", content: input.keyword }
11797
+ { role: "user", content: prompt }
11776
11798
  ]
11777
11799
  });
11778
11800
  const rawResponse = responseToRecord4(response);
@@ -11800,6 +11822,12 @@ function normalizeResult6(raw) {
11800
11822
  searchQueries: raw.searchQueries
11801
11823
  };
11802
11824
  }
11825
+ function buildPrompt4(keyword, location) {
11826
+ if (location) {
11827
+ return `${keyword} (searching from ${location.city}, ${location.region}, ${location.country})`;
11828
+ }
11829
+ return keyword;
11830
+ }
11803
11831
  function extractCitations(rawResponse) {
11804
11832
  if (Array.isArray(rawResponse.citations)) {
11805
11833
  return rawResponse.citations.filter((c) => typeof c === "string");
package/dist/cli.js CHANGED
@@ -26,7 +26,7 @@ import {
26
26
  setGoogleAuthConfig,
27
27
  showFirstRunNotice,
28
28
  trackEvent
29
- } from "./chunk-5Q6LISDM.js";
29
+ } from "./chunk-WRNSBFNQ.js";
30
30
 
31
31
  // src/cli.ts
32
32
  import { pathToFileURL } from "url";
@@ -1776,10 +1776,10 @@ Open this URL in your browser to authorize Google ${opts.type.toUpperCase()} acc
1776
1776
  console.log("(Ensure this URI is listed in your Google Cloud Console OAuth client's authorized redirect URIs)\n");
1777
1777
  }
1778
1778
  try {
1779
- const { exec } = await import("child_process");
1779
+ const { spawn: spawn2 } = await import("child_process");
1780
1780
  const platform = process.platform;
1781
- const cmd = platform === "darwin" ? "open" : platform === "win32" ? "start" : "xdg-open";
1782
- exec(`${cmd} "${authUrl}"`);
1781
+ const [cmd, ...extraArgs] = platform === "darwin" ? ["open", authUrl] : platform === "win32" ? ["cmd", "/c", "start", "", authUrl] : ["xdg-open", authUrl];
1782
+ spawn2(cmd, [...extraArgs], { detached: true, stdio: "ignore" }).unref();
1783
1783
  console.log("(Browser opened automatically)");
1784
1784
  } catch {
1785
1785
  console.log("(Could not open browser automatically \u2014 please copy the URL above)");
@@ -4025,7 +4025,7 @@ async function showSchedule(project, format) {
4025
4025
  async function enableSchedule(project, format) {
4026
4026
  const client = getClient14();
4027
4027
  const current = await client.getSchedule(project);
4028
- const body = { timezone: current.timezone };
4028
+ const body = { timezone: current.timezone, enabled: true };
4029
4029
  if (current.preset) body.preset = current.preset;
4030
4030
  else body.cron = current.cronExpr;
4031
4031
  if (current.providers.length) body.providers = current.providers;
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  createServer,
3
3
  loadConfig
4
- } from "./chunk-5Q6LISDM.js";
4
+ } from "./chunk-WRNSBFNQ.js";
5
5
  export {
6
6
  createServer,
7
7
  loadConfig
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ainyc/canonry",
3
- "version": "1.32.0",
3
+ "version": "1.33.0",
4
4
  "type": "module",
5
5
  "description": "The ultimate open-source AEO monitoring tool - track how answer engines cite your domain",
6
6
  "license": "FSL-1.1-ALv2",
@@ -55,18 +55,18 @@
55
55
  "tsup": "^8.5.1",
56
56
  "tsx": "^4.19.0",
57
57
  "@ainyc/canonry-api-routes": "0.0.0",
58
- "@ainyc/canonry-config": "0.0.0",
59
58
  "@ainyc/canonry-contracts": "0.0.0",
60
- "@ainyc/canonry-integration-google": "0.0.0",
59
+ "@ainyc/canonry-config": "0.0.0",
61
60
  "@ainyc/canonry-integration-bing": "0.0.0",
62
- "@ainyc/canonry-db": "0.0.0",
63
- "@ainyc/canonry-provider-cdp": "0.0.0",
61
+ "@ainyc/canonry-integration-google": "0.0.0",
64
62
  "@ainyc/canonry-integration-wordpress": "0.0.0",
63
+ "@ainyc/canonry-provider-cdp": "0.0.0",
65
64
  "@ainyc/canonry-provider-claude": "0.0.0",
65
+ "@ainyc/canonry-db": "0.0.0",
66
66
  "@ainyc/canonry-provider-gemini": "0.0.0",
67
67
  "@ainyc/canonry-provider-local": "0.0.0",
68
- "@ainyc/canonry-provider-openai": "0.0.0",
69
- "@ainyc/canonry-provider-perplexity": "0.0.0"
68
+ "@ainyc/canonry-provider-perplexity": "0.0.0",
69
+ "@ainyc/canonry-provider-openai": "0.0.0"
70
70
  },
71
71
  "scripts": {
72
72
  "build": "tsup && tsx build-web.ts",