Explorar el Código

core: add explore agent for fast codebase navigation and improve task UI display

Dax Raad hace 4 meses
padre
commit
813d287a09

+ 7 - 0
.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",
+      },
+    },
   },
 }

+ 35 - 0
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 },

+ 2 - 2
packages/opencode/src/cli/cmd/tui/routes/session/index.tsx

@@ -1405,8 +1405,8 @@ ToolRegistry.register<typeof TaskTool>({
 
     return (
       <>
-        <ToolTitle icon="%" fallback="Delegating..." when={props.input.subagent_type ?? props.input.description}>
-          Task [{props.input.subagent_type ?? "unknown"}] {props.input.description}
+        <ToolTitle icon="" fallback="Delegating..." when={props.input.subagent_type ?? props.input.description}>
+          {Locale.titlecase(props.input.subagent_type ?? "unknown")} Task "{props.input.description}"
         </ToolTitle>
         <Show when={props.metadata.summary?.length}>
           <box>

+ 1 - 0
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()

+ 15 - 0
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()