jarvis-ai-assistant 0.1.98__py3-none-any.whl → 0.1.100__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 jarvis-ai-assistant might be problematic. Click here for more details.

Files changed (45) hide show
  1. jarvis/__init__.py +1 -1
  2. jarvis/agent.py +199 -157
  3. jarvis/jarvis_code_agent/__init__.py +0 -0
  4. jarvis/jarvis_code_agent/main.py +202 -0
  5. jarvis/jarvis_codebase/main.py +415 -287
  6. jarvis/jarvis_coder/file_select.py +209 -0
  7. jarvis/jarvis_coder/git_utils.py +64 -2
  8. jarvis/jarvis_coder/main.py +13 -397
  9. jarvis/jarvis_coder/patch_handler.py +229 -81
  10. jarvis/jarvis_coder/plan_generator.py +49 -7
  11. jarvis/jarvis_platform/main.py +2 -2
  12. jarvis/jarvis_rag/main.py +11 -11
  13. jarvis/jarvis_smart_shell/main.py +5 -5
  14. jarvis/models/base.py +6 -1
  15. jarvis/models/kimi.py +2 -2
  16. jarvis/models/ollama.py +2 -2
  17. jarvis/models/openai.py +1 -1
  18. jarvis/models/registry.py +38 -18
  19. jarvis/tools/ask_user.py +12 -9
  20. jarvis/tools/chdir.py +9 -5
  21. jarvis/tools/create_code_sub_agent.py +56 -0
  22. jarvis/tools/{sub_agent.py → create_sub_agent.py} +6 -2
  23. jarvis/tools/execute_code_modification.py +70 -0
  24. jarvis/tools/{shell.py → execute_shell.py} +2 -2
  25. jarvis/tools/{file_ops.py → file_operation.py} +19 -15
  26. jarvis/tools/find_files.py +119 -0
  27. jarvis/tools/{generator.py → generate_tool.py} +27 -25
  28. jarvis/tools/methodology.py +32 -26
  29. jarvis/tools/rag.py +37 -33
  30. jarvis/tools/{webpage.py → read_webpage.py} +4 -2
  31. jarvis/tools/registry.py +94 -48
  32. jarvis/tools/search.py +19 -16
  33. jarvis/tools/select_code_files.py +61 -0
  34. jarvis/tools/thinker.py +7 -5
  35. jarvis/utils.py +155 -32
  36. {jarvis_ai_assistant-0.1.98.dist-info → jarvis_ai_assistant-0.1.100.dist-info}/METADATA +9 -8
  37. jarvis_ai_assistant-0.1.100.dist-info/RECORD +51 -0
  38. {jarvis_ai_assistant-0.1.98.dist-info → jarvis_ai_assistant-0.1.100.dist-info}/entry_points.txt +2 -1
  39. jarvis/main.py +0 -155
  40. jarvis/tools/codebase_qa.py +0 -74
  41. jarvis/tools/coder.py +0 -69
  42. jarvis_ai_assistant-0.1.98.dist-info/RECORD +0 -47
  43. {jarvis_ai_assistant-0.1.98.dist-info → jarvis_ai_assistant-0.1.100.dist-info}/LICENSE +0 -0
  44. {jarvis_ai_assistant-0.1.98.dist-info → jarvis_ai_assistant-0.1.100.dist-info}/WHEEL +0 -0
  45. {jarvis_ai_assistant-0.1.98.dist-info → jarvis_ai_assistant-0.1.100.dist-info}/top_level.txt +0 -0
jarvis/models/kimi.py CHANGED
@@ -35,8 +35,8 @@ class KimiModel(BasePlatform):
35
35
  PrettyOutput.print(" • Find the Authorization header in the request", OutputType.INFO)
36
36
  PrettyOutput.print(" • Copy the token value (remove the 'Bearer ' prefix)", OutputType.INFO)
37
37
  PrettyOutput.print("\n2. Set environment variable:", OutputType.INFO)
38
- PrettyOutput.print(" • Method 1: Create or edit ~/.jarvis_env file:", OutputType.INFO)
39
- PrettyOutput.print(" echo 'KIMI_API_KEY=your_key_here' > ~/.jarvis_env", OutputType.INFO)
38
+ PrettyOutput.print(" • Method 1: Create or edit ~/.jarvis/env file:", OutputType.INFO)
39
+ PrettyOutput.print(" echo 'KIMI_API_KEY=your_key_here' > ~/.jarvis/env", OutputType.INFO)
40
40
  PrettyOutput.print("\n • Method 2: Set environment variable directly:", OutputType.INFO)
41
41
  PrettyOutput.print(" export KIMI_API_KEY=your_key_here", OutputType.INFO)
42
42
  PrettyOutput.print("\nAfter setting, run Jarvis again.", OutputType.INFO)
jarvis/models/ollama.py CHANGED
@@ -1,7 +1,7 @@
1
1
  import requests
2
2
  from typing import List, Dict, Tuple
3
3
  from jarvis.models.base import BasePlatform
4
- from jarvis.utils import OutputType, PrettyOutput
4
+ from jarvis.utils import OutputType, PrettyOutput, get_single_line_input
5
5
  import os
6
6
  import json
7
7
 
@@ -136,7 +136,7 @@ if __name__ == "__main__":
136
136
  ollama = OllamaPlatform()
137
137
  while True:
138
138
  try:
139
- message = input("\nInput question (Ctrl+C to exit): ")
139
+ message = get_single_line_input("\nInput question (Ctrl+C to exit)")
140
140
  ollama.chat_until_success(message)
141
141
  except KeyboardInterrupt:
142
142
  print("\nGoodbye!")
jarvis/models/openai.py CHANGED
@@ -23,7 +23,7 @@ class OpenAIModel(BasePlatform):
23
23
  PrettyOutput.print(" • OPENAI_API_KEY: API key", OutputType.INFO)
24
24
  PrettyOutput.print(" • OPENAI_API_BASE: (optional) API base address, default using https://api.openai.com/v1", OutputType.INFO)
25
25
  PrettyOutput.print("\nYou can set them in the following ways:", OutputType.INFO)
26
- PrettyOutput.print("1. Create or edit ~/.jarvis_env file:", OutputType.INFO)
26
+ PrettyOutput.print("1. Create or edit ~/.jarvis/env file:", OutputType.INFO)
27
27
  PrettyOutput.print(" OPENAI_API_KEY=your_api_key", OutputType.INFO)
28
28
  PrettyOutput.print(" OPENAI_API_BASE=your_api_base", OutputType.INFO)
29
29
  PrettyOutput.print(" OPENAI_MODEL_NAME=your_model_name", OutputType.INFO)
jarvis/models/registry.py CHANGED
@@ -3,8 +3,8 @@ import inspect
3
3
  import os
4
4
  import sys
5
5
  from typing import Dict, Type, Optional, List
6
- from .base import BasePlatform
7
- from ..utils import PrettyOutput, OutputType
6
+ from jarvis.models.base import BasePlatform
7
+ from jarvis.utils import PrettyOutput, OutputType
8
8
 
9
9
  REQUIRED_METHODS = [
10
10
  ('chat', ['message']), # 方法名和参数列表
@@ -23,11 +23,10 @@ class PlatformRegistry:
23
23
 
24
24
  global_platform_name = "kimi"
25
25
  global_platform_registry = None
26
- suppress_output = False
27
26
 
28
27
  @staticmethod
29
28
  def get_platform_dir() -> str:
30
- user_platform_dir = os.path.expanduser("~/.jarvis_models")
29
+ user_platform_dir = os.path.expanduser("~/.jarvis/models")
31
30
  if not os.path.exists(user_platform_dir):
32
31
  try:
33
32
  os.makedirs(user_platform_dir)
@@ -117,7 +116,7 @@ class PlatformRegistry:
117
116
  module = importlib.import_module(module_name)
118
117
 
119
118
  # 遍历模块中的所有类
120
- for name, obj in inspect.getmembers(module):
119
+ for _, obj in inspect.getmembers(module):
121
120
  # 检查是否是BasePlatform的子类,但不是BasePlatform本身
122
121
  if (inspect.isclass(obj) and
123
122
  issubclass(obj, BasePlatform) and
@@ -126,8 +125,6 @@ class PlatformRegistry:
126
125
  # 检查平台实现
127
126
  if not PlatformRegistry.check_platform_implementation(obj):
128
127
  continue
129
- if not PlatformRegistry.suppress_output:
130
- PrettyOutput.print(f"Load platform from {os.path.join(directory, filename)}: {obj.platform_name}", OutputType.SUCCESS) # type: ignore
131
128
  platforms[obj.platform_name] = obj # type: ignore
132
129
  break
133
130
  except Exception as e:
@@ -140,22 +137,22 @@ class PlatformRegistry:
140
137
  def get_global_platform_registry():
141
138
  """Get global platform registry"""
142
139
  if PlatformRegistry.global_platform_registry is None:
143
- PlatformRegistry.global_platform_registry = PlatformRegistry()
144
-
145
- # 从用户平台目录加载额外平台
146
- platform_dir = PlatformRegistry.get_platform_dir()
147
- if platform_dir and os.path.exists(platform_dir):
148
- for platform_name, platform_class in PlatformRegistry.load_platform_from_dir(platform_dir).items():
149
- PlatformRegistry.global_platform_registry.register_platform(platform_name, platform_class)
150
- platform_dir = os.path.dirname(__file__)
151
- if platform_dir and os.path.exists(platform_dir):
152
- for platform_name, platform_class in PlatformRegistry.load_platform_from_dir(platform_dir).items():
153
- PlatformRegistry.global_platform_registry.register_platform(platform_name, platform_class)
140
+ PlatformRegistry.global_platform_registry = PlatformRegistry()
154
141
  return PlatformRegistry.global_platform_registry
155
142
 
156
143
  def __init__(self):
157
144
  """Initialize platform registry"""
158
145
  self.platforms: Dict[str, Type[BasePlatform]] = {}
146
+ # 从用户平台目录加载额外平台
147
+ platform_dir = PlatformRegistry.get_platform_dir()
148
+ if platform_dir and os.path.exists(platform_dir):
149
+ for platform_name, platform_class in PlatformRegistry.load_platform_from_dir(platform_dir).items():
150
+ self.register_platform(platform_name, platform_class)
151
+ platform_dir = os.path.dirname(__file__)
152
+ if platform_dir and os.path.exists(platform_dir):
153
+ for platform_name, platform_class in PlatformRegistry.load_platform_from_dir(platform_dir).items():
154
+ self.register_platform(platform_name, platform_class)
155
+
159
156
 
160
157
  def get_normal_platform(self) -> BasePlatform:
161
158
  platform_name = os.environ.get("JARVIS_PLATFORM", "kimi")
@@ -215,6 +212,29 @@ class PlatformRegistry:
215
212
  PrettyOutput.print(f"Create platform failed: {str(e)}", OutputType.ERROR)
216
213
  return None
217
214
 
215
+ def use_platforms(self, platform_names: List[str]):
216
+ """Restrict available platforms to the specified list
217
+
218
+ Args:
219
+ platform_names: List of platform names to use
220
+ """
221
+ self.platforms = {
222
+ name: cls
223
+ for name, cls in self.platforms.items()
224
+ if name in platform_names
225
+ }
226
+
227
+ def dont_use_platforms(self, platform_names: List[str]):
228
+ """Restrict available platforms by excluding the specified list
229
+
230
+ Args:
231
+ platform_names: List of platform names to exclude
232
+ """
233
+ self.platforms = {
234
+ name: cls
235
+ for name, cls in self.platforms.items()
236
+ if name not in platform_names
237
+ }
218
238
  def get_available_platforms(self) -> List[str]:
219
239
  """Get available platform list"""
220
240
  return list(self.platforms.keys())
jarvis/tools/ask_user.py CHANGED
@@ -18,37 +18,40 @@ class AskUserTool:
18
18
 
19
19
 
20
20
  def execute(self, args: Dict[str, Any]) -> Dict[str, Any]:
21
- """执行询问用户操作
21
+ """Execute the operation of asking the user
22
22
 
23
23
  Args:
24
- args: 包含问题的字典
24
+ args: A dictionary containing the question
25
25
 
26
26
  Returns:
27
- Dict: 包含用户响应的字典
27
+ Dict: A dictionary containing the user's response
28
28
  """
29
29
  try:
30
30
  question = args["question"]
31
31
 
32
- # 显示问题
33
- PrettyOutput.print("\n问题:", OutputType.SYSTEM)
32
+ # Display the question
33
+ PrettyOutput.print("\nQuestion:", OutputType.SYSTEM)
34
34
  PrettyOutput.print(question, OutputType.SYSTEM)
35
35
 
36
- # 获取用户输入
36
+ # Get user input
37
37
  user_response = get_multiline_input("Please enter your answer (input empty line to end)")
38
38
 
39
39
  if user_response == "__interrupt__":
40
40
  return {
41
41
  "success": False,
42
- "error": "User canceled input"
42
+ "stdout": "",
43
+ "stderr": "User canceled input"
43
44
  }
44
45
 
45
46
  return {
46
47
  "success": True,
47
- "stdout": user_response
48
+ "stdout": user_response,
49
+ "stderr": ""
48
50
  }
49
51
 
50
52
  except Exception as e:
51
53
  return {
52
54
  "success": False,
53
- "error": f"Failed to ask user: {str(e)}"
55
+ "stdout": "",
56
+ "stderr": f"Failed to ask user: {str(e)}"
54
57
  }
jarvis/tools/chdir.py CHANGED
@@ -38,14 +38,16 @@ class ChdirTool:
38
38
  if not os.path.exists(path):
39
39
  return {
40
40
  "success": False,
41
- "error": f"Directory does not exist: {path}"
41
+ "stdout": "",
42
+ "stderr": f"Directory does not exist: {path}"
42
43
  }
43
44
 
44
45
  # 检查是否是目录
45
46
  if not os.path.isdir(path):
46
47
  return {
47
48
  "success": False,
48
- "error": f"The path is not a directory: {path}"
49
+ "stdout": "",
50
+ "stderr": f"The path is not a directory: {path}"
49
51
  }
50
52
 
51
53
  # 尝试切换目录
@@ -61,12 +63,14 @@ class ChdirTool:
61
63
  except PermissionError:
62
64
  return {
63
65
  "success": False,
64
- "error": f"No permission to access directory: {path}"
66
+ "stdout": "",
67
+ "stderr": f"No permission to access directory: {path}"
65
68
  }
66
69
  except Exception as e:
67
70
  return {
68
71
  "success": False,
69
- "error": f"Failed to switch directory: {str(e)}"
72
+ "stdout": "",
73
+ "stderr": f"Failed to switch directory: {str(e)}"
70
74
  }
71
75
 
72
76
  def main():
@@ -83,7 +87,7 @@ def main():
83
87
  if result["success"]:
84
88
  PrettyOutput.print(result["stdout"], OutputType.SUCCESS)
85
89
  else:
86
- PrettyOutput.print(result["error"], OutputType.ERROR)
90
+ PrettyOutput.print(result["stderr"], OutputType.ERROR)
87
91
 
88
92
  if __name__ == "__main__":
89
93
  main()
@@ -0,0 +1,56 @@
1
+ from typing import Dict, Any
2
+
3
+ from jarvis.agent import Agent
4
+ from jarvis.utils import OutputType, PrettyOutput
5
+ from jarvis.jarvis_code_agent.main import system_prompt
6
+
7
+
8
+ class CodeSubAgentTool:
9
+ name = "create_code_sub_agent"
10
+ description = "Create a sub-agent to handle specific code development subtasks"
11
+ parameters = {
12
+ "type": "object",
13
+ "properties": {
14
+ "name": {
15
+ "type": "string",
16
+ "description": "The name of the sub-agent"
17
+ },
18
+ "subtask": {
19
+ "type": "string",
20
+ "description": "The specific code development subtask to complete"
21
+ },
22
+ },
23
+ "required": ["subtask", "name"]
24
+ }
25
+
26
+ def execute(self, args: Dict) -> Dict[str, Any]:
27
+ """Execute code development subtask"""
28
+ try:
29
+ subtask = args["subtask"]
30
+ name = args["name"]
31
+
32
+ PrettyOutput.print(f"Creating code sub-agent {name} for subtask: {subtask}", OutputType.INFO)
33
+
34
+ # Create sub-agent
35
+ sub_agent = Agent(
36
+ system_prompt=system_prompt,
37
+ name=name,
38
+ is_sub_agent=True
39
+ )
40
+
41
+ # Execute subtask
42
+ result = sub_agent.run(subtask)
43
+
44
+ return {
45
+ "success": True,
46
+ "stdout": f"Code Development Subtask Results:\n\n{result}",
47
+ "stderr": ""
48
+ }
49
+
50
+ except Exception as e:
51
+ PrettyOutput.print(str(e), OutputType.ERROR)
52
+ return {
53
+ "success": False,
54
+ "stdout": "",
55
+ "stderr": f"Failed to execute code development subtask: {str(e)}"
56
+ }
@@ -1,7 +1,7 @@
1
1
  from typing import Dict, Any
2
2
 
3
3
 
4
- from jarvis.agent import Agent
4
+ from jarvis.agent import Agent, origin_agent_system_prompt
5
5
  from jarvis.utils import OutputType, PrettyOutput
6
6
 
7
7
 
@@ -58,8 +58,11 @@ class SubAgentTool:
58
58
  if goal:
59
59
  task_description += f"\n\nCompletion goal:\n{goal}"
60
60
 
61
+
62
+
61
63
  # Create sub-agent
62
64
  sub_agent = Agent(
65
+ system_prompt=origin_agent_system_prompt,
63
66
  name=agent_name,
64
67
  is_sub_agent=True
65
68
  )
@@ -78,5 +81,6 @@ class SubAgentTool:
78
81
  PrettyOutput.print(str(e), OutputType.ERROR)
79
82
  return {
80
83
  "success": False,
81
- "error": f"Sub-agent execution failed: {str(e)}"
84
+ "stdout": "",
85
+ "stderr": f"Sub-agent execution failed: {str(e)}"
82
86
  }
@@ -0,0 +1,70 @@
1
+ from typing import Dict, Any
2
+
3
+ from jarvis.agent import Agent
4
+ from jarvis.utils import OutputType, PrettyOutput
5
+ from jarvis.jarvis_coder.patch_handler import PatchHandler
6
+
7
+
8
+ class CodeModifyTool:
9
+ name = "execute_code_modification"
10
+ description = "Execute code modifications according to the provided plan"
11
+ parameters = {
12
+ "type": "object",
13
+ "properties": {
14
+ "task": {
15
+ "type": "string",
16
+ "description": "The code modification task description"
17
+ },
18
+ "structured_plan": {
19
+ "type": "object",
20
+ "description": "Dictionary mapping file paths to their modification plans. Example: {'path/to/file.py': 'Add function foo() to handle...'}",
21
+ "additionalProperties": {
22
+ "type": "string",
23
+ "description": "Modification plan for a specific file"
24
+ },
25
+ "examples": [{
26
+ "src/file1.py": "Add error handling to process_data()",
27
+ "src/file2.py": "Update API endpoint URL in get_data()"
28
+ }]
29
+ }
30
+ },
31
+ "required": ["task", "raw_plan", "structured_plan"]
32
+ }
33
+
34
+ def execute(self, args: Dict) -> Dict[str, Any]:
35
+ """Execute code modifications using PatchHandler"""
36
+ try:
37
+ task = args["task"]
38
+ structured_plan = args["structured_plan"]
39
+
40
+ PrettyOutput.print("Executing code modifications...", OutputType.INFO)
41
+
42
+ # Create patch handler instance
43
+ patch_handler = PatchHandler()
44
+
45
+ # Apply patches and handle the process
46
+ success, additional_info = patch_handler.handle_patch_application(
47
+ feature=task,
48
+ structed_plan=structured_plan
49
+ )
50
+
51
+ if not success:
52
+ return {
53
+ "success": False,
54
+ "stdout": "Changes have been rolled back",
55
+ "stderr": additional_info
56
+ }
57
+
58
+ return {
59
+ "success": True,
60
+ "stdout": "Code modifications have been successfully applied and committed",
61
+ "stderr": additional_info
62
+ }
63
+
64
+ except Exception as e:
65
+ PrettyOutput.print(str(e), OutputType.ERROR)
66
+ return {
67
+ "success": False,
68
+ "stdout": "",
69
+ "stderr": f"Failed to execute code modifications: {str(e)}"
70
+ }
@@ -64,7 +64,6 @@ class ShellTool:
64
64
  "success": return_code == 0,
65
65
  "stdout": output,
66
66
  "stderr": "",
67
- "return_code": return_code
68
67
  }
69
68
 
70
69
  except Exception as e:
@@ -74,5 +73,6 @@ class ShellTool:
74
73
  PrettyOutput.print(str(e), OutputType.ERROR)
75
74
  return {
76
75
  "success": False,
77
- "error": str(e)
76
+ "stdout": "",
77
+ "stderr": str(e)
78
78
  }
@@ -1,6 +1,5 @@
1
- from typing import Dict, Any, Protocol
1
+ from typing import Dict, Any
2
2
  import os
3
- from enum import Enum
4
3
 
5
4
  from jarvis.utils import OutputType, PrettyOutput
6
5
 
@@ -36,15 +35,15 @@ class FileOperationTool:
36
35
 
37
36
 
38
37
  def execute(self, args: Dict) -> Dict[str, Any]:
39
- """执行文件操作"""
38
+ """Execute file operations"""
40
39
  try:
41
40
  operation = args["operation"]
42
41
  filepath = args["filepath"]
43
42
  encoding = args.get("encoding", "utf-8")
44
43
 
45
- # 记录操作和完整路径
44
+ # Record the operation and the full path
46
45
  abs_path = os.path.abspath(filepath)
47
- PrettyOutput.print(f"文件操作: {operation} - {abs_path}", OutputType.INFO)
46
+ PrettyOutput.print(f"File operation: {operation} - {abs_path}", OutputType.INFO)
48
47
 
49
48
  if operation == "exists":
50
49
  exists = os.path.exists(filepath)
@@ -58,18 +57,20 @@ class FileOperationTool:
58
57
  if not os.path.exists(filepath):
59
58
  return {
60
59
  "success": False,
61
- "error": f"文件不存在: {filepath}"
60
+ "stdout": "",
61
+ "stderr": f"文件不存在: {filepath}"
62
62
  }
63
63
 
64
- # 检查文件大小
64
+ # Check file size
65
65
  if os.path.getsize(filepath) > 10 * 1024 * 1024: # 10MB
66
66
  return {
67
67
  "success": False,
68
- "error": "文件过大 (>10MB)"
68
+ "stdout": "",
69
+ "stderr": "File too large (>10MB)"
69
70
  }
70
71
 
71
- with open(filepath, 'r', encoding=encoding) as f:
72
- content = f.read()
72
+ content = open(filepath, 'r', encoding=encoding).read()
73
+ PrettyOutput.print(content, OutputType.INFO)
73
74
  return {
74
75
  "success": True,
75
76
  "stdout": content,
@@ -80,10 +81,11 @@ class FileOperationTool:
80
81
  if not args.get("content"):
81
82
  return {
82
83
  "success": False,
83
- "error": "写入/追加操作需要提供content参数"
84
+ "stdout": "",
85
+ "stderr": "Write/append operation requires providing the content parameter"
84
86
  }
85
87
 
86
- # 创建目录(如果不存在)
88
+ # Create directory (if it doesn't exist)
87
89
  os.makedirs(os.path.dirname(os.path.abspath(filepath)), exist_ok=True)
88
90
 
89
91
  mode = 'a' if operation == "append" else 'w'
@@ -92,19 +94,21 @@ class FileOperationTool:
92
94
 
93
95
  return {
94
96
  "success": True,
95
- "stdout": f"成功{operation}内容到 {filepath}",
97
+ "stdout": f"Successfully {operation} content to {filepath}",
96
98
  "stderr": ""
97
99
  }
98
100
 
99
101
  else:
100
102
  return {
101
103
  "success": False,
102
- "error": f"未知操作: {operation}"
104
+ "stdout": "",
105
+ "stderr": f"Unknown operation: {operation}"
103
106
  }
104
107
 
105
108
  except Exception as e:
106
109
  PrettyOutput.print(str(e), OutputType.ERROR)
107
110
  return {
108
111
  "success": False,
109
- "error": f"文件操作失败: {str(e)}"
112
+ "stdout": "",
113
+ "stderr": f"File operation failed: {str(e)}"
110
114
  }
@@ -0,0 +1,119 @@
1
+ from typing import Dict, Any
2
+
3
+ from jarvis.agent import Agent
4
+ from jarvis.tools.registry import ToolRegistry
5
+ from jarvis.utils import OutputType, PrettyOutput
6
+
7
+ find_files_system_prompt = """You are a Find Files Agent specialized in searching and identifying relevant code files in a codebase. Your task is to find files that are most likely related to the given requirements or problems.
8
+
9
+ SEARCH WORKFLOW:
10
+ 1. Understand Search Requirements
11
+ - Analyze the search query thoroughly
12
+ - Identify key technical terms and concepts
13
+ - Break down complex requirements into searchable terms
14
+
15
+ 2. Execute Search Strategy
16
+ - Use shell commands to search systematically:
17
+ * Search for key terms:
18
+ <TOOL_CALL>
19
+ name: execute_shell
20
+ arguments:
21
+ command: grep -r "pattern" .
22
+ </TOOL_CALL>
23
+ * Find files by name patterns:
24
+ <TOOL_CALL>
25
+ name: execute_shell
26
+ arguments:
27
+ command: find . -name "pattern"
28
+ </TOOL_CALL>
29
+ * Examine file contents:
30
+ <TOOL_CALL>
31
+ name: execute_shell
32
+ arguments:
33
+ command: grep -A 5 -B 5 "pattern" file.py
34
+ </TOOL_CALL>
35
+
36
+ 3. Analyze Results
37
+ - Review each potential file
38
+ - Check file relevance
39
+ - Examine file relationships
40
+ - Consider file dependencies
41
+
42
+ 4. Generate File List
43
+ - List all relevant files
44
+ - Sort by relevance
45
+ - Include brief explanation for each file
46
+ - Format output as YAML
47
+
48
+ OUTPUT FORMAT:
49
+ files:
50
+ - path: path/to/file1
51
+ relevance: "Brief explanation of why this file is relevant"
52
+ - path: path/to/file2
53
+ relevance: "Brief explanation of why this file is relevant"
54
+
55
+ SEARCH BEST PRACTICES:
56
+ - Use multiple search terms
57
+ - Consider file naming conventions
58
+ - Check both file names and contents
59
+ - Look for related files (imports, dependencies)
60
+ - Use grep with context (-A, -B options)
61
+ - Search in specific directories when appropriate
62
+ - Exclude irrelevant directories (like .git, __pycache__)
63
+
64
+ IMPORTANT:
65
+ 1. Focus on finding the most relevant files
66
+ 2. Avoid listing irrelevant files
67
+ 3. Explain relevance clearly but concisely
68
+ 4. Consider both direct and indirect relevance
69
+ 5. Use file content to confirm relevance
70
+ """
71
+
72
+ class FindFilesTool:
73
+ name = "find_files"
74
+ description = "Search and identify relevant code files in the codebase based on requirements or problems"
75
+ parameters = {
76
+ "type": "object",
77
+ "properties": {
78
+ "query": {
79
+ "type": "string",
80
+ "description": "The search query or requirement description"
81
+ }
82
+ },
83
+ "required": ["query"]
84
+ }
85
+
86
+ def execute(self, args: Dict) -> Dict[str, Any]:
87
+ """Execute file search task"""
88
+ try:
89
+ query = args["query"]
90
+
91
+ PrettyOutput.print(f"Creating Find Files agent to search for: {query}", OutputType.INFO)
92
+
93
+ tool_registry = ToolRegistry()
94
+ tool_registry.use_tools(["ask_user", "execute_shell", "file_operation"])
95
+
96
+ # Create find files agent
97
+ find_agent = Agent(
98
+ system_prompt=find_files_system_prompt,
99
+ name="Find Files Agent",
100
+ is_sub_agent=True,
101
+ tool_registry=tool_registry
102
+ )
103
+
104
+ # Execute search
105
+ result = find_agent.run(query)
106
+
107
+ return {
108
+ "success": True,
109
+ "stdout": result,
110
+ "stderr": ""
111
+ }
112
+
113
+ except Exception as e:
114
+ PrettyOutput.print(str(e), OutputType.ERROR)
115
+ return {
116
+ "success": False,
117
+ "stdout": "",
118
+ "stderr": f"Failed to execute file search: {str(e)}"
119
+ }