@debriefer/sources 1.0.1

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 (194) hide show
  1. package/README.md +59 -0
  2. package/dist/__tests__/archives/chronicling-america.test.d.ts +8 -0
  3. package/dist/__tests__/archives/chronicling-america.test.d.ts.map +1 -0
  4. package/dist/__tests__/archives/chronicling-america.test.js +151 -0
  5. package/dist/__tests__/archives/chronicling-america.test.js.map +1 -0
  6. package/dist/__tests__/archives/europeana.test.d.ts +8 -0
  7. package/dist/__tests__/archives/europeana.test.d.ts.map +1 -0
  8. package/dist/__tests__/archives/europeana.test.js +200 -0
  9. package/dist/__tests__/archives/europeana.test.js.map +1 -0
  10. package/dist/__tests__/archives/internet-archive.test.d.ts +8 -0
  11. package/dist/__tests__/archives/internet-archive.test.d.ts.map +1 -0
  12. package/dist/__tests__/archives/internet-archive.test.js +189 -0
  13. package/dist/__tests__/archives/internet-archive.test.js.map +1 -0
  14. package/dist/__tests__/archives/trove.test.d.ts +8 -0
  15. package/dist/__tests__/archives/trove.test.d.ts.map +1 -0
  16. package/dist/__tests__/archives/trove.test.js +202 -0
  17. package/dist/__tests__/archives/trove.test.js.map +1 -0
  18. package/dist/__tests__/books/google-books.test.d.ts +8 -0
  19. package/dist/__tests__/books/google-books.test.d.ts.map +1 -0
  20. package/dist/__tests__/books/google-books.test.js +221 -0
  21. package/dist/__tests__/books/google-books.test.js.map +1 -0
  22. package/dist/__tests__/books/open-library.test.d.ts +8 -0
  23. package/dist/__tests__/books/open-library.test.d.ts.map +1 -0
  24. package/dist/__tests__/books/open-library.test.js +159 -0
  25. package/dist/__tests__/books/open-library.test.js.map +1 -0
  26. package/dist/__tests__/news/guardian.test.d.ts +9 -0
  27. package/dist/__tests__/news/guardian.test.d.ts.map +1 -0
  28. package/dist/__tests__/news/guardian.test.js +224 -0
  29. package/dist/__tests__/news/guardian.test.js.map +1 -0
  30. package/dist/__tests__/news/nytimes.test.d.ts +9 -0
  31. package/dist/__tests__/news/nytimes.test.d.ts.map +1 -0
  32. package/dist/__tests__/news/nytimes.test.js +271 -0
  33. package/dist/__tests__/news/nytimes.test.js.map +1 -0
  34. package/dist/__tests__/news/site-search-source.test.d.ts +9 -0
  35. package/dist/__tests__/news/site-search-source.test.d.ts.map +1 -0
  36. package/dist/__tests__/news/site-search-source.test.js +342 -0
  37. package/dist/__tests__/news/site-search-source.test.js.map +1 -0
  38. package/dist/__tests__/obituary/find-a-grave.test.d.ts +8 -0
  39. package/dist/__tests__/obituary/find-a-grave.test.d.ts.map +1 -0
  40. package/dist/__tests__/obituary/find-a-grave.test.js +238 -0
  41. package/dist/__tests__/obituary/find-a-grave.test.js.map +1 -0
  42. package/dist/__tests__/shared/duckduckgo-search.test.d.ts +9 -0
  43. package/dist/__tests__/shared/duckduckgo-search.test.d.ts.map +1 -0
  44. package/dist/__tests__/shared/duckduckgo-search.test.js +218 -0
  45. package/dist/__tests__/shared/duckduckgo-search.test.js.map +1 -0
  46. package/dist/__tests__/shared/fetch-page.test.d.ts +9 -0
  47. package/dist/__tests__/shared/fetch-page.test.d.ts.map +1 -0
  48. package/dist/__tests__/shared/fetch-page.test.js +281 -0
  49. package/dist/__tests__/shared/fetch-page.test.js.map +1 -0
  50. package/dist/__tests__/shared/html-utils.test.d.ts +2 -0
  51. package/dist/__tests__/shared/html-utils.test.d.ts.map +1 -0
  52. package/dist/__tests__/shared/html-utils.test.js +169 -0
  53. package/dist/__tests__/shared/html-utils.test.js.map +1 -0
  54. package/dist/__tests__/shared/readability-extract.test.d.ts +2 -0
  55. package/dist/__tests__/shared/readability-extract.test.d.ts.map +1 -0
  56. package/dist/__tests__/shared/readability-extract.test.js +107 -0
  57. package/dist/__tests__/shared/readability-extract.test.js.map +1 -0
  58. package/dist/__tests__/shared/sanitize-text.test.d.ts +2 -0
  59. package/dist/__tests__/shared/sanitize-text.test.d.ts.map +1 -0
  60. package/dist/__tests__/shared/sanitize-text.test.js +77 -0
  61. package/dist/__tests__/shared/sanitize-text.test.js.map +1 -0
  62. package/dist/__tests__/shared/search-utils.test.d.ts +2 -0
  63. package/dist/__tests__/shared/search-utils.test.d.ts.map +1 -0
  64. package/dist/__tests__/shared/search-utils.test.js +26 -0
  65. package/dist/__tests__/shared/search-utils.test.js.map +1 -0
  66. package/dist/__tests__/structured/wikidata.test.d.ts +9 -0
  67. package/dist/__tests__/structured/wikidata.test.d.ts.map +1 -0
  68. package/dist/__tests__/structured/wikidata.test.js +509 -0
  69. package/dist/__tests__/structured/wikidata.test.js.map +1 -0
  70. package/dist/__tests__/structured/wikipedia.test.d.ts +9 -0
  71. package/dist/__tests__/structured/wikipedia.test.d.ts.map +1 -0
  72. package/dist/__tests__/structured/wikipedia.test.js +643 -0
  73. package/dist/__tests__/structured/wikipedia.test.js.map +1 -0
  74. package/dist/__tests__/web-search/base.test.d.ts +9 -0
  75. package/dist/__tests__/web-search/base.test.d.ts.map +1 -0
  76. package/dist/__tests__/web-search/base.test.js +622 -0
  77. package/dist/__tests__/web-search/base.test.js.map +1 -0
  78. package/dist/__tests__/web-search/bing.test.d.ts +10 -0
  79. package/dist/__tests__/web-search/bing.test.d.ts.map +1 -0
  80. package/dist/__tests__/web-search/bing.test.js +277 -0
  81. package/dist/__tests__/web-search/bing.test.js.map +1 -0
  82. package/dist/__tests__/web-search/brave.test.d.ts +10 -0
  83. package/dist/__tests__/web-search/brave.test.d.ts.map +1 -0
  84. package/dist/__tests__/web-search/brave.test.js +264 -0
  85. package/dist/__tests__/web-search/brave.test.js.map +1 -0
  86. package/dist/__tests__/web-search/duckduckgo.test.d.ts +10 -0
  87. package/dist/__tests__/web-search/duckduckgo.test.d.ts.map +1 -0
  88. package/dist/__tests__/web-search/duckduckgo.test.js +107 -0
  89. package/dist/__tests__/web-search/duckduckgo.test.js.map +1 -0
  90. package/dist/__tests__/web-search/google.test.d.ts +9 -0
  91. package/dist/__tests__/web-search/google.test.d.ts.map +1 -0
  92. package/dist/__tests__/web-search/google.test.js +189 -0
  93. package/dist/__tests__/web-search/google.test.js.map +1 -0
  94. package/dist/archives/chronicling-america.d.ts +33 -0
  95. package/dist/archives/chronicling-america.d.ts.map +1 -0
  96. package/dist/archives/chronicling-america.js +85 -0
  97. package/dist/archives/chronicling-america.js.map +1 -0
  98. package/dist/archives/europeana.d.ts +37 -0
  99. package/dist/archives/europeana.d.ts.map +1 -0
  100. package/dist/archives/europeana.js +92 -0
  101. package/dist/archives/europeana.js.map +1 -0
  102. package/dist/archives/internet-archive.d.ts +32 -0
  103. package/dist/archives/internet-archive.d.ts.map +1 -0
  104. package/dist/archives/internet-archive.js +90 -0
  105. package/dist/archives/internet-archive.js.map +1 -0
  106. package/dist/archives/trove.d.ts +37 -0
  107. package/dist/archives/trove.d.ts.map +1 -0
  108. package/dist/archives/trove.js +97 -0
  109. package/dist/archives/trove.js.map +1 -0
  110. package/dist/books/google-books.d.ts +48 -0
  111. package/dist/books/google-books.d.ts.map +1 -0
  112. package/dist/books/google-books.js +111 -0
  113. package/dist/books/google-books.js.map +1 -0
  114. package/dist/books/open-library.d.ts +44 -0
  115. package/dist/books/open-library.d.ts.map +1 -0
  116. package/dist/books/open-library.js +103 -0
  117. package/dist/books/open-library.js.map +1 -0
  118. package/dist/index.d.ts +45 -0
  119. package/dist/index.d.ts.map +1 -0
  120. package/dist/index.js +35 -0
  121. package/dist/index.js.map +1 -0
  122. package/dist/news/guardian.d.ts +51 -0
  123. package/dist/news/guardian.d.ts.map +1 -0
  124. package/dist/news/guardian.js +131 -0
  125. package/dist/news/guardian.js.map +1 -0
  126. package/dist/news/nytimes.d.ts +27 -0
  127. package/dist/news/nytimes.d.ts.map +1 -0
  128. package/dist/news/nytimes.js +104 -0
  129. package/dist/news/nytimes.js.map +1 -0
  130. package/dist/news/site-search-source.d.ts +89 -0
  131. package/dist/news/site-search-source.d.ts.map +1 -0
  132. package/dist/news/site-search-source.js +182 -0
  133. package/dist/news/site-search-source.js.map +1 -0
  134. package/dist/news/sources.d.ts +52 -0
  135. package/dist/news/sources.d.ts.map +1 -0
  136. package/dist/news/sources.js +276 -0
  137. package/dist/news/sources.js.map +1 -0
  138. package/dist/obituary/find-a-grave.d.ts +43 -0
  139. package/dist/obituary/find-a-grave.d.ts.map +1 -0
  140. package/dist/obituary/find-a-grave.js +173 -0
  141. package/dist/obituary/find-a-grave.js.map +1 -0
  142. package/dist/shared/duckduckgo-search.d.ts +86 -0
  143. package/dist/shared/duckduckgo-search.d.ts.map +1 -0
  144. package/dist/shared/duckduckgo-search.js +218 -0
  145. package/dist/shared/duckduckgo-search.js.map +1 -0
  146. package/dist/shared/fetch-page.d.ts +50 -0
  147. package/dist/shared/fetch-page.d.ts.map +1 -0
  148. package/dist/shared/fetch-page.js +212 -0
  149. package/dist/shared/fetch-page.js.map +1 -0
  150. package/dist/shared/html-utils.d.ts +99 -0
  151. package/dist/shared/html-utils.d.ts.map +1 -0
  152. package/dist/shared/html-utils.js +246 -0
  153. package/dist/shared/html-utils.js.map +1 -0
  154. package/dist/shared/readability-extract.d.ts +33 -0
  155. package/dist/shared/readability-extract.d.ts.map +1 -0
  156. package/dist/shared/readability-extract.js +45 -0
  157. package/dist/shared/readability-extract.js.map +1 -0
  158. package/dist/shared/sanitize-text.d.ts +24 -0
  159. package/dist/shared/sanitize-text.d.ts.map +1 -0
  160. package/dist/shared/sanitize-text.js +49 -0
  161. package/dist/shared/sanitize-text.js.map +1 -0
  162. package/dist/shared/search-utils.d.ts +18 -0
  163. package/dist/shared/search-utils.d.ts.map +1 -0
  164. package/dist/shared/search-utils.js +20 -0
  165. package/dist/shared/search-utils.js.map +1 -0
  166. package/dist/structured/wikidata.d.ts +128 -0
  167. package/dist/structured/wikidata.d.ts.map +1 -0
  168. package/dist/structured/wikidata.js +361 -0
  169. package/dist/structured/wikidata.js.map +1 -0
  170. package/dist/structured/wikipedia.d.ts +184 -0
  171. package/dist/structured/wikipedia.d.ts.map +1 -0
  172. package/dist/structured/wikipedia.js +275 -0
  173. package/dist/structured/wikipedia.js.map +1 -0
  174. package/dist/web-search/base.d.ts +128 -0
  175. package/dist/web-search/base.d.ts.map +1 -0
  176. package/dist/web-search/base.js +251 -0
  177. package/dist/web-search/base.js.map +1 -0
  178. package/dist/web-search/bing.d.ts +21 -0
  179. package/dist/web-search/bing.d.ts.map +1 -0
  180. package/dist/web-search/bing.js +53 -0
  181. package/dist/web-search/bing.js.map +1 -0
  182. package/dist/web-search/brave.d.ts +21 -0
  183. package/dist/web-search/brave.d.ts.map +1 -0
  184. package/dist/web-search/brave.js +56 -0
  185. package/dist/web-search/brave.js.map +1 -0
  186. package/dist/web-search/duckduckgo.d.ts +15 -0
  187. package/dist/web-search/duckduckgo.d.ts.map +1 -0
  188. package/dist/web-search/duckduckgo.js +21 -0
  189. package/dist/web-search/duckduckgo.js.map +1 -0
  190. package/dist/web-search/google.d.ts +24 -0
  191. package/dist/web-search/google.d.ts.map +1 -0
  192. package/dist/web-search/google.js +48 -0
  193. package/dist/web-search/google.js.map +1 -0
  194. package/package.json +58 -0
@@ -0,0 +1,251 @@
1
+ /**
2
+ * Abstract base class for web search sources using the template method pattern.
3
+ *
4
+ * Subclasses only implement `performSearch()` — the base class handles the
5
+ * full pipeline: search → score/rank links → fetch pages → extract content →
6
+ * sanitize → combine with attribution.
7
+ *
8
+ * Used by Google, Bing, Brave, and DuckDuckGo search sources.
9
+ */
10
+ import { BaseResearchSource, } from "@debriefer/core";
11
+ import { fetchPage } from "../shared/fetch-page.js";
12
+ import { extractArticleContent } from "../shared/readability-extract.js";
13
+ import { sanitizeSourceText } from "../shared/sanitize-text.js";
14
+ // ============================================================================
15
+ // WebSearchBase
16
+ // ============================================================================
17
+ /**
18
+ * Abstract base class for web search sources.
19
+ *
20
+ * Implements the template method pattern: subclasses provide `performSearch()`
21
+ * and this class handles the rest of the pipeline (scoring, fetching,
22
+ * extracting, sanitizing, combining).
23
+ */
24
+ export class WebSearchBase extends BaseResearchSource {
25
+ maxLinksToFollow;
26
+ minContentLength;
27
+ domainScores;
28
+ boostKeywords;
29
+ penaltyKeywords;
30
+ blockedDomains;
31
+ maxLinkCost;
32
+ linkSelector;
33
+ customFetchPage;
34
+ constructor(options = {}) {
35
+ super(options);
36
+ this.maxLinksToFollow = options.maxLinksToFollow ?? 3;
37
+ this.minContentLength = options.minContentLength ?? 200;
38
+ this.domainScores = options.domainScores ?? {};
39
+ this.boostKeywords = options.boostKeywords ?? [];
40
+ this.penaltyKeywords = options.penaltyKeywords ?? [];
41
+ this.blockedDomains = options.blockedDomains ?? [];
42
+ this.maxLinkCost = options.maxLinkCost;
43
+ this.linkSelector = options.linkSelector;
44
+ this.customFetchPage = options.fetchPage;
45
+ }
46
+ /**
47
+ * Full search pipeline: search → score → fetch → extract → combine.
48
+ *
49
+ * @param subject - The research subject
50
+ * @param signal - Abort signal for cancellation
51
+ * @returns RawFinding with combined text, or null if no content extracted
52
+ */
53
+ async fetchResult(subject, signal) {
54
+ // 1. Build query and perform search
55
+ const query = this.buildQuery(subject);
56
+ const searchResults = await this.performSearch(query, signal);
57
+ if (searchResults.length === 0) {
58
+ return null;
59
+ }
60
+ // 2. Filter blocked domains
61
+ const filtered = searchResults.filter((r) => !this.isDomainBlocked(r.url));
62
+ if (filtered.length === 0) {
63
+ return null;
64
+ }
65
+ // 3. Score & rank links
66
+ const ranked = this.scoreAndRank(filtered);
67
+ // 4. Apply custom link selector if provided, then take top N
68
+ let selectedResults = ranked.map((r) => r.result);
69
+ if (this.linkSelector) {
70
+ selectedResults = await this.linkSelector(selectedResults, subject);
71
+ }
72
+ const linksToFollow = selectedResults.slice(0, this.maxLinksToFollow);
73
+ // 5. Fetch and extract content from each page
74
+ const extractedPages = [];
75
+ let linksAttempted = 0;
76
+ let linkCostUsd = 0;
77
+ for (const result of linksToFollow) {
78
+ if (signal.aborted)
79
+ break;
80
+ if (this.maxLinkCost !== undefined && linkCostUsd >= this.maxLinkCost)
81
+ break;
82
+ linksAttempted++;
83
+ // Use custom fetch if provided, otherwise default pipeline
84
+ if (this.customFetchPage) {
85
+ const text = await this.customFetchPage(result.url, signal);
86
+ if (text && text.length >= this.minContentLength) {
87
+ extractedPages.push({
88
+ url: result.url,
89
+ title: result.title ?? result.url,
90
+ text,
91
+ });
92
+ linkCostUsd += this.estimatedCostPerQuery;
93
+ }
94
+ continue;
95
+ }
96
+ const pageResult = await fetchPage({ url: result.url, signal });
97
+ if (pageResult.fetchMethod === "none" || !pageResult.content) {
98
+ continue;
99
+ }
100
+ // Use the actual fetched URL (may be archive.org URL if fallback was used)
101
+ const actualUrl = pageResult.url || result.url;
102
+ const extracted = extractArticleContent(pageResult.content, actualUrl);
103
+ if (!extracted) {
104
+ continue;
105
+ }
106
+ // 6. Filter by minimum content length
107
+ if (extracted.text.length < this.minContentLength) {
108
+ continue;
109
+ }
110
+ extractedPages.push({
111
+ url: actualUrl,
112
+ title: extracted.title ?? result.title ?? result.url,
113
+ text: extracted.text,
114
+ });
115
+ linkCostUsd += this.estimatedCostPerQuery;
116
+ }
117
+ if (extractedPages.length === 0) {
118
+ return null;
119
+ }
120
+ // 7. Sanitize each page's text
121
+ const sanitizedPages = extractedPages.map((page) => ({
122
+ ...page,
123
+ text: sanitizeSourceText(page.text),
124
+ }));
125
+ // 8. Combine texts with source attribution
126
+ const combinedText = sanitizedPages
127
+ .map((page) => `${page.title}\n${page.text}`)
128
+ .join("\n\n---\n\n");
129
+ // 9. Return RawFinding
130
+ return {
131
+ text: combinedText,
132
+ confidence: -1,
133
+ costUsd: this.estimatedCostPerQuery + linkCostUsd,
134
+ url: extractedPages[0].url,
135
+ metadata: {
136
+ searchEngine: this.name,
137
+ linksFollowed: linksAttempted,
138
+ pagesExtracted: extractedPages.length,
139
+ urls: extractedPages.map((p) => p.url),
140
+ },
141
+ };
142
+ }
143
+ /**
144
+ * Score and rank search results by relevance.
145
+ *
146
+ * Scoring:
147
+ * - Base: 50 - index (preserves search engine ordering)
148
+ * - + domainScores[domain] if hostname matches
149
+ * - + boost for each boostKeyword found in title+snippet
150
+ * - - penalty for each penaltyKeyword found in title+snippet
151
+ */
152
+ scoreAndRank(results) {
153
+ const scored = results.map((result, index) => {
154
+ let score = 50 - index;
155
+ // Domain score bonus
156
+ let hostname = null;
157
+ try {
158
+ hostname = new URL(result.url).hostname;
159
+ }
160
+ catch {
161
+ // Invalid URL — skip domain scoring
162
+ }
163
+ for (const [domain, domainScore] of Object.entries(this.domainScores)) {
164
+ if (!hostname)
165
+ break;
166
+ if (this.hostnameMatchesDomain(hostname, domain)) {
167
+ score += domainScore;
168
+ break;
169
+ }
170
+ }
171
+ // Boost keywords
172
+ const combined = `${result.title} ${result.snippet}`.toLowerCase();
173
+ for (const { keyword, boost } of this.boostKeywords) {
174
+ if (combined.includes(keyword.toLowerCase())) {
175
+ score += boost;
176
+ }
177
+ }
178
+ // Penalty keywords
179
+ for (const { keyword, penalty } of this.penaltyKeywords) {
180
+ if (combined.includes(keyword.toLowerCase())) {
181
+ score -= penalty;
182
+ }
183
+ }
184
+ return { result, score };
185
+ });
186
+ // Sort by score descending
187
+ scored.sort((a, b) => b.score - a.score);
188
+ return scored;
189
+ }
190
+ /**
191
+ * Check whether a URL should be excluded (blocked domain or unsafe URL).
192
+ * Blocks: non-http(s) schemes, localhost, private IP ranges, and user-specified domains.
193
+ */
194
+ isDomainBlocked(url) {
195
+ let parsed;
196
+ try {
197
+ parsed = new URL(url);
198
+ }
199
+ catch {
200
+ return true; // Unparseable URLs are blocked
201
+ }
202
+ // Only allow http and https
203
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
204
+ return true;
205
+ }
206
+ // Block localhost, private IPs, and link-local addresses (SSRF prevention)
207
+ // Normalize IPv4-mapped IPv6 (e.g., ::ffff:127.0.0.1) to plain IPv4
208
+ let hostname = parsed.hostname;
209
+ const mappedMatch = /^::ffff:(\d+\.\d+\.\d+\.\d+)$/i.exec(hostname);
210
+ if (mappedMatch) {
211
+ hostname = mappedMatch[1];
212
+ }
213
+ if (hostname === "localhost" ||
214
+ hostname.startsWith("127.") || // 127.0.0.0/8 loopback
215
+ hostname === "::1" || // IPv6 loopback
216
+ hostname === "[::1]" || // IPv6 loopback (bracketed form)
217
+ hostname.startsWith("10.") || // RFC 1918
218
+ hostname.startsWith("192.168.") || // RFC 1918
219
+ hostname.startsWith("169.254.") || // Link-local / cloud metadata (169.254.169.254)
220
+ hostname === "0.0.0.0" ||
221
+ hostname.endsWith(".local") ||
222
+ (hostname.includes(":") && hostname.startsWith("fc")) || // IPv6 unique local (fc00::/7)
223
+ (hostname.includes(":") && hostname.startsWith("fd")) || // IPv6 unique local (fc00::/7)
224
+ (hostname.includes(":") && hostname.startsWith("fe80")) || // IPv6 link-local (fe80::/10)
225
+ this.isPrivate172(hostname)) {
226
+ return true;
227
+ }
228
+ return this.blockedDomains.some((domain) => this.hostnameMatchesDomain(hostname, domain));
229
+ }
230
+ /**
231
+ * Check if a hostname matches a domain (exact or subdomain match).
232
+ * Normalizes domain to lowercase since URL.hostname is always lowercase.
233
+ *
234
+ * "www.example.com" matches "example.com"
235
+ * "sub.example.com" matches "example.com"
236
+ * "example.com" matches "example.com"
237
+ * "notexample.com" does NOT match "example.com"
238
+ */
239
+ hostnameMatchesDomain(hostname, domain) {
240
+ const d = domain.toLowerCase();
241
+ return hostname === d || hostname.endsWith("." + d);
242
+ }
243
+ /** Check if hostname is in the 172.16.0.0–172.31.255.255 private range (RFC 1918). */
244
+ isPrivate172(hostname) {
245
+ if (!hostname.startsWith("172."))
246
+ return false;
247
+ const secondOctet = parseInt(hostname.split(".")[1], 10);
248
+ return secondOctet >= 16 && secondOctet <= 31;
249
+ }
250
+ }
251
+ //# sourceMappingURL=base.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.js","sourceRoot":"","sources":["../../src/web-search/base.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import { ReliabilityTier } from "@debriefer/core";
2
+ import { WebSearchBase, type WebSearchOptions, type WebSearchResult } from "./base.js";
3
+ export interface BingSearchOptions extends WebSearchOptions {
4
+ apiKey?: string;
5
+ maxResults?: number;
6
+ }
7
+ export declare class BingSearchSource extends WebSearchBase {
8
+ readonly name = "Bing Search";
9
+ readonly type = "bing-search";
10
+ readonly reliabilityTier = ReliabilityTier.SEARCH_AGGREGATOR;
11
+ readonly domain = "api.bing.microsoft.com";
12
+ readonly isFree = false;
13
+ readonly estimatedCostPerQuery = 0.003;
14
+ private apiKey;
15
+ private maxResults;
16
+ constructor(options?: BingSearchOptions);
17
+ isAvailable(): boolean;
18
+ protected performSearch(query: string, signal: AbortSignal): Promise<WebSearchResult[]>;
19
+ }
20
+ export declare function bingSearch(options?: BingSearchOptions): BingSearchSource;
21
+ //# sourceMappingURL=bing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bing.d.ts","sourceRoot":"","sources":["../../src/web-search/bing.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AACjD,OAAO,EAAE,aAAa,EAAE,KAAK,gBAAgB,EAAE,KAAK,eAAe,EAAE,MAAM,WAAW,CAAA;AAItF,MAAM,WAAW,iBAAkB,SAAQ,gBAAgB;IACzD,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,qBAAa,gBAAiB,SAAQ,aAAa;IACjD,QAAQ,CAAC,IAAI,iBAAgB;IAC7B,QAAQ,CAAC,IAAI,iBAAgB;IAC7B,QAAQ,CAAC,eAAe,qCAAoC;IAC5D,QAAQ,CAAC,MAAM,4BAA2B;IAC1C,QAAQ,CAAC,MAAM,SAAQ;IACvB,QAAQ,CAAC,qBAAqB,SAAQ;IAEtC,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,UAAU,CAAQ;gBAEd,OAAO,GAAE,iBAAsB;IAMlC,WAAW,IAAI,OAAO;cAIf,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;CAoC9F;AAED,wBAAgB,UAAU,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,gBAAgB,CAExE"}
@@ -0,0 +1,53 @@
1
+ import { ReliabilityTier } from "@debriefer/core";
2
+ import { WebSearchBase } from "./base.js";
3
+ const BING_SEARCH_URL = "https://api.bing.microsoft.com/v7.0/search";
4
+ export class BingSearchSource extends WebSearchBase {
5
+ name = "Bing Search";
6
+ type = "bing-search";
7
+ reliabilityTier = ReliabilityTier.SEARCH_AGGREGATOR;
8
+ domain = "api.bing.microsoft.com";
9
+ isFree = false;
10
+ estimatedCostPerQuery = 0.003;
11
+ apiKey;
12
+ maxResults;
13
+ constructor(options = {}) {
14
+ super({ rateLimitMs: 500, ...options });
15
+ this.apiKey = options.apiKey ?? process.env.BING_SEARCH_API_KEY;
16
+ this.maxResults = options.maxResults ?? 20;
17
+ }
18
+ isAvailable() {
19
+ return Boolean(this.apiKey);
20
+ }
21
+ async performSearch(query, signal) {
22
+ if (!this.apiKey)
23
+ return [];
24
+ const url = `${BING_SEARCH_URL}?q=${encodeURIComponent(query)}&count=${this.maxResults}&mkt=en-US&responseFilter=Webpages,News`;
25
+ const response = await fetch(url, {
26
+ headers: { "Ocp-Apim-Subscription-Key": this.apiKey },
27
+ signal,
28
+ });
29
+ if (!response.ok) {
30
+ throw new Error(`Bing Search error: HTTP ${response.status} ${response.statusText}`);
31
+ }
32
+ const data = (await response.json());
33
+ const results = [];
34
+ const seenUrls = new Set();
35
+ for (const item of data.webPages?.value ?? []) {
36
+ if (seenUrls.has(item.url))
37
+ continue;
38
+ seenUrls.add(item.url);
39
+ results.push({ url: item.url, title: item.name, snippet: item.snippet });
40
+ }
41
+ for (const item of data.news?.value ?? []) {
42
+ if (seenUrls.has(item.url))
43
+ continue;
44
+ seenUrls.add(item.url);
45
+ results.push({ url: item.url, title: item.name, snippet: item.description });
46
+ }
47
+ return results;
48
+ }
49
+ }
50
+ export function bingSearch(options) {
51
+ return new BingSearchSource(options);
52
+ }
53
+ //# sourceMappingURL=bing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bing.js","sourceRoot":"","sources":["../../src/web-search/bing.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AACjD,OAAO,EAAE,aAAa,EAA+C,MAAM,WAAW,CAAA;AAEtF,MAAM,eAAe,GAAG,4CAA4C,CAAA;AAOpE,MAAM,OAAO,gBAAiB,SAAQ,aAAa;IACxC,IAAI,GAAG,aAAa,CAAA;IACpB,IAAI,GAAG,aAAa,CAAA;IACpB,eAAe,GAAG,eAAe,CAAC,iBAAiB,CAAA;IACnD,MAAM,GAAG,wBAAwB,CAAA;IACjC,MAAM,GAAG,KAAK,CAAA;IACd,qBAAqB,GAAG,KAAK,CAAA;IAE9B,MAAM,CAAoB;IAC1B,UAAU,CAAQ;IAE1B,YAAY,UAA6B,EAAE;QACzC,KAAK,CAAC,EAAE,WAAW,EAAE,GAAG,EAAE,GAAG,OAAO,EAAE,CAAC,CAAA;QACvC,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAA;QAC/D,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,EAAE,CAAA;IAC5C,CAAC;IAEQ,WAAW;QAClB,OAAO,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IAC7B,CAAC;IAES,KAAK,CAAC,aAAa,CAAC,KAAa,EAAE,MAAmB;QAC9D,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,OAAO,EAAE,CAAA;QAE3B,MAAM,GAAG,GAAG,GAAG,eAAe,MAAM,kBAAkB,CAAC,KAAK,CAAC,UAAU,IAAI,CAAC,UAAU,yCAAyC,CAAA;QAE/H,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAChC,OAAO,EAAE,EAAE,2BAA2B,EAAE,IAAI,CAAC,MAAM,EAAE;YACrD,MAAM;SACP,CAAC,CAAA;QAEF,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,2BAA2B,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAA;QACtF,CAAC;QAED,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAGlC,CAAA;QAED,MAAM,OAAO,GAAsB,EAAE,CAAA;QACrC,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAA;QAElC,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,QAAQ,EAAE,KAAK,IAAI,EAAE,EAAE,CAAC;YAC9C,IAAI,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC;gBAAE,SAAQ;YACpC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;YACtB,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAA;QAC1E,CAAC;QAED,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,IAAI,EAAE,EAAE,CAAC;YAC1C,IAAI,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC;gBAAE,SAAQ;YACpC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;YACtB,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC,CAAA;QAC9E,CAAC;QAED,OAAO,OAAO,CAAA;IAChB,CAAC;CACF;AAED,MAAM,UAAU,UAAU,CAAC,OAA2B;IACpD,OAAO,IAAI,gBAAgB,CAAC,OAAO,CAAC,CAAA;AACtC,CAAC"}
@@ -0,0 +1,21 @@
1
+ import { ReliabilityTier } from "@debriefer/core";
2
+ import { WebSearchBase, type WebSearchOptions, type WebSearchResult } from "./base.js";
3
+ export interface BraveSearchOptions extends WebSearchOptions {
4
+ apiKey?: string;
5
+ maxResults?: number;
6
+ }
7
+ export declare class BraveSearchSource extends WebSearchBase {
8
+ readonly name = "Brave Search";
9
+ readonly type = "brave-search";
10
+ readonly reliabilityTier = ReliabilityTier.SEARCH_AGGREGATOR;
11
+ readonly domain = "api.search.brave.com";
12
+ readonly isFree = false;
13
+ readonly estimatedCostPerQuery = 0.005;
14
+ private apiKey;
15
+ private maxResults;
16
+ constructor(options?: BraveSearchOptions);
17
+ isAvailable(): boolean;
18
+ protected performSearch(query: string, signal: AbortSignal): Promise<WebSearchResult[]>;
19
+ }
20
+ export declare function braveSearch(options?: BraveSearchOptions): BraveSearchSource;
21
+ //# sourceMappingURL=brave.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"brave.d.ts","sourceRoot":"","sources":["../../src/web-search/brave.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AACjD,OAAO,EAAE,aAAa,EAAE,KAAK,gBAAgB,EAAE,KAAK,eAAe,EAAE,MAAM,WAAW,CAAA;AAItF,MAAM,WAAW,kBAAmB,SAAQ,gBAAgB;IAC1D,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,qBAAa,iBAAkB,SAAQ,aAAa;IAClD,QAAQ,CAAC,IAAI,kBAAiB;IAC9B,QAAQ,CAAC,IAAI,kBAAiB;IAC9B,QAAQ,CAAC,eAAe,qCAAoC;IAC5D,QAAQ,CAAC,MAAM,0BAAyB;IACxC,QAAQ,CAAC,MAAM,SAAQ;IACvB,QAAQ,CAAC,qBAAqB,SAAQ;IAEtC,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,UAAU,CAAQ;gBAEd,OAAO,GAAE,kBAAuB;IAMnC,WAAW,IAAI,OAAO;cAIf,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;CAuC9F;AAED,wBAAgB,WAAW,CAAC,OAAO,CAAC,EAAE,kBAAkB,GAAG,iBAAiB,CAE3E"}
@@ -0,0 +1,56 @@
1
+ import { ReliabilityTier } from "@debriefer/core";
2
+ import { WebSearchBase } from "./base.js";
3
+ const BRAVE_SEARCH_URL = "https://api.search.brave.com/res/v1/web/search";
4
+ export class BraveSearchSource extends WebSearchBase {
5
+ name = "Brave Search";
6
+ type = "brave-search";
7
+ reliabilityTier = ReliabilityTier.SEARCH_AGGREGATOR;
8
+ domain = "api.search.brave.com";
9
+ isFree = false;
10
+ estimatedCostPerQuery = 0.005;
11
+ apiKey;
12
+ maxResults;
13
+ constructor(options = {}) {
14
+ super({ rateLimitMs: 500, ...options });
15
+ this.apiKey = options.apiKey ?? process.env.BRAVE_SEARCH_API_KEY;
16
+ this.maxResults = options.maxResults ?? 20;
17
+ }
18
+ isAvailable() {
19
+ return Boolean(this.apiKey);
20
+ }
21
+ async performSearch(query, signal) {
22
+ if (!this.apiKey)
23
+ return [];
24
+ const url = `${BRAVE_SEARCH_URL}?q=${encodeURIComponent(query)}&count=${this.maxResults}&search_lang=en`;
25
+ const response = await fetch(url, {
26
+ headers: {
27
+ "X-Subscription-Token": this.apiKey,
28
+ Accept: "application/json",
29
+ },
30
+ signal,
31
+ });
32
+ if (!response.ok) {
33
+ throw new Error(`Brave Search error: HTTP ${response.status} ${response.statusText}`);
34
+ }
35
+ const data = (await response.json());
36
+ const results = [];
37
+ const seenUrls = new Set();
38
+ for (const item of data.web?.results ?? []) {
39
+ if (seenUrls.has(item.url))
40
+ continue;
41
+ seenUrls.add(item.url);
42
+ results.push({ url: item.url, title: item.title, snippet: item.description });
43
+ }
44
+ for (const item of data.news?.results ?? []) {
45
+ if (seenUrls.has(item.url))
46
+ continue;
47
+ seenUrls.add(item.url);
48
+ results.push({ url: item.url, title: item.title, snippet: item.description });
49
+ }
50
+ return results;
51
+ }
52
+ }
53
+ export function braveSearch(options) {
54
+ return new BraveSearchSource(options);
55
+ }
56
+ //# sourceMappingURL=brave.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"brave.js","sourceRoot":"","sources":["../../src/web-search/brave.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import { ReliabilityTier } from "@debriefer/core";
2
+ import { WebSearchBase, type WebSearchOptions, type WebSearchResult } from "./base.js";
3
+ export type DuckDuckGoSourceOptions = WebSearchOptions;
4
+ export declare class DuckDuckGoSearchSource extends WebSearchBase {
5
+ readonly name = "DuckDuckGo";
6
+ readonly type = "duckduckgo-search";
7
+ readonly reliabilityTier = ReliabilityTier.SEARCH_AGGREGATOR;
8
+ readonly domain = "html.duckduckgo.com";
9
+ readonly isFree = true;
10
+ readonly estimatedCostPerQuery = 0;
11
+ constructor(options?: DuckDuckGoSourceOptions);
12
+ protected performSearch(query: string, signal: AbortSignal): Promise<WebSearchResult[]>;
13
+ }
14
+ export declare function duckduckgoSearch(options?: DuckDuckGoSourceOptions): DuckDuckGoSearchSource;
15
+ //# sourceMappingURL=duckduckgo.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"duckduckgo.d.ts","sourceRoot":"","sources":["../../src/web-search/duckduckgo.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AACjD,OAAO,EAAE,aAAa,EAAE,KAAK,gBAAgB,EAAE,KAAK,eAAe,EAAE,MAAM,WAAW,CAAA;AAGtF,MAAM,MAAM,uBAAuB,GAAG,gBAAgB,CAAA;AAEtD,qBAAa,sBAAuB,SAAQ,aAAa;IACvD,QAAQ,CAAC,IAAI,gBAAe;IAC5B,QAAQ,CAAC,IAAI,uBAAsB;IACnC,QAAQ,CAAC,eAAe,qCAAoC;IAC5D,QAAQ,CAAC,MAAM,yBAAwB;IACvC,QAAQ,CAAC,MAAM,QAAO;IACtB,QAAQ,CAAC,qBAAqB,KAAI;gBAEtB,OAAO,GAAE,uBAA4B;cAIjC,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;CAG9F;AAED,wBAAgB,gBAAgB,CAAC,OAAO,CAAC,EAAE,uBAAuB,GAAG,sBAAsB,CAE1F"}
@@ -0,0 +1,21 @@
1
+ import { ReliabilityTier } from "@debriefer/core";
2
+ import { WebSearchBase } from "./base.js";
3
+ import { searchDuckDuckGo } from "../shared/duckduckgo-search.js";
4
+ export class DuckDuckGoSearchSource extends WebSearchBase {
5
+ name = "DuckDuckGo";
6
+ type = "duckduckgo-search";
7
+ reliabilityTier = ReliabilityTier.SEARCH_AGGREGATOR;
8
+ domain = "html.duckduckgo.com";
9
+ isFree = true;
10
+ estimatedCostPerQuery = 0;
11
+ constructor(options = {}) {
12
+ super({ rateLimitMs: 1000, ...options });
13
+ }
14
+ async performSearch(query, signal) {
15
+ return searchDuckDuckGo({ query, signal });
16
+ }
17
+ }
18
+ export function duckduckgoSearch(options) {
19
+ return new DuckDuckGoSearchSource(options);
20
+ }
21
+ //# sourceMappingURL=duckduckgo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"duckduckgo.js","sourceRoot":"","sources":["../../src/web-search/duckduckgo.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AACjD,OAAO,EAAE,aAAa,EAA+C,MAAM,WAAW,CAAA;AACtF,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAA;AAIjE,MAAM,OAAO,sBAAuB,SAAQ,aAAa;IAC9C,IAAI,GAAG,YAAY,CAAA;IACnB,IAAI,GAAG,mBAAmB,CAAA;IAC1B,eAAe,GAAG,eAAe,CAAC,iBAAiB,CAAA;IACnD,MAAM,GAAG,qBAAqB,CAAA;IAC9B,MAAM,GAAG,IAAI,CAAA;IACb,qBAAqB,GAAG,CAAC,CAAA;IAElC,YAAY,UAAmC,EAAE;QAC/C,KAAK,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,GAAG,OAAO,EAAE,CAAC,CAAA;IAC1C,CAAC;IAES,KAAK,CAAC,aAAa,CAAC,KAAa,EAAE,MAAmB;QAC9D,OAAO,gBAAgB,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAA;IAC5C,CAAC;CACF;AAED,MAAM,UAAU,gBAAgB,CAAC,OAAiC;IAChE,OAAO,IAAI,sBAAsB,CAAC,OAAO,CAAC,CAAA;AAC5C,CAAC"}
@@ -0,0 +1,24 @@
1
+ import { ReliabilityTier } from "@debriefer/core";
2
+ import { WebSearchBase, type WebSearchOptions, type WebSearchResult } from "./base.js";
3
+ export interface GoogleSearchOptions extends WebSearchOptions {
4
+ apiKey?: string;
5
+ cx?: string;
6
+ /** Number of results (1–10, Google CSE limit). Default: 10. */
7
+ maxResults?: number;
8
+ }
9
+ export declare class GoogleSearchSource extends WebSearchBase {
10
+ readonly name = "Google Search";
11
+ readonly type = "google-search";
12
+ readonly reliabilityTier = ReliabilityTier.SEARCH_AGGREGATOR;
13
+ readonly domain = "www.googleapis.com";
14
+ readonly isFree = false;
15
+ readonly estimatedCostPerQuery = 0.005;
16
+ private apiKey;
17
+ private cx;
18
+ private maxResults;
19
+ constructor(options?: GoogleSearchOptions);
20
+ isAvailable(): boolean;
21
+ protected performSearch(query: string, signal: AbortSignal): Promise<WebSearchResult[]>;
22
+ }
23
+ export declare function googleSearch(options?: GoogleSearchOptions): GoogleSearchSource;
24
+ //# sourceMappingURL=google.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"google.d.ts","sourceRoot":"","sources":["../../src/web-search/google.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AACjD,OAAO,EAAE,aAAa,EAAE,KAAK,gBAAgB,EAAE,KAAK,eAAe,EAAE,MAAM,WAAW,CAAA;AAItF,MAAM,WAAW,mBAAoB,SAAQ,gBAAgB;IAC3D,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,+DAA+D;IAC/D,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,qBAAa,kBAAmB,SAAQ,aAAa;IACnD,QAAQ,CAAC,IAAI,mBAAkB;IAC/B,QAAQ,CAAC,IAAI,mBAAkB;IAC/B,QAAQ,CAAC,eAAe,qCAAoC;IAC5D,QAAQ,CAAC,MAAM,wBAAuB;IACtC,QAAQ,CAAC,MAAM,SAAQ;IACvB,QAAQ,CAAC,qBAAqB,SAAQ;IAEtC,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,EAAE,CAAoB;IAC9B,OAAO,CAAC,UAAU,CAAQ;gBAEd,OAAO,GAAE,mBAAwB;IAOpC,WAAW,IAAI,OAAO;cAIf,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;CA2B9F;AAED,wBAAgB,YAAY,CAAC,OAAO,CAAC,EAAE,mBAAmB,GAAG,kBAAkB,CAE9E"}
@@ -0,0 +1,48 @@
1
+ import { ReliabilityTier } from "@debriefer/core";
2
+ import { WebSearchBase } from "./base.js";
3
+ const GOOGLE_CSE_URL = "https://www.googleapis.com/customsearch/v1";
4
+ export class GoogleSearchSource extends WebSearchBase {
5
+ name = "Google Search";
6
+ type = "google-search";
7
+ reliabilityTier = ReliabilityTier.SEARCH_AGGREGATOR;
8
+ domain = "www.googleapis.com";
9
+ isFree = false;
10
+ estimatedCostPerQuery = 0.005;
11
+ apiKey;
12
+ cx;
13
+ maxResults;
14
+ constructor(options = {}) {
15
+ super({ rateLimitMs: 500, ...options });
16
+ this.apiKey = options.apiKey ?? process.env.GOOGLE_SEARCH_API_KEY;
17
+ this.cx = options.cx ?? process.env.GOOGLE_SEARCH_CX;
18
+ this.maxResults = Math.min(Math.max(options.maxResults ?? 10, 1), 10);
19
+ }
20
+ isAvailable() {
21
+ return Boolean(this.apiKey && this.cx);
22
+ }
23
+ async performSearch(query, signal) {
24
+ if (!this.apiKey || !this.cx)
25
+ return [];
26
+ const url = new URL(GOOGLE_CSE_URL);
27
+ url.searchParams.set("key", this.apiKey);
28
+ url.searchParams.set("cx", this.cx);
29
+ url.searchParams.set("q", query);
30
+ url.searchParams.set("num", String(this.maxResults));
31
+ const response = await fetch(url.toString(), { signal });
32
+ if (!response.ok) {
33
+ throw new Error(`Google CSE error: HTTP ${response.status} ${response.statusText}`);
34
+ }
35
+ const data = (await response.json());
36
+ if (!data.items || data.items.length === 0)
37
+ return [];
38
+ return data.items.map((item) => ({
39
+ url: item.link,
40
+ title: item.title,
41
+ snippet: item.snippet,
42
+ }));
43
+ }
44
+ }
45
+ export function googleSearch(options) {
46
+ return new GoogleSearchSource(options);
47
+ }
48
+ //# sourceMappingURL=google.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"google.js","sourceRoot":"","sources":["../../src/web-search/google.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AACjD,OAAO,EAAE,aAAa,EAA+C,MAAM,WAAW,CAAA;AAEtF,MAAM,cAAc,GAAG,4CAA4C,CAAA;AASnE,MAAM,OAAO,kBAAmB,SAAQ,aAAa;IAC1C,IAAI,GAAG,eAAe,CAAA;IACtB,IAAI,GAAG,eAAe,CAAA;IACtB,eAAe,GAAG,eAAe,CAAC,iBAAiB,CAAA;IACnD,MAAM,GAAG,oBAAoB,CAAA;IAC7B,MAAM,GAAG,KAAK,CAAA;IACd,qBAAqB,GAAG,KAAK,CAAA;IAE9B,MAAM,CAAoB;IAC1B,EAAE,CAAoB;IACtB,UAAU,CAAQ;IAE1B,YAAY,UAA+B,EAAE;QAC3C,KAAK,CAAC,EAAE,WAAW,EAAE,GAAG,EAAE,GAAG,OAAO,EAAE,CAAC,CAAA;QACvC,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAA;QACjE,IAAI,CAAC,EAAE,GAAG,OAAO,CAAC,EAAE,IAAI,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAA;QACpD,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;IACvE,CAAC;IAEQ,WAAW;QAClB,OAAO,OAAO,CAAC,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,EAAE,CAAC,CAAA;IACxC,CAAC;IAES,KAAK,CAAC,aAAa,CAAC,KAAa,EAAE,MAAmB;QAC9D,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,EAAE;YAAE,OAAO,EAAE,CAAA;QAEvC,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,cAAc,CAAC,CAAA;QACnC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,CAAA;QACxC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC,CAAA;QACnC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;QAChC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAA;QAEpD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAA;QAExD,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,0BAA0B,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAA;QACrF,CAAC;QAED,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAElC,CAAA;QAED,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,CAAA;QAErD,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YAC/B,GAAG,EAAE,IAAI,CAAC,IAAI;YACd,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,OAAO,EAAE,IAAI,CAAC,OAAO;SACtB,CAAC,CAAC,CAAA;IACL,CAAC;CACF;AAED,MAAM,UAAU,YAAY,CAAC,OAA6B;IACxD,OAAO,IAAI,kBAAkB,CAAC,OAAO,CAAC,CAAA;AACxC,CAAC"}
package/package.json ADDED
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "@debriefer/sources",
3
+ "version": "1.0.1",
4
+ "description": "Built-in research sources for debriefer: Wikipedia, Wikidata, web search, news, archives, and more",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist"
16
+ ],
17
+ "scripts": {
18
+ "build": "tsc",
19
+ "test": "vitest run --passWithNoTests",
20
+ "lint": "eslint src/",
21
+ "type-check": "tsc --noEmit"
22
+ },
23
+ "keywords": [
24
+ "research",
25
+ "wikipedia",
26
+ "wikidata",
27
+ "web-scraping",
28
+ "news",
29
+ "archives",
30
+ "debriefer"
31
+ ],
32
+ "author": "Chris Henderson",
33
+ "license": "MIT",
34
+ "repository": {
35
+ "type": "git",
36
+ "url": "https://github.com/chenders/debriefer.git",
37
+ "directory": "packages/sources"
38
+ },
39
+ "homepage": "https://github.com/chenders/debriefer#readme",
40
+ "bugs": {
41
+ "url": "https://github.com/chenders/debriefer/issues"
42
+ },
43
+ "dependencies": {
44
+ "@mozilla/readability": "^0.6",
45
+ "@debriefer/core": ">=1.0.0",
46
+ "he": "^1",
47
+ "jsdom": "^28",
48
+ "wtf_wikipedia": "^10"
49
+ },
50
+ "optionalDependencies": {
51
+ "fingerprint-injector": "^2",
52
+ "playwright-core": "^1.50"
53
+ },
54
+ "devDependencies": {
55
+ "@types/he": "^1.2.3",
56
+ "@types/jsdom": "^28.0.0"
57
+ }
58
+ }