@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,47 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const citationTrendInputSchema: {
|
|
3
|
+
panel: z.ZodString;
|
|
4
|
+
since: z.ZodOptional<z.ZodString>;
|
|
5
|
+
};
|
|
6
|
+
declare const inputSchema: z.ZodObject<{
|
|
7
|
+
panel: z.ZodString;
|
|
8
|
+
since: z.ZodOptional<z.ZodString>;
|
|
9
|
+
}, "strip", z.ZodTypeAny, {
|
|
10
|
+
panel: string;
|
|
11
|
+
since?: string | undefined;
|
|
12
|
+
}, {
|
|
13
|
+
panel: string;
|
|
14
|
+
since?: string | undefined;
|
|
15
|
+
}>;
|
|
16
|
+
export declare function citationTrend(input: z.infer<typeof inputSchema>): Promise<{
|
|
17
|
+
panel: string;
|
|
18
|
+
snapshots: number;
|
|
19
|
+
message: string;
|
|
20
|
+
domain?: undefined;
|
|
21
|
+
first_taken_at?: undefined;
|
|
22
|
+
last_taken_at?: undefined;
|
|
23
|
+
series?: undefined;
|
|
24
|
+
query_deltas?: undefined;
|
|
25
|
+
} | {
|
|
26
|
+
panel: string;
|
|
27
|
+
domain: string;
|
|
28
|
+
snapshots: number;
|
|
29
|
+
first_taken_at: string;
|
|
30
|
+
last_taken_at: string;
|
|
31
|
+
series: {
|
|
32
|
+
taken_at: string;
|
|
33
|
+
engine: string;
|
|
34
|
+
queries_total: number;
|
|
35
|
+
queries_cited: number;
|
|
36
|
+
citation_rate: number;
|
|
37
|
+
}[];
|
|
38
|
+
query_deltas: {
|
|
39
|
+
query: string;
|
|
40
|
+
change: "gained" | "lost" | "unchanged";
|
|
41
|
+
first: boolean;
|
|
42
|
+
last: boolean;
|
|
43
|
+
}[];
|
|
44
|
+
message?: undefined;
|
|
45
|
+
}>;
|
|
46
|
+
export {};
|
|
47
|
+
//# sourceMappingURL=citation-trend.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"citation-trend.d.ts","sourceRoot":"","sources":["../../src/tools/citation-trend.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,wBAAwB;;;CAMpC,CAAC;AAEF,QAAA,MAAM,WAAW;;;;;;;;;EAAqC,CAAC;AAkBvD,wBAAsB,aAAa,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC;;;;;;;;;;;;;;;;;;;;;;;eATvC,MAAM;gBAAU,QAAQ,GAAG,MAAM,GAAG,WAAW;eAAS,OAAO;cAAQ,OAAO;;;GAiC5G"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { readSnapshots } from "../lib/panels.js";
|
|
3
|
+
export const citationTrendInputSchema = {
|
|
4
|
+
panel: z.string().min(1).describe("Panel name to report on."),
|
|
5
|
+
since: z
|
|
6
|
+
.string()
|
|
7
|
+
.optional()
|
|
8
|
+
.describe("ISO date floor, e.g. '2026-01-01'. Only include snapshots on or after."),
|
|
9
|
+
};
|
|
10
|
+
const inputSchema = z.object(citationTrendInputSchema);
|
|
11
|
+
function queryDeltas(snapshots) {
|
|
12
|
+
if (snapshots.length < 2)
|
|
13
|
+
return [];
|
|
14
|
+
const first = snapshots[0];
|
|
15
|
+
const last = snapshots[snapshots.length - 1];
|
|
16
|
+
const firstMap = new Map(first.per_query.map((q) => [q.query, q.cited]));
|
|
17
|
+
const deltas = [];
|
|
18
|
+
for (const q of last.per_query) {
|
|
19
|
+
const wasCited = firstMap.get(q.query) ?? false;
|
|
20
|
+
const change = !wasCited && q.cited ? "gained" : wasCited && !q.cited ? "lost" : "unchanged";
|
|
21
|
+
deltas.push({ query: q.query, change, first: wasCited, last: q.cited });
|
|
22
|
+
}
|
|
23
|
+
return deltas;
|
|
24
|
+
}
|
|
25
|
+
export async function citationTrend(input) {
|
|
26
|
+
const parsed = inputSchema.parse(input);
|
|
27
|
+
const snapshots = await readSnapshots(parsed.panel, parsed.since);
|
|
28
|
+
if (snapshots.length === 0) {
|
|
29
|
+
return { panel: parsed.panel, snapshots: 0, message: "no snapshots found" };
|
|
30
|
+
}
|
|
31
|
+
const series = snapshots.map((s) => ({
|
|
32
|
+
taken_at: s.taken_at,
|
|
33
|
+
engine: s.engine,
|
|
34
|
+
queries_total: s.summary.queries_total,
|
|
35
|
+
queries_cited: s.summary.queries_cited,
|
|
36
|
+
citation_rate: s.summary.citation_rate,
|
|
37
|
+
}));
|
|
38
|
+
return {
|
|
39
|
+
panel: parsed.panel,
|
|
40
|
+
domain: snapshots[snapshots.length - 1].domain,
|
|
41
|
+
snapshots: snapshots.length,
|
|
42
|
+
first_taken_at: snapshots[0].taken_at,
|
|
43
|
+
last_taken_at: snapshots[snapshots.length - 1].taken_at,
|
|
44
|
+
series,
|
|
45
|
+
query_deltas: queryDeltas(snapshots),
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=citation-trend.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"citation-trend.js","sourceRoot":"","sources":["../../src/tools/citation-trend.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const citedForDiffInputSchema: {
|
|
3
|
+
domain: z.ZodString;
|
|
4
|
+
baseline_until: z.ZodString;
|
|
5
|
+
current_since: z.ZodOptional<z.ZodString>;
|
|
6
|
+
engine: z.ZodOptional<z.ZodEnum<["perplexity", "claude", "openai", "gemini", "bing"]>>;
|
|
7
|
+
};
|
|
8
|
+
declare const inputSchema: z.ZodObject<{
|
|
9
|
+
domain: z.ZodString;
|
|
10
|
+
baseline_until: z.ZodString;
|
|
11
|
+
current_since: z.ZodOptional<z.ZodString>;
|
|
12
|
+
engine: z.ZodOptional<z.ZodEnum<["perplexity", "claude", "openai", "gemini", "bing"]>>;
|
|
13
|
+
}, "strip", z.ZodTypeAny, {
|
|
14
|
+
domain: string;
|
|
15
|
+
baseline_until: string;
|
|
16
|
+
engine?: "perplexity" | "claude" | "openai" | "gemini" | "bing" | undefined;
|
|
17
|
+
current_since?: string | undefined;
|
|
18
|
+
}, {
|
|
19
|
+
domain: string;
|
|
20
|
+
baseline_until: string;
|
|
21
|
+
engine?: "perplexity" | "claude" | "openai" | "gemini" | "bing" | undefined;
|
|
22
|
+
current_since?: string | undefined;
|
|
23
|
+
}>;
|
|
24
|
+
export declare function citedForDiff(input: z.infer<typeof inputSchema>): Promise<{
|
|
25
|
+
domain: string;
|
|
26
|
+
engine_filter: "perplexity" | "claude" | "openai" | "gemini" | "bing" | undefined;
|
|
27
|
+
baseline_until: string;
|
|
28
|
+
current_since: string;
|
|
29
|
+
fetched_at: string;
|
|
30
|
+
counts: {
|
|
31
|
+
baseline_unique_queries: number;
|
|
32
|
+
current_unique_queries: number;
|
|
33
|
+
gained: number;
|
|
34
|
+
lost: number;
|
|
35
|
+
unchanged: number;
|
|
36
|
+
};
|
|
37
|
+
gained: {
|
|
38
|
+
query: string;
|
|
39
|
+
engine: string;
|
|
40
|
+
rank: number;
|
|
41
|
+
fetched_at: string;
|
|
42
|
+
url: string;
|
|
43
|
+
}[];
|
|
44
|
+
lost: {
|
|
45
|
+
query: string;
|
|
46
|
+
engine: string;
|
|
47
|
+
fetched_at: string;
|
|
48
|
+
url: string;
|
|
49
|
+
}[];
|
|
50
|
+
unchanged_queries: string[];
|
|
51
|
+
source: "local_cache";
|
|
52
|
+
}>;
|
|
53
|
+
export {};
|
|
54
|
+
//# sourceMappingURL=cited-for-diff.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cited-for-diff.d.ts","sourceRoot":"","sources":["../../src/tools/cited-for-diff.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,eAAO,MAAM,uBAAuB;;;;;CAanC,CAAC;AAEF,QAAA,MAAM,WAAW;;;;;;;;;;;;;;;EAAoC,CAAC;AAEtD,wBAAsB,YAAY,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC;;;;;;;;;;;;;;eAuBtC,MAAM;gBAAU,MAAM;cAAQ,MAAM;oBAAc,MAAM;aAAO,MAAM;;;eACvE,MAAM;gBAAU,MAAM;oBAAc,MAAM;aAAO,MAAM;;;;GAmDnF"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { citedForDomain } from "../lib/cache.js";
|
|
3
|
+
import { log } from "../lib/log.js";
|
|
4
|
+
export const citedForDiffInputSchema = {
|
|
5
|
+
domain: z.string().min(1).describe("Domain to diff, e.g. 'automatelab.tech'."),
|
|
6
|
+
baseline_until: z
|
|
7
|
+
.string()
|
|
8
|
+
.describe("ISO date (or ISO datetime). Baseline window = all cache entries fetched on or before this timestamp."),
|
|
9
|
+
current_since: z
|
|
10
|
+
.string()
|
|
11
|
+
.optional()
|
|
12
|
+
.describe("ISO date floor for the 'current' window. Defaults to baseline_until."),
|
|
13
|
+
engine: z
|
|
14
|
+
.enum(["perplexity", "claude", "openai", "gemini", "bing"])
|
|
15
|
+
.optional()
|
|
16
|
+
.describe("Filter by engine. Omit to include all."),
|
|
17
|
+
};
|
|
18
|
+
const inputSchema = z.object(citedForDiffInputSchema);
|
|
19
|
+
export async function citedForDiff(input) {
|
|
20
|
+
const parsed = inputSchema.parse(input);
|
|
21
|
+
log.debug("cited_for_diff start", { domain: parsed.domain, baseline_until: parsed.baseline_until });
|
|
22
|
+
const baselineUntilMs = Date.parse(parsed.baseline_until);
|
|
23
|
+
if (Number.isNaN(baselineUntilMs)) {
|
|
24
|
+
throw new Error(`baseline_until is not a parsable ISO date: ${parsed.baseline_until}`);
|
|
25
|
+
}
|
|
26
|
+
const currentSince = parsed.current_since ?? parsed.baseline_until;
|
|
27
|
+
const currentSinceMs = Date.parse(currentSince);
|
|
28
|
+
if (Number.isNaN(currentSinceMs)) {
|
|
29
|
+
throw new Error(`current_since is not a parsable ISO date: ${currentSince}`);
|
|
30
|
+
}
|
|
31
|
+
// Pull a generous slice from the cache, then partition by timestamp here.
|
|
32
|
+
const all = await citedForDomain(parsed.domain, undefined, parsed.engine, 500);
|
|
33
|
+
const baseline = all.filter((r) => Date.parse(r.fetched_at) <= baselineUntilMs);
|
|
34
|
+
const current = all.filter((r) => Date.parse(r.fetched_at) >= currentSinceMs);
|
|
35
|
+
const baselineQueries = new Set(baseline.map((r) => r.query.toLowerCase()));
|
|
36
|
+
const currentQueries = new Set(current.map((r) => r.query.toLowerCase()));
|
|
37
|
+
const gained = [];
|
|
38
|
+
const lost = [];
|
|
39
|
+
const unchanged = [];
|
|
40
|
+
for (const q of currentQueries) {
|
|
41
|
+
if (!baselineQueries.has(q)) {
|
|
42
|
+
const sample = current.find((r) => r.query.toLowerCase() === q);
|
|
43
|
+
if (sample) {
|
|
44
|
+
gained.push({
|
|
45
|
+
query: sample.query,
|
|
46
|
+
engine: sample.engine,
|
|
47
|
+
rank: sample.rank,
|
|
48
|
+
fetched_at: sample.fetched_at,
|
|
49
|
+
url: sample.url,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
unchanged.push(q);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
for (const q of baselineQueries) {
|
|
58
|
+
if (!currentQueries.has(q)) {
|
|
59
|
+
const sample = baseline.find((r) => r.query.toLowerCase() === q);
|
|
60
|
+
if (sample) {
|
|
61
|
+
lost.push({
|
|
62
|
+
query: sample.query,
|
|
63
|
+
engine: sample.engine,
|
|
64
|
+
fetched_at: sample.fetched_at,
|
|
65
|
+
url: sample.url,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return {
|
|
71
|
+
domain: parsed.domain,
|
|
72
|
+
engine_filter: parsed.engine,
|
|
73
|
+
baseline_until: parsed.baseline_until,
|
|
74
|
+
current_since: currentSince,
|
|
75
|
+
fetched_at: new Date().toISOString(),
|
|
76
|
+
counts: {
|
|
77
|
+
baseline_unique_queries: baselineQueries.size,
|
|
78
|
+
current_unique_queries: currentQueries.size,
|
|
79
|
+
gained: gained.length,
|
|
80
|
+
lost: lost.length,
|
|
81
|
+
unchanged: unchanged.length,
|
|
82
|
+
},
|
|
83
|
+
gained,
|
|
84
|
+
lost,
|
|
85
|
+
unchanged_queries: unchanged,
|
|
86
|
+
source: "local_cache",
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=cited-for-diff.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cited-for-diff.js","sourceRoot":"","sources":["../../src/tools/cited-for-diff.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const citedForInputSchema: {
|
|
3
|
+
domain: z.ZodString;
|
|
4
|
+
since: z.ZodOptional<z.ZodString>;
|
|
5
|
+
engine: z.ZodOptional<z.ZodEnum<["perplexity", "claude", "openai", "gemini", "bing"]>>;
|
|
6
|
+
limit: z.ZodDefault<z.ZodNumber>;
|
|
7
|
+
};
|
|
8
|
+
declare const inputSchema: z.ZodObject<{
|
|
9
|
+
domain: z.ZodString;
|
|
10
|
+
since: z.ZodOptional<z.ZodString>;
|
|
11
|
+
engine: z.ZodOptional<z.ZodEnum<["perplexity", "claude", "openai", "gemini", "bing"]>>;
|
|
12
|
+
limit: z.ZodDefault<z.ZodNumber>;
|
|
13
|
+
}, "strip", z.ZodTypeAny, {
|
|
14
|
+
domain: string;
|
|
15
|
+
limit: number;
|
|
16
|
+
engine?: "perplexity" | "claude" | "openai" | "gemini" | "bing" | undefined;
|
|
17
|
+
since?: string | undefined;
|
|
18
|
+
}, {
|
|
19
|
+
domain: string;
|
|
20
|
+
engine?: "perplexity" | "claude" | "openai" | "gemini" | "bing" | undefined;
|
|
21
|
+
since?: string | undefined;
|
|
22
|
+
limit?: number | undefined;
|
|
23
|
+
}>;
|
|
24
|
+
export declare function citedFor(input: z.infer<typeof inputSchema>): Promise<{
|
|
25
|
+
domain: string;
|
|
26
|
+
since: string | undefined;
|
|
27
|
+
engine_filter: "perplexity" | "claude" | "openai" | "gemini" | "bing" | undefined;
|
|
28
|
+
results: {
|
|
29
|
+
query: string;
|
|
30
|
+
engine: import("../types.js").Engine;
|
|
31
|
+
rank: number;
|
|
32
|
+
fetched_at: string;
|
|
33
|
+
url: string;
|
|
34
|
+
}[];
|
|
35
|
+
total: number;
|
|
36
|
+
source: "local_cache";
|
|
37
|
+
}>;
|
|
38
|
+
export {};
|
|
39
|
+
//# sourceMappingURL=cited-for.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cited-for.d.ts","sourceRoot":"","sources":["../../src/tools/cited-for.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,mBAAmB;;;;;CAW/B,CAAC;AAEF,QAAA,MAAM,WAAW;;;;;;;;;;;;;;;EAAgC,CAAC;AAElD,wBAAsB,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC;;;;;;;;;;;;;GAgBhE"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { citedForDomain } from "../lib/cache.js";
|
|
3
|
+
export const citedForInputSchema = {
|
|
4
|
+
domain: z.string().min(1).describe("Domain to look up, e.g. 'automatelab.tech'."),
|
|
5
|
+
since: z
|
|
6
|
+
.string()
|
|
7
|
+
.optional()
|
|
8
|
+
.describe("ISO date floor, e.g. '2026-01-01'. Only return entries fetched on or after this date."),
|
|
9
|
+
engine: z
|
|
10
|
+
.enum(["perplexity", "claude", "openai", "gemini", "bing"])
|
|
11
|
+
.optional()
|
|
12
|
+
.describe("Filter by engine. Omit to include all."),
|
|
13
|
+
limit: z.number().int().min(1).max(500).default(50).describe("Maximum results."),
|
|
14
|
+
};
|
|
15
|
+
const inputSchema = z.object(citedForInputSchema);
|
|
16
|
+
export async function citedFor(input) {
|
|
17
|
+
const parsed = inputSchema.parse(input);
|
|
18
|
+
const results = await citedForDomain(parsed.domain, parsed.since, parsed.engine, parsed.limit);
|
|
19
|
+
return {
|
|
20
|
+
domain: parsed.domain,
|
|
21
|
+
since: parsed.since,
|
|
22
|
+
engine_filter: parsed.engine,
|
|
23
|
+
results,
|
|
24
|
+
total: results.length,
|
|
25
|
+
source: "local_cache",
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=cited-for.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cited-for.js","sourceRoot":"","sources":["../../src/tools/cited-for.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEjD,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,6CAA6C,CAAC;IACjF,KAAK,EAAE,CAAC;SACL,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CAAC,uFAAuF,CAAC;IACpG,MAAM,EAAE,CAAC;SACN,IAAI,CAAC,CAAC,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;SAC1D,QAAQ,EAAE;SACV,QAAQ,CAAC,wCAAwC,CAAC;IACrD,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,kBAAkB,CAAC;CACjF,CAAC;AAEF,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;AAElD,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,KAAkC;IAC/D,MAAM,MAAM,GAAG,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACxC,MAAM,OAAO,GAAG,MAAM,cAAc,CAClC,MAAM,CAAC,MAAM,EACb,MAAM,CAAC,KAAK,EACZ,MAAM,CAAC,MAAM,EACb,MAAM,CAAC,KAAK,CACb,CAAC;IACF,OAAO;QACL,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,aAAa,EAAE,MAAM,CAAC,MAAM;QAC5B,OAAO;QACP,KAAK,EAAE,OAAO,CAAC,MAAM;QACrB,MAAM,EAAE,aAAsB;KAC/B,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const compareDomainsInputSchema: {
|
|
3
|
+
urls: z.ZodArray<z.ZodString, "many">;
|
|
4
|
+
};
|
|
5
|
+
declare const inputSchema: z.ZodObject<{
|
|
6
|
+
urls: z.ZodArray<z.ZodString, "many">;
|
|
7
|
+
}, "strip", z.ZodTypeAny, {
|
|
8
|
+
urls: string[];
|
|
9
|
+
}, {
|
|
10
|
+
urls: string[];
|
|
11
|
+
}>;
|
|
12
|
+
export declare function compareDomains(input: z.infer<typeof inputSchema>): Promise<{
|
|
13
|
+
fetched_at: string;
|
|
14
|
+
rows: ({
|
|
15
|
+
url: string;
|
|
16
|
+
score: number;
|
|
17
|
+
grade: "A" | "B" | "C" | "D" | "F";
|
|
18
|
+
signals: import("../adapters/predictors.js").PredictorSignals;
|
|
19
|
+
error?: undefined;
|
|
20
|
+
} | {
|
|
21
|
+
url: string;
|
|
22
|
+
error: string;
|
|
23
|
+
score?: undefined;
|
|
24
|
+
grade?: undefined;
|
|
25
|
+
signals?: undefined;
|
|
26
|
+
})[];
|
|
27
|
+
diverging_signals: {
|
|
28
|
+
signal: "wikipedia_linked" | "github_referenced" | "reddit_referenced" | "llms_txt_present" | "canonical_clean" | "https" | "schema_org_present";
|
|
29
|
+
per_url: {
|
|
30
|
+
url: string;
|
|
31
|
+
value: boolean;
|
|
32
|
+
}[];
|
|
33
|
+
}[];
|
|
34
|
+
}>;
|
|
35
|
+
export {};
|
|
36
|
+
//# sourceMappingURL=compare-domains.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compare-domains.d.ts","sourceRoot":"","sources":["../../src/tools/compare-domains.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,yBAAyB;;CAMrC,CAAC;AAEF,QAAA,MAAM,WAAW;;;;;;EAAsC,CAAC;AAExD,wBAAsB,cAAc,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC;;;;;;;;;;;;;;;;;;;;;;GAiDtE"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { predictCitation } from "./predict-citation.js";
|
|
3
|
+
export const compareDomainsInputSchema = {
|
|
4
|
+
urls: z
|
|
5
|
+
.array(z.string().url())
|
|
6
|
+
.min(2)
|
|
7
|
+
.max(10)
|
|
8
|
+
.describe("URLs to compare side-by-side. 2-10 URLs. One is typically yours and the rest are cited competitors."),
|
|
9
|
+
};
|
|
10
|
+
const inputSchema = z.object(compareDomainsInputSchema);
|
|
11
|
+
export async function compareDomains(input) {
|
|
12
|
+
const parsed = inputSchema.parse(input);
|
|
13
|
+
const rows = await Promise.all(parsed.urls.map(async (url) => {
|
|
14
|
+
try {
|
|
15
|
+
const r = await predictCitation({ url });
|
|
16
|
+
return {
|
|
17
|
+
url,
|
|
18
|
+
score: r.score,
|
|
19
|
+
grade: r.grade,
|
|
20
|
+
signals: r.signals,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
catch (err) {
|
|
24
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
25
|
+
return { url, error: message };
|
|
26
|
+
}
|
|
27
|
+
}));
|
|
28
|
+
const scored = rows.filter((r) => "score" in r);
|
|
29
|
+
const signalKeys = [
|
|
30
|
+
"wikipedia_linked",
|
|
31
|
+
"schema_org_present",
|
|
32
|
+
"llms_txt_present",
|
|
33
|
+
"github_referenced",
|
|
34
|
+
"reddit_referenced",
|
|
35
|
+
"canonical_clean",
|
|
36
|
+
"https",
|
|
37
|
+
];
|
|
38
|
+
const gaps = scored.length >= 2
|
|
39
|
+
? signalKeys
|
|
40
|
+
.map((k) => {
|
|
41
|
+
const values = scored.map((r) => Boolean(r.signals[k]));
|
|
42
|
+
const trueCount = values.filter(Boolean).length;
|
|
43
|
+
const hasMix = trueCount > 0 && trueCount < values.length;
|
|
44
|
+
return hasMix ? { signal: k, per_url: scored.map((r, i) => ({ url: r.url, value: values[i] })) } : null;
|
|
45
|
+
})
|
|
46
|
+
.filter((x) => x !== null)
|
|
47
|
+
: [];
|
|
48
|
+
return {
|
|
49
|
+
fetched_at: new Date().toISOString(),
|
|
50
|
+
rows,
|
|
51
|
+
diverging_signals: gaps,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=compare-domains.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compare-domains.js","sourceRoot":"","sources":["../../src/tools/compare-domains.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAExD,MAAM,CAAC,MAAM,yBAAyB,GAAG;IACvC,IAAI,EAAE,CAAC;SACJ,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC;SACvB,GAAG,CAAC,CAAC,CAAC;SACN,GAAG,CAAC,EAAE,CAAC;SACP,QAAQ,CAAC,qGAAqG,CAAC;CACnH,CAAC;AAEF,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC,yBAAyB,CAAC,CAAC;AAExD,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,KAAkC;IACrE,MAAM,MAAM,GAAG,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAExC,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,GAAG,CAC5B,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;QAC5B,IAAI,CAAC;YACH,MAAM,CAAC,GAAG,MAAM,eAAe,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;YACzC,OAAO;gBACL,GAAG;gBACH,KAAK,EAAE,CAAC,CAAC,KAAK;gBACd,KAAK,EAAE,CAAC,CAAC,KAAK;gBACd,OAAO,EAAE,CAAC,CAAC,OAAO;aACnB,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACjE,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;QACjC,CAAC;IACH,CAAC,CAAC,CACH,CAAC;IAEF,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,IAAI,CAAC,CAE7C,CAAC;IACF,MAAM,UAAU,GAAG;QACjB,kBAAkB;QAClB,oBAAoB;QACpB,kBAAkB;QAClB,mBAAmB;QACnB,mBAAmB;QACnB,iBAAiB;QACjB,OAAO;KACC,CAAC;IAEX,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,IAAI,CAAC;QAC7B,CAAC,CAAC,UAAU;aACP,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;YACT,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAE,CAAC,CAAC,OAAmC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACrF,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC;YAChD,MAAM,MAAM,GAAG,SAAS,GAAG,CAAC,IAAI,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC;YAC1D,OAAO,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;QAC1G,CAAC,CAAC;aACD,MAAM,CAAC,CAAC,CAAC,EAA8B,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC;QAC1D,CAAC,CAAC,EAAE,CAAC;IAEP,OAAO;QACL,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACpC,IAAI;QACJ,iBAAiB,EAAE,IAAI;KACxB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const competeForQueryInputSchema: {
|
|
3
|
+
query: z.ZodString;
|
|
4
|
+
your_url: z.ZodString;
|
|
5
|
+
engine: z.ZodDefault<z.ZodEnum<["perplexity", "claude", "openai", "gemini", "bing", "auto"]>>;
|
|
6
|
+
max_competitors: z.ZodDefault<z.ZodNumber>;
|
|
7
|
+
};
|
|
8
|
+
declare const inputSchema: z.ZodObject<{
|
|
9
|
+
query: z.ZodString;
|
|
10
|
+
your_url: z.ZodString;
|
|
11
|
+
engine: z.ZodDefault<z.ZodEnum<["perplexity", "claude", "openai", "gemini", "bing", "auto"]>>;
|
|
12
|
+
max_competitors: z.ZodDefault<z.ZodNumber>;
|
|
13
|
+
}, "strip", z.ZodTypeAny, {
|
|
14
|
+
query: string;
|
|
15
|
+
engine: "perplexity" | "claude" | "openai" | "gemini" | "bing" | "auto";
|
|
16
|
+
your_url: string;
|
|
17
|
+
max_competitors: number;
|
|
18
|
+
}, {
|
|
19
|
+
query: string;
|
|
20
|
+
your_url: string;
|
|
21
|
+
engine?: "perplexity" | "claude" | "openai" | "gemini" | "bing" | "auto" | undefined;
|
|
22
|
+
max_competitors?: number | undefined;
|
|
23
|
+
}>;
|
|
24
|
+
export declare function competeForQuery(input: z.infer<typeof inputSchema>): Promise<{
|
|
25
|
+
query: string;
|
|
26
|
+
engine: import("../types.js").Engine;
|
|
27
|
+
fetched_at: string;
|
|
28
|
+
your_url: string;
|
|
29
|
+
competitors: never[];
|
|
30
|
+
comparison: null;
|
|
31
|
+
note: string;
|
|
32
|
+
your_score?: undefined;
|
|
33
|
+
your_in_citations?: undefined;
|
|
34
|
+
average_competitor_score?: undefined;
|
|
35
|
+
score_gap?: undefined;
|
|
36
|
+
} | {
|
|
37
|
+
query: string;
|
|
38
|
+
engine: import("../types.js").Engine;
|
|
39
|
+
fetched_at: string;
|
|
40
|
+
your_url: string;
|
|
41
|
+
your_score: number | null;
|
|
42
|
+
your_in_citations: boolean;
|
|
43
|
+
competitors: string[];
|
|
44
|
+
average_competitor_score: number | null;
|
|
45
|
+
score_gap: number | null;
|
|
46
|
+
comparison: {
|
|
47
|
+
fetched_at: string;
|
|
48
|
+
rows: ({
|
|
49
|
+
url: string;
|
|
50
|
+
score: number;
|
|
51
|
+
grade: "A" | "B" | "C" | "D" | "F";
|
|
52
|
+
signals: import("../adapters/predictors.js").PredictorSignals;
|
|
53
|
+
error?: undefined;
|
|
54
|
+
} | {
|
|
55
|
+
url: string;
|
|
56
|
+
error: string;
|
|
57
|
+
score?: undefined;
|
|
58
|
+
grade?: undefined;
|
|
59
|
+
signals?: undefined;
|
|
60
|
+
})[];
|
|
61
|
+
diverging_signals: {
|
|
62
|
+
signal: "wikipedia_linked" | "github_referenced" | "reddit_referenced" | "llms_txt_present" | "canonical_clean" | "https" | "schema_org_present";
|
|
63
|
+
per_url: {
|
|
64
|
+
url: string;
|
|
65
|
+
value: boolean;
|
|
66
|
+
}[];
|
|
67
|
+
}[];
|
|
68
|
+
};
|
|
69
|
+
note?: undefined;
|
|
70
|
+
}>;
|
|
71
|
+
export {};
|
|
72
|
+
//# sourceMappingURL=compete-for-query.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compete-for-query.d.ts","sourceRoot":"","sources":["../../src/tools/compete-for-query.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,eAAO,MAAM,0BAA0B;;;;;CAiBtC,CAAC;AAEF,QAAA,MAAM,WAAW;;;;;;;;;;;;;;;EAAuC,CAAC;AAEzD,wBAAsB,eAAe,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuEvE"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { checkCitations } from "./check-citations.js";
|
|
3
|
+
import { compareDomains } from "./compare-domains.js";
|
|
4
|
+
import { log } from "../lib/log.js";
|
|
5
|
+
export const competeForQueryInputSchema = {
|
|
6
|
+
query: z.string().min(1).describe("Search query to test (what would a user ask an AI?)."),
|
|
7
|
+
your_url: z
|
|
8
|
+
.string()
|
|
9
|
+
.url()
|
|
10
|
+
.describe("Your URL to benchmark against the cited competitors."),
|
|
11
|
+
engine: z
|
|
12
|
+
.enum(["perplexity", "claude", "openai", "gemini", "bing", "auto"])
|
|
13
|
+
.default("auto")
|
|
14
|
+
.describe("AI engine to query for the citation set. 'auto' picks the first available key."),
|
|
15
|
+
max_competitors: z
|
|
16
|
+
.number()
|
|
17
|
+
.int()
|
|
18
|
+
.min(1)
|
|
19
|
+
.max(9)
|
|
20
|
+
.default(4)
|
|
21
|
+
.describe("How many cited URLs to compare against your_url. Capped at 9 (compare_domains accepts max 10 URLs total including yours)."),
|
|
22
|
+
};
|
|
23
|
+
const inputSchema = z.object(competeForQueryInputSchema);
|
|
24
|
+
export async function competeForQuery(input) {
|
|
25
|
+
const parsed = inputSchema.parse(input);
|
|
26
|
+
log.debug("compete_for_query start", { query: parsed.query, your_url: parsed.your_url });
|
|
27
|
+
const citations = await checkCitations({
|
|
28
|
+
query: parsed.query,
|
|
29
|
+
engine: parsed.engine,
|
|
30
|
+
max_results: parsed.max_competitors,
|
|
31
|
+
});
|
|
32
|
+
const yourHost = new URL(parsed.your_url).hostname.toLowerCase();
|
|
33
|
+
const competitorUrls = [];
|
|
34
|
+
for (const c of citations.citations) {
|
|
35
|
+
try {
|
|
36
|
+
const host = new URL(c.url).hostname.toLowerCase();
|
|
37
|
+
if (host === yourHost)
|
|
38
|
+
continue;
|
|
39
|
+
if (competitorUrls.length >= parsed.max_competitors)
|
|
40
|
+
break;
|
|
41
|
+
competitorUrls.push(c.url);
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
// skip malformed
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
if (competitorUrls.length === 0) {
|
|
48
|
+
return {
|
|
49
|
+
query: parsed.query,
|
|
50
|
+
engine: citations.engine,
|
|
51
|
+
fetched_at: new Date().toISOString(),
|
|
52
|
+
your_url: parsed.your_url,
|
|
53
|
+
competitors: [],
|
|
54
|
+
comparison: null,
|
|
55
|
+
note: "No competitor URLs found in citation set. Either no citations returned, or all citations came from your own domain.",
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
const comparison = await compareDomains({ urls: [parsed.your_url, ...competitorUrls] });
|
|
59
|
+
const yourRow = comparison.rows.find((r) => r.url === parsed.your_url);
|
|
60
|
+
const competitorRows = comparison.rows.filter((r) => r.url !== parsed.your_url);
|
|
61
|
+
const yourScore = yourRow && "score" in yourRow ? yourRow.score : undefined;
|
|
62
|
+
const competitorScores = competitorRows
|
|
63
|
+
.map((r) => ("score" in r ? r.score : undefined))
|
|
64
|
+
.filter((s) => typeof s === "number");
|
|
65
|
+
const avgCompetitorScore = competitorScores.length > 0
|
|
66
|
+
? Math.round(competitorScores.reduce((a, b) => a + b, 0) / competitorScores.length)
|
|
67
|
+
: null;
|
|
68
|
+
const gap = typeof yourScore === "number" && avgCompetitorScore !== null
|
|
69
|
+
? yourScore - avgCompetitorScore
|
|
70
|
+
: null;
|
|
71
|
+
return {
|
|
72
|
+
query: parsed.query,
|
|
73
|
+
engine: citations.engine,
|
|
74
|
+
fetched_at: new Date().toISOString(),
|
|
75
|
+
your_url: parsed.your_url,
|
|
76
|
+
your_score: yourScore ?? null,
|
|
77
|
+
your_in_citations: citations.citations.some((c) => {
|
|
78
|
+
try {
|
|
79
|
+
return new URL(c.url).hostname.toLowerCase() === yourHost;
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
}),
|
|
85
|
+
competitors: competitorUrls,
|
|
86
|
+
average_competitor_score: avgCompetitorScore,
|
|
87
|
+
score_gap: gap,
|
|
88
|
+
comparison,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=compete-for-query.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compete-for-query.js","sourceRoot":"","sources":["../../src/tools/compete-for-query.ts"],"names":[],"mappings":"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"}
|