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/__init__.py CHANGED
@@ -1,3 +1,3 @@
1
1
  """Jarvis AI Assistant"""
2
2
 
3
- __version__ = "0.1.98"
3
+ __version__ = "0.1.100"
jarvis/agent.py CHANGED
@@ -1,32 +1,39 @@
1
+ import argparse
1
2
  import time
2
3
  from typing import Dict, List, Optional
3
4
 
5
+ from prompt_toolkit import prompt
4
6
  import yaml
5
- import numpy as np
6
- import faiss
7
7
 
8
- from .models.registry import PlatformRegistry
9
- from .tools import ToolRegistry
10
- from .utils import PrettyOutput, OutputType, get_max_context_length, get_multiline_input, load_embedding_model
8
+ from jarvis.models.registry import PlatformRegistry
9
+ from jarvis.tools import ToolRegistry
10
+ from jarvis.tools.registry import load_tools
11
+ from jarvis.utils import PrettyOutput, OutputType, get_single_line_input, load_methodology, add_agent, delete_current_agent, get_max_context_length, get_multiline_input, load_embedding_model, init_env
11
12
  import os
12
13
 
13
14
  class Agent:
14
- def __init__(self, name: str = "Jarvis", is_sub_agent: bool = False):
15
+
16
+ def __del__(self):
17
+ delete_current_agent()
18
+
19
+ def __init__(self, system_prompt: str, name: str = "Jarvis", is_sub_agent: bool = False, tool_registry: Optional[ToolRegistry] = None):
15
20
  """Initialize Agent with a model, optional tool registry and name
16
21
 
17
22
  Args:
18
- model: LLM model instance
19
- tool_registry: Tool registry instance
23
+ system_prompt: System prompt
20
24
  name: Agent name, default is "Jarvis"
21
25
  is_sub_agent: Whether it is a sub-agent, default is False
26
+ tool_registry: Tool registry instance
22
27
  """
28
+ add_agent(name)
29
+ PrettyOutput.print(f"Welcome to Jarvis, your AI assistant, Initiating...", OutputType.SYSTEM)
23
30
  self.model = PlatformRegistry.get_global_platform_registry().get_normal_platform()
24
- self.tool_registry = ToolRegistry.get_global_tool_registry()
31
+ self.tool_registry = tool_registry if tool_registry else ToolRegistry.get_global_tool_registry()
25
32
  self.name = name
26
33
  self.is_sub_agent = is_sub_agent
27
34
  self.prompt = ""
28
35
  self.conversation_length = 0 # Use length counter instead
29
-
36
+ self.system_prompt = system_prompt
30
37
  # Load configuration from environment variables
31
38
  self.embedding_dimension = 1536 # Default for many embedding models
32
39
  self.max_context_length = get_max_context_length()
@@ -46,10 +53,7 @@ class Agent:
46
53
  PrettyOutput.print("Successfully loaded embedding model", OutputType.SUCCESS)
47
54
 
48
55
  # Initialize HNSW index (use correct dimension)
49
- hnsw_index = faiss.IndexHNSWFlat(self.embedding_dimension, 16)
50
- hnsw_index.hnsw.efConstruction = 40
51
- hnsw_index.hnsw.efSearch = 16
52
- self.methodology_index = faiss.IndexIDMap(hnsw_index)
56
+
53
57
 
54
58
  except Exception as e:
55
59
  PrettyOutput.print(f"Failed to load embedding model: {str(e)}", OutputType.ERROR)
@@ -58,6 +62,8 @@ class Agent:
58
62
  # Initialize methodology related attributes
59
63
  self.methodology_data = []
60
64
 
65
+ PrettyOutput.section(f"Jarvis initialized - With {self.model.name()}", OutputType.SYSTEM)
66
+
61
67
  @staticmethod
62
68
  def extract_tool_calls(content: str) -> List[Dict]:
63
69
  """Extract tool calls from content, if multiple tool calls are detected, raise an exception, and return the content before the tool call and the tool call"""
@@ -65,7 +71,16 @@ class Agent:
65
71
  lines = content.split('\n')
66
72
  tool_call_lines = []
67
73
  in_tool_call = False
68
-
74
+
75
+ tool_call_help = """Tool Usage Format:
76
+
77
+ <TOOL_CALL>
78
+ name: tool_name
79
+ arguments:
80
+ param1: value1
81
+ param2: value2
82
+ </TOOL_CALL>"""
83
+
69
84
  # Process line by line
70
85
  for line in lines:
71
86
  if '<TOOL_CALL>' in line:
@@ -87,7 +102,7 @@ class Agent:
87
102
  }]
88
103
  else:
89
104
  PrettyOutput.print("Tool call missing necessary fields", OutputType.ERROR)
90
- raise Exception("Tool call missing necessary fields")
105
+ raise Exception("Tool call missing necessary fields, " + tool_call_help)
91
106
  except yaml.YAMLError as e:
92
107
  PrettyOutput.print(f"YAML parsing error: {str(e)}", OutputType.ERROR)
93
108
  raise Exception(f"YAML parsing error: {str(e)}")
@@ -117,78 +132,6 @@ class Agent:
117
132
  sleep_time = 30
118
133
  continue
119
134
 
120
- def _create_methodology_embedding(self, methodology_text: str) -> np.ndarray:
121
- """Create embedding vector for methodology text"""
122
- try:
123
- # Truncate long text
124
- max_length = 512
125
- text = ' '.join(methodology_text.split()[:max_length])
126
-
127
- # 使用sentence_transformers模型获取嵌入向量
128
- embedding = self.embedding_model.encode([text],
129
- convert_to_tensor=True,
130
- normalize_embeddings=True)
131
- vector = np.array(embedding.cpu().numpy(), dtype=np.float32)
132
- return vector[0] # Return first vector, because we only encoded one text
133
- except Exception as e:
134
- PrettyOutput.print(f"Failed to create methodology embedding vector: {str(e)}", OutputType.ERROR)
135
- return np.zeros(self.embedding_dimension, dtype=np.float32)
136
-
137
- def _load_methodology(self, user_input: str) -> Dict[str, str]:
138
- """Load methodology and build vector index"""
139
- PrettyOutput.print("Loading methodology...", OutputType.PROGRESS)
140
- user_jarvis_methodology = os.path.expanduser("~/.jarvis_methodology")
141
- if not os.path.exists(user_jarvis_methodology):
142
- return {}
143
-
144
- try:
145
- with open(user_jarvis_methodology, "r", encoding="utf-8") as f:
146
- data = yaml.safe_load(f)
147
-
148
- # Reset data structure
149
- self.methodology_data = []
150
- vectors = []
151
- ids = []
152
-
153
- # Create embedding vector for each methodology
154
- for i, (key, value) in enumerate(data.items()):
155
- PrettyOutput.print(f"Vectorizing methodology: {key} ...", OutputType.INFO)
156
- methodology_text = f"{key}\n{value}"
157
- embedding = self._create_methodology_embedding(methodology_text)
158
- vectors.append(embedding)
159
- ids.append(i)
160
- self.methodology_data.append({"key": key, "value": value})
161
-
162
- if vectors:
163
- vectors_array = np.vstack(vectors)
164
- self.methodology_index.add_with_ids(vectors_array, np.array(ids)) # type: ignore
165
- query_embedding = self._create_methodology_embedding(user_input)
166
- k = min(5, len(self.methodology_data))
167
- PrettyOutput.print(f"Retrieving methodology...", OutputType.INFO)
168
- distances, indices = self.methodology_index.search(
169
- query_embedding.reshape(1, -1), k
170
- ) # type: ignore
171
-
172
- relevant_methodologies = {}
173
- for dist, idx in zip(distances[0], indices[0]):
174
- if idx >= 0:
175
- similarity = 1.0 / (1.0 + float(dist))
176
- methodology = self.methodology_data[idx]
177
- PrettyOutput.print(
178
- f"Methodology '{methodology['key']}' similarity: {similarity:.3f}",
179
- OutputType.INFO
180
- )
181
- if similarity >= 0.5:
182
- relevant_methodologies[methodology["key"]] = methodology["value"]
183
-
184
- if relevant_methodologies:
185
- return relevant_methodologies
186
-
187
- return {}
188
-
189
- except Exception as e:
190
- PrettyOutput.print(f"Error loading methodology: {str(e)}", OutputType.ERROR)
191
- return {}
192
135
 
193
136
  def _summarize_and_clear_history(self) -> None:
194
137
  """
@@ -244,7 +187,7 @@ Please continue the task based on the above information.
244
187
 
245
188
  # 询问是否生成方法论,带输入验证
246
189
  while True:
247
- user_input = input("Generate methodology for this task? (y/n): ").strip().lower()
190
+ user_input = get_single_line_input("Generate methodology for this task? (y/n)").strip().lower()
248
191
  if user_input in ['y', 'n', '']:
249
192
  break
250
193
  PrettyOutput.print("Invalid input, please enter y or n", OutputType.WARNING)
@@ -307,84 +250,20 @@ Please describe in concise bullet points, highlighting important information.
307
250
  self.model.upload_files(file_list)
308
251
 
309
252
  # Load methodology
310
- methodology = self._load_methodology(user_input)
311
- methodology_prompt = ""
312
- if methodology:
313
- methodology_prompt = f"""This is the standard methodology for handling previous problems, if the current task is similar, you can refer to it:
314
- {methodology}
315
-
316
- """
317
- tools_prompt = ""
318
-
319
- # 选择工具
320
- PrettyOutput.section("Available tools", OutputType.PLANNING)
321
- tools = self.tool_registry.get_all_tools()
322
- if tools:
323
- tools_prompt += "Available tools:\n"
324
- for tool in tools:
325
- PrettyOutput.print(f"{tool['name']}: {tool['description']}", OutputType.INFO)
326
- tools_prompt += f"- Name: {tool['name']}\n"
327
- tools_prompt += f" Description: {tool['description']}\n"
328
- tools_prompt += f" Parameters: {tool['parameters']}\n"
253
+ methodology_prompt = load_methodology(user_input)
254
+ tools_prompt = load_tools()
329
255
 
330
256
  # 显示任务开始
331
257
  PrettyOutput.section(f"Starting new task: {self.name}", OutputType.PLANNING)
332
258
 
333
259
  self.clear_history()
334
260
 
335
- self.model.set_system_message(f"""You are {self.name}, an AI assistant with powerful problem-solving capabilities.
336
-
337
- When users need to execute tasks, you will strictly follow these steps to handle problems:
338
- 1. Problem Restatement: Confirm understanding of the problem
339
- 2. Root Cause Analysis (only if needed for problem analysis tasks)
340
- 3. Set Objectives: Define achievable and verifiable goals
341
- 4. Generate Solutions: Create one or more actionable solutions
342
- 5. Evaluate Solutions: Select the optimal solution from multiple options
343
- 6. Create Action Plan: Based on available tools, create an action plan using PlantUML format for clear execution flow
344
- 7. Execute Action Plan: Execute one step at a time, **use at most one tool** (wait for tool execution results before proceeding)
345
- 8. Monitor and Adjust: If execution results don't match expectations, reflect and adjust the action plan, iterate previous steps
346
- 9. Methodology: If the current task has general applicability and valuable experience is gained, use methodology tools to record it for future similar problems
347
- 10. Task Completion: End the task using task completion command when finished
348
-
349
- Methodology Template:
350
- 1. Problem Restatement
351
- 2. Optimal Solution
352
- 3. Optimal Solution Steps (exclude failed actions)
353
-
354
- -------------------------------------------------------------
261
+ self.model.set_system_message(f"""
262
+ {self.system_prompt}
355
263
 
356
264
  {tools_prompt}
357
265
 
358
- -------------------------------------------------------------
359
-
360
- Tool Usage Format:
361
-
362
- <TOOL_CALL>
363
- name: tool_name
364
- arguments:
365
- param1: value1
366
- param2: value2
367
- </TOOL_CALL>
368
-
369
- -------------------------------------------------------------
370
-
371
- Strict Rules:
372
- - Execute only one tool at a time
373
- - Tool execution must strictly follow the tool usage format
374
- - Wait for user to provide execution results
375
- - Don't assume or imagine results
376
- - Don't create fake dialogues
377
- - If current information is insufficient, you may ask the user
378
- - Not all problem-solving steps are mandatory, skip as appropriate
379
- - Ask user before executing tools that might damage system or user's codebase
380
- - Request user guidance when multiple iterations show no progress
381
- - If yaml string contains colons, wrap the entire string in quotes to avoid yaml parsing errors
382
- - Use | syntax for multi-line strings in yaml
383
-
384
266
  {methodology_prompt}
385
-
386
- -------------------------------------------------------------
387
-
388
267
  """)
389
268
  self.prompt = f"{user_input}"
390
269
 
@@ -446,3 +325,166 @@ Strict Rules:
446
325
 
447
326
 
448
327
 
328
+
329
+ def load_tasks() -> dict:
330
+ """Load tasks from .jarvis files in user home and current directory."""
331
+ tasks = {}
332
+
333
+ # Check .jarvis/pre-command in user directory
334
+ user_jarvis = os.path.expanduser("~/.jarvis/pre-command")
335
+ if os.path.exists(user_jarvis):
336
+ try:
337
+ with open(user_jarvis, "r", encoding="utf-8") as f:
338
+ user_tasks = yaml.safe_load(f)
339
+
340
+ if isinstance(user_tasks, dict):
341
+ # Validate and add user directory tasks
342
+ for name, desc in user_tasks.items():
343
+ if desc: # Ensure description is not empty
344
+ tasks[str(name)] = str(desc)
345
+ else:
346
+ PrettyOutput.print("Warning: ~/.jarvis/pre-command file should contain a dictionary of task_name: task_description", OutputType.ERROR)
347
+ except Exception as e:
348
+ PrettyOutput.print(f"Error loading ~/.jarvis/pre-command file: {str(e)}", OutputType.ERROR)
349
+
350
+ # Check .jarvis/pre-command in current directory
351
+ if os.path.exists(".jarvis/pre-command"):
352
+ try:
353
+ with open(".jarvis/pre-command", "r", encoding="utf-8") as f:
354
+ local_tasks = yaml.safe_load(f)
355
+
356
+ if isinstance(local_tasks, dict):
357
+ # Validate and add current directory tasks, overwrite user directory tasks if there is a name conflict
358
+ for name, desc in local_tasks.items():
359
+ if desc: # Ensure description is not empty
360
+ tasks[str(name)] = str(desc)
361
+ else:
362
+ PrettyOutput.print("Warning: .jarvis/pre-command file should contain a dictionary of task_name: task_description", OutputType.ERROR)
363
+ except Exception as e:
364
+ PrettyOutput.print(f"Error loading .jarvis/pre-command file: {str(e)}", OutputType.ERROR)
365
+
366
+ # Read methodology
367
+ method_path = os.path.expanduser("~/.jarvis/methodology")
368
+ if os.path.exists(method_path):
369
+ with open(method_path, "r", encoding="utf-8") as f:
370
+ methodology = yaml.safe_load(f)
371
+ if isinstance(methodology, dict):
372
+ for name, desc in methodology.items():
373
+ tasks[f"Run Methodology: {str(name)}\n {str(desc)}" ] = str(desc)
374
+
375
+ return tasks
376
+
377
+ def select_task(tasks: dict) -> str:
378
+ """Let user select a task from the list or skip. Returns task description if selected."""
379
+ if not tasks:
380
+ return ""
381
+
382
+ # Convert tasks to list for ordered display
383
+ task_names = list(tasks.keys())
384
+
385
+ PrettyOutput.print("\nAvailable tasks:", OutputType.INFO)
386
+ for i, name in enumerate(task_names, 1):
387
+ PrettyOutput.print(f"[{i}] {name}", OutputType.INFO)
388
+ PrettyOutput.print("[0] Skip predefined tasks", OutputType.INFO)
389
+
390
+
391
+ while True:
392
+ try:
393
+ choice = prompt(
394
+ "\nPlease select a task number (0 to skip): ",
395
+ ).strip()
396
+
397
+ if not choice:
398
+ return ""
399
+
400
+ choice = int(choice)
401
+ if choice == 0:
402
+ return ""
403
+ elif 1 <= choice <= len(task_names):
404
+ selected_name = task_names[choice - 1]
405
+ return tasks[selected_name] # Return the task description
406
+ else:
407
+ PrettyOutput.print("Invalid choice. Please select a number from the list.", OutputType.ERROR)
408
+
409
+ except KeyboardInterrupt:
410
+ return "" # Return empty on Ctrl+C
411
+ except EOFError:
412
+ return "" # Return empty on Ctrl+D
413
+ except Exception as e:
414
+ PrettyOutput.print(f"Failed to select task: {str(e)}", OutputType.ERROR)
415
+ continue
416
+
417
+ origin_agent_system_prompt = """You are Jarvis, an AI assistant with powerful problem-solving capabilities.
418
+
419
+ When users need to execute tasks, you will strictly follow these steps to handle problems:
420
+ 1. Problem Restatement: Confirm understanding of the problem
421
+ 2. Root Cause Analysis (only if needed for problem analysis tasks)
422
+ 3. Set Objectives: Define achievable and verifiable goals
423
+ 4. Generate Solutions: Create one or more actionable solutions
424
+ 5. Evaluate Solutions: Select the optimal solution from multiple options
425
+ 6. Create Action Plan: Based on available tools, create an action plan using PlantUML format for clear execution flow
426
+ 7. Execute Action Plan: Execute one step at a time, **use at most one tool** (wait for tool execution results before proceeding)
427
+ 8. Monitor and Adjust: If execution results don't match expectations, reflect and adjust the action plan, iterate previous steps
428
+ 9. Methodology: If the current task has general applicability and valuable experience is gained, use methodology tools to record it for future similar problems
429
+ 10. Task Completion: End the task using task completion command when finished
430
+
431
+ Methodology Template:
432
+ 1. Problem Restatement
433
+ 2. Optimal Solution
434
+ 3. Optimal Solution Steps (exclude failed actions)
435
+
436
+ Strict Rules:
437
+ - Execute only one tool at a time
438
+ - Tool execution must strictly follow the tool usage format
439
+ - Wait for user to provide execution results
440
+ - Don't assume or imagine results
441
+ - Don't create fake dialogues
442
+ - If current information is insufficient, you may ask the user
443
+ - Not all problem-solving steps are mandatory, skip as appropriate
444
+ - Ask user before executing tools that might damage system or user's codebase
445
+ - Request user guidance when multiple iterations show no progress
446
+ - If yaml string contains colons, wrap the entire string in quotes to avoid yaml parsing errors
447
+ - Use | syntax for multi-line strings in yaml
448
+ - If you can start executing the task, please start directly without asking the user if you can begin.
449
+
450
+ -------------------------------------------------------------"""
451
+
452
+ def main():
453
+ """Jarvis main entry point"""
454
+ # Add argument parser
455
+ init_env()
456
+ parser = argparse.ArgumentParser(description='Jarvis AI assistant')
457
+ parser.add_argument('-f', '--files', nargs='*', help='List of files to process')
458
+ args = parser.parse_args()
459
+
460
+ try:
461
+ # 获取全局模型实例
462
+ agent = Agent(system_prompt=origin_agent_system_prompt)
463
+
464
+ # 加载预定义任务
465
+ tasks = load_tasks()
466
+ if tasks:
467
+ selected_task = select_task(tasks)
468
+ if selected_task:
469
+ PrettyOutput.print(f"\nExecute task: {selected_task}", OutputType.INFO)
470
+ agent.run(selected_task, args.files)
471
+ return 0
472
+
473
+ # 如果没有选择预定义任务,进入交互模式
474
+ while True:
475
+ try:
476
+ user_input = get_multiline_input("Please enter your task (input empty line to exit):")
477
+ if not user_input or user_input == "__interrupt__":
478
+ break
479
+ agent.run(user_input, args.files)
480
+ except Exception as e:
481
+ PrettyOutput.print(f"Error: {str(e)}", OutputType.ERROR)
482
+
483
+ except Exception as e:
484
+ PrettyOutput.print(f"Initialization error: {str(e)}", OutputType.ERROR)
485
+ return 1
486
+
487
+ return 0
488
+
489
+ if __name__ == "__main__":
490
+ exit(main())
File without changes
@@ -0,0 +1,202 @@
1
+ from jarvis.agent import Agent
2
+ from jarvis.tools.registry import ToolRegistry
3
+ from jarvis.utils import OutputType, PrettyOutput, get_multiline_input, init_env
4
+
5
+
6
+
7
+
8
+ system_prompt = """You are Jarvis Code Agent, an AI code development assistant specialized in code analysis, modification, and version control. Your role is to help users with coding tasks systematically and reliably.
9
+
10
+ DEVELOPMENT WORKFLOW:
11
+ 1. Task Analysis
12
+ - Understand the requirements thoroughly
13
+ - IMPORTANT: Before suggesting any changes:
14
+ * Thoroughly examine existing code implementation
15
+ * Never assume code structure or implementation details
16
+ * Always verify current code behavior and patterns
17
+ - Break down complex tasks into subtasks
18
+ - IMPORTANT: Each subtask should:
19
+ * Modify only ONE file
20
+ * Change no more than 20 lines of code
21
+ * Be focused and atomic
22
+ - Define success criteria
23
+
24
+ 2. Code Discovery & Analysis
25
+ - Initial code search:
26
+ * CRITICAL: Always examine actual code implementation first
27
+ * Use shell commands to find and understand patterns:
28
+ <TOOL_CALL>
29
+ name: execute_shell
30
+ arguments:
31
+ command: grep -r 'pattern' directory/
32
+ </TOOL_CALL>
33
+ <TOOL_CALL>
34
+ name: execute_shell
35
+ arguments:
36
+ command: grep -A 5 -B 5 'pattern' file.py
37
+ </TOOL_CALL>
38
+ * Use shell commands to locate files:
39
+ <TOOL_CALL>
40
+ name: execute_shell
41
+ arguments:
42
+ command: find . -name 'pattern'
43
+ </TOOL_CALL>
44
+ * Use shell commands to preview:
45
+ <TOOL_CALL>
46
+ name: execute_shell
47
+ arguments:
48
+ command: head -n 50 file.py
49
+ </TOOL_CALL>
50
+ - File selection and confirmation:
51
+ * Let user confirm selection:
52
+ <TOOL_CALL>
53
+ name: select_code_files
54
+ arguments:
55
+ related_files:
56
+ - auth.py
57
+ - user.py
58
+ root_dir: .
59
+ </TOOL_CALL>
60
+
61
+ 3. Modification Planning
62
+ - CRITICAL: Base all plans on actual code implementation, not assumptions
63
+ - Generate a detailed modification plan based on:
64
+ * Current code structure and patterns
65
+ * Existing implementation details
66
+ * User requirements
67
+ * Actual code conditions
68
+
69
+ 4. Code Implementation
70
+ - For small changes (≤20 lines):
71
+ <TOOL_CALL>
72
+ name: execute_code_modification
73
+ arguments:
74
+ task: Add password validation
75
+ structured_plan:
76
+ auth.py: Add password strength check in validate_password()
77
+ </TOOL_CALL>
78
+ - For large changes:
79
+ <TOOL_CALL>
80
+ name: create_code_sub_agent
81
+ arguments:
82
+ subtask: Implement new authentication flow
83
+ codebase_dir: .
84
+ </TOOL_CALL>
85
+
86
+ FILE SELECTION WORKFLOW:
87
+ 1. Initial Search
88
+ - Use shell commands to find relevant files
89
+ - Review search results for relevance
90
+
91
+ 2. User Confirmation
92
+ - Use select_code_files to:
93
+ * Display found files
94
+ * Let user review selection
95
+ * Allow file list adjustment
96
+ * Enable file supplementation
97
+
98
+ 3. File Validation
99
+ - Verify selected files exist
100
+ - Check file permissions
101
+ - Validate file types
102
+ - Ensure completeness
103
+
104
+ CODE SEARCH BEST PRACTICES:
105
+ - Use grep for pattern matching:
106
+ * grep -r "pattern" directory/
107
+ * grep -A 5 -B 5 for context
108
+ * grep -n for line numbers
109
+ - Use find for file location:
110
+ * find . -name "pattern"
111
+ * find . -type f -exec grep "pattern" {} \\;
112
+ - Use head/tail for previews:
113
+ * head -n 50 file.py
114
+ * tail -n 50 file.py
115
+ * head -n +100 | tail -n 50
116
+ - Avoid loading entire large files
117
+ - Focus on relevant sections
118
+ - Use line numbers for reference
119
+
120
+ SUBTASK MANAGEMENT RULES:
121
+ - One subtask = One file modification
122
+ - Each subtask ≤20 lines of code changes
123
+ - Break down larger changes into multiple subtasks
124
+ - Create separate sub-agent for each subtask
125
+ - Follow dependency order in execution
126
+ - Verify each change independently
127
+
128
+ CODE MODIFICATION LIMITS:
129
+ - Maximum 20 lines per change
130
+ - Count both added and modified lines
131
+ - Exclude comment and blank lines
132
+ - Include only actual code changes
133
+ - Split larger changes into subtasks
134
+
135
+ ITERATION GUIDELINES:
136
+ - Each iteration should be small and focused
137
+ - Keep changes minimal and clear
138
+ - Verify changes before moving forward
139
+ - Document issues and solutions
140
+ - Learn from previous iterations
141
+
142
+ TOOL USAGE:
143
+ 1. Analysis Tools:
144
+ - execute_shell: Run grep/find/head/tail commands
145
+ - find_files: Search and identify relevant code files in the codebase based on requirements or problems
146
+ - select_code_files: Confirm and supplement files
147
+ - ask_user: Ask user for confirmation and information if needed
148
+ - create_code_sub_agent: Create agent for each small change
149
+ - file_operation: Read files
150
+ - rag: Ask questions based on a document directory, supporting multiple document formats (txt, pdf, docx, etc.)
151
+ - search: Use Bing search engine to search for information, and extract key information based on the question
152
+ - thinker: Deep thinking and logical reasoning
153
+
154
+ 2. Planning Tools:
155
+ - thinker: Generate a detailed modification plan based on user requirements and actual code conditions.
156
+ - create_code_sub_agent: Create agent for each small change
157
+ - ask_user: Ask user for confirmation and information if needed
158
+
159
+ 3. Implementation Tools:
160
+ - execute_shell: Run shell commands, some changes can use sed/awk/etc. to modify the code
161
+ - execute_code_modification: Apply small changes (≤20 lines)
162
+ - file_operation: Read, write, or append to files
163
+
164
+ IMPORTANT:
165
+ 1. If you can start executing the task, please start directly without asking the user if you can begin.
166
+ 2. NEVER assume code structure or implementation - always examine the actual code first.
167
+ 3. Base all suggestions and modifications on the current implementation, not assumptions.
168
+ 4. If code implementation is unclear, use available tools to investigate before proceeding.
169
+ 5. Before you start modifying the code, you should ask the user for confirmation of the modification plan.
170
+ 6. For some small changes, you can modify the code using the execute_shell tool directly or use file_operation tool to read the file and modify it.
171
+ """
172
+
173
+ def main():
174
+ """Jarvis main entry point"""
175
+ # Add argument parser
176
+ init_env()
177
+
178
+
179
+ try:
180
+ tool_registry = ToolRegistry()
181
+ tool_registry.dont_use_tools(["create_sub_agent"])
182
+ # Get global model instance
183
+ agent = Agent(system_prompt=system_prompt, name="Jarvis Code Agent", tool_registry=tool_registry)
184
+
185
+ # Interactive mode
186
+ while True:
187
+ try:
188
+ user_input = get_multiline_input("Please enter your task (input empty line to exit):")
189
+ if not user_input or user_input == "__interrupt__":
190
+ break
191
+ agent.run(user_input)
192
+ except Exception as e:
193
+ PrettyOutput.print(f"Error: {str(e)}", OutputType.ERROR)
194
+
195
+ except Exception as e:
196
+ PrettyOutput.print(f"Initialization error: {str(e)}", OutputType.ERROR)
197
+ return 1
198
+
199
+ return 0
200
+
201
+ if __name__ == "__main__":
202
+ exit(main())