Created
November 8, 2025 17:21
-
-
Save shariqriazz/db5da387da2461da8bdcf9e1cce4adb8 to your computer and use it in GitHub Desktop.
web search + other shit using tavily in opencode
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { tool } from "@opencode-ai/plugin" | |
| export default tool({ | |
| description: "Execute a search query using Tavily Search API to get real-time web search results", | |
| args: { | |
| query: tool.schema.string().describe("The search query to execute with Tavily"), | |
| topic: tool.schema.enum(["general", "news", "finance"]).default("general").describe("The category of the search"), | |
| search_depth: tool.schema.enum(["basic", "advanced"]).default("basic").describe("The depth of the search - advanced costs 2 credits, basic costs 1"), | |
| max_results: tool.schema.number().min(0).max(20).default(5).describe("The maximum number of search results to return"), | |
| include_answer: tool.schema.boolean().default(false).describe("Include an LLM-generated answer to the provided query"), | |
| include_raw_content: tool.schema.boolean().default(false).describe("Include the cleaned and parsed HTML content of each search result"), | |
| include_images: tool.schema.boolean().default(false).describe("Also perform an image search and include the results in the response"), | |
| include_image_descriptions: tool.schema.boolean().default(false).describe("When include_images is true, also add a descriptive text for each image"), | |
| include_favicon: tool.schema.boolean().default(false).describe("Whether to include the favicon URL for each result"), | |
| include_domains: tool.schema.array(tool.schema.string()).default([]).describe("A list of domains to specifically include in the search results"), | |
| exclude_domains: tool.schema.array(tool.schema.string()).default([]).describe("A list of domains to specifically exclude from the search results"), | |
| time_range: tool.schema.enum(["day", "week", "month", "year", "d", "w", "m", "y"]).optional().describe("The time range back from the current date to filter results"), | |
| start_date: tool.schema.string().optional().describe("Will return all results after the specified start date in YYYY-MM-DD format"), | |
| end_date: tool.schema.string().optional().describe("Will return all results before the specified end date in YYYY-MM-DD format"), | |
| country: tool.schema.string().optional().describe("Boost search results from a specific country"), | |
| chunks_per_source: tool.schema.number().min(1).max(3).default(3).describe("Maximum number of relevant chunks returned per source (advanced search only)"), | |
| auto_parameters: tool.schema.boolean().default(false).describe("When enabled, Tavily automatically configures search parameters based on your query's content and intent") | |
| }, | |
| async execute(args, context) { | |
| const apiKey = process.env.TAVILY_API_KEY | |
| if (!apiKey) { | |
| throw new Error("TAVILY_API_KEY environment variable is not set. Please set it to use the Tavily search tool.") | |
| } | |
| const requestBody = { | |
| query: args.query, | |
| auto_parameters: args.auto_parameters, | |
| topic: args.topic, | |
| search_depth: args.search_depth, | |
| chunks_per_source: args.chunks_per_source, | |
| max_results: args.max_results, | |
| time_range: args.time_range || null, | |
| start_date: args.start_date || null, | |
| end_date: args.end_date || null, | |
| include_answer: args.include_answer, | |
| include_raw_content: args.include_raw_content, | |
| include_images: args.include_images, | |
| include_image_descriptions: args.include_image_descriptions, | |
| include_favicon: args.include_favicon, | |
| include_domains: args.include_domains, | |
| exclude_domains: args.exclude_domains, | |
| country: args.country || null | |
| } | |
| try { | |
| const response = await fetch('https://api.tavily.com/search', { | |
| method: 'POST', | |
| headers: { | |
| 'Content-Type': 'application/json', | |
| 'Authorization': `Bearer ${apiKey}` | |
| }, | |
| body: JSON.stringify(requestBody) | |
| }) | |
| if (!response.ok) { | |
| const errorData = await response.json().catch(() => ({ detail: { error: 'Unknown error' } })) | |
| throw new Error(`Tavily API error (${response.status}): ${errorData.detail?.error || response.statusText}`) | |
| } | |
| const data = await response.json() | |
| // Format the response for better readability | |
| const formattedResponse = { | |
| query: data.query, | |
| answer: data.answer, | |
| results: data.results?.map(result => ({ | |
| title: result.title, | |
| url: result.url, | |
| content: result.content, | |
| score: result.score, | |
| raw_content: result.raw_content, | |
| favicon: result.favicon | |
| })), | |
| images: data.images, | |
| response_time: data.response_time, | |
| request_id: data.request_id, | |
| auto_parameters: data.auto_parameters | |
| } | |
| return JSON.stringify(formattedResponse, null, 2) | |
| } catch (error) { | |
| if (error instanceof Error) { | |
| throw new Error(`Tavily search failed: ${error.message}`) | |
| } | |
| throw new Error('Unknown error occurred during Tavily search') | |
| } | |
| }, | |
| }) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment