Spaces:
Paused
Paused
Download src/lib/web-search.ts from WaveCut/Bonsai-Chat-WebGPU: direct link, hf CLI and curl.
- Browser
- Download file 2.87 kB
-
https://huggingface.co/spaces/WaveCut/Bonsai-Chat-WebGPU/resolve/main/src/lib/web-search.ts
- Command line
-
hf download hf://spaces/WaveCut/Bonsai-Chat-WebGPU/src/lib/web-search.ts
-
curl -L -o web-search.ts https://huggingface.co/spaces/WaveCut/Bonsai-Chat-WebGPU/resolve/main/src/lib/web-search.ts
2.87 kB
| export interface WebSearchResult { | |
| title: string; | |
| snippet: string; | |
| url: string; | |
| updatedAt?: string; | |
| } | |
| export interface WebSearchResponse { | |
| provider: 'wikipedia'; | |
| query: string; | |
| language: 'en' | 'ru'; | |
| results: WebSearchResult[]; | |
| } | |
| function plainText(value: unknown): string { | |
| return String(value ?? '') | |
| .replace(/<[^>]*>/gu, '') | |
| .replaceAll('"', '"') | |
| .replaceAll(''', "'") | |
| .replaceAll('&', '&') | |
| .replaceAll('<', '<') | |
| .replaceAll('>', '>') | |
| .replace(/\s+/gu, ' ') | |
| .trim() | |
| .slice(0, 1200); | |
| } | |
| export async function searchWikipedia( | |
| query: string, | |
| requestedLanguage?: string, | |
| requestedLimit?: number, | |
| signal?: AbortSignal, | |
| fetchImpl: typeof fetch = fetch, | |
| ): Promise<WebSearchResponse> { | |
| const normalizedQuery = query.trim().slice(0, 500); | |
| if (!normalizedQuery) throw new Error('web_search.query must be a non-empty string'); | |
| const language: 'en' | 'ru' = requestedLanguage === 'ru' | |
| || (requestedLanguage !== 'en' && /\p{Script=Cyrillic}/u.test(normalizedQuery)) | |
| ? 'ru' | |
| : 'en'; | |
| const limit = Math.min(8, Math.max(1, Math.round(requestedLimit ?? 5))); | |
| const params = new URLSearchParams({ | |
| action: 'query', | |
| list: 'search', | |
| srsearch: normalizedQuery, | |
| srlimit: String(limit), | |
| srprop: 'snippet|timestamp', | |
| format: 'json', | |
| formatversion: '2', | |
| origin: '*', | |
| }); | |
| const controller = new AbortController(); | |
| const abort = () => controller.abort(signal?.reason); | |
| signal?.addEventListener('abort', abort, { once: true }); | |
| const timer = setTimeout(() => controller.abort(new DOMException('web_search timed out', 'TimeoutError')), 8000); | |
| try { | |
| const response = await fetchImpl(`https://${language}.wikipedia.org/w/api.php?${params}`, { | |
| method: 'GET', | |
| credentials: 'omit', | |
| referrerPolicy: 'no-referrer', | |
| signal: controller.signal, | |
| }); | |
| if (!response.ok) throw new Error(`web_search provider returned HTTP ${response.status}`); | |
| const payload = await response.json() as { | |
| query?: { search?: Array<{ title?: unknown; snippet?: unknown; timestamp?: unknown }> }; | |
| error?: { info?: unknown }; | |
| }; | |
| if (payload.error) throw new Error(`web_search provider error: ${String(payload.error.info ?? 'unknown error')}`); | |
| const results = (payload.query?.search ?? []).slice(0, limit).map((item) => { | |
| const title = plainText(item.title); | |
| return { | |
| title, | |
| snippet: plainText(item.snippet), | |
| url: `https://${language}.wikipedia.org/wiki/${encodeURIComponent(title.replaceAll(' ', '_'))}`, | |
| ...(typeof item.timestamp === 'string' ? { updatedAt: item.timestamp } : {}), | |
| }; | |
| }); | |
| return { provider: 'wikipedia', query: normalizedQuery, language, results }; | |
| } finally { | |
| clearTimeout(timer); | |
| signal?.removeEventListener('abort', abort); | |
| } | |
| } | |