UNPKG

@deep-assistant/agent

Version:

A minimal, public domain AI CLI agent compatible with OpenCode's JSON interface. Bun-only runtime.

124 lines (109 loc) 3.4 kB
import z from "zod" import { Tool } from "./tool" import DESCRIPTION from "./codesearch.txt" const API_CONFIG = { BASE_URL: "https://mcp.exa.ai", ENDPOINTS: { CONTEXT: "/mcp", }, } as const interface McpCodeRequest { jsonrpc: string id: number method: string params: { name: string arguments: { query: string tokensNum: number } } } interface McpCodeResponse { jsonrpc: string result: { content: Array<{ type: string text: string }> } } export const CodeSearchTool = Tool.define("codesearch", { description: DESCRIPTION, parameters: z.object({ query: z .string() .describe( "Search query to find relevant context for APIs, Libraries, and SDKs. For example, 'React useState hook examples', 'Python pandas dataframe filtering', 'Express.js middleware', 'Next js partial prerendering configuration'", ), tokensNum: z .number() .min(1000) .max(50000) .default(5000) .describe( "Number of tokens to return (1000-50000). Default is 5000 tokens. Adjust this value based on how much context you need - use lower values for focused queries and higher values for comprehensive documentation.", ), }), async execute(params, ctx) { // No restrictions - unrestricted code search const codeRequest: McpCodeRequest = { jsonrpc: "2.0", id: 1, method: "tools/call", params: { name: "get_code_context_exa", arguments: { query: params.query, tokensNum: params.tokensNum || 5000, }, }, } const controller = new AbortController() const timeoutId = setTimeout(() => controller.abort(), 30000) try { const headers: Record<string, string> = { accept: "application/json, text/event-stream", "content-type": "application/json", } const response = await fetch(`${API_CONFIG.BASE_URL}${API_CONFIG.ENDPOINTS.CONTEXT}`, { method: "POST", headers, body: JSON.stringify(codeRequest), signal: AbortSignal.any([controller.signal, ctx.abort]), }) clearTimeout(timeoutId) if (!response.ok) { const errorText = await response.text() throw new Error(`Code search error (${response.status}): ${errorText}`) } const responseText = await response.text() // Parse SSE response const lines = responseText.split("\n") for (const line of lines) { if (line.startsWith("data: ")) { const data: McpCodeResponse = JSON.parse(line.substring(6)) if (data.result && data.result.content && data.result.content.length > 0) { return { output: data.result.content[0].text, title: `Code search: ${params.query}`, metadata: {}, } } } } return { output: "No code snippets or documentation found. Please try a different query, be more specific about the library or programming concept, or check the spelling of framework names.", title: `Code search: ${params.query}`, metadata: {}, } } catch (error) { clearTimeout(timeoutId) if (error instanceof Error && error.name === "AbortError") { throw new Error("Code search request timed out") } throw error } }, })