import type { Plugin } from "@opencode-ai/plugin"; export const WebSearchPlugin: Plugin = async ({ client, $ }) => { const hasExaKey = !!process.env.EXA_API_KEY; return { config: async (config) => { config.agent = config.agent || {}; config.command = config.command || {}; config.tools = config.tools || {}; if (hasExaKey) { // === EXA MCP MODE === // Register MCP server config.mcp = config.mcp || {}; config.mcp["exa"] = { type: "remote", url: "https://mcp.exa.ai/mcp", }; // web-search agent with Exa tools config.agent["web-search"] = { description: "General web research: docs, articles, best practices", mode: "subagent", permission: { edit: "ask", bash: {}, }, tools: { "exa_web_search_exa": true, "exa_crawling": true, "exa_deep_researcher_start": true, "exa_deep_researcher_check": true, }, prompt: `You are a web research specialist helping with programming tasks. ## Your Job Find documentation, best practices, articles, and general information. Return contextual, actionable results. ## Tools - **web_search_exa**: Real-time web search. Use for most queries. - **crawling**: Fetch content from specific URLs when you need the full page. - **deep_researcher_start/deep_researcher_check**: Comprehensive research across many sources. Use when: - The question requires synthesizing multiple perspectives - A quick search won't provide sufficient depth - Explicitly requested via /deep-research ## Output Format - Summarize key findings with source links - Format code examples in fenced code blocks with language tags - Be concise - skip preamble, get to the answer - After tool calls, provide a brief summary of what you found`, }; // code-search agent with Exa tools config.agent["code-search"] = { description: "Find concrete code examples, API signatures, implementations", mode: "subagent", permission: { edit: "ask", bash: {}, }, tools: { "exa_get_code_context_exa": true, "exa_crawling": true, }, prompt: `You are a code context specialist helping find concrete implementations. ## Your Job Find actual code examples, API signatures, implementation patterns, and SDK documentation. Users want specific, working code - not general advice. ## Tools - **get_code_context_exa**: Search for code snippets, examples, and documentation from open source libraries, GitHub repos, and programming frameworks. - **crawling**: Fetch content from specific URLs (GitHub files, documentation pages). ## Output Format - Show actual code snippets in fenced code blocks with language tags - Include source links to repositories/docs - Highlight relevant API signatures and usage patterns - Be precise and concise - users want concrete examples - After tool calls, briefly summarize what you found and where`, }; // Commands config.command["web-search"] = { description: "Search the web for information", template: ` $ARGUMENTS If the user input above is empty or contains only whitespace, respond with: "A search query is required. Please try again with: /web-search Example: /web-search best practices for Django REST framework pagination" Otherwise, search the web for the query. Provide a concise summary with source links.`, agent: "web-search", }; config.command["code-search"] = { description: "Find code examples and implementations", template: ` $ARGUMENTS If the user input above is empty or contains only whitespace, respond with: "A search query is required. Please try again with: /code-search Example: /code-search React useEffect cleanup function examples" Otherwise, find code examples and implementations. Show actual code snippets with source links.`, agent: "code-search", }; config.command["deep-research"] = { description: "Comprehensive research across multiple sources", template: ` $ARGUMENTS If the user input above is empty or contains only whitespace, respond with: "A research query is required. Please try again with: /deep-research Example: /deep-research comparison of PostgreSQL vs MongoDB for time-series data" Otherwise, use the deep researcher tools (deep_researcher_start, then deep_researcher_check) to thoroughly research the query. Synthesize findings from multiple sources.`, agent: "web-search", }; // Disable all Exa tools globally (they're scoped to agents above) config.tools["exa_*"] = false; } else { // === FALLBACK MODE (built-in OpenCode tools) === // web-search agent with built-in tools config.agent["web-search"] = { description: "General web research: docs, articles, best practices", mode: "subagent", permission: { edit: "ask", bash: {}, }, tools: { websearch: true, webfetch: true, }, prompt: `You are a web research specialist helping with programming tasks. ## Your Job Find documentation, best practices, articles, and general information. Return contextual, actionable results. ## Tools - **websearch**: Real-time web search. Use for most queries. - **webfetch**: Fetch content from specific URLs when you need the full page. ## Output Format - Summarize key findings with source links - Format code examples in fenced code blocks with language tags - Be concise - skip preamble, get to the answer - After tool calls, provide a brief summary of what you found`, }; // code-search agent with built-in tools config.agent["code-search"] = { description: "Find concrete code examples, API signatures, implementations", mode: "subagent", permission: { edit: "ask", bash: {}, }, tools: { codesearch: true, webfetch: true, }, prompt: `You are a code context specialist helping find concrete implementations. ## Your Job Find actual code examples, API signatures, implementation patterns, and SDK documentation. Users want specific, working code - not general advice. ## Tools - **codesearch**: Search for code snippets, examples, and documentation from open source libraries, GitHub repos, and programming frameworks. - **webfetch**: Fetch content from specific URLs (GitHub files, documentation pages). ## Output Format - Show actual code snippets in fenced code blocks with language tags - Include source links to repositories/docs - Highlight relevant API signatures and usage patterns - Be precise and concise - users want concrete examples - After tool calls, briefly summarize what you found and where`, }; // Commands (no deep-research in fallback mode) config.command["web-search"] = { description: "Search the web for information", template: ` $ARGUMENTS If the user input above is empty or contains only whitespace, respond with: "A search query is required. Please try again with: /web-search Example: /web-search Next.js server components best practices" Otherwise, search the web for the query. Provide a concise summary with source links.`, agent: "web-search", }; config.command["code-search"] = { description: "Find code examples and implementations", template: ` $ARGUMENTS If the user input above is empty or contains only whitespace, respond with: "A search query is required. Please try again with: /code-search Example: /code-search Python asyncio gather vs wait usage" Otherwise, find code examples and implementations. Show actual code snippets with source links.`, agent: "code-search", }; } }, }; };