fix(web-search): align Tavily API key resolution with Perplexity pattern

This commit is contained in:
Zachary 2026-01-26 12:11:48 -05:00
parent 18657bf90c
commit 396b610d57

View File

@ -109,6 +109,8 @@ type TavilyConfig = {
apiKey?: string; apiKey?: string;
}; };
type TavilyApiKeySource = "config" | "tavily_env" | "none";
type TavilySearchResult = { type TavilySearchResult = {
title?: string; title?: string;
url?: string; url?: string;
@ -254,12 +256,21 @@ function resolveTavilyConfig(search?: WebSearchConfig): TavilyConfig {
return tavily as TavilyConfig; return tavily as TavilyConfig;
} }
function resolveTavilyApiKey(tavily?: TavilyConfig): string | undefined { function resolveTavilyApiKey(tavily?: TavilyConfig): {
apiKey?: string;
source: TavilyApiKeySource;
} {
const fromConfig = normalizeApiKey(tavily?.apiKey); const fromConfig = normalizeApiKey(tavily?.apiKey);
if (fromConfig) return fromConfig; if (fromConfig) {
return { apiKey: fromConfig, source: "config" };
}
const fromEnv = normalizeApiKey(process.env.TAVILY_API_KEY); const fromEnv = normalizeApiKey(process.env.TAVILY_API_KEY);
if (fromEnv) return fromEnv; if (fromEnv) {
return undefined; return { apiKey: fromEnv, source: "tavily_env" };
}
return { apiKey: undefined, source: "none" };
} }
function resolveSearchCount(value: unknown, fallback: number): number { function resolveSearchCount(value: unknown, fallback: number): number {
@ -374,12 +385,14 @@ async function runTavilySearch(params: {
const data = (await res.json()) as TavilySearchResponse; const data = (await res.json()) as TavilySearchResponse;
const results = Array.isArray(data.results) ? data.results : []; const results = Array.isArray(data.results) ? data.results : [];
return results.map((entry) => ({ return results
title: entry.title ?? "", .filter((entry) => entry.url && entry.url.trim() !== "")
url: entry.url ?? "", .map((entry) => ({
description: entry.content ?? "", title: entry.title ?? "",
siteName: resolveSiteName(entry.url ?? ""), url: entry.url ?? "",
})); description: entry.content ?? "",
siteName: resolveSiteName(entry.url ?? ""),
}));
} }
async function runWebSearch(params: { async function runWebSearch(params: {
@ -527,11 +540,12 @@ export function createWebSearchTool(options?: {
execute: async (_toolCallId, args) => { execute: async (_toolCallId, args) => {
const perplexityAuth = const perplexityAuth =
provider === "perplexity" ? resolvePerplexityApiKey(perplexityConfig) : undefined; provider === "perplexity" ? resolvePerplexityApiKey(perplexityConfig) : undefined;
const tavilyAuth = provider === "tavily" ? resolveTavilyApiKey(tavilyConfig) : undefined;
const apiKey = const apiKey =
provider === "perplexity" provider === "perplexity"
? perplexityAuth?.apiKey ? perplexityAuth?.apiKey
: provider === "tavily" : provider === "tavily"
? resolveTavilyApiKey(tavilyConfig) ? tavilyAuth?.apiKey
: resolveSearchApiKey(search); : resolveSearchApiKey(search);
if (!apiKey) { if (!apiKey) {
@ -588,4 +602,6 @@ export const __testing = {
inferPerplexityBaseUrlFromApiKey, inferPerplexityBaseUrlFromApiKey,
resolvePerplexityBaseUrl, resolvePerplexityBaseUrl,
normalizeFreshness, normalizeFreshness,
resolveTavilyConfig,
resolveTavilyApiKey,
} as const; } as const;