* Build the fallback chain. If the primary backend fails or returns nothing, * we try the others in order. Order: primary first, then any backend whose * auth (if needed) is satisfied via environment variable. * * Why auto-fallback: real users hit network blocks (DDG from Iran, etc) and * havin
(primaryName: string | undefined)
| 42 | * retries against the same blocked endpoint. |
| 43 | */ |
| 44 | function buildFallbackChain(primaryName: string | undefined): WebSearchBackend[] { |
| 45 | const all: WebSearchBackend[] = []; |
| 46 | const primary = selectBackend(primaryName); |
| 47 | all.push(primary); |
| 48 | // Add other backends that have credentials available, deduped |
| 49 | const seen = new Set([primary.name]); |
| 50 | if (!seen.has('firecrawl') && process.env.FIRECRAWL_API_KEY) { |
| 51 | all.push(new FirecrawlBackend()); |
| 52 | seen.add('firecrawl'); |
| 53 | } |
| 54 | if (!seen.has('brave') && process.env.BRAVE_SEARCH_API_KEY) { |
| 55 | all.push(new BraveBackend()); |
| 56 | seen.add('brave'); |
| 57 | } |
| 58 | if (!seen.has('tavily') && process.env.TAVILY_API_KEY) { |
| 59 | all.push(new TavilyBackend()); |
| 60 | seen.add('tavily'); |
| 61 | } |
| 62 | if (!seen.has('duckduckgo')) { |
| 63 | all.push(new DuckDuckGoBackend()); |
| 64 | } |
| 65 | return all; |
| 66 | } |
| 67 | |
| 68 | /** |
| 69 | * `web_search` tool. Pluggable backend, model never sees the choice. |
no test coverage detected