diff --git a/src/resources/extensions/search-the-web/provider.ts b/src/resources/extensions/search-the-web/provider.ts index 65ee265aa..49363b8e2 100644 --- a/src/resources/extensions/search-the-web/provider.ts +++ b/src/resources/extensions/search-the-web/provider.ts @@ -35,6 +35,15 @@ export function getBraveApiKey(): string { return process.env.BRAVE_API_KEY || '' } +/** Standard headers for Brave Search API requests. */ +export function braveHeaders(): Record { + return { + "Accept": "application/json", + "Accept-Encoding": "gzip", + "X-Subscription-Token": getBraveApiKey(), + } +} + /** Returns the Ollama API key from the environment, or empty string if not set. */ export function getOllamaApiKey(): string { return process.env.OLLAMA_API_KEY || '' diff --git a/src/resources/extensions/search-the-web/tool-llm-context.ts b/src/resources/extensions/search-the-web/tool-llm-context.ts index 59aa4371a..cf6fd6fa1 100644 --- a/src/resources/extensions/search-the-web/tool-llm-context.ts +++ b/src/resources/extensions/search-the-web/tool-llm-context.ts @@ -27,7 +27,7 @@ import { normalizeQuery, extractDomain } from "./url-utils.js"; import { formatLLMContext, type LLMContextSnippet, type LLMContextSource } from "./format.js"; import type { TavilyResult, TavilySearchResponse } from "./tavily.js"; import { publishedDateToAge } from "./tavily.js"; -import { getTavilyApiKey, getOllamaApiKey, resolveSearchProvider } from "./provider.js"; +import { getTavilyApiKey, getOllamaApiKey, getBraveApiKey, braveHeaders, resolveSearchProvider } from "./provider.js"; // ============================================================================= // Types @@ -94,18 +94,6 @@ contextCache.startPurgeInterval(60_000); // Helpers // ============================================================================= -function getBraveApiKey(): string { - return process.env.BRAVE_API_KEY || ""; -} - -function braveHeaders(): Record { - return { - "Accept": "application/json", - "Accept-Encoding": "gzip", - "X-Subscription-Token": getBraveApiKey(), - }; -} - /** Rough token estimate: ~4 chars per token for English text. */ function estimateTokens(text: string): number { return Math.ceil(text.length / 4); diff --git a/src/resources/extensions/search-the-web/tool-search.ts b/src/resources/extensions/search-the-web/tool-search.ts index dcfdceccf..ba39b1332 100644 --- a/src/resources/extensions/search-the-web/tool-search.ts +++ b/src/resources/extensions/search-the-web/tool-search.ts @@ -20,7 +20,7 @@ import { LRUTTLCache } from "./cache.js"; import { fetchWithRetryTimed, fetchWithRetry, classifyError, type RateLimitInfo } from "./http.js"; import { normalizeQuery, toDedupeKey, detectFreshness } from "./url-utils.js"; import { formatSearchResults, type SearchResultFormatted, type FormatSearchOptions } from "./format.js"; -import { getTavilyApiKey, getOllamaApiKey, resolveSearchProvider } from "./provider.js"; +import { getTavilyApiKey, getOllamaApiKey, getBraveApiKey, braveHeaders, resolveSearchProvider } from "./provider.js"; import { normalizeTavilyResult, mapFreshnessToTavily, type TavilySearchResponse } from "./tavily.js"; // ============================================================================= @@ -117,18 +117,6 @@ const summarizerCache = new LRUTTLCache({ max: 50, ttlMs: 900_000 }); // Brave API helpers // ============================================================================= -function getBraveApiKey(): string { - return process.env.BRAVE_API_KEY || ""; -} - -function braveHeaders(): Record { - return { - "Accept": "application/json", - "Accept-Encoding": "gzip", - "X-Subscription-Token": getBraveApiKey(), - }; -} - /** * Normalize a Brave result into our formatted result type. */ diff --git a/src/tests/provider.test.ts b/src/tests/provider.test.ts index dbf692cce..85a7b99e8 100644 --- a/src/tests/provider.test.ts +++ b/src/tests/provider.test.ts @@ -245,7 +245,7 @@ test('getBraveApiKey reads from process.env.BRAVE_API_KEY', async () => { // 4. Boundary contract — S01→S02 public API surface // ═══════════════════════════════════════════════════════════════════════════ -test('provider.ts exports exactly the 6 expected functions', async () => { +test('provider.ts exports exactly the 7 expected functions', async () => { const provider = await import( '../resources/extensions/search-the-web/provider.ts' ) @@ -254,6 +254,7 @@ test('provider.ts exports exactly the 6 expected functions', async () => { 'resolveSearchProvider', 'getTavilyApiKey', 'getBraveApiKey', + 'braveHeaders', 'getOllamaApiKey', 'getSearchProviderPreference', 'setSearchProviderPreference', @@ -271,6 +272,6 @@ test('provider.ts exports exactly the 6 expected functions', async () => { assert.deepEqual( actualFunctions.sort(), [...expectedExports].sort(), - 'provider.ts should export exactly the 6 expected functions (no extra function exports)', + 'provider.ts should export exactly the 7 expected functions (no extra function exports)', ) })