Created
February 6, 2026 16:31
-
-
Save yanosh-k/2aac282fb646fe50fcaddafc853aada0 to your computer and use it in GitHub Desktop.
Web search tool for opencode using the python ddgs package
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 os from 'os' | |
| const { tool } = await import(os.homedir().replace(/\/$/, '') + '/.config/opencode/node_modules/@opencode-ai/plugin/dist/') | |
| export default tool({ | |
| description: "Performs web searches and returns a list of relevant results. Each result includes a title, URL, and snippet/description of the page content. Use this tool when you need current information from the internet, want to find specific websites, research topics, verify facts, or gather multiple perspectives on a subject. The tool returns up to 10 search results ranked by relevance. Note: This tool only provides brief snippets - use a web fetching tool with the returned URLs to access the full page content when needed. Do not make parallel requests with this tool as it will hit the usage limit, instead make single calls to it.", | |
| args: { | |
| query: tool.schema.string().describe("Search query"), | |
| }, | |
| async execute(args) { | |
| // Validate query | |
| if (!args.query.trim()) { | |
| return "Error: Search query cannot be empty" | |
| } | |
| // Hardcoded parameters (you can edit these directly in the code) | |
| const REGION = "bg-bg" | |
| const BACKEND = "duckduckgo" | |
| const MAX_RESULTS = 10 | |
| const VERIFY_SSL = false | |
| const SEARCH_FILE = `/tmp/opencode_ddgs_search_${Date.now()}.json` | |
| try { | |
| // Build the command with hardcoded parameters | |
| const cmdParts = [ | |
| "PATH_TO_DDGS_EXECUTABLE/ddgs", | |
| "text", | |
| "-q", args.query, | |
| "-r", REGION, | |
| "-b", BACKEND, | |
| "-m", MAX_RESULTS.toString(), | |
| "-v", VERIFY_SSL ? "true" : "false", | |
| "-o", SEARCH_FILE | |
| ] | |
| // Execute the ddgs command | |
| const proc = await Bun.$`${cmdParts}`.quiet().nothrow() | |
| // Check if the command failed | |
| if (proc.exitCode !== 0) { | |
| const stdout = proc.stdout.toString() | |
| const stderr = proc.stderr.toString() | |
| throw new Error(`Command failed with exit code ${proc.exitCode}. stdout: ${stdout || '(empty)'}. stderr: ${stderr || '(empty)'}`) | |
| } | |
| // Read the results | |
| const file = Bun.file(SEARCH_FILE) | |
| if (!await file.exists()) { | |
| throw new Error(`Search results file was not created at ${SEARCH_FILE}`) | |
| } | |
| const fileContent = await file.text() | |
| if (!fileContent) { | |
| throw new Error(`Search results file is empty`) | |
| } | |
| // Parse the JSON to validate and potentially format it | |
| const results = JSON.parse(fileContent) | |
| // Format the output for better readability | |
| let formattedOutput = `Search results for "${args.query}":\n\n` | |
| if (Array.isArray(results) && results.length > 0) { | |
| results.forEach((result, index) => { | |
| formattedOutput += `${index + 1}. ${result.title || 'No title'}\n` | |
| formattedOutput += ` URL: ${result.href || result.url || 'N/A'}\n` | |
| formattedOutput += ` ${result.body || result.description || ''}\n\n` | |
| }) | |
| } else { | |
| formattedOutput += "No results found." | |
| } | |
| // Clean up temporary file | |
| try { | |
| await Bun.$`rm ${SEARCH_FILE}`.quiet() | |
| } catch { | |
| // Ignore cleanup errors | |
| } | |
| return formattedOutput | |
| } catch (error) { | |
| // Clean up on error | |
| try { | |
| await Bun.$`rm ${SEARCH_FILE}`.quiet() | |
| } catch { | |
| // Ignore cleanup errors | |
| } | |
| return `Error performing search: ${error instanceof Error ? error.message : String(error)}` | |
| } | |
| } | |
| }) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment