@automatelab/citation-intelligence 0.4.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 (119) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +302 -0
  3. package/dist/adapters/anthropic.d.ts +3 -0
  4. package/dist/adapters/anthropic.d.ts.map +1 -0
  5. package/dist/adapters/anthropic.js +52 -0
  6. package/dist/adapters/anthropic.js.map +1 -0
  7. package/dist/adapters/bing.d.ts +3 -0
  8. package/dist/adapters/bing.d.ts.map +1 -0
  9. package/dist/adapters/bing.js +31 -0
  10. package/dist/adapters/bing.js.map +1 -0
  11. package/dist/adapters/gemini.d.ts +3 -0
  12. package/dist/adapters/gemini.d.ts.map +1 -0
  13. package/dist/adapters/gemini.js +47 -0
  14. package/dist/adapters/gemini.js.map +1 -0
  15. package/dist/adapters/openai.d.ts +3 -0
  16. package/dist/adapters/openai.d.ts.map +1 -0
  17. package/dist/adapters/openai.js +49 -0
  18. package/dist/adapters/openai.js.map +1 -0
  19. package/dist/adapters/perplexity.d.ts +3 -0
  20. package/dist/adapters/perplexity.d.ts.map +1 -0
  21. package/dist/adapters/perplexity.js +55 -0
  22. package/dist/adapters/perplexity.js.map +1 -0
  23. package/dist/adapters/predictors.d.ts +42 -0
  24. package/dist/adapters/predictors.d.ts.map +1 -0
  25. package/dist/adapters/predictors.js +495 -0
  26. package/dist/adapters/predictors.js.map +1 -0
  27. package/dist/adapters/serpapi.d.ts +8 -0
  28. package/dist/adapters/serpapi.d.ts.map +1 -0
  29. package/dist/adapters/serpapi.js +45 -0
  30. package/dist/adapters/serpapi.js.map +1 -0
  31. package/dist/index.d.ts +3 -0
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/index.js +132 -0
  34. package/dist/index.js.map +1 -0
  35. package/dist/lib/cache.d.ts +33 -0
  36. package/dist/lib/cache.d.ts.map +1 -0
  37. package/dist/lib/cache.js +110 -0
  38. package/dist/lib/cache.js.map +1 -0
  39. package/dist/lib/config.d.ts +6 -0
  40. package/dist/lib/config.d.ts.map +1 -0
  41. package/dist/lib/config.js +12 -0
  42. package/dist/lib/config.js.map +1 -0
  43. package/dist/lib/fetch.d.ts +18 -0
  44. package/dist/lib/fetch.d.ts.map +1 -0
  45. package/dist/lib/fetch.js +75 -0
  46. package/dist/lib/fetch.js.map +1 -0
  47. package/dist/lib/log.d.ts +11 -0
  48. package/dist/lib/log.d.ts.map +1 -0
  49. package/dist/lib/log.js +37 -0
  50. package/dist/lib/log.js.map +1 -0
  51. package/dist/lib/panels.d.ts +30 -0
  52. package/dist/lib/panels.d.ts.map +1 -0
  53. package/dist/lib/panels.js +69 -0
  54. package/dist/lib/panels.js.map +1 -0
  55. package/dist/tools/ai-overview.d.ts +29 -0
  56. package/dist/tools/ai-overview.d.ts.map +1 -0
  57. package/dist/tools/ai-overview.js +47 -0
  58. package/dist/tools/ai-overview.js.map +1 -0
  59. package/dist/tools/am-i-cited.d.ts +39 -0
  60. package/dist/tools/am-i-cited.d.ts.map +1 -0
  61. package/dist/tools/am-i-cited.js +73 -0
  62. package/dist/tools/am-i-cited.js.map +1 -0
  63. package/dist/tools/audit-sitemap.d.ts +49 -0
  64. package/dist/tools/audit-sitemap.d.ts.map +1 -0
  65. package/dist/tools/audit-sitemap.js +100 -0
  66. package/dist/tools/audit-sitemap.js.map +1 -0
  67. package/dist/tools/check-citations.d.ts +30 -0
  68. package/dist/tools/check-citations.d.ts.map +1 -0
  69. package/dist/tools/check-citations.js +101 -0
  70. package/dist/tools/check-citations.js.map +1 -0
  71. package/dist/tools/citation-freshness-score.d.ts +53 -0
  72. package/dist/tools/citation-freshness-score.d.ts.map +1 -0
  73. package/dist/tools/citation-freshness-score.js +89 -0
  74. package/dist/tools/citation-freshness-score.js.map +1 -0
  75. package/dist/tools/citation-trend.d.ts +47 -0
  76. package/dist/tools/citation-trend.d.ts.map +1 -0
  77. package/dist/tools/citation-trend.js +48 -0
  78. package/dist/tools/citation-trend.js.map +1 -0
  79. package/dist/tools/cited-for-diff.d.ts +54 -0
  80. package/dist/tools/cited-for-diff.d.ts.map +1 -0
  81. package/dist/tools/cited-for-diff.js +89 -0
  82. package/dist/tools/cited-for-diff.js.map +1 -0
  83. package/dist/tools/cited-for.d.ts +39 -0
  84. package/dist/tools/cited-for.d.ts.map +1 -0
  85. package/dist/tools/cited-for.js +28 -0
  86. package/dist/tools/cited-for.js.map +1 -0
  87. package/dist/tools/compare-domains.d.ts +36 -0
  88. package/dist/tools/compare-domains.d.ts.map +1 -0
  89. package/dist/tools/compare-domains.js +54 -0
  90. package/dist/tools/compare-domains.js.map +1 -0
  91. package/dist/tools/compete-for-query.d.ts +72 -0
  92. package/dist/tools/compete-for-query.d.ts.map +1 -0
  93. package/dist/tools/compete-for-query.js +91 -0
  94. package/dist/tools/compete-for-query.js.map +1 -0
  95. package/dist/tools/gsc-citation-gap.d.ts +77 -0
  96. package/dist/tools/gsc-citation-gap.d.ts.map +1 -0
  97. package/dist/tools/gsc-citation-gap.js +121 -0
  98. package/dist/tools/gsc-citation-gap.js.map +1 -0
  99. package/dist/tools/predict-citation.d.ts +25 -0
  100. package/dist/tools/predict-citation.d.ts.map +1 -0
  101. package/dist/tools/predict-citation.js +32 -0
  102. package/dist/tools/predict-citation.js.map +1 -0
  103. package/dist/tools/run-panel.d.ts +46 -0
  104. package/dist/tools/run-panel.d.ts.map +1 -0
  105. package/dist/tools/run-panel.js +60 -0
  106. package/dist/tools/run-panel.js.map +1 -0
  107. package/dist/tools/track-queries.d.ts +52 -0
  108. package/dist/tools/track-queries.d.ts.map +1 -0
  109. package/dist/tools/track-queries.js +52 -0
  110. package/dist/tools/track-queries.js.map +1 -0
  111. package/dist/tools/wikipedia-mentions.d.ts +32 -0
  112. package/dist/tools/wikipedia-mentions.d.ts.map +1 -0
  113. package/dist/tools/wikipedia-mentions.js +56 -0
  114. package/dist/tools/wikipedia-mentions.js.map +1 -0
  115. package/dist/types.d.ts +42 -0
  116. package/dist/types.d.ts.map +1 -0
  117. package/dist/types.js +2 -0
  118. package/dist/types.js.map +1 -0
  119. package/package.json +57 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-overview.d.ts","sourceRoot":"","sources":["../../src/tools/ai-overview.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,eAAO,MAAM,qBAAqB;;;;CAOjC,CAAC;AAEF,QAAA,MAAM,WAAW;;;;;;;;;;;;EAAkC,CAAC;AAEpD,wBAAsB,UAAU,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC;;;;;;;GAqClE"}
@@ -0,0 +1,47 @@
1
+ import { z } from "zod";
2
+ import { serpapiAiOverview } from "../adapters/serpapi.js";
3
+ import { getAiOverview, putAiOverview } from "../lib/cache.js";
4
+ export const aiOverviewInputSchema = {
5
+ query: z.string().min(1).describe("Search query to check for Google AI Overview."),
6
+ location: z
7
+ .string()
8
+ .optional()
9
+ .describe("Location string, e.g. 'United States'. Affects AI Overview eligibility."),
10
+ hl: z.string().default("en").describe("Language code, default 'en'."),
11
+ };
12
+ const inputSchema = z.object(aiOverviewInputSchema);
13
+ export async function aiOverview(input) {
14
+ const parsed = inputSchema.parse(input);
15
+ const cached = await getAiOverview(parsed.query, parsed.location, parsed.hl);
16
+ if (cached) {
17
+ return {
18
+ query: parsed.query,
19
+ fetched_at: cached.fetched_at,
20
+ ai_overview_present: cached.ai_overview_present,
21
+ ai_overview_text: cached.ai_overview_text,
22
+ sources: cached.sources,
23
+ cached: true,
24
+ };
25
+ }
26
+ const res = await serpapiAiOverview(parsed.query, parsed.location, parsed.hl);
27
+ const fetched_at = new Date().toISOString();
28
+ await putAiOverview({
29
+ type: "ai_overview",
30
+ query: parsed.query,
31
+ location: parsed.location,
32
+ hl: parsed.hl,
33
+ fetched_at,
34
+ ai_overview_present: res.ai_overview_present,
35
+ ai_overview_text: res.ai_overview_text,
36
+ sources: res.sources,
37
+ });
38
+ return {
39
+ query: parsed.query,
40
+ fetched_at,
41
+ ai_overview_present: res.ai_overview_present,
42
+ ai_overview_text: res.ai_overview_text,
43
+ sources: res.sources,
44
+ cached: false,
45
+ };
46
+ }
47
+ //# sourceMappingURL=ai-overview.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-overview.js","sourceRoot":"","sources":["../../src/tools/ai-overview.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAE/D,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,+CAA+C,CAAC;IAClF,QAAQ,EAAE,CAAC;SACR,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CAAC,yEAAyE,CAAC;IACtF,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,8BAA8B,CAAC;CACtE,CAAC;AAEF,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC;AAEpD,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,KAAkC;IACjE,MAAM,MAAM,GAAG,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAExC,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;IAC7E,IAAI,MAAM,EAAE,CAAC;QACX,OAAO;YACL,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,UAAU,EAAE,MAAM,CAAC,UAAU;YAC7B,mBAAmB,EAAE,MAAM,CAAC,mBAAmB;YAC/C,gBAAgB,EAAE,MAAM,CAAC,gBAAgB;YACzC,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,MAAM,EAAE,IAAI;SACb,CAAC;IACJ,CAAC;IAED,MAAM,GAAG,GAAG,MAAM,iBAAiB,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;IAC9E,MAAM,UAAU,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAE5C,MAAM,aAAa,CAAC;QAClB,IAAI,EAAE,aAAa;QACnB,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,EAAE,EAAE,MAAM,CAAC,EAAE;QACb,UAAU;QACV,mBAAmB,EAAE,GAAG,CAAC,mBAAmB;QAC5C,gBAAgB,EAAE,GAAG,CAAC,gBAAgB;QACtC,OAAO,EAAE,GAAG,CAAC,OAAO;KACrB,CAAC,CAAC;IAEH,OAAO;QACL,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,UAAU;QACV,mBAAmB,EAAE,GAAG,CAAC,mBAAmB;QAC5C,gBAAgB,EAAE,GAAG,CAAC,gBAAgB;QACtC,OAAO,EAAE,GAAG,CAAC,OAAO;QACpB,MAAM,EAAE,KAAK;KACd,CAAC;AACJ,CAAC"}
@@ -0,0 +1,39 @@
1
+ import { z } from "zod";
2
+ import type { Engine } from "../types.js";
3
+ export declare const amICitedInputSchema: {
4
+ domain: z.ZodString;
5
+ queries: z.ZodArray<z.ZodString, "many">;
6
+ engine: z.ZodDefault<z.ZodEnum<["perplexity", "claude", "openai", "gemini", "bing", "auto"]>>;
7
+ };
8
+ declare const inputSchema: z.ZodObject<{
9
+ domain: z.ZodString;
10
+ queries: z.ZodArray<z.ZodString, "many">;
11
+ engine: z.ZodDefault<z.ZodEnum<["perplexity", "claude", "openai", "gemini", "bing", "auto"]>>;
12
+ }, "strip", z.ZodTypeAny, {
13
+ engine: "perplexity" | "claude" | "openai" | "gemini" | "bing" | "auto";
14
+ domain: string;
15
+ queries: string[];
16
+ }, {
17
+ domain: string;
18
+ queries: string[];
19
+ engine?: "perplexity" | "claude" | "openai" | "gemini" | "bing" | "auto" | undefined;
20
+ }>;
21
+ export declare function amICited(input: z.infer<typeof inputSchema>): Promise<{
22
+ domain: string;
23
+ engine: Engine;
24
+ fetched_at: string;
25
+ results: {
26
+ query: string;
27
+ cited: boolean;
28
+ rank?: number;
29
+ matching_urls: string[];
30
+ }[];
31
+ summary: {
32
+ queries_total: number;
33
+ queries_cited: number;
34
+ citation_rate: number;
35
+ average_rank: number | undefined;
36
+ };
37
+ }>;
38
+ export {};
39
+ //# sourceMappingURL=am-i-cited.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"am-i-cited.d.ts","sourceRoot":"","sources":["../../src/tools/am-i-cited.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,eAAO,MAAM,mBAAmB;;;;CAc/B,CAAC;AAEF,QAAA,MAAM,WAAW;;;;;;;;;;;;EAAgC,CAAC;AAoBlD,wBAAsB,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC;;;;;eAKtD,MAAM;eACN,OAAO;eACP,MAAM;uBACE,MAAM,EAAE;;;;;;;;GAwC1B"}
@@ -0,0 +1,73 @@
1
+ import { z } from "zod";
2
+ import { checkCitations } from "./check-citations.js";
3
+ export const amICitedInputSchema = {
4
+ domain: z
5
+ .string()
6
+ .min(1)
7
+ .describe("Domain to check, e.g. 'automatelab.tech' (without protocol)."),
8
+ queries: z
9
+ .array(z.string().min(1))
10
+ .min(1)
11
+ .max(20)
12
+ .describe("Queries to test the domain against. 1-20 queries per call."),
13
+ engine: z
14
+ .enum(["perplexity", "claude", "openai", "gemini", "bing", "auto"])
15
+ .default("auto")
16
+ .describe("AI engine to query."),
17
+ };
18
+ const inputSchema = z.object(amICitedInputSchema);
19
+ function normalizeDomain(d) {
20
+ return d
21
+ .replace(/^https?:\/\//, "")
22
+ .replace(/^www\./, "")
23
+ .replace(/\/$/, "")
24
+ .toLowerCase();
25
+ }
26
+ function urlMatchesDomain(url, needle) {
27
+ try {
28
+ const u = new URL(url);
29
+ const host = u.hostname.toLowerCase().replace(/^www\./, "");
30
+ return host === needle || host.endsWith("." + needle);
31
+ }
32
+ catch {
33
+ return false;
34
+ }
35
+ }
36
+ export async function amICited(input) {
37
+ const parsed = inputSchema.parse(input);
38
+ const needle = normalizeDomain(parsed.domain);
39
+ const results = [];
40
+ let resolvedEngine = parsed.engine;
41
+ for (const query of parsed.queries) {
42
+ const res = await checkCitations({
43
+ query,
44
+ engine: parsed.engine,
45
+ max_results: 20,
46
+ });
47
+ resolvedEngine = res.engine;
48
+ const matches = res.citations.filter((c) => urlMatchesDomain(c.url, needle));
49
+ const rank = matches.length > 0 ? matches[0].rank : undefined;
50
+ results.push({
51
+ query,
52
+ cited: matches.length > 0,
53
+ rank,
54
+ matching_urls: matches.map((m) => m.url),
55
+ });
56
+ }
57
+ const cited = results.filter((r) => r.cited);
58
+ const ranks = cited.map((r) => r.rank).filter((r) => r !== undefined);
59
+ const average_rank = ranks.length > 0 ? ranks.reduce((a, b) => a + b, 0) / ranks.length : undefined;
60
+ return {
61
+ domain: parsed.domain,
62
+ engine: resolvedEngine,
63
+ fetched_at: new Date().toISOString(),
64
+ results,
65
+ summary: {
66
+ queries_total: parsed.queries.length,
67
+ queries_cited: cited.length,
68
+ citation_rate: parsed.queries.length > 0 ? cited.length / parsed.queries.length : 0,
69
+ average_rank,
70
+ },
71
+ };
72
+ }
73
+ //# sourceMappingURL=am-i-cited.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"am-i-cited.js","sourceRoot":"","sources":["../../src/tools/am-i-cited.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ import { z } from "zod";
2
+ export declare const auditSitemapInputSchema: {
3
+ sitemap_url: z.ZodString;
4
+ limit: z.ZodDefault<z.ZodNumber>;
5
+ concurrency: z.ZodDefault<z.ZodNumber>;
6
+ };
7
+ declare const inputSchema: z.ZodObject<{
8
+ sitemap_url: z.ZodString;
9
+ limit: z.ZodDefault<z.ZodNumber>;
10
+ concurrency: z.ZodDefault<z.ZodNumber>;
11
+ }, "strip", z.ZodTypeAny, {
12
+ limit: number;
13
+ sitemap_url: string;
14
+ concurrency: number;
15
+ }, {
16
+ sitemap_url: string;
17
+ limit?: number | undefined;
18
+ concurrency?: number | undefined;
19
+ }>;
20
+ export declare function auditSitemap(input: z.infer<typeof inputSchema>): Promise<{
21
+ sitemap_url: string;
22
+ total_urls: number;
23
+ audited: number;
24
+ message: string;
25
+ fetched_at?: undefined;
26
+ average_score?: undefined;
27
+ worst_first?: undefined;
28
+ errors?: undefined;
29
+ } | {
30
+ sitemap_url: string;
31
+ fetched_at: string;
32
+ total_urls: number;
33
+ audited: number;
34
+ average_score: number;
35
+ worst_first: {
36
+ url: string;
37
+ score: number;
38
+ grade: string;
39
+ signals: Record<string, unknown>;
40
+ top_fix?: string;
41
+ }[];
42
+ errors: {
43
+ url: string;
44
+ error: string;
45
+ }[];
46
+ message?: undefined;
47
+ }>;
48
+ export {};
49
+ //# sourceMappingURL=audit-sitemap.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit-sitemap.d.ts","sourceRoot":"","sources":["../../src/tools/audit-sitemap.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,eAAO,MAAM,uBAAuB;;;;CAmBnC,CAAC;AAEF,QAAA,MAAM,WAAW;;;;;;;;;;;;EAAoC,CAAC;AAkCtD,wBAAsB,YAAY,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC;;;;;;;;;;;;;;;;aAcxD,MAAM;eAAS,MAAM;eAAS,MAAM;iBAAW,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;kBAAY,MAAM;;;aACxF,MAAM;eAAS,MAAM;;;GAmCjC"}
@@ -0,0 +1,100 @@
1
+ import { z } from "zod";
2
+ import * as cheerio from "cheerio";
3
+ import { fetchText } from "../lib/fetch.js";
4
+ import { predictCitation } from "./predict-citation.js";
5
+ export const auditSitemapInputSchema = {
6
+ sitemap_url: z
7
+ .string()
8
+ .url()
9
+ .describe("URL of sitemap.xml (or a sitemap index). Nested sitemaps are followed."),
10
+ limit: z
11
+ .number()
12
+ .int()
13
+ .min(1)
14
+ .max(500)
15
+ .default(50)
16
+ .describe("Max URLs to score. Sitemap is sliced after parsing."),
17
+ concurrency: z
18
+ .number()
19
+ .int()
20
+ .min(1)
21
+ .max(10)
22
+ .default(3)
23
+ .describe("Parallel predict_citation calls. Higher is faster but more rate-limit risk."),
24
+ };
25
+ const inputSchema = z.object(auditSitemapInputSchema);
26
+ async function parseSitemap(url, depth = 0) {
27
+ if (depth > 2)
28
+ return [];
29
+ const { text } = await fetchText(url, { timeoutMs: 15_000 });
30
+ const $ = cheerio.load(text, { xmlMode: true });
31
+ const childSitemaps = $("sitemap > loc")
32
+ .toArray()
33
+ .map((el) => $(el).text().trim())
34
+ .filter(Boolean);
35
+ if (childSitemaps.length > 0) {
36
+ const nested = await Promise.all(childSitemaps.map((s) => parseSitemap(s, depth + 1)));
37
+ return nested.flat();
38
+ }
39
+ return $("url > loc")
40
+ .toArray()
41
+ .map((el) => $(el).text().trim())
42
+ .filter(Boolean);
43
+ }
44
+ async function pool(items, n, fn) {
45
+ const out = new Array(items.length);
46
+ let i = 0;
47
+ const workers = Array.from({ length: Math.min(n, items.length) }, async () => {
48
+ while (true) {
49
+ const idx = i++;
50
+ if (idx >= items.length)
51
+ return;
52
+ out[idx] = await fn(items[idx]);
53
+ }
54
+ });
55
+ await Promise.all(workers);
56
+ return out;
57
+ }
58
+ export async function auditSitemap(input) {
59
+ const parsed = inputSchema.parse(input);
60
+ const urls = (await parseSitemap(parsed.sitemap_url)).slice(0, parsed.limit);
61
+ if (urls.length === 0) {
62
+ return {
63
+ sitemap_url: parsed.sitemap_url,
64
+ total_urls: 0,
65
+ audited: 0,
66
+ message: "no URLs found in sitemap",
67
+ };
68
+ }
69
+ const rows = await pool(urls, parsed.concurrency, async (url) => {
70
+ try {
71
+ const r = await predictCitation({ url });
72
+ return {
73
+ url,
74
+ score: r.score,
75
+ grade: r.grade,
76
+ signals: r.signals,
77
+ top_fix: r.fixes?.[0]?.suggestion,
78
+ };
79
+ }
80
+ catch (err) {
81
+ const message = err instanceof Error ? err.message : String(err);
82
+ return { url, error: message };
83
+ }
84
+ });
85
+ const scored = rows.filter((r) => "score" in r);
86
+ scored.sort((a, b) => a.score - b.score);
87
+ const avg = scored.length > 0
88
+ ? scored.reduce((s, r) => s + r.score, 0) / scored.length
89
+ : 0;
90
+ return {
91
+ sitemap_url: parsed.sitemap_url,
92
+ fetched_at: new Date().toISOString(),
93
+ total_urls: urls.length,
94
+ audited: rows.length,
95
+ average_score: Math.round(avg),
96
+ worst_first: scored.slice(0, 20),
97
+ errors: rows.filter((r) => "error" in r),
98
+ };
99
+ }
100
+ //# sourceMappingURL=audit-sitemap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit-sitemap.js","sourceRoot":"","sources":["../../src/tools/audit-sitemap.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import { z } from "zod";
2
+ import type { Engine } from "../types.js";
3
+ export declare const checkCitationsInputSchema: {
4
+ query: z.ZodString;
5
+ engine: z.ZodDefault<z.ZodEnum<["perplexity", "claude", "openai", "gemini", "bing", "auto"]>>;
6
+ max_results: z.ZodDefault<z.ZodNumber>;
7
+ };
8
+ declare const inputSchema: z.ZodObject<{
9
+ query: z.ZodString;
10
+ engine: z.ZodDefault<z.ZodEnum<["perplexity", "claude", "openai", "gemini", "bing", "auto"]>>;
11
+ max_results: z.ZodDefault<z.ZodNumber>;
12
+ }, "strip", z.ZodTypeAny, {
13
+ query: string;
14
+ engine: "perplexity" | "claude" | "openai" | "gemini" | "bing" | "auto";
15
+ max_results: number;
16
+ }, {
17
+ query: string;
18
+ engine?: "perplexity" | "claude" | "openai" | "gemini" | "bing" | "auto" | undefined;
19
+ max_results?: number | undefined;
20
+ }>;
21
+ export declare function checkCitations(input: z.infer<typeof inputSchema>): Promise<{
22
+ query: string;
23
+ engine: Engine;
24
+ fetched_at: string;
25
+ citations: import("../types.js").Citation[];
26
+ raw_answer: string | undefined;
27
+ cached: boolean;
28
+ }>;
29
+ export {};
30
+ //# sourceMappingURL=check-citations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check-citations.d.ts","sourceRoot":"","sources":["../../src/tools/check-citations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AASxB,OAAO,KAAK,EAAiB,MAAM,EAAE,MAAM,aAAa,CAAC;AAEzD,eAAO,MAAM,yBAAyB;;;;CAarC,CAAC;AAEF,QAAA,MAAM,WAAW;;;;;;;;;;;;EAAsC,CAAC;AAgCxD,wBAAsB,cAAc,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC;;;;;;;GAmDtE"}
@@ -0,0 +1,101 @@
1
+ import { z } from "zod";
2
+ import { perplexitySearch } from "../adapters/perplexity.js";
3
+ import { bingSearch } from "../adapters/bing.js";
4
+ import { claudeSearch } from "../adapters/anthropic.js";
5
+ import { openaiSearch } from "../adapters/openai.js";
6
+ import { geminiSearch } from "../adapters/gemini.js";
7
+ import { envKey } from "../lib/config.js";
8
+ import { getCitations, putCitations } from "../lib/cache.js";
9
+ import { ToolFetchError } from "../lib/fetch.js";
10
+ export const checkCitationsInputSchema = {
11
+ query: z.string().min(1).describe("The search query to test (what would a user ask an AI?)"),
12
+ engine: z
13
+ .enum(["perplexity", "claude", "openai", "gemini", "bing", "auto"])
14
+ .default("auto")
15
+ .describe("AI engine to query. 'auto' picks the first available based on configured API keys."),
16
+ max_results: z
17
+ .number()
18
+ .int()
19
+ .min(1)
20
+ .max(50)
21
+ .default(10)
22
+ .describe("Maximum citations to return."),
23
+ };
24
+ const inputSchema = z.object(checkCitationsInputSchema);
25
+ function pickAutoEngine() {
26
+ if (envKey("PERPLEXITY_API_KEY"))
27
+ return "perplexity";
28
+ if (envKey("ANTHROPIC_API_KEY"))
29
+ return "claude";
30
+ if (envKey("OPENAI_API_KEY"))
31
+ return "openai";
32
+ if (envKey("GEMINI_API_KEY"))
33
+ return "gemini";
34
+ if (envKey("BING_API_KEY"))
35
+ return "bing";
36
+ return null;
37
+ }
38
+ async function runEngine(engine, query, maxResults) {
39
+ switch (engine) {
40
+ case "perplexity":
41
+ return perplexitySearch(query, maxResults);
42
+ case "claude":
43
+ return claudeSearch(query, maxResults);
44
+ case "openai":
45
+ return openaiSearch(query, maxResults);
46
+ case "gemini":
47
+ return geminiSearch(query, maxResults);
48
+ case "bing":
49
+ return bingSearch(query, maxResults);
50
+ case "auto":
51
+ throw new Error("auto engine should be resolved before runEngine");
52
+ }
53
+ }
54
+ export async function checkCitations(input) {
55
+ const parsed = inputSchema.parse(input);
56
+ const requested = parsed.engine;
57
+ let engine;
58
+ if (requested === "auto") {
59
+ const picked = pickAutoEngine();
60
+ if (!picked) {
61
+ throw new ToolFetchError({
62
+ type: "no_engine_available",
63
+ message: "No engine API key configured. Set one of: PERPLEXITY_API_KEY, ANTHROPIC_API_KEY, OPENAI_API_KEY, GEMINI_API_KEY, BING_API_KEY.",
64
+ });
65
+ }
66
+ engine = picked;
67
+ }
68
+ else {
69
+ engine = requested;
70
+ }
71
+ const cached = await getCitations(parsed.query, engine);
72
+ if (cached) {
73
+ return {
74
+ query: parsed.query,
75
+ engine,
76
+ fetched_at: cached.fetched_at,
77
+ citations: cached.citations.slice(0, parsed.max_results),
78
+ raw_answer: cached.raw_answer,
79
+ cached: true,
80
+ };
81
+ }
82
+ const result = await runEngine(engine, parsed.query, parsed.max_results);
83
+ const fetched_at = new Date().toISOString();
84
+ await putCitations({
85
+ type: "citation_check",
86
+ engine,
87
+ query: parsed.query,
88
+ fetched_at,
89
+ citations: result.citations,
90
+ raw_answer: result.raw_answer,
91
+ });
92
+ return {
93
+ query: parsed.query,
94
+ engine,
95
+ fetched_at,
96
+ citations: result.citations,
97
+ raw_answer: result.raw_answer,
98
+ cached: false,
99
+ };
100
+ }
101
+ //# sourceMappingURL=check-citations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check-citations.js","sourceRoot":"","sources":["../../src/tools/check-citations.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ import { z } from "zod";
2
+ export declare const citationFreshnessScoreInputSchema: {
3
+ query: z.ZodString;
4
+ engine: z.ZodDefault<z.ZodEnum<["perplexity", "claude", "openai", "gemini", "bing", "auto"]>>;
5
+ max_results: z.ZodDefault<z.ZodNumber>;
6
+ };
7
+ declare const inputSchema: z.ZodObject<{
8
+ query: z.ZodString;
9
+ engine: z.ZodDefault<z.ZodEnum<["perplexity", "claude", "openai", "gemini", "bing", "auto"]>>;
10
+ max_results: z.ZodDefault<z.ZodNumber>;
11
+ }, "strip", z.ZodTypeAny, {
12
+ query: string;
13
+ engine: "perplexity" | "claude" | "openai" | "gemini" | "bing" | "auto";
14
+ max_results: number;
15
+ }, {
16
+ query: string;
17
+ engine?: "perplexity" | "claude" | "openai" | "gemini" | "bing" | "auto" | undefined;
18
+ max_results?: number | undefined;
19
+ }>;
20
+ export declare function citationFreshnessScore(input: z.infer<typeof inputSchema>): Promise<{
21
+ query: string;
22
+ engine: import("../types.js").Engine;
23
+ fetched_at: string;
24
+ recency_score: number;
25
+ average_days_old: number | null;
26
+ buckets: {
27
+ fresh: number;
28
+ current: number;
29
+ stale: number;
30
+ ancient: number;
31
+ unknown: number;
32
+ };
33
+ per_url: ({
34
+ url: string;
35
+ rank: number;
36
+ date_modified_iso: string | null;
37
+ last_modified_days_ago: number | null;
38
+ bucket: "fresh" | "current" | "stale" | "ancient" | "unknown";
39
+ weight: number;
40
+ error?: undefined;
41
+ } | {
42
+ url: string;
43
+ rank: number;
44
+ error: string;
45
+ date_modified_iso?: undefined;
46
+ last_modified_days_ago?: undefined;
47
+ bucket?: undefined;
48
+ weight?: undefined;
49
+ })[];
50
+ note: string;
51
+ }>;
52
+ export {};
53
+ //# sourceMappingURL=citation-freshness-score.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"citation-freshness-score.d.ts","sourceRoot":"","sources":["../../src/tools/citation-freshness-score.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,eAAO,MAAM,iCAAiC;;;;CAa7C,CAAC;AAEF,QAAA,MAAM,WAAW;;;;;;;;;;;;EAA8C,CAAC;AAiBhE,wBAAsB,sBAAsB,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2D9E"}
@@ -0,0 +1,89 @@
1
+ import { z } from "zod";
2
+ import { checkCitations } from "./check-citations.js";
3
+ import { collectSignals } from "../adapters/predictors.js";
4
+ import { log } from "../lib/log.js";
5
+ export const citationFreshnessScoreInputSchema = {
6
+ query: z.string().min(1).describe("Search query whose cited URLs to score for freshness."),
7
+ engine: z
8
+ .enum(["perplexity", "claude", "openai", "gemini", "bing", "auto"])
9
+ .default("auto")
10
+ .describe("AI engine to query for the citation set."),
11
+ max_results: z
12
+ .number()
13
+ .int()
14
+ .min(1)
15
+ .max(20)
16
+ .default(10)
17
+ .describe("How many cited URLs to inspect."),
18
+ };
19
+ const inputSchema = z.object(citationFreshnessScoreInputSchema);
20
+ function freshnessBucket(daysAgo) {
21
+ if (daysAgo === undefined)
22
+ return "unknown";
23
+ if (daysAgo <= 180)
24
+ return "fresh";
25
+ if (daysAgo <= 365)
26
+ return "current";
27
+ if (daysAgo <= 730)
28
+ return "stale";
29
+ return "ancient";
30
+ }
31
+ // Recency weight from 0..1; halves every 365 days.
32
+ function weight(daysAgo) {
33
+ if (daysAgo === undefined)
34
+ return 0;
35
+ const halflife = 365;
36
+ return Math.max(0, Math.pow(0.5, daysAgo / halflife));
37
+ }
38
+ export async function citationFreshnessScore(input) {
39
+ const parsed = inputSchema.parse(input);
40
+ log.debug("citation_freshness_score start", { query: parsed.query });
41
+ const citations = await checkCitations({
42
+ query: parsed.query,
43
+ engine: parsed.engine,
44
+ max_results: parsed.max_results,
45
+ });
46
+ const perUrl = await Promise.all(citations.citations.map(async (c) => {
47
+ try {
48
+ const signals = await collectSignals(c.url);
49
+ return {
50
+ url: c.url,
51
+ rank: c.rank,
52
+ date_modified_iso: signals.date_modified_iso ?? null,
53
+ last_modified_days_ago: signals.last_modified_days_ago ?? null,
54
+ bucket: freshnessBucket(signals.last_modified_days_ago),
55
+ weight: Number(weight(signals.last_modified_days_ago).toFixed(3)),
56
+ };
57
+ }
58
+ catch (err) {
59
+ const msg = err instanceof Error ? err.message : String(err);
60
+ return { url: c.url, rank: c.rank, error: msg };
61
+ }
62
+ }));
63
+ const scored = perUrl.filter((r) => "weight" in r);
64
+ const known = scored.filter((r) => r.last_modified_days_ago !== null);
65
+ const avgDaysAgo = known.length > 0
66
+ ? Math.round(known.reduce((a, r) => a + r.last_modified_days_ago, 0) / known.length)
67
+ : null;
68
+ const recencyScore = scored.length > 0
69
+ ? Math.round((scored.reduce((a, r) => a + r.weight, 0) / scored.length) * 100)
70
+ : 0;
71
+ const counts = {
72
+ fresh: scored.filter((r) => r.bucket === "fresh").length,
73
+ current: scored.filter((r) => r.bucket === "current").length,
74
+ stale: scored.filter((r) => r.bucket === "stale").length,
75
+ ancient: scored.filter((r) => r.bucket === "ancient").length,
76
+ unknown: perUrl.length - known.length,
77
+ };
78
+ return {
79
+ query: parsed.query,
80
+ engine: citations.engine,
81
+ fetched_at: new Date().toISOString(),
82
+ recency_score: recencyScore,
83
+ average_days_old: avgDaysAgo,
84
+ buckets: counts,
85
+ per_url: perUrl,
86
+ note: "recency_score is a 0-100 average of per-URL recency weights (halflife=365d). Pages with no detectable dateModified contribute weight 0.",
87
+ };
88
+ }
89
+ //# sourceMappingURL=citation-freshness-score.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"citation-freshness-score.js","sourceRoot":"","sources":["../../src/tools/citation-freshness-score.ts"],"names":[],"mappings":"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"}