diff --git a/.opencode/opencode.jsonc b/.opencode/opencode.jsonc index 369832f9f..ce4a6658b 100644 --- a/.opencode/opencode.jsonc +++ b/.opencode/opencode.jsonc @@ -16,5 +16,12 @@ "type": "remote", "url": "https://mcp.exa.ai/mcp", }, + "morph": { + "type": "local", + "command": ["bunx", "@morphllm/morphmcp"], + "environment": { + "ENABLED_TOOLS": "warp_grep", + }, + }, }, } diff --git a/packages/opencode/src/agent/agent.ts b/packages/opencode/src/agent/agent.ts index 740f67b7e..cee7ddef2 100644 --- a/packages/opencode/src/agent/agent.ts +++ b/packages/opencode/src/agent/agent.ts @@ -114,6 +114,41 @@ export namespace Agent { mode: "subagent", builtIn: true, }, + explore: { + name: "explore", + tools: { + todoread: false, + todowrite: false, + edit: false, + write: false, + ...defaultTools, + }, + description: `Fast agent specialized for exploring codebases. Use this when you need to quickly find files by patterns (eg. "src/components/**/*.tsx"), search code for keywords (eg. "API endpoints"), or answer questions about the codebase (eg. "how do API endpoints work?"). When calling this agent, specify the desired thoroughness level: "quick" for basic searches, "medium" for moderate exploration, or "very thorough" for comprehensive analysis across multiple locations and naming conventions. (Tools: All tools)`, + prompt: [ + `You are a file search specialist. You excel at thoroughly navigating and exploring codebases.`, + ``, + `Your strengths:`, + `- Rapidly finding files using glob patterns`, + `- Searching code and text with powerful regex patterns`, + `- Reading and analyzing file contents`, + ``, + `Guidelines:`, + `- Use Glob for broad file pattern matching`, + `- Use Grep for searching file contents with regex`, + `- Use Read when you know the specific file path you need to read`, + `- Use Bash for file operations like copying, moving, or listing directory contents`, + `- Adapt your search approach based on the thoroughness level specified by the caller`, + `- Return file paths as absolute paths in your final response`, + `- For clear communication, avoid using emojis`, + `- Do not create any files, or run bash commands that modify the user's system state in any way`, + ``, + `Complete the user's search request efficiently and report your findings clearly.`, + ].join("\n"), + options: {}, + permission: agentPermission, + mode: "subagent", + builtIn: true, + }, build: { name: "build", tools: { ...defaultTools }, diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx index fcf562782..3d14db149 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx @@ -1405,8 +1405,8 @@ ToolRegistry.register({ return ( <> - - Task [{props.input.subagent_type ?? "unknown"}] {props.input.description} + + {Locale.titlecase(props.input.subagent_type ?? "unknown")} Task "{props.input.description}" diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts index 383a47566..a49612090 100644 --- a/packages/opencode/src/config/config.ts +++ b/packages/opencode/src/config/config.ts @@ -527,6 +527,7 @@ export namespace Config { plan: Agent.optional(), build: Agent.optional(), general: Agent.optional(), + explore: Agent.optional(), }) .catchall(Agent) .optional() diff --git a/packages/opencode/src/provider/provider.ts b/packages/opencode/src/provider/provider.ts index a4c406c0f..ded0b9b19 100644 --- a/packages/opencode/src/provider/provider.ts +++ b/packages/opencode/src/provider/provider.ts @@ -677,6 +677,21 @@ export namespace Provider { } } + export async function closest(providerID: string, query: string[]) { + const s = await state() + const provider = s.providers[providerID] + if (!provider) return undefined + for (const item of query) { + for (const modelID of Object.keys(provider.info.models)) { + if (modelID.includes(item)) + return { + providerID, + modelID, + } + } + } + } + export async function getSmallModel(providerID: string) { const cfg = await Config.get()