|
| 1 | +import { publisher } from '../constants' |
| 2 | + |
| 3 | +import type { SecretAgentDefinition } from '../types/secret-agent-definition' |
| 4 | + |
| 5 | +const editor: SecretAgentDefinition = { |
| 6 | + id: 'editor', |
| 7 | + publisher, |
| 8 | + model: 'anthropic/claude-4-sonnet-20250522', |
| 9 | + displayName: 'Code Editor', |
| 10 | + spawnerPrompt: |
| 11 | + 'Expert code editor that reads files first, then implements changes with high precision. If you are spawning only one editor, you should set show_output to true unless otherwise stated.', |
| 12 | + inputSchema: { |
| 13 | + prompt: { |
| 14 | + type: 'string', |
| 15 | + description: 'The coding task to implement', |
| 16 | + }, |
| 17 | + params: { |
| 18 | + type: 'object', |
| 19 | + properties: { |
| 20 | + maxContextLength: { |
| 21 | + type: 'number', |
| 22 | + }, |
| 23 | + }, |
| 24 | + required: [], |
| 25 | + }, |
| 26 | + }, |
| 27 | + outputMode: 'structured_output', |
| 28 | + includeMessageHistory: true, |
| 29 | + toolNames: [ |
| 30 | + 'read_files', |
| 31 | + 'write_file', |
| 32 | + 'str_replace', |
| 33 | + 'run_terminal_command', |
| 34 | + 'code_search', |
| 35 | + 'spawn_agents', |
| 36 | + 'add_message', |
| 37 | + 'set_output', |
| 38 | + 'end_turn', |
| 39 | + ], |
| 40 | + spawnableAgents: ['file-explorer'], |
| 41 | + |
| 42 | + systemPrompt: `You are an expert code editor with deep understanding of software engineering principles. |
| 43 | +
|
| 44 | +You are extremely skilled at: |
| 45 | +- Reading and understanding existing codebases |
| 46 | +- Making surgical code changes |
| 47 | +- Following established patterns |
| 48 | +- Ensuring code quality and correctness |
| 49 | +- Never duplicating existing code and always reusing existing code when possible |
| 50 | +- Making the minimal change necessary to implement the user request |
| 51 | +`, |
| 52 | + |
| 53 | + instructionsPrompt: `Implement the requested coding changes with precision, especially following any plans that have been provided. |
| 54 | +
|
| 55 | +Workflow: |
| 56 | +1. First, spawn a file explorer discover all the relevant files for implementing the plan. |
| 57 | +2. Read all relevant files to understand the current state. You must read any file that could be relevant to the plan, especially files you need to modify, but also files that could show codebase patterns you could imitate. Try to read all the files in a single tool call. E.g. use read_files on 20 different files. |
| 58 | +3. Implement the changes using str_replace or write_file. |
| 59 | +4. End turn when complete. |
| 60 | +
|
| 61 | +Principles: |
| 62 | +- Read before you write |
| 63 | +- Make minimal changes |
| 64 | +- Follow existing patterns |
| 65 | +- Ensure correctness |
| 66 | +- IMPORTANT: Make as few changes as possible to satisfy the user request! |
| 67 | +- IMPORTANT: When you edit files, you must make all your edits in a single message. You should edit multiple files in a single response by calling str_replace or write_file multiple times before stopping. Try to make all your edits in a single response, even if you need to call the tool 20 times in a row.`, |
| 68 | + |
| 69 | + handleSteps: function* ({ agentState: initialAgentState }) { |
| 70 | + const stepLimit = 15 |
| 71 | + let stepCount = 0 |
| 72 | + let agentState = initialAgentState |
| 73 | + |
| 74 | + while (true) { |
| 75 | + stepCount++ |
| 76 | + |
| 77 | + const stepResult = yield 'STEP' |
| 78 | + agentState = stepResult.agentState // Capture the latest state |
| 79 | + |
| 80 | + if (stepResult.stepsComplete) { |
| 81 | + break |
| 82 | + } |
| 83 | + |
| 84 | + // If we've reached within one of the step limit, ask LLM to summarize progress |
| 85 | + if (stepCount === stepLimit - 1) { |
| 86 | + yield { |
| 87 | + toolName: 'add_message', |
| 88 | + input: { |
| 89 | + role: 'user', |
| 90 | + content: |
| 91 | + 'You have reached the step limit. Please summarize your progress so far, what you still need to solve, and provide any insights that could help complete the remaining work. Please end your turn after producing this summary with the end_turn tool.', |
| 92 | + }, |
| 93 | + } |
| 94 | + |
| 95 | + // One final step to produce the summary |
| 96 | + const finalStepResult = yield 'STEP' |
| 97 | + agentState = finalStepResult.agentState |
| 98 | + break |
| 99 | + } |
| 100 | + } |
| 101 | + |
| 102 | + // Collect all the edits from the conversation |
| 103 | + const { messageHistory } = agentState |
| 104 | + const editToolResults: string[] = [] |
| 105 | + for (const message of messageHistory) { |
| 106 | + if ( |
| 107 | + message.role === 'user' && |
| 108 | + message.content.includes('<tool_result>') |
| 109 | + ) { |
| 110 | + // Parse out tool results for write_file and str_replace |
| 111 | + const writeFileMatches = message.content.match( |
| 112 | + /<tool_result>\s*<tool>write_file<\/tool>\s*<result>([\s\S]*?)<\/result>\s*<\/tool_result>/g, |
| 113 | + ) |
| 114 | + const strReplaceMatches = message.content.match( |
| 115 | + /<tool_result>\s*<tool>str_replace<\/tool>\s*<result>([\s\S]*?)<\/result>\s*<\/tool_result>/g, |
| 116 | + ) |
| 117 | + |
| 118 | + // Extract inner <result> content from write_file matches |
| 119 | + if (writeFileMatches) { |
| 120 | + for (const match of writeFileMatches) { |
| 121 | + const resultMatch = match.match(/<result>([\s\S]*?)<\/result>/) |
| 122 | + if (resultMatch) { |
| 123 | + editToolResults.push(resultMatch[1]) |
| 124 | + } |
| 125 | + } |
| 126 | + } |
| 127 | + |
| 128 | + // Extract inner <result> content from str_replace matches |
| 129 | + if (strReplaceMatches) { |
| 130 | + for (const match of strReplaceMatches) { |
| 131 | + const resultMatch = match.match(/<result>([\s\S]*?)<\/result>/) |
| 132 | + if (resultMatch) { |
| 133 | + editToolResults.push(resultMatch[1]) |
| 134 | + } |
| 135 | + } |
| 136 | + } |
| 137 | + } |
| 138 | + } |
| 139 | + const lastAssistantMessage = |
| 140 | + messageHistory.findLast((message) => message.role === 'assistant') |
| 141 | + ?.content ?? '' |
| 142 | + |
| 143 | + yield { |
| 144 | + toolName: 'set_output', |
| 145 | + input: { |
| 146 | + message: lastAssistantMessage, |
| 147 | + edits: editToolResults, |
| 148 | + }, |
| 149 | + } |
| 150 | + }, |
| 151 | +} |
| 152 | + |
| 153 | +export default editor |
0 commit comments