* fix: WebSearch providers + MCPTool bugs WebSearchTool: - custom.ts: fix buildAuthHeadersForPreset WEB_AUTH_HEADER opt-out - custom.ts: fix WEB_AUTH_SCHEME empty string handling - custom.ts: fix walkJsonPath null safety for jsonPath parsing - duckduckgo.ts: use SafeSearchType enum instead of raw 0 - mojeek.ts: always send Accept: application/json header - README: fix timeout documentation (15s -> 120s to match code) - custom.test.ts: add tests for auth header behavior MCPTool: - MCPTool.ts: fix outputSchema to accept ContentBlockParam[] (not just string) - MCPTool.ts: fix isResultTruncated for array output (iterates text blocks) * fix: address PR #593 review feedback 1. Export buildAuthHeadersForPreset and add direct tests for: - WEB_AUTH_HEADER="" explicit opt-out behavior - WEB_AUTH_SCHEME="" stripping scheme prefix - Preset defaults (authHeader + authScheme) - No WEB_KEY returns empty headers 2. Add duckduckgo.test.ts verifying SafeSearchType.STRICT === 0, confirming the enum change is semantically identical to the previous raw value. Addresses review by @Vasanthdev2004 at pullrequestreview-4093533095 --------- Co-authored-by: FluxLuFFy <flux@openclaude.dev> Co-authored-by: Fix Bot <fix@openclaude.local>
54 lines
1.5 KiB
TypeScript
54 lines
1.5 KiB
TypeScript
/**
|
|
* Mojeek Search API adapter.
|
|
* GET https://www.mojeek.com/search?q=...&fmt=json
|
|
* Auth: optional Bearer for API tier
|
|
*/
|
|
|
|
import type { SearchInput, SearchProvider } from './types.js'
|
|
import { applyDomainFilters, safeHostname, type ProviderOutput } from './types.js'
|
|
|
|
export const mojeekProvider: SearchProvider = {
|
|
name: 'mojeek',
|
|
|
|
isConfigured() {
|
|
return Boolean(process.env.MOJEEK_API_KEY)
|
|
},
|
|
|
|
async search(input: SearchInput, signal?: AbortSignal): Promise<ProviderOutput> {
|
|
const start = performance.now()
|
|
|
|
const url = new URL('https://www.mojeek.com/search')
|
|
url.searchParams.set('q', input.query)
|
|
url.searchParams.set('fmt', 'json')
|
|
|
|
const headers: Record<string, string> = {
|
|
'Accept': 'application/json',
|
|
}
|
|
if (process.env.MOJEEK_API_KEY) {
|
|
headers['Authorization'] = `Bearer ${process.env.MOJEEK_API_KEY}`
|
|
}
|
|
|
|
const res = await fetch(url.toString(), { headers, signal })
|
|
|
|
if (!res.ok) {
|
|
throw new Error(`Mojeek search error ${res.status}: ${await res.text().catch(() => '')}`)
|
|
}
|
|
|
|
const data = await res.json()
|
|
const rawResults = data?.response?.results ?? data?.results ?? []
|
|
|
|
const hits = rawResults.map((r: any) => ({
|
|
title: r.title ?? '',
|
|
url: r.url ?? '',
|
|
description: r.snippet ?? r.desc,
|
|
source: r.url ? safeHostname(r.url) : undefined,
|
|
}))
|
|
|
|
return {
|
|
hits: applyDomainFilters(hits, input),
|
|
providerName: 'mojeek',
|
|
durationSeconds: (performance.now() - start) / 1000,
|
|
}
|
|
},
|
|
}
|