@agentsean/providers 1.0.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 (62) hide show
  1. package/LICENSE +661 -0
  2. package/dist/autocomplete.d.ts +14 -0
  3. package/dist/autocomplete.d.ts.map +1 -0
  4. package/dist/autocomplete.js +40 -0
  5. package/dist/autocomplete.js.map +1 -0
  6. package/dist/bing.d.ts +23 -0
  7. package/dist/bing.d.ts.map +1 -0
  8. package/dist/bing.js +128 -0
  9. package/dist/bing.js.map +1 -0
  10. package/dist/dataforseo.d.ts +33 -0
  11. package/dist/dataforseo.d.ts.map +1 -0
  12. package/dist/dataforseo.js +267 -0
  13. package/dist/dataforseo.js.map +1 -0
  14. package/dist/gsc.d.ts +4 -0
  15. package/dist/gsc.d.ts.map +1 -0
  16. package/dist/gsc.js +26 -0
  17. package/dist/gsc.js.map +1 -0
  18. package/dist/index.d.ts +16 -0
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +15 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/jina.d.ts +6 -0
  23. package/dist/jina.d.ts.map +1 -0
  24. package/dist/jina.js +18 -0
  25. package/dist/jina.js.map +1 -0
  26. package/dist/ledger.d.ts +13 -0
  27. package/dist/ledger.d.ts.map +1 -0
  28. package/dist/ledger.js +64 -0
  29. package/dist/ledger.js.map +1 -0
  30. package/dist/openpagerank.d.ts +11 -0
  31. package/dist/openpagerank.d.ts.map +1 -0
  32. package/dist/openpagerank.js +44 -0
  33. package/dist/openpagerank.js.map +1 -0
  34. package/dist/rates.d.ts +28 -0
  35. package/dist/rates.d.ts.map +1 -0
  36. package/dist/rates.js +47 -0
  37. package/dist/rates.js.map +1 -0
  38. package/dist/refuse.d.ts +33 -0
  39. package/dist/refuse.d.ts.map +1 -0
  40. package/dist/refuse.js +52 -0
  41. package/dist/refuse.js.map +1 -0
  42. package/dist/registry.d.ts +15 -0
  43. package/dist/registry.d.ts.map +1 -0
  44. package/dist/registry.js +71 -0
  45. package/dist/registry.js.map +1 -0
  46. package/dist/types.d.ts +119 -0
  47. package/dist/types.d.ts.map +1 -0
  48. package/dist/types.js +3 -0
  49. package/dist/types.js.map +1 -0
  50. package/dist/unavailable.d.ts +10 -0
  51. package/dist/unavailable.d.ts.map +1 -0
  52. package/dist/unavailable.js +65 -0
  53. package/dist/unavailable.js.map +1 -0
  54. package/dist/wayback.d.ts +6 -0
  55. package/dist/wayback.d.ts.map +1 -0
  56. package/dist/wayback.js +25 -0
  57. package/dist/wayback.js.map +1 -0
  58. package/dist/wikidata.d.ts +6 -0
  59. package/dist/wikidata.d.ts.map +1 -0
  60. package/dist/wikidata.js +23 -0
  61. package/dist/wikidata.js.map +1 -0
  62. package/package.json +52 -0
package/dist/jina.js ADDED
@@ -0,0 +1,18 @@
1
+ /** Jina Reader keyless, 20 RPM. */
2
+ export async function jinaRead(url, opts) {
3
+ const fetchFn = opts?.fetch ?? fetch;
4
+ const res = await fetchFn(`https://r.jina.ai/${url}`, {
5
+ headers: { accept: "text/plain" },
6
+ });
7
+ if (!res.ok)
8
+ throw new Error(`Jina Reader HTTP ${res.status}`);
9
+ const text = await res.text();
10
+ const titleMatch = text.match(/^Title:\s*(.+)$/m);
11
+ return {
12
+ url,
13
+ text,
14
+ provider: "jina",
15
+ ...(titleMatch?.[1] ? { title: titleMatch[1].trim() } : {}),
16
+ };
17
+ }
18
+ //# sourceMappingURL=jina.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jina.js","sourceRoot":"","sources":["../src/jina.ts"],"names":[],"mappings":"AAEA,mCAAmC;AACnC,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,GAAW,EACX,IAA+B;IAE/B,MAAM,OAAO,GAAG,IAAI,EAAE,KAAK,IAAI,KAAK,CAAC;IACrC,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,qBAAqB,GAAG,EAAE,EAAE;QACpD,OAAO,EAAE,EAAE,MAAM,EAAE,YAAY,EAAE;KAClC,CAAC,CAAC;IACH,IAAI,CAAC,GAAG,CAAC,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,oBAAoB,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;IAC/D,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;IAC9B,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;IAClD,OAAO;QACL,GAAG;QACH,IAAI;QACJ,QAAQ,EAAE,MAAM;QAChB,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC5D,CAAC;AACJ,CAAC"}
@@ -0,0 +1,13 @@
1
+ import { type SqliteDatabase } from "@agentsean/db";
2
+ import type { CostEstimate } from "./types.js";
3
+ export declare function recordQuote(db: SqliteDatabase, estimate: CostEstimate, opts?: {
4
+ siteId?: string | null;
5
+ actualUsd?: number | null;
6
+ }): string;
7
+ export declare function debitProvider(db: SqliteDatabase, estimate: CostEstimate, opts?: {
8
+ siteId?: string | null;
9
+ actualUsd?: number | null;
10
+ }): void;
11
+ export declare function spendTodayUsd(db: SqliteDatabase, siteId: string, now?: Date): number;
12
+ export declare function remainingBudgetUsd(db: SqliteDatabase, siteId: string, dailyBudgetUsd: number, now?: Date): number;
13
+ //# sourceMappingURL=ledger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ledger.d.ts","sourceRoot":"","sources":["../src/ledger.ts"],"names":[],"mappings":"AAEA,OAAO,EAA8B,KAAK,cAAc,EAAE,MAAM,eAAe,CAAC;AAChF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,wBAAgB,WAAW,CACzB,EAAE,EAAE,cAAc,EAClB,QAAQ,EAAE,YAAY,EACtB,IAAI,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAC3D,MAAM,CAkBR;AAED,wBAAgB,aAAa,CAC3B,EAAE,EAAE,cAAc,EAClB,QAAQ,EAAE,YAAY,EACtB,IAAI,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAC3D,IAAI,CA2BN;AAED,wBAAgB,aAAa,CAC3B,EAAE,EAAE,cAAc,EAClB,MAAM,EAAE,MAAM,EACd,GAAG,OAAa,GACf,MAAM,CAQR;AAED,wBAAgB,kBAAkB,CAChC,EAAE,EAAE,cAAc,EAClB,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,MAAM,EACtB,GAAG,OAAa,GACf,MAAM,CAER"}
package/dist/ledger.js ADDED
@@ -0,0 +1,64 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { and, eq, gte } from "drizzle-orm";
3
+ import { costLedger, providerQuotes } from "@agentsean/db";
4
+ export function recordQuote(db, estimate, opts) {
5
+ const now = new Date().toISOString();
6
+ const id = randomUUID();
7
+ db.insert(providerQuotes)
8
+ .values({
9
+ id,
10
+ siteId: opts?.siteId ?? null,
11
+ provider: estimate.provider,
12
+ capability: estimate.capability,
13
+ operation: estimate.operation,
14
+ units: estimate.units,
15
+ estimatedUsd: estimate.estimatedUsd,
16
+ actualUsd: opts?.actualUsd ?? null,
17
+ free: estimate.free ? 1 : 0,
18
+ createdAt: now,
19
+ })
20
+ .run();
21
+ return id;
22
+ }
23
+ export function debitProvider(db, estimate, opts) {
24
+ const now = new Date().toISOString();
25
+ const actual = opts?.actualUsd ?? estimate.estimatedUsd;
26
+ recordQuote(db, estimate, { siteId: opts?.siteId ?? null, actualUsd: actual });
27
+ if (actual <= 0 && estimate.free)
28
+ return;
29
+ db.insert(costLedger)
30
+ .values({
31
+ id: randomUUID(),
32
+ siteId: opts?.siteId ?? null,
33
+ ts: now,
34
+ provider: estimate.provider,
35
+ model: null,
36
+ operation: `${estimate.capability}:${estimate.operation}`,
37
+ inputTokens: null,
38
+ outputTokens: null,
39
+ costUsd: actual,
40
+ currency: "USD",
41
+ meta: JSON.stringify({
42
+ units: estimate.units,
43
+ unitUsd: estimate.unitUsd,
44
+ estimatedUsd: estimate.estimatedUsd,
45
+ free: estimate.free,
46
+ notes: estimate.notes ?? null,
47
+ }),
48
+ createdAt: now,
49
+ })
50
+ .run();
51
+ }
52
+ export function spendTodayUsd(db, siteId, now = new Date()) {
53
+ const day = now.toISOString().slice(0, 10);
54
+ const rows = db
55
+ .select()
56
+ .from(costLedger)
57
+ .where(and(eq(costLedger.siteId, siteId), gte(costLedger.ts, day)))
58
+ .all();
59
+ return rows.reduce((s, r) => s + (r.costUsd ?? 0), 0);
60
+ }
61
+ export function remainingBudgetUsd(db, siteId, dailyBudgetUsd, now = new Date()) {
62
+ return Math.max(0, dailyBudgetUsd - spendTodayUsd(db, siteId, now));
63
+ }
64
+ //# sourceMappingURL=ledger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ledger.js","sourceRoot":"","sources":["../src/ledger.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { BacklinkOverview, BacklinksCapability } from "./types.js";
2
+ export declare function fetchOpenPageRank(domain: string, opts: {
3
+ apiKey: string;
4
+ fetch?: typeof fetch;
5
+ }): Promise<BacklinkOverview>;
6
+ /** 30k free domain lookups/month. Authority proxy, not a backlink graph. */
7
+ export declare function createOpenPageRank(opts: {
8
+ apiKey: string;
9
+ fetch?: typeof fetch;
10
+ }): BacklinksCapability;
11
+ //# sourceMappingURL=openpagerank.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openpagerank.d.ts","sourceRoot":"","sources":["../src/openpagerank.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,mBAAmB,EAAgB,MAAM,YAAY,CAAC;AAKtF,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,MAAM,EACd,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,KAAK,CAAA;CAAE,GAC7C,OAAO,CAAC,gBAAgB,CAAC,CAmB3B;AAED,4EAA4E;AAC5E,wBAAgB,kBAAkB,CAAC,IAAI,EAAE;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;CACtB,GAAG,mBAAmB,CAkBtB"}
@@ -0,0 +1,44 @@
1
+ import { freeEstimate } from "./rates.js";
2
+ const OPR_URL = "https://openpagerank.com/api/v1.0/getPageRank";
3
+ export async function fetchOpenPageRank(domain, opts) {
4
+ const fetchFn = opts.fetch ?? fetch;
5
+ const url = new URL(OPR_URL);
6
+ url.searchParams.append("domains[]", domain);
7
+ const res = await fetchFn(url, {
8
+ headers: { "API-OPR": opts.apiKey, accept: "application/json" },
9
+ });
10
+ if (!res.ok)
11
+ throw new Error(`OpenPageRank HTTP ${res.status}`);
12
+ const json = (await res.json());
13
+ const row = json.response?.[0];
14
+ return {
15
+ target: domain,
16
+ provider: "openpagerank",
17
+ kind: "authority_proxy",
18
+ pageRank: typeof row?.page_rank_decimal === "number" ? row.page_rank_decimal : null,
19
+ rank: row?.rank && Number.isFinite(Number(row.rank)) ? Number(row.rank) : null,
20
+ };
21
+ }
22
+ /** 30k free domain lookups/month. Authority proxy, not a backlink graph. */
23
+ export function createOpenPageRank(opts) {
24
+ return {
25
+ id: "openpagerank",
26
+ available: true,
27
+ overview(target) {
28
+ const host = hostOf(target);
29
+ return {
30
+ estimate: freeEstimate("openpagerank", "backlinks", "getPageRank", 1, "authority proxy · 30k free lookups/month"),
31
+ run: () => fetchOpenPageRank(host, opts),
32
+ };
33
+ },
34
+ };
35
+ }
36
+ function hostOf(target) {
37
+ try {
38
+ return new URL(target.includes("://") ? target : `https://${target}`).hostname.replace(/^www\./, "");
39
+ }
40
+ catch {
41
+ return target.replace(/^www\./, "");
42
+ }
43
+ }
44
+ //# sourceMappingURL=openpagerank.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openpagerank.js","sourceRoot":"","sources":["../src/openpagerank.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,MAAM,OAAO,GAAG,+CAA+C,CAAC;AAEhE,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,MAAc,EACd,IAA8C;IAE9C,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC;IACpC,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;IAC7B,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IAC7C,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE;QAC7B,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,kBAAkB,EAAE;KAChE,CAAC,CAAC;IACH,IAAI,CAAC,GAAG,CAAC,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,qBAAqB,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;IAChE,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAE7B,CAAC;IACF,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC;IAC/B,OAAO;QACL,MAAM,EAAE,MAAM;QACd,QAAQ,EAAE,cAAc;QACxB,IAAI,EAAE,iBAAiB;QACvB,QAAQ,EAAE,OAAO,GAAG,EAAE,iBAAiB,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC,IAAI;QACnF,IAAI,EAAE,GAAG,EAAE,IAAI,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI;KAC/E,CAAC;AACJ,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,kBAAkB,CAAC,IAGlC;IACC,OAAO;QACL,EAAE,EAAE,cAAc;QAClB,SAAS,EAAE,IAAI;QACf,QAAQ,CAAC,MAAc;YACrB,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;YAC5B,OAAO;gBACL,QAAQ,EAAE,YAAY,CACpB,cAAc,EACd,WAAW,EACX,aAAa,EACb,CAAC,EACD,0CAA0C,CAC3C;gBACD,GAAG,EAAE,GAAG,EAAE,CAAC,iBAAiB,CAAC,IAAI,EAAE,IAAI,CAAC;aACzC,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC;AAED,SAAS,MAAM,CAAC,MAAc;IAC5B,IAAI,CAAC;QACH,OAAO,IAAI,GAAG,CACZ,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,MAAM,EAAE,CACtD,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IACnC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,MAAM,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IACtC,CAAC;AACH,CAAC"}
@@ -0,0 +1,28 @@
1
+ import type { Capability, CostEstimate } from "./types.js";
2
+ /**
3
+ * DataForSEO published rates (PLAN Phase 6). Quoted *before* the call.
4
+ * SERP $0.60/1k standard queue · Keywords Data $0.06/task (≤1,000 keywords)
5
+ * Labs $0.012/task · Backlinks $0.024/req + $0.000036/row · On-Page $0.15/1k.
6
+ */
7
+ export declare const DFS_RATES: {
8
+ readonly serpPerKeyword: number;
9
+ readonly keywordsDataPerTask: 0.06;
10
+ readonly keywordsDataMaxKeywords: 1000;
11
+ readonly labsPerTask: 0.012;
12
+ readonly backlinksPerRequest: 0.024;
13
+ readonly backlinksPerRow: 0.000036;
14
+ readonly onPagePerPage: number;
15
+ };
16
+ export declare const FREE_NOTE = "zero paid keys";
17
+ export declare function freeEstimate(provider: string, capability: Capability, operation: string, units?: number, notes?: string): CostEstimate;
18
+ export declare function paidEstimate(opts: {
19
+ provider: string;
20
+ capability: Capability;
21
+ operation: string;
22
+ units: number;
23
+ unitUsd: number;
24
+ notes?: string;
25
+ }): CostEstimate;
26
+ export declare function roundUsd(n: number): number;
27
+ export declare function keywordsDataTasks(keywordCount: number): number;
28
+ //# sourceMappingURL=rates.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rates.d.ts","sourceRoot":"","sources":["../src/rates.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE3D;;;;GAIG;AACH,eAAO,MAAM,SAAS;;;;;;;;CAQZ,CAAC;AAEX,eAAO,MAAM,SAAS,mBAAmB,CAAC;AAE1C,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,MAAM,EACjB,KAAK,SAAI,EACT,KAAK,CAAC,EAAE,MAAM,GACb,YAAY,CAWd;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,UAAU,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,YAAY,CAYf;AAED,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE1C;AAED,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAE9D"}
package/dist/rates.js ADDED
@@ -0,0 +1,47 @@
1
+ /**
2
+ * DataForSEO published rates (PLAN Phase 6). Quoted *before* the call.
3
+ * SERP $0.60/1k standard queue · Keywords Data $0.06/task (≤1,000 keywords)
4
+ * Labs $0.012/task · Backlinks $0.024/req + $0.000036/row · On-Page $0.15/1k.
5
+ */
6
+ export const DFS_RATES = {
7
+ serpPerKeyword: 0.6 / 1000,
8
+ keywordsDataPerTask: 0.06,
9
+ keywordsDataMaxKeywords: 1000,
10
+ labsPerTask: 0.012,
11
+ backlinksPerRequest: 0.024,
12
+ backlinksPerRow: 0.000036,
13
+ onPagePerPage: 0.15 / 1000,
14
+ };
15
+ export const FREE_NOTE = "zero paid keys";
16
+ export function freeEstimate(provider, capability, operation, units = 1, notes) {
17
+ return {
18
+ provider,
19
+ capability,
20
+ operation,
21
+ units,
22
+ unitUsd: 0,
23
+ estimatedUsd: 0,
24
+ free: true,
25
+ ...(notes ? { notes } : {}),
26
+ };
27
+ }
28
+ export function paidEstimate(opts) {
29
+ const estimatedUsd = roundUsd(opts.units * opts.unitUsd);
30
+ return {
31
+ provider: opts.provider,
32
+ capability: opts.capability,
33
+ operation: opts.operation,
34
+ units: opts.units,
35
+ unitUsd: opts.unitUsd,
36
+ estimatedUsd,
37
+ free: false,
38
+ ...(opts.notes ? { notes: opts.notes } : {}),
39
+ };
40
+ }
41
+ export function roundUsd(n) {
42
+ return Math.round(n * 1_000_000) / 1_000_000;
43
+ }
44
+ export function keywordsDataTasks(keywordCount) {
45
+ return Math.max(1, Math.ceil(keywordCount / DFS_RATES.keywordsDataMaxKeywords));
46
+ }
47
+ //# sourceMappingURL=rates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rates.js","sourceRoot":"","sources":["../src/rates.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB,cAAc,EAAE,GAAG,GAAG,IAAI;IAC1B,mBAAmB,EAAE,IAAI;IACzB,uBAAuB,EAAE,IAAI;IAC7B,WAAW,EAAE,KAAK;IAClB,mBAAmB,EAAE,KAAK;IAC1B,eAAe,EAAE,QAAQ;IACzB,aAAa,EAAE,IAAI,GAAG,IAAI;CAClB,CAAC;AAEX,MAAM,CAAC,MAAM,SAAS,GAAG,gBAAgB,CAAC;AAE1C,MAAM,UAAU,YAAY,CAC1B,QAAgB,EAChB,UAAsB,EACtB,SAAiB,EACjB,KAAK,GAAG,CAAC,EACT,KAAc;IAEd,OAAO;QACL,QAAQ;QACR,UAAU;QACV,SAAS;QACT,KAAK;QACL,OAAO,EAAE,CAAC;QACV,YAAY,EAAE,CAAC;QACf,IAAI,EAAE,IAAI;QACV,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC5B,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAO5B;IACC,MAAM,YAAY,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC;IACzD,OAAO;QACL,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,UAAU,EAAE,IAAI,CAAC,UAAU;QAC3B,SAAS,EAAE,IAAI,CAAC,SAAS;QACzB,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,YAAY;QACZ,IAAI,EAAE,KAAK;QACX,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC7C,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,CAAS;IAChC,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,SAAS,CAAC,GAAG,SAAS,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,YAAoB;IACpD,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,YAAY,GAAG,SAAS,CAAC,uBAAuB,CAAC,CAAC,CAAC;AAClF,CAAC"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Dead options (PLAN Phase 6) and T4: Sean never scrapes Google itself.
3
+ * Google's spam policy names "scraping results for rank-checking purposes".
4
+ */
5
+ export declare const DEAD_PROVIDERS: readonly [{
6
+ readonly id: "bing_search_api";
7
+ readonly reason: "Bing Search API was decommissioned 2025-08-11";
8
+ }, {
9
+ readonly id: "google_cse";
10
+ readonly reason: "Google Custom Search JSON API is closed to new customers with a hard shutdown 2027-01-01";
11
+ }, {
12
+ readonly id: "brave_search";
13
+ readonly reason: "Brave removed its free tier in Feb 2026 and forbids storing results";
14
+ }, {
15
+ readonly id: "pytrends";
16
+ readonly reason: "pytrends was archived 2025-04-17";
17
+ }, {
18
+ readonly id: "google_trends_api";
19
+ readonly reason: "Google Trends API remains invite-only alpha with no self-serve key";
20
+ }, {
21
+ readonly id: "serpapi";
22
+ readonly reason: "Google sued SerpApi on 2025-12-19; Sean does not scrape Google";
23
+ }];
24
+ export declare class ProviderRefusedError extends Error {
25
+ name: string;
26
+ readonly code: string;
27
+ constructor(code: string, message: string);
28
+ }
29
+ export declare function isDeadProvider(id: string): boolean;
30
+ export declare function refuseDeadProvider(id: string): never;
31
+ /** T4 — SERP scraping bundled by default is refused. No setting exists. */
32
+ export declare function scrapeGoogleSerp(): never;
33
+ //# sourceMappingURL=refuse.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"refuse.d.ts","sourceRoot":"","sources":["../src/refuse.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;EA0BjB,CAAC;AAEX,qBAAa,oBAAqB,SAAQ,KAAK;IACpC,IAAI,SAA0B;IACvC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBACV,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;CAI1C;AAED,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAGlD;AAED,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,MAAM,GAAG,KAAK,CAOpD;AAED,2EAA2E;AAC3E,wBAAgB,gBAAgB,IAAI,KAAK,CAKxC"}
package/dist/refuse.js ADDED
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Dead options (PLAN Phase 6) and T4: Sean never scrapes Google itself.
3
+ * Google's spam policy names "scraping results for rank-checking purposes".
4
+ */
5
+ export const DEAD_PROVIDERS = [
6
+ {
7
+ id: "bing_search_api",
8
+ reason: "Bing Search API was decommissioned 2025-08-11",
9
+ },
10
+ {
11
+ id: "google_cse",
12
+ reason: "Google Custom Search JSON API is closed to new customers with a hard shutdown 2027-01-01",
13
+ },
14
+ {
15
+ id: "brave_search",
16
+ reason: "Brave removed its free tier in Feb 2026 and forbids storing results",
17
+ },
18
+ {
19
+ id: "pytrends",
20
+ reason: "pytrends was archived 2025-04-17",
21
+ },
22
+ {
23
+ id: "google_trends_api",
24
+ reason: "Google Trends API remains invite-only alpha with no self-serve key",
25
+ },
26
+ {
27
+ id: "serpapi",
28
+ reason: "Google sued SerpApi on 2025-12-19; Sean does not scrape Google",
29
+ },
30
+ ];
31
+ export class ProviderRefusedError extends Error {
32
+ name = "ProviderRefusedError";
33
+ code;
34
+ constructor(code, message) {
35
+ super(message);
36
+ this.code = code;
37
+ }
38
+ }
39
+ export function isDeadProvider(id) {
40
+ const key = id.toLowerCase().replace(/[\s-]+/g, "_");
41
+ return DEAD_PROVIDERS.some((p) => p.id === key || key.includes(p.id));
42
+ }
43
+ export function refuseDeadProvider(id) {
44
+ const key = id.toLowerCase().replace(/[\s-]+/g, "_");
45
+ const hit = DEAD_PROVIDERS.find((p) => p.id === key || key.includes(p.id));
46
+ throw new ProviderRefusedError("dead_provider", hit?.reason ?? `Provider ${id} is not supported.`);
47
+ }
48
+ /** T4 — SERP scraping bundled by default is refused. No setting exists. */
49
+ export function scrapeGoogleSerp() {
50
+ throw new ProviderRefusedError("serp_scrape_refused", "Sean never scrapes Google. Rank data comes from a licensed vendor you configure (DataForSEO), or not at all. Autocomplete is expansion, not rank checking.");
51
+ }
52
+ //# sourceMappingURL=refuse.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"refuse.js","sourceRoot":"","sources":["../src/refuse.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B;QACE,EAAE,EAAE,iBAAiB;QACrB,MAAM,EAAE,+CAA+C;KACxD;IACD;QACE,EAAE,EAAE,YAAY;QAChB,MAAM,EACJ,0FAA0F;KAC7F;IACD;QACE,EAAE,EAAE,cAAc;QAClB,MAAM,EAAE,qEAAqE;KAC9E;IACD;QACE,EAAE,EAAE,UAAU;QACd,MAAM,EAAE,kCAAkC;KAC3C;IACD;QACE,EAAE,EAAE,mBAAmB;QACvB,MAAM,EAAE,oEAAoE;KAC7E;IACD;QACE,EAAE,EAAE,SAAS;QACb,MAAM,EAAE,gEAAgE;KACzE;CACO,CAAC;AAEX,MAAM,OAAO,oBAAqB,SAAQ,KAAK;IACpC,IAAI,GAAG,sBAAsB,CAAC;IAC9B,IAAI,CAAS;IACtB,YAAY,IAAY,EAAE,OAAe;QACvC,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF;AAED,MAAM,UAAU,cAAc,CAAC,EAAU;IACvC,MAAM,GAAG,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;IACrD,OAAO,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AACxE,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,EAAU;IAC3C,MAAM,GAAG,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;IACrD,MAAM,GAAG,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC3E,MAAM,IAAI,oBAAoB,CAC5B,eAAe,EACf,GAAG,EAAE,MAAM,IAAI,YAAY,EAAE,oBAAoB,CAClD,CAAC;AACJ,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,gBAAgB;IAC9B,MAAM,IAAI,oBAAoB,CAC5B,qBAAqB,EACrB,4JAA4J,CAC7J,CAAC;AACJ,CAAC"}
@@ -0,0 +1,15 @@
1
+ import type { CredentialStore } from "@agentsean/credentials";
2
+ import type { KeywordRow, ProviderKeys, ProviderStack } from "./types.js";
3
+ export declare const PROVIDER_ACCOUNTS: {
4
+ readonly dataforseo: "provider:dataforseo";
5
+ readonly bing: "provider:bing";
6
+ readonly openpagerank: "provider:openpagerank";
7
+ readonly openseo: "provider:openseo";
8
+ };
9
+ export declare function loadProviderKeys(store?: CredentialStore, extra?: ProviderKeys): Promise<ProviderKeys>;
10
+ export declare function createProviderStack(opts: {
11
+ keys?: ProviderKeys;
12
+ gsc?: KeywordRow[];
13
+ fetch?: typeof fetch;
14
+ }): ProviderStack;
15
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAkB1E,eAAO,MAAM,iBAAiB;;;;;CAKpB,CAAC;AAEX,wBAAsB,gBAAgB,CACpC,KAAK,CAAC,EAAE,eAAe,EACvB,KAAK,CAAC,EAAE,YAAY,GACnB,OAAO,CAAC,YAAY,CAAC,CAUvB;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE;IACxC,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,GAAG,CAAC,EAAE,UAAU,EAAE,CAAC;IACnB,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;CACtB,GAAG,aAAa,CA0ChB"}
@@ -0,0 +1,71 @@
1
+ import { createGscKeywords } from "./gsc.js";
2
+ import { createBingClient, createBingVolume } from "./bing.js";
3
+ import { createDataForSeoBacklinks, createDataForSeoClient, createDataForSeoSerp, createDataForSeoVolume, } from "./dataforseo.js";
4
+ import { createOpenPageRank } from "./openpagerank.js";
5
+ import { emptyKeywords, unavailableBacklinks, unavailableSerp, unavailableVolume, } from "./unavailable.js";
6
+ import { isDeadProvider, refuseDeadProvider } from "./refuse.js";
7
+ export const PROVIDER_ACCOUNTS = {
8
+ dataforseo: "provider:dataforseo",
9
+ bing: "provider:bing",
10
+ openpagerank: "provider:openpagerank",
11
+ openseo: "provider:openseo",
12
+ };
13
+ export async function loadProviderKeys(store, extra) {
14
+ const keys = { ...extra };
15
+ if (!store)
16
+ return keys;
17
+ const dfs = await store.get(PROVIDER_ACCOUNTS.dataforseo);
18
+ const bing = await store.get(PROVIDER_ACCOUNTS.bing);
19
+ const opr = await store.get(PROVIDER_ACCOUNTS.openpagerank);
20
+ if (dfs)
21
+ keys.dataforseo = dfs.unwrap();
22
+ if (bing)
23
+ keys.bing = bing.unwrap();
24
+ if (opr)
25
+ keys.openpagerank = opr.unwrap();
26
+ return keys;
27
+ }
28
+ export function createProviderStack(opts) {
29
+ const keys = opts.keys ?? {};
30
+ for (const id of Object.keys(keys)) {
31
+ if (isDeadProvider(id))
32
+ refuseDeadProvider(id);
33
+ }
34
+ const gsc = opts.gsc?.length ? createGscKeywords(opts.gsc) : emptyKeywords();
35
+ const dfs = keys.dataforseo
36
+ ? createDataForSeoClient({
37
+ loginPassword: keys.dataforseo,
38
+ ...(opts.fetch ? { fetch: opts.fetch } : {}),
39
+ })
40
+ : null;
41
+ const bing = keys.bing
42
+ ? createBingClient({
43
+ apiKey: keys.bing,
44
+ ...(opts.fetch ? { fetch: opts.fetch } : {}),
45
+ })
46
+ : null;
47
+ return {
48
+ keywords: gsc,
49
+ volume: dfs
50
+ ? createDataForSeoVolume(dfs)
51
+ : bing
52
+ ? createBingVolume(bing)
53
+ : unavailableVolume(),
54
+ serp: dfs ? createDataForSeoSerp(dfs) : unavailableSerp(),
55
+ backlinks: dfs
56
+ ? createDataForSeoBacklinks(dfs)
57
+ : keys.openpagerank
58
+ ? createOpenPageRank({
59
+ apiKey: keys.openpagerank,
60
+ ...(opts.fetch ? { fetch: opts.fetch } : {}),
61
+ })
62
+ : unavailableBacklinks(),
63
+ keys: {
64
+ dataforseo: Boolean(keys.dataforseo),
65
+ bing: Boolean(keys.bing),
66
+ openpagerank: Boolean(keys.openpagerank),
67
+ },
68
+ paidUpgrade: Boolean(keys.dataforseo),
69
+ };
70
+ }
71
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,119 @@
1
+ /** One interface per capability. Cost is quoted before the call. */
2
+ export declare const CAPABILITIES: readonly ["serp", "keywords", "backlinks", "volume"];
3
+ export type Capability = (typeof CAPABILITIES)[number];
4
+ export type CostEstimate = {
5
+ provider: string;
6
+ capability: Capability;
7
+ operation: string;
8
+ units: number;
9
+ unitUsd: number;
10
+ estimatedUsd: number;
11
+ free: boolean;
12
+ notes?: string;
13
+ };
14
+ export type ProviderCall<T> = {
15
+ estimate: CostEstimate;
16
+ run: () => Promise<T>;
17
+ };
18
+ export type KeywordRow = {
19
+ query: string;
20
+ source: string;
21
+ clicks?: number;
22
+ impressions?: number;
23
+ position?: number | null;
24
+ page?: string | null;
25
+ volume?: number | null;
26
+ relatedTo?: string;
27
+ };
28
+ export type VolumeRow = {
29
+ query: string;
30
+ volume: number | null;
31
+ source: string;
32
+ country?: string;
33
+ };
34
+ export type SerpItem = {
35
+ rank: number;
36
+ url: string;
37
+ title: string;
38
+ snippet?: string;
39
+ };
40
+ export type SerpResult = {
41
+ query: string;
42
+ provider: string;
43
+ items: SerpItem[];
44
+ paa?: string[];
45
+ related?: string[];
46
+ };
47
+ export type BacklinkOverview = {
48
+ target: string;
49
+ provider: string;
50
+ /** OpenPageRank is an authority proxy, not a backlink graph. */
51
+ kind: "authority_proxy" | "backlinks";
52
+ pageRank?: number | null;
53
+ rank?: number | null;
54
+ referringDomains?: number | null;
55
+ backlinks?: number | null;
56
+ };
57
+ export type KeywordsCapability = {
58
+ id: string;
59
+ demand(opts: {
60
+ queries: KeywordRow[];
61
+ }): ProviderCall<KeywordRow[]>;
62
+ related(seed: string, opts?: {
63
+ limit?: number;
64
+ }): ProviderCall<KeywordRow[]>;
65
+ };
66
+ export type VolumeCapability = {
67
+ id: string;
68
+ volume(queries: string[], opts?: {
69
+ country?: string;
70
+ }): ProviderCall<VolumeRow[]>;
71
+ };
72
+ export type SerpCapability = {
73
+ id: string;
74
+ available: boolean;
75
+ serp(query: string, opts?: {
76
+ location?: string;
77
+ }): ProviderCall<SerpResult>;
78
+ };
79
+ export type BacklinksCapability = {
80
+ id: string;
81
+ available: boolean;
82
+ overview(target: string): ProviderCall<BacklinkOverview>;
83
+ };
84
+ export type ExtractPage = {
85
+ url: string;
86
+ title?: string;
87
+ text: string;
88
+ provider: string;
89
+ };
90
+ export type EntityHit = {
91
+ id: string;
92
+ label: string;
93
+ description?: string;
94
+ url?: string;
95
+ };
96
+ export type WaybackCapture = {
97
+ url: string;
98
+ timestamp: string;
99
+ status?: string;
100
+ original?: string;
101
+ };
102
+ export type ProviderKeys = {
103
+ dataforseo?: string;
104
+ bing?: string;
105
+ openpagerank?: string;
106
+ };
107
+ export type ProviderStack = {
108
+ keywords: KeywordsCapability;
109
+ volume: VolumeCapability;
110
+ serp: SerpCapability;
111
+ backlinks: BacklinksCapability;
112
+ keys: {
113
+ dataforseo: boolean;
114
+ bing: boolean;
115
+ openpagerank: boolean;
116
+ };
117
+ paidUpgrade: boolean;
118
+ };
119
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,3 @@
1
+ /** One interface per capability. Cost is quoted before the call. */
2
+ export const CAPABILITIES = ["serp", "keywords", "backlinks", "volume"];
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,oEAAoE;AAEpE,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,CAAU,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { BacklinksCapability, KeywordRow, ProviderCall, SerpCapability, VolumeCapability } from "./types.js";
2
+ export declare function unavailableSerp(): SerpCapability;
3
+ export declare function unavailableVolume(): VolumeCapability;
4
+ export declare function unavailableBacklinks(): BacklinksCapability;
5
+ export declare function emptyKeywords(): {
6
+ id: string;
7
+ demand: () => ProviderCall<KeywordRow[]>;
8
+ related: (seed: string) => ProviderCall<KeywordRow[]>;
9
+ };
10
+ //# sourceMappingURL=unavailable.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unavailable.d.ts","sourceRoot":"","sources":["../src/unavailable.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAEV,mBAAmB,EACnB,UAAU,EACV,YAAY,EACZ,cAAc,EAEd,gBAAgB,EAEjB,MAAM,YAAY,CAAC;AAEpB,wBAAgB,eAAe,IAAI,cAAc,CAsBhD;AAED,wBAAgB,iBAAiB,IAAI,gBAAgB,CAkBpD;AAED,wBAAgB,oBAAoB,IAAI,mBAAmB,CAgB1D;AAED,wBAAgB,aAAa,IAAI;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,YAAY,CAAC,UAAU,EAAE,CAAC,CAAC;IACzC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,YAAY,CAAC,UAAU,EAAE,CAAC,CAAC;CACvD,CAoBA"}