{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "webresearch-opencode", "title": "OpenCode Web Research", "description": "Web research tool that runs Codex web_search_request via OpenCode.", "files": [ { "path": "registry/webresearch/opencode/files/tool/webresearch.ts", "content": "import { tool } from \"@opencode-ai/plugin\";\n\nconst QUALITY_PRESETS = {\n fast: {\n effort: \"low\",\n directive: \"Keep it quick; use only the most relevant sources.\",\n },\n balanced: {\n effort: \"medium\",\n directive: \"Cover the main angles; resolve contradictions if they appear.\",\n },\n deep: {\n effort: \"high\",\n directive:\n \"Follow second-order leads and resolve contradictions until extra sources stop adding value.\",\n },\n} as const;\n\ntype Quality = keyof typeof QUALITY_PRESETS;\n\nfunction buildPrompt({\n reason,\n query,\n additionalContext,\n quality,\n}: {\n reason: string;\n query: string;\n additionalContext?: string;\n quality: Quality;\n}) {\n const preset = QUALITY_PRESETS[quality];\n const contextBlock = additionalContext\n ? `Additional context (optional): ${additionalContext}`\n : \"Additional context (optional):\";\n\n return [\n \"Hi, I’m stuck and need help with a research task.\",\n \"\",\n `Reason: ${reason}`,\n `Search queries: ${query}`,\n contextBlock,\n `Depth: ${quality}`,\n \"\",\n \"Please search the web and send back:\",\n \"- A 2-4 sentence summary\",\n \"- Key findings or caveats (bullets)\",\n \"- Sources with full URLs\",\n \"\",\n \"If anything is ambiguous, cover the plausible interpretations and state your assumptions instead of asking questions.\",\n \"Please don’t edit any code or files.\",\n preset.directive,\n ].join(\"\\n\");\n}\n\nasync function runCodex({\n prompt,\n effort,\n}: {\n prompt: string;\n effort: string;\n}) {\n const args = [\n \"exec\",\n \"--enable\",\n \"web_search_request\",\n \"--sandbox\",\n \"read-only\",\n \"-c\",\n `model_reasoning_effort=${effort}`,\n prompt,\n ];\n\n const proc = Bun.spawn([\"codex\", ...args], {\n stdout: \"pipe\",\n stderr: \"pipe\",\n });\n\n const [stdout, stderr] = await Promise.all([\n new Response(proc.stdout).text(),\n new Response(proc.stderr).text(),\n ]);\n const exitCode = await proc.exited;\n\n if (exitCode !== 0) {\n const message = stderr.trim() || `codex exec failed with exit code ${exitCode}`;\n throw new Error(message);\n }\n\n return stdout.trim();\n}\n\nexport default tool({\n description:\n \"Run a web search and return a concise summary with source links. Expect 5-10 minutes for deep queries; only run parallel calls for separate deep dives (one run can handle multiple related queries).\",\n args: {\n reason: tool.schema\n .string()\n .describe(\n \"Describe the core reason you’re reaching for web search and the decision or output you’re aiming for.\",\n ),\n query: tool.schema\n .string()\n .describe(\n 'List the search queries you want run; use new lines or \";\" to include multiple angles in one run. Only split into parallel calls for distinct deep dives.',\n ),\n additional_context: tool.schema\n .string()\n .optional()\n .describe(\n \"Add constraints or background: versions, product names, prior findings, relevant files/code, or must-include sources.\",\n ),\n quality: tool.schema\n .enum([\"fast\", \"balanced\", \"deep\"])\n .describe(\n \"Fast = quick scan, balanced = normal depth, deep = thorough with follow-up leads (deep can take 5-10 minutes).\",\n ),\n },\n async execute(args) {\n const quality = args.quality as Quality;\n const prompt = buildPrompt({\n reason: args.reason,\n query: args.query,\n additionalContext: args.additional_context,\n quality,\n });\n\n const effort = QUALITY_PRESETS[quality].effort;\n return runCodex({\n prompt,\n effort,\n });\n },\n});\n", "type": "registry:file", "target": "~/.opencode/tool/webresearch.ts" } ], "meta": { "concept": "webresearch", "platform": "opencode", "kind": [ "tool" ] }, "docs": "Requires the `codex` CLI on PATH. Restart OpenCode after installing to register the tool. Targets prefixed with ~ are repo-scoped (project-root) paths.", "type": "registry:item" }