import type { LangSearchConfig, WebSearchParams, WebSearchResponse, ToolResult } from '../types.js';
/**
* Web Search Tool Implementation
*
* Searches the web using LangSearch's Web Search API.
* Returns web pages with titles, URLs, snippets, and optional summaries.
*/
export async function webSearchTool(
params: WebSearchParams,
config: LangSearchConfig
): Promise<ToolResult> {
try {
// Build request body with defaults
const requestBody = {
query: params.query,
freshness: params.freshness || 'noLimit',
summary: params.summary !== undefined ? params.summary : true,
count: params.count || 10
};
// Make API request
const response = await fetch(`${config.baseUrl}/v1/web-search`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${config.apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(requestBody)
});
if (!response.ok) {
const errorText = await response.text();
throw new Error(`LangSearch API error (${response.status}): ${errorText}`);
}
const result = await response.json() as WebSearchResponse;
// Check for API-level errors
if (result.code !== 200) {
throw new Error(`LangSearch API returned error code ${result.code}: ${result.msg || 'Unknown error'}`);
}
// Format results for display
const resultCount = result.data.webPages.value.length;
const formattedResults = result.data.webPages.value.map((page, idx) => {
let text = `${idx + 1}. ${page.name}\n`;
text += ` URL: ${page.url}\n`;
text += ` Snippet: ${page.snippet}\n`;
if (page.summary) {
text += ` Summary: ${page.summary}\n`;
}
return text;
}).join('\n');
const displayText = `Web Search Results for "${result.data.queryContext.originalQuery}"\n` +
`Found ${resultCount} result(s)\n` +
`Search URL: ${result.data.webPages.webSearchUrl}\n\n` +
formattedResults;
return {
content: [{
type: 'text',
text: displayText
}],
structuredContent: result.data as unknown as { [x: string]: unknown }
};
} catch (error: unknown) {
const err = error as Error;
const errorMessage = `Web search failed: ${err.message}`;
return {
content: [{
type: 'text',
text: errorMessage
}],
isError: true
};
}
}