@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.
- package/LICENSE +21 -0
- package/README.md +302 -0
- package/dist/adapters/anthropic.d.ts +3 -0
- package/dist/adapters/anthropic.d.ts.map +1 -0
- package/dist/adapters/anthropic.js +52 -0
- package/dist/adapters/anthropic.js.map +1 -0
- package/dist/adapters/bing.d.ts +3 -0
- package/dist/adapters/bing.d.ts.map +1 -0
- package/dist/adapters/bing.js +31 -0
- package/dist/adapters/bing.js.map +1 -0
- package/dist/adapters/gemini.d.ts +3 -0
- package/dist/adapters/gemini.d.ts.map +1 -0
- package/dist/adapters/gemini.js +47 -0
- package/dist/adapters/gemini.js.map +1 -0
- package/dist/adapters/openai.d.ts +3 -0
- package/dist/adapters/openai.d.ts.map +1 -0
- package/dist/adapters/openai.js +49 -0
- package/dist/adapters/openai.js.map +1 -0
- package/dist/adapters/perplexity.d.ts +3 -0
- package/dist/adapters/perplexity.d.ts.map +1 -0
- package/dist/adapters/perplexity.js +55 -0
- package/dist/adapters/perplexity.js.map +1 -0
- package/dist/adapters/predictors.d.ts +42 -0
- package/dist/adapters/predictors.d.ts.map +1 -0
- package/dist/adapters/predictors.js +495 -0
- package/dist/adapters/predictors.js.map +1 -0
- package/dist/adapters/serpapi.d.ts +8 -0
- package/dist/adapters/serpapi.d.ts.map +1 -0
- package/dist/adapters/serpapi.js +45 -0
- package/dist/adapters/serpapi.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +132 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/cache.d.ts +33 -0
- package/dist/lib/cache.d.ts.map +1 -0
- package/dist/lib/cache.js +110 -0
- package/dist/lib/cache.js.map +1 -0
- package/dist/lib/config.d.ts +6 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +12 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/fetch.d.ts +18 -0
- package/dist/lib/fetch.d.ts.map +1 -0
- package/dist/lib/fetch.js +75 -0
- package/dist/lib/fetch.js.map +1 -0
- package/dist/lib/log.d.ts +11 -0
- package/dist/lib/log.d.ts.map +1 -0
- package/dist/lib/log.js +37 -0
- package/dist/lib/log.js.map +1 -0
- package/dist/lib/panels.d.ts +30 -0
- package/dist/lib/panels.d.ts.map +1 -0
- package/dist/lib/panels.js +69 -0
- package/dist/lib/panels.js.map +1 -0
- package/dist/tools/ai-overview.d.ts +29 -0
- package/dist/tools/ai-overview.d.ts.map +1 -0
- package/dist/tools/ai-overview.js +47 -0
- package/dist/tools/ai-overview.js.map +1 -0
- package/dist/tools/am-i-cited.d.ts +39 -0
- package/dist/tools/am-i-cited.d.ts.map +1 -0
- package/dist/tools/am-i-cited.js +73 -0
- package/dist/tools/am-i-cited.js.map +1 -0
- package/dist/tools/audit-sitemap.d.ts +49 -0
- package/dist/tools/audit-sitemap.d.ts.map +1 -0
- package/dist/tools/audit-sitemap.js +100 -0
- package/dist/tools/audit-sitemap.js.map +1 -0
- package/dist/tools/check-citations.d.ts +30 -0
- package/dist/tools/check-citations.d.ts.map +1 -0
- package/dist/tools/check-citations.js +101 -0
- package/dist/tools/check-citations.js.map +1 -0
- package/dist/tools/citation-freshness-score.d.ts +53 -0
- package/dist/tools/citation-freshness-score.d.ts.map +1 -0
- package/dist/tools/citation-freshness-score.js +89 -0
- package/dist/tools/citation-freshness-score.js.map +1 -0
- package/dist/tools/citation-trend.d.ts +47 -0
- package/dist/tools/citation-trend.d.ts.map +1 -0
- package/dist/tools/citation-trend.js +48 -0
- package/dist/tools/citation-trend.js.map +1 -0
- package/dist/tools/cited-for-diff.d.ts +54 -0
- package/dist/tools/cited-for-diff.d.ts.map +1 -0
- package/dist/tools/cited-for-diff.js +89 -0
- package/dist/tools/cited-for-diff.js.map +1 -0
- package/dist/tools/cited-for.d.ts +39 -0
- package/dist/tools/cited-for.d.ts.map +1 -0
- package/dist/tools/cited-for.js +28 -0
- package/dist/tools/cited-for.js.map +1 -0
- package/dist/tools/compare-domains.d.ts +36 -0
- package/dist/tools/compare-domains.d.ts.map +1 -0
- package/dist/tools/compare-domains.js +54 -0
- package/dist/tools/compare-domains.js.map +1 -0
- package/dist/tools/compete-for-query.d.ts +72 -0
- package/dist/tools/compete-for-query.d.ts.map +1 -0
- package/dist/tools/compete-for-query.js +91 -0
- package/dist/tools/compete-for-query.js.map +1 -0
- package/dist/tools/gsc-citation-gap.d.ts +77 -0
- package/dist/tools/gsc-citation-gap.d.ts.map +1 -0
- package/dist/tools/gsc-citation-gap.js +121 -0
- package/dist/tools/gsc-citation-gap.js.map +1 -0
- package/dist/tools/predict-citation.d.ts +25 -0
- package/dist/tools/predict-citation.d.ts.map +1 -0
- package/dist/tools/predict-citation.js +32 -0
- package/dist/tools/predict-citation.js.map +1 -0
- package/dist/tools/run-panel.d.ts +46 -0
- package/dist/tools/run-panel.d.ts.map +1 -0
- package/dist/tools/run-panel.js +60 -0
- package/dist/tools/run-panel.js.map +1 -0
- package/dist/tools/track-queries.d.ts +52 -0
- package/dist/tools/track-queries.d.ts.map +1 -0
- package/dist/tools/track-queries.js +52 -0
- package/dist/tools/track-queries.js.map +1 -0
- package/dist/tools/wikipedia-mentions.d.ts +32 -0
- package/dist/tools/wikipedia-mentions.d.ts.map +1 -0
- package/dist/tools/wikipedia-mentions.js +56 -0
- package/dist/tools/wikipedia-mentions.js.map +1 -0
- package/dist/types.d.ts +42 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- 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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"}
|