auto-coder 0.1.361__py3-none-any.whl → 0.1.363__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of auto-coder might be problematic. Click here for more details.

Files changed (57) hide show
  1. {auto_coder-0.1.361.dist-info → auto_coder-0.1.363.dist-info}/METADATA +2 -1
  2. {auto_coder-0.1.361.dist-info → auto_coder-0.1.363.dist-info}/RECORD +57 -29
  3. autocoder/agent/auto_learn.py +249 -262
  4. autocoder/agent/base_agentic/__init__.py +0 -0
  5. autocoder/agent/base_agentic/agent_hub.py +169 -0
  6. autocoder/agent/base_agentic/agentic_lang.py +112 -0
  7. autocoder/agent/base_agentic/agentic_tool_display.py +180 -0
  8. autocoder/agent/base_agentic/base_agent.py +1582 -0
  9. autocoder/agent/base_agentic/default_tools.py +683 -0
  10. autocoder/agent/base_agentic/test_base_agent.py +82 -0
  11. autocoder/agent/base_agentic/tool_registry.py +425 -0
  12. autocoder/agent/base_agentic/tools/__init__.py +12 -0
  13. autocoder/agent/base_agentic/tools/ask_followup_question_tool_resolver.py +72 -0
  14. autocoder/agent/base_agentic/tools/attempt_completion_tool_resolver.py +37 -0
  15. autocoder/agent/base_agentic/tools/base_tool_resolver.py +35 -0
  16. autocoder/agent/base_agentic/tools/example_tool_resolver.py +46 -0
  17. autocoder/agent/base_agentic/tools/execute_command_tool_resolver.py +72 -0
  18. autocoder/agent/base_agentic/tools/list_files_tool_resolver.py +110 -0
  19. autocoder/agent/base_agentic/tools/plan_mode_respond_tool_resolver.py +35 -0
  20. autocoder/agent/base_agentic/tools/read_file_tool_resolver.py +54 -0
  21. autocoder/agent/base_agentic/tools/replace_in_file_tool_resolver.py +156 -0
  22. autocoder/agent/base_agentic/tools/search_files_tool_resolver.py +134 -0
  23. autocoder/agent/base_agentic/tools/talk_to_group_tool_resolver.py +96 -0
  24. autocoder/agent/base_agentic/tools/talk_to_tool_resolver.py +79 -0
  25. autocoder/agent/base_agentic/tools/use_mcp_tool_resolver.py +44 -0
  26. autocoder/agent/base_agentic/tools/write_to_file_tool_resolver.py +58 -0
  27. autocoder/agent/base_agentic/types.py +189 -0
  28. autocoder/agent/base_agentic/utils.py +100 -0
  29. autocoder/auto_coder.py +1 -1
  30. autocoder/auto_coder_runner.py +36 -14
  31. autocoder/chat/conf_command.py +11 -10
  32. autocoder/commands/auto_command.py +227 -159
  33. autocoder/common/__init__.py +2 -2
  34. autocoder/common/ignorefiles/ignore_file_utils.py +12 -8
  35. autocoder/common/result_manager.py +10 -2
  36. autocoder/common/rulefiles/autocoderrules_utils.py +169 -0
  37. autocoder/common/save_formatted_log.py +1 -1
  38. autocoder/common/v2/agent/agentic_edit.py +53 -41
  39. autocoder/common/v2/agent/agentic_edit_tools/read_file_tool_resolver.py +15 -12
  40. autocoder/common/v2/agent/agentic_edit_tools/replace_in_file_tool_resolver.py +73 -1
  41. autocoder/common/v2/agent/agentic_edit_tools/write_to_file_tool_resolver.py +132 -4
  42. autocoder/common/v2/agent/agentic_edit_types.py +1 -2
  43. autocoder/common/v2/agent/agentic_tool_display.py +2 -3
  44. autocoder/common/v2/code_auto_generate_editblock.py +3 -1
  45. autocoder/index/index.py +14 -8
  46. autocoder/privacy/model_filter.py +297 -35
  47. autocoder/rag/long_context_rag.py +424 -397
  48. autocoder/rag/test_doc_filter.py +393 -0
  49. autocoder/rag/test_long_context_rag.py +473 -0
  50. autocoder/rag/test_token_limiter.py +342 -0
  51. autocoder/shadows/shadow_manager.py +1 -3
  52. autocoder/utils/_markitdown.py +22 -3
  53. autocoder/version.py +1 -1
  54. {auto_coder-0.1.361.dist-info → auto_coder-0.1.363.dist-info}/LICENSE +0 -0
  55. {auto_coder-0.1.361.dist-info → auto_coder-0.1.363.dist-info}/WHEEL +0 -0
  56. {auto_coder-0.1.361.dist-info → auto_coder-0.1.363.dist-info}/entry_points.txt +0 -0
  57. {auto_coder-0.1.361.dist-info → auto_coder-0.1.363.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,683 @@
1
+ """
2
+ Default tools initialization module
3
+ Used to initialize and register default tools
4
+ """
5
+ from typing import Dict, Type, List, Any
6
+ from loguru import logger
7
+ import byzerllm
8
+ from .tool_registry import ToolRegistry
9
+ from .types import BaseTool, ToolDescription, ToolExample
10
+
11
+ # Import all tool classes
12
+ from .types import (
13
+ ExecuteCommandTool, ReadFileTool, WriteToFileTool, ReplaceInFileTool,
14
+ SearchFilesTool, ListFilesTool, AskFollowupQuestionTool,
15
+ AttemptCompletionTool, PlanModeRespondTool, UseMcpTool,
16
+ TalkToTool, TalkToGroupTool
17
+ )
18
+
19
+ # Import all resolvers
20
+ from .tools.execute_command_tool_resolver import ExecuteCommandToolResolver
21
+ from .tools.read_file_tool_resolver import ReadFileToolResolver
22
+ from .tools.write_to_file_tool_resolver import WriteToFileToolResolver
23
+ from .tools.replace_in_file_tool_resolver import ReplaceInFileToolResolver
24
+ from .tools.search_files_tool_resolver import SearchFilesToolResolver
25
+ from .tools.list_files_tool_resolver import ListFilesToolResolver
26
+ from .tools.ask_followup_question_tool_resolver import AskFollowupQuestionToolResolver
27
+ from .tools.attempt_completion_tool_resolver import AttemptCompletionToolResolver
28
+ from .tools.plan_mode_respond_tool_resolver import PlanModeRespondToolResolver
29
+ from .tools.use_mcp_tool_resolver import UseMcpToolResolver
30
+ from .tools.talk_to_tool_resolver import TalkToToolResolver
31
+ from .tools.talk_to_group_tool_resolver import TalkToGroupToolResolver
32
+
33
+
34
+ # Tool description generators with byzerllm.prompt() decorators
35
+
36
+ class ToolsCaseGenerator:
37
+
38
+ def __init__(self, params: Dict[str, Any]):
39
+ self.params = params
40
+
41
+ @byzerllm.prompt()
42
+ def editing_files_doc(self) -> str:
43
+ """
44
+ You have access to two tools for working with files: **write_to_file** and **replace_in_file**. Understanding their roles and selecting the right one for the job will help ensure efficient and accurate modifications.
45
+
46
+ # write_to_file
47
+
48
+ ## Purpose
49
+
50
+ - Create a new file, or overwrite the entire contents of an existing file.
51
+
52
+ ## When to Use
53
+
54
+ - Initial file creation, such as when scaffolding a new research plan.
55
+ - Overwriting large research documents where you want to replace the entire content at once.
56
+ - When the complexity or number of changes would make replace_in_file unwieldy or error-prone.
57
+
58
+ ## Important Considerations
59
+
60
+ - Using write_to_file requires providing the file's complete final content.
61
+ - If you only need to make small changes to an existing file, consider using replace_in_file instead to avoid unnecessarily rewriting the entire file.
62
+ - Only use this for research planning and documentation, not system files.
63
+
64
+ # replace_in_file
65
+
66
+ ## Purpose
67
+
68
+ - Make targeted edits to specific parts of an existing file without overwriting the entire file.
69
+
70
+ ## When to Use
71
+
72
+ - Small, localized changes like updating a few lines in a research document, modifying a search strategy, or adding new findings.
73
+ - Targeted improvements where only specific portions of the file's content needs to be altered.
74
+ - Especially useful for long research documents where much of the file will remain unchanged.
75
+
76
+ ## Advantages
77
+
78
+ - More efficient for minor edits, since you don't need to supply the entire file content.
79
+ - Reduces the chance of errors that can occur when overwriting large files.
80
+
81
+ # Choosing the Appropriate Tool
82
+
83
+ - **Default to replace_in_file** for most changes to existing research documents. It's the safer, more precise option that minimizes potential issues.
84
+ - **Use write_to_file** when:
85
+ - Creating new research documents
86
+ - The changes are so extensive that using replace_in_file would be more complex or risky
87
+ - You need to completely reorganize or restructure a document
88
+ - The file is relatively small and the changes affect most of its content
89
+
90
+ # Auto-formatting Considerations
91
+
92
+ - After using either write_to_file or replace_in_file, the user's editor may automatically format the file
93
+ - This auto-formatting may modify the file contents, for example:
94
+ - Breaking single lines into multiple lines
95
+ - Adjusting indentation to match project style (e.g. 2 spaces vs 4 spaces vs tabs)
96
+ - Converting single quotes to double quotes (or vice versa based on project preferences)
97
+ - Organizing imports (e.g. sorting, grouping by type)
98
+ - Adding/removing trailing commas in objects and arrays
99
+ - Enforcing consistent brace style (e.g. same-line vs new-line)
100
+ - Standardizing semicolon usage (adding or removing based on style)
101
+ - The write_to_file and replace_in_file tool responses will include the final state of the file after any auto-formatting
102
+ - Use this final state as your reference point for any subsequent edits. This is ESPECIALLY important when crafting SEARCH blocks for replace_in_file which require the content to match what's in the file exactly.
103
+
104
+ # Workflow Tips
105
+
106
+ 1. Before editing, assess the scope of your changes and decide which tool to use.
107
+ 2. For targeted edits, apply replace_in_file with carefully crafted SEARCH/REPLACE blocks. If you need multiple changes, you can stack multiple SEARCH/REPLACE blocks within a single replace_in_file call.
108
+ 3. For major overhauls or initial file creation, rely on write_to_file.
109
+ 4. Once the file has been edited with either write_to_file or replace_in_file, the system will provide you with the final state of the modified file. Use this updated content as the reference point for any subsequent SEARCH/REPLACE operations, since it reflects any auto-formatting or user-applied changes.
110
+
111
+ By thoughtfully selecting between write_to_file and replace_in_file, you can make your file editing process smoother, safer, and more efficient.
112
+ """
113
+ return self.params
114
+
115
+
116
+ class ToolDescGenerators:
117
+
118
+ def __init__(self, params: Dict[str, Any]):
119
+ self.params = params
120
+
121
+ @byzerllm.prompt()
122
+ def execute_command(self) -> Dict:
123
+ """
124
+ Description: Request to execute a CLI command on the system. Use this when you need to perform system operations or run specific commands to accomplish any step in the user's task. You must tailor your command to the user's system and provide a clear explanation of what the command does. For command chaining, use the appropriate chaining syntax for the user's shell. Prefer to execute complex CLI commands over creating executable scripts, as they are more flexible and easier to run. Commands will be executed in the current working directory: {{current_project}}
125
+ Parameters:
126
+ - command: (required) The CLI command to execute. This should be valid for the current operating system. Ensure the command is properly formatted and does not contain any harmful instructions.
127
+ - requires_approval: (required) A boolean indicating whether this command requires explicit user approval before execution in case the user has auto-approve mode enabled. Set to 'true' for potentially impactful operations like installing/uninstalling packages, deleting/overwriting files, system configuration changes, network operations, or any commands that could have unintended side effects. Set to 'false' for safe operations like reading files/directories, running development servers, building projects, and other non-destructive operations.
128
+ Usage:
129
+ <execute_command>
130
+ <command>Your command here</command>
131
+ <requires_approval>true or false</requires_approval>
132
+ </execute_command>
133
+ """
134
+ return self.params
135
+
136
+ @byzerllm.prompt()
137
+ def list_package_info(self) -> Dict:
138
+ """
139
+ Description: Request to retrieve information about a source code package, such as recent changes or documentation summary, to better understand the code context. It accepts a directory path (absolute or relative to the current project).
140
+ Parameters:
141
+ - path: (required) The source code package directory path.
142
+ Usage:
143
+ <list_package_info>
144
+ <path>relative/or/absolute/package/path</path>
145
+ </list_package_info>
146
+ """
147
+ return self.params
148
+
149
+ @byzerllm.prompt()
150
+ def read_file(self) -> Dict:
151
+ """
152
+ Description: Request to read the contents of a file at the specified path. Use this when you need to examine the contents of an existing file you do not know the contents of, for example to analyze code, review text files, or extract information from configuration files. Automatically extracts raw text from PDF and DOCX files. May not be suitable for other types of binary files, as it returns the raw content as a string.
153
+ Parameters:
154
+ - path: (required) The path of the file to read (relative to the current working directory ${cwd.toPosix()})
155
+ Usage:
156
+ <read_file>
157
+ <path>File path here</path>
158
+ </read_file>
159
+ """
160
+ return self.params
161
+
162
+ @byzerllm.prompt()
163
+ def write_to_file(self) -> Dict:
164
+ """
165
+ Description: Request to write content to a file at the specified path. If the file exists, it will be overwritten with the provided content. If the file doesn't exist, it will be created. This tool will automatically create any directories needed to write the file.
166
+ Parameters:
167
+ - path: (required) The path of the file to write to (relative to the current working directory ${cwd.toPosix()})
168
+ - content: (required) The content to write to the file. ALWAYS provide the COMPLETE intended content of the file, without any truncation or omissions. You MUST include ALL parts of the file, even if they haven't been modified.
169
+ Usage:
170
+ <write_to_file>
171
+ <path>File path here</path>
172
+ <content>
173
+ Your file content here
174
+ </content>
175
+ </write_to_file>
176
+ """
177
+ return self.params
178
+
179
+ @byzerllm.prompt()
180
+ def replace_in_file(self) -> Dict:
181
+ """
182
+ Description: Request to replace sections of content in an existing file using SEARCH/REPLACE blocks that define exact changes to specific parts of the file. This tool should be used when you need to make targeted changes to specific parts of a file.
183
+ Parameters:
184
+ - path: (required) The path of the file to modify (relative to the current working directory ${cwd.toPosix()})
185
+ - diff: (required) One or more SEARCH/REPLACE blocks following this exact format:
186
+ ```
187
+ <<<<<<< SEARCH
188
+ [exact content to find]
189
+ =======
190
+ [new content to replace with]
191
+ >>>>>>> REPLACE
192
+ ```
193
+ Critical rules:
194
+ 1. SEARCH content must match the associated file section to find EXACTLY:
195
+ * Match character-for-character including whitespace, indentation, line endings
196
+ * Include all comments, docstrings, etc.
197
+ 2. SEARCH/REPLACE blocks will ONLY replace the first match occurrence.
198
+ * Including multiple unique SEARCH/REPLACE blocks if you need to make multiple changes.
199
+ * Include *just* enough lines in each SEARCH section to uniquely match each set of lines that need to change.
200
+ * When using multiple SEARCH/REPLACE blocks, list them in the order they appear in the file.
201
+ 3. Keep SEARCH/REPLACE blocks concise:
202
+ * Break large SEARCH/REPLACE blocks into a series of smaller blocks that each change a small portion of the file.
203
+ * Include just the changing lines, and a few surrounding lines if needed for uniqueness.
204
+ * Do not include long runs of unchanging lines in SEARCH/REPLACE blocks.
205
+ * Each line must be complete. Never truncate lines mid-way through as this can cause matching failures.
206
+ 4. Special operations:
207
+ * To move code: Use two SEARCH/REPLACE blocks (one to delete from original + one to insert at new location)
208
+ * To delete code: Use empty REPLACE section
209
+ Usage:
210
+ <replace_in_file>
211
+ <path>File path here</path>
212
+ <diff>
213
+ Search and replace blocks here
214
+ </diff>
215
+ </replace_in_file>
216
+ """
217
+ return self.params
218
+
219
+ @byzerllm.prompt()
220
+ def search_files(self) -> Dict:
221
+ """
222
+ Description: Request to perform a regex search across files in a specified directory, providing context-rich results. This tool searches for patterns or specific content across multiple files, displaying each match with encapsulating context.
223
+ Parameters:
224
+ - path: (required) The path of the directory to search in (relative to the current working directory ${cwd.toPosix()}). This directory will be recursively searched.
225
+ - regex: (required) The regular expression pattern to search for. Uses Rust regex syntax.
226
+ - file_pattern: (optional) Glob pattern to filter files (e.g., '*.ts' for TypeScript files). If not provided, it will search all files (*).
227
+ Usage:
228
+ <search_files>
229
+ <path>Directory path here</path>
230
+ <regex>Your regex pattern here</regex>
231
+ <file_pattern>file pattern here (optional)</file_pattern>
232
+ </search_files>
233
+ """
234
+ return self.params
235
+
236
+ @byzerllm.prompt()
237
+ def list_files(self) -> Dict:
238
+ """
239
+ Description: Request to list files and directories within the specified directory. If recursive is true, it will list all files and directories recursively. If recursive is false or not provided, it will only list the top-level contents. Do not use this tool to confirm the existence of files you may have created, as the user will let you know if the files were created successfully or not.
240
+ Parameters:
241
+ - path: (required) The path of the directory to list contents for (relative to the current working directory ${cwd.toPosix()})
242
+ - recursive: (optional) Whether to list files recursively. Use true for recursive listing, false or omit for top-level only.
243
+ Usage:
244
+ <list_files>
245
+ <path>Directory path here</path>
246
+ <recursive>true or false (optional)</recursive>
247
+ </list_files>
248
+ """
249
+ return self.params
250
+
251
+ @byzerllm.prompt()
252
+ def list_code_definition_names(self) -> Dict:
253
+ """
254
+ Description: Request to list definition names (classes, functions, methods, etc.) used in source code files at the top level of the specified directory. This tool provides insights into the codebase structure and important constructs, encapsulating high-level concepts and relationships that are crucial for understanding the overall architecture.
255
+ Parameters:
256
+ - path: (required) The path of the directory (relative to the current working directory ${cwd.toPosix()}) to list top level source code definitions for.
257
+ Usage:
258
+ <list_code_definition_names>
259
+ <path>Directory path here</path>
260
+ </list_code_definition_names>
261
+ """
262
+ return self.params
263
+
264
+ @byzerllm.prompt()
265
+ def ask_followup_question(self) -> Dict:
266
+ """
267
+ Description: Ask the user a question to gather additional information needed to complete the task. This tool should be used when you encounter ambiguities, need clarification, or require more details to proceed effectively. It allows for interactive problem-solving by enabling direct communication with the user. Use this tool judiciously to maintain a balance between gathering necessary information and avoiding excessive back-and-forth.
268
+ Parameters:
269
+ - question: (required) The question to ask the user. This should be a clear, specific question that addresses the information you need.
270
+ - options: (optional) An array of 2-5 options for the user to choose from. Each option should be a string describing a possible answer. You may not always need to provide options, but it may be helpful in many cases where it can save the user from having to type out a response manually. IMPORTANT: NEVER include an option to toggle to Act mode, as this would be something you need to direct the user to do manually themselves if needed.
271
+ Usage:
272
+ <ask_followup_question>
273
+ <question>Your question here</question>
274
+ <options>
275
+ Array of options here (optional), e.g. ["Option 1", "Option 2", "Option 3"]
276
+ </options>
277
+ </ask_followup_question>
278
+ """
279
+ return self.params
280
+
281
+ @byzerllm.prompt()
282
+ def attempt_completion(self) -> Dict:
283
+ """
284
+ Description: After each tool use, the user will respond with the result of that tool use, i.e. if it succeeded or failed, along with any reasons for failure. Once you've received the results of tool uses and can confirm that the task is complete, use this tool to present the result of your work to the user. Optionally you may provide a CLI command to showcase the result of your work. The user may respond with feedback if they are not satisfied with the result, which you can use to make improvements and try again.
285
+ IMPORTANT NOTE: This tool CANNOT be used until you've confirmed from the user that any previous tool uses were successful. Failure to do so will result in code corruption and system failure. Before using this tool, you must ask yourself in <thinking></thinking> tags if you've confirmed from the user that any previous tool uses were successful. If not, then DO NOT use this tool.
286
+ Parameters:
287
+ - result: (required) The result of the task. Formulate this result in a way that is final and does not require further input from the user. Don't end your result with questions or offers for further assistance.
288
+ - command: (optional) A CLI command to execute to show a live demo of the result to the user. For example, use \`open index.html\` to display a created html website, or \`open localhost:3000\` to display a locally running development server. But DO NOT use commands like \`echo\` or \`cat\` that merely print text. This command should be valid for the current operating system. Ensure the command is properly formatted and does not contain any harmful instructions.
289
+ Usage:
290
+ <attempt_completion>
291
+ <result>
292
+ Your final result description here
293
+ </result>
294
+ <command>Command to demonstrate result (optional)</command>
295
+ </attempt_completion>
296
+ """
297
+ return self.params
298
+
299
+ @byzerllm.prompt()
300
+ def plan_mode_respond(self) -> Dict:
301
+ """
302
+ Description: Respond to the user's inquiry in an effort to plan a solution to the user's task. This tool should be used when you need to provide a response to a question or statement from the user about how you plan to accomplish the task. This tool is only available in PLAN MODE. The environment_details will specify the current mode, if it is not PLAN MODE then you should not use this tool. Depending on the user's message, you may ask questions to get clarification about the user's request, architect a solution to the task, and to brainstorm ideas with the user. For example, if the user's task is to create a website, you may start by asking some clarifying questions, then present a detailed plan for how you will accomplish the task given the context, and perhaps engage in a back and forth to finalize the details before the user switches you to ACT MODE to implement the solution.
303
+ Parameters:
304
+ - response: (required) The response to provide to the user. Do not try to use tools in this parameter, this is simply a chat response. (You MUST use the response parameter, do not simply place the response text directly within <plan_mode_respond> tags.)
305
+ - options: (optional) An array of 2-5 options for the user to choose from. Each option should be a string describing a possible choice or path forward in the planning process. This can help guide the discussion and make it easier for the user to provide input on key decisions. You may not always need to provide options, but it may be helpful in many cases where it can save the user from having to type out a response manually. Do NOT present an option to toggle to Act mode, as this will be something you need to direct the user to do manually themselves.
306
+ Usage:
307
+ <plan_mode_respond>
308
+ <response>Your response here</response>
309
+ <options>
310
+ Array of options here (optional), e.g. ["Option 1", "Option 2", "Option 3"]
311
+ </options>
312
+ </plan_mode_respond>
313
+ """
314
+ return {}
315
+
316
+ @byzerllm.prompt()
317
+ def use_mcp_tool(self) -> Dict:
318
+ """
319
+ Description: Request to execute a tool via the Model Context Protocol (MCP) server. Use this when you need to execute a tool that is not natively supported by the agentic edit tools.
320
+ Parameters:
321
+ - server_name: (optional) The name of the MCP server to use. If not provided, the tool will automatically choose the best server based on the query.
322
+ - tool_name: (optional) The name of the tool to execute. If not provided, the tool will automatically choose the best tool in the selected server based on the query.
323
+ - query: (required) The query to pass to the tool.
324
+ Usage:
325
+ <use_mcp_tool>
326
+ <server_name>xxx</server_name>
327
+ <tool_name>xxxx</tool_name>
328
+ <query>
329
+ Your query here
330
+ </query>
331
+ </use_mcp_tool>
332
+ """
333
+ return self.params
334
+
335
+ @byzerllm.prompt()
336
+ def talk_to(self) -> Dict:
337
+ """
338
+ Description: Send a message to another agent
339
+ Parameters:
340
+ - agent_name: (required) The name of the agent to talk to
341
+ - content: (required) The message content
342
+ - mentions: (optional) An array of agent names to mention in the message
343
+ - print_conversation: (optional) Whether to print the conversation to the console
344
+ Usage:
345
+ <talk_to>
346
+ <agent_name>assistant2</agent_name>
347
+ <content>Hello assistant2, can you help me with this task?</content>
348
+ <mentions>["assistant3"]</mentions>
349
+ <print_conversation>true</print_conversation>
350
+ </talk_to>
351
+ """
352
+ return self.params
353
+
354
+ @byzerllm.prompt()
355
+ def talk_to_group_description(self) -> Dict:
356
+ """
357
+ Description: Send a message to a group of agents
358
+ Parameters:
359
+ - group_name: (required) The name of the group to talk to
360
+ - content: (required) The message content
361
+ - mentions: (optional) An array of agent names to mention in the message
362
+ - print_conversation: (optional) Whether to print the conversation to the console
363
+ Usage:
364
+ <talk_to_group>
365
+ <group_name>research_team</group_name>
366
+ <content>Hello team, I need your input on the research plan.</content>
367
+ <mentions>["assistant2", "assistant3"]</mentions>
368
+ <print_conversation>true</print_conversation>
369
+ </talk_to_group>
370
+ """
371
+ return self.params
372
+
373
+
374
+ class ToolExampleGenerators:
375
+ def __init__(self, params: Dict):
376
+ self.params = params
377
+
378
+ @byzerllm.prompt()
379
+ def example_1(self) -> Dict:
380
+ """
381
+ <execute_command>
382
+ <command>npm run dev</command>
383
+ <requires_approval>false</requires_approval>
384
+ </execute_command>
385
+ """
386
+ return self.params
387
+
388
+ @byzerllm.prompt()
389
+ def example_2(self) -> Dict:
390
+ """
391
+ <write_to_file>
392
+ <path>src/frontend-config.json</path>
393
+ <content>
394
+ {
395
+ "apiEndpoint": "https://api.example.com",
396
+ "theme": {
397
+ "primaryColor": "#007bff",
398
+ "secondaryColor": "#6c757d",
399
+ "fontFamily": "Arial, sans-serif"
400
+ },
401
+ "features": {
402
+ "darkMode": true,
403
+ "notifications": true,
404
+ "analytics": false
405
+ },
406
+ "version": "1.0.0"
407
+ }
408
+ </content>
409
+ </write_to_file>
410
+ """
411
+ return self.params
412
+
413
+ @byzerllm.prompt()
414
+ def example_3(self) -> Dict:
415
+ """
416
+ <replace_in_file>
417
+ <path>src/components/App.tsx</path>
418
+ <diff>
419
+ <<<<<<< SEARCH
420
+ import React from 'react';
421
+ =======
422
+ import React, { useState } from 'react';
423
+ >>>>>>> REPLACE
424
+
425
+ <<<<<<< SEARCH
426
+ function handleSubmit() {
427
+ saveData();
428
+ setLoading(false);
429
+ }
430
+
431
+ =======
432
+ >>>>>>> REPLACE
433
+
434
+ <<<<<<< SEARCH
435
+ return (
436
+ <div>
437
+ =======
438
+ function handleSubmit() {
439
+ saveData();
440
+ setLoading(false);
441
+ }
442
+
443
+ return (
444
+ <div>
445
+ >>>>>>> REPLACE
446
+ </diff>
447
+ </replace_in_file>
448
+ """
449
+ return self.params
450
+
451
+ @byzerllm.prompt()
452
+ def example_4(self) -> Dict:
453
+ """
454
+ <use_mcp_tool>
455
+ <server_name>github</server_name>
456
+ <tool_name>create_issue</tool_name>
457
+ <query>ower is octocat, repo is hello-world, title is Found a bug, body is I'm having a problem with this. labels is "bug" and "help wanted",assignees is "octocat"</query>
458
+ </use_mcp_tool>
459
+ """
460
+ return self.params
461
+
462
+
463
+ def register_default_tools_case_doc(params: Dict[str, Any]):
464
+ """
465
+ 注册默认工具用例文档
466
+ """
467
+ # 获取所有已注册的工具
468
+ registered_tools = set(ToolRegistry.get_all_registered_tools())
469
+
470
+ tool_case_gen = ToolsCaseGenerator(params)
471
+
472
+ # 定义默认工具用例文档
473
+ DEFAULT_TOOLS_CASE_DOC = {
474
+ "editing_files": {
475
+ "tools": ["replace_in_file", "write_to_file"],
476
+ "doc": tool_case_gen.editing_files_doc.prompt()
477
+ }
478
+ }
479
+
480
+ for case_name, case_info in DEFAULT_TOOLS_CASE_DOC.items():
481
+ # 检查所有工具是否存在
482
+ tools = case_info["tools"]
483
+ valid_tools = []
484
+
485
+ for tool in tools:
486
+ if tool in registered_tools:
487
+ valid_tools.append(tool)
488
+ else:
489
+ logger.warning(f"用例文档 {case_name} 引用了不存在的工具: {tool}")
490
+
491
+ # 只有当存在有效工具时才注册用例文档
492
+ if valid_tools:
493
+ ToolRegistry.register_tools_case_doc(
494
+ case_name=case_name,
495
+ tools=valid_tools,
496
+ doc=case_info["doc"]
497
+ )
498
+ logger.info(
499
+ f"成功注册用例文档 {case_name}, 有效工具: {', '.join(valid_tools)}")
500
+ else:
501
+ logger.warning(f"跳过注册用例文档 {case_name}, 因为没有有效工具")
502
+
503
+ logger.info(f"处理了 {len(DEFAULT_TOOLS_CASE_DOC)} 个默认工具用例文档")
504
+
505
+
506
+ def register_default_tools(params: Dict[str, Any]):
507
+ """
508
+ Register all default tools
509
+ """
510
+ tool_desc_gen = ToolDescGenerators(params)
511
+ tool_examples_gen = ToolExampleGenerators(params)
512
+
513
+ # 统一的工具定义数据结构
514
+ DEFAULT_TOOLS = {
515
+ "execute_command": {
516
+ "tool_cls": ExecuteCommandTool,
517
+ "resolver_cls": ExecuteCommandToolResolver,
518
+ "description": ToolDescription(
519
+ description=tool_desc_gen.execute_command.prompt(),
520
+ ),
521
+ "example": ToolExample(
522
+ title="Requesting to execute a command",
523
+ body=tool_examples_gen.example_1.prompt()
524
+ ),
525
+ "use_guideline": "",
526
+ "category": "system",
527
+ "is_default": True,
528
+ "case_docs": []
529
+ },
530
+ "read_file": {
531
+ "tool_cls": ReadFileTool,
532
+ "resolver_cls": ReadFileToolResolver,
533
+ "description": ToolDescription(
534
+ description=tool_desc_gen.read_file.prompt(),
535
+ ),
536
+ "use_guideline": "",
537
+ "category": "file_operation",
538
+ "is_default": True,
539
+ "case_docs": []
540
+ },
541
+ "write_to_file": {
542
+ "tool_cls": WriteToFileTool,
543
+ "resolver_cls": WriteToFileToolResolver,
544
+ "description": ToolDescription(
545
+ description=tool_desc_gen.write_to_file.prompt(),
546
+ ),
547
+ "example": ToolExample(
548
+ title="Requesting to create a new file",
549
+ body=tool_examples_gen.example_2.prompt()
550
+ ),
551
+ "use_guideline": "",
552
+ "category": "file_operation",
553
+ "is_default": True,
554
+ "case_docs": ["editing_files"]
555
+ },
556
+ "replace_in_file": {
557
+ "tool_cls": ReplaceInFileTool,
558
+ "resolver_cls": ReplaceInFileToolResolver,
559
+ "description": ToolDescription(
560
+ description=tool_desc_gen.replace_in_file.prompt(),
561
+ ),
562
+ "use_guideline": "",
563
+ "example": ToolExample(
564
+ title="Requesting to make targeted edits to a file",
565
+ body=tool_examples_gen.example_3.prompt()
566
+ ),
567
+ "category": "file_operation",
568
+ "is_default": True,
569
+ "case_docs": ["editing_files"]
570
+ },
571
+ "search_files": {
572
+ "tool_cls": SearchFilesTool,
573
+ "resolver_cls": SearchFilesToolResolver,
574
+ "description": ToolDescription(
575
+ description=tool_desc_gen.search_files.prompt(),
576
+ ),
577
+ "use_guideline": "",
578
+ "category": "file_operation",
579
+ "is_default": True,
580
+ "case_docs": []
581
+ },
582
+ "list_files": {
583
+ "tool_cls": ListFilesTool,
584
+ "resolver_cls": ListFilesToolResolver,
585
+ "description": ToolDescription(
586
+ description=tool_desc_gen.list_files.prompt(),
587
+ ),
588
+ "use_guideline": "",
589
+ "category": "file_operation",
590
+ "is_default": True,
591
+ "case_docs": []
592
+ },
593
+ "ask_followup_question": {
594
+ "tool_cls": AskFollowupQuestionTool,
595
+ "resolver_cls": AskFollowupQuestionToolResolver,
596
+ "description": ToolDescription(
597
+ description=tool_desc_gen.ask_followup_question.prompt(),
598
+ ),
599
+ "use_guideline": "",
600
+ "category": "interaction",
601
+ "is_default": True,
602
+ "case_docs": []
603
+ },
604
+ "attempt_completion": {
605
+ "tool_cls": AttemptCompletionTool,
606
+ "resolver_cls": AttemptCompletionToolResolver,
607
+ "description": ToolDescription(
608
+ description=tool_desc_gen.attempt_completion.prompt(),
609
+ ),
610
+ "use_guideline": "",
611
+ "category": "interaction",
612
+ "is_default": True,
613
+ "case_docs": []
614
+ },
615
+ "plan_mode_respond": {
616
+ "tool_cls": PlanModeRespondTool,
617
+ "resolver_cls": PlanModeRespondToolResolver,
618
+ "description": ToolDescription(
619
+ description=tool_desc_gen.plan_mode_respond.prompt(),
620
+ ),
621
+ "use_guideline": "",
622
+ "category": "interaction",
623
+ "is_default": True,
624
+ "case_docs": []
625
+ },
626
+ "use_mcp_tool": {
627
+ "tool_cls": UseMcpTool,
628
+ "resolver_cls": UseMcpToolResolver,
629
+ "description": ToolDescription(
630
+ description=tool_desc_gen.use_mcp_tool.prompt(),
631
+ ),
632
+ "example": ToolExample(
633
+ title="Another example of using an MCP tool (where the server name is a unique identifier listed in MCP_SERVER_LIST)",
634
+ body=tool_examples_gen.example_4.prompt()
635
+ ),
636
+ "use_guideline": "",
637
+ "category": "external",
638
+ "is_default": True,
639
+ "case_docs": []
640
+ },
641
+ "talk_to": {
642
+ "tool_cls": TalkToTool,
643
+ "resolver_cls": TalkToToolResolver,
644
+ "description": ToolDescription(
645
+ description=tool_desc_gen.talk_to.prompt(),
646
+ ),
647
+ "use_guideline": "",
648
+ "category": "interaction",
649
+ "is_default": True,
650
+ "case_docs": []
651
+ },
652
+ "talk_to_group": {
653
+ "tool_cls": TalkToGroupTool,
654
+ "resolver_cls": TalkToGroupToolResolver,
655
+ "description": ToolDescription(
656
+ description=tool_desc_gen.talk_to_group_description.prompt(),
657
+ ),
658
+ "use_guideline": "",
659
+ "category": "interaction",
660
+ "is_default": True,
661
+ "case_docs": []
662
+ }
663
+ }
664
+ # 先使用统一的工具注册方法注册所有工具
665
+ for tool_tag, tool_info in DEFAULT_TOOLS.items():
666
+ ToolRegistry.register_unified_tool(tool_tag, tool_info)
667
+
668
+ logger.info(
669
+ f"Registered {len(DEFAULT_TOOLS)} default tools using unified registration")
670
+
671
+ # 然后注册默认工具用例文档
672
+ # 这样可以确保在注册用例文档时,所有工具已经注册完成
673
+ register_default_tools_case_doc(params)
674
+
675
+
676
+ def get_registered_default_tools() -> List[str]:
677
+ """
678
+ Get the list of registered default tools
679
+
680
+ Returns:
681
+ List of default tool tags
682
+ """
683
+ return ToolRegistry.get_default_tools()