jarvis-ai-assistant 0.1.101__py3-none-any.whl → 0.1.103__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 (54) hide show
  1. jarvis/__init__.py +1 -1
  2. jarvis/agent.py +140 -140
  3. jarvis/jarvis_code_agent/code_agent.py +234 -0
  4. jarvis/{jarvis_coder → jarvis_code_agent}/file_select.py +16 -17
  5. jarvis/jarvis_code_agent/patch.py +118 -0
  6. jarvis/jarvis_code_agent/relevant_files.py +66 -0
  7. jarvis/jarvis_codebase/main.py +32 -29
  8. jarvis/jarvis_platform/main.py +5 -3
  9. jarvis/jarvis_rag/main.py +11 -15
  10. jarvis/jarvis_smart_shell/main.py +2 -2
  11. jarvis/models/ai8.py +1 -0
  12. jarvis/models/kimi.py +36 -30
  13. jarvis/models/ollama.py +17 -11
  14. jarvis/models/openai.py +15 -12
  15. jarvis/models/oyi.py +22 -7
  16. jarvis/models/registry.py +1 -25
  17. jarvis/tools/__init__.py +0 -6
  18. jarvis/tools/ask_codebase.py +99 -0
  19. jarvis/tools/ask_user.py +1 -9
  20. jarvis/tools/chdir.py +1 -1
  21. jarvis/tools/code_review.py +163 -0
  22. jarvis/tools/create_code_sub_agent.py +19 -45
  23. jarvis/tools/create_code_test_agent.py +115 -0
  24. jarvis/tools/create_ctags_agent.py +176 -0
  25. jarvis/tools/create_sub_agent.py +2 -2
  26. jarvis/tools/execute_shell.py +2 -2
  27. jarvis/tools/file_operation.py +2 -2
  28. jarvis/tools/find_in_codebase.py +108 -0
  29. jarvis/tools/git_commiter.py +68 -0
  30. jarvis/tools/methodology.py +3 -3
  31. jarvis/tools/rag.py +6 -3
  32. jarvis/tools/read_code.py +147 -0
  33. jarvis/tools/read_webpage.py +1 -1
  34. jarvis/tools/registry.py +92 -68
  35. jarvis/tools/search.py +8 -6
  36. jarvis/tools/select_code_files.py +4 -4
  37. jarvis/utils.py +270 -95
  38. {jarvis_ai_assistant-0.1.101.dist-info → jarvis_ai_assistant-0.1.103.dist-info}/METADATA +9 -5
  39. jarvis_ai_assistant-0.1.103.dist-info/RECORD +51 -0
  40. {jarvis_ai_assistant-0.1.101.dist-info → jarvis_ai_assistant-0.1.103.dist-info}/entry_points.txt +4 -2
  41. jarvis/jarvis_code_agent/main.py +0 -202
  42. jarvis/jarvis_coder/__init__.py +0 -0
  43. jarvis/jarvis_coder/git_utils.py +0 -123
  44. jarvis/jarvis_coder/main.py +0 -241
  45. jarvis/jarvis_coder/patch_handler.py +0 -340
  46. jarvis/jarvis_coder/plan_generator.py +0 -145
  47. jarvis/tools/execute_code_modification.py +0 -70
  48. jarvis/tools/find_files.py +0 -119
  49. jarvis/tools/generate_tool.py +0 -174
  50. jarvis/tools/thinker.py +0 -151
  51. jarvis_ai_assistant-0.1.101.dist-info/RECORD +0 -51
  52. {jarvis_ai_assistant-0.1.101.dist-info → jarvis_ai_assistant-0.1.103.dist-info}/LICENSE +0 -0
  53. {jarvis_ai_assistant-0.1.101.dist-info → jarvis_ai_assistant-0.1.103.dist-info}/WHEEL +0 -0
  54. {jarvis_ai_assistant-0.1.101.dist-info → jarvis_ai_assistant-0.1.103.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.101"
3
+ __version__ = "0.1.103"
jarvis/agent.py CHANGED
@@ -1,22 +1,38 @@
1
1
  import argparse
2
2
  import time
3
- from typing import Dict, List, Optional
3
+ from typing import Callable, Dict, List, Optional
4
4
 
5
5
  from prompt_toolkit import prompt
6
6
  import yaml
7
7
 
8
+ from jarvis.models.base import BasePlatform
8
9
  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
10
+ from jarvis.tools.registry import ToolRegistry, tool_call_help
11
+ from jarvis.utils import PrettyOutput, OutputType, is_auto_complete, load_methodology, add_agent, delete_current_agent, get_max_context_length, get_multiline_input, init_env
12
12
  import os
13
13
 
14
14
  class Agent:
15
15
 
16
16
  def __del__(self):
17
17
  delete_current_agent()
18
+
19
+ def set_summary_prompt(self, summary_prompt: str):
20
+ self.summary_prompt = summary_prompt
21
+
22
+ def set_output_filter(self, output_filter: List[Callable]):
23
+ self.output_filter = output_filter
18
24
 
19
- def __init__(self, system_prompt: str, name: str = "Jarvis", is_sub_agent: bool = False, tool_registry: Optional[ToolRegistry] = None):
25
+ def __init__(self,
26
+ system_prompt: str,
27
+ name: str = "Jarvis",
28
+ is_sub_agent: bool = False,
29
+ tool_registry: Optional[ToolRegistry] = None,
30
+ platform: Optional[BasePlatform] = None,
31
+ summary_prompt: Optional[str] = None,
32
+ auto_complete: bool = False,
33
+ record_methodology: bool = True,
34
+ output_filter: Optional[List[Callable]] = None,
35
+ need_summary: bool = True):
20
36
  """Initialize Agent with a model, optional tool registry and name
21
37
 
22
38
  Args:
@@ -24,45 +40,70 @@ class Agent:
24
40
  name: Agent name, default is "Jarvis"
25
41
  is_sub_agent: Whether it is a sub-agent, default is False
26
42
  tool_registry: Tool registry instance
43
+ platform: Optional platform instance, default uses normal platform
27
44
  """
28
45
  add_agent(name)
29
46
  PrettyOutput.print(f"Welcome to Jarvis, your AI assistant, Initiating...", OutputType.SYSTEM)
30
- self.model = PlatformRegistry.get_global_platform_registry().get_normal_platform()
31
- self.tool_registry = tool_registry if tool_registry else ToolRegistry.get_global_tool_registry()
47
+ if platform is not None:
48
+ self.model = platform
49
+ else:
50
+ self.model = PlatformRegistry.get_global_platform_registry().get_normal_platform()
51
+ self.tool_registry = tool_registry if tool_registry else ToolRegistry()
52
+ self.record_methodology = record_methodology
32
53
  self.name = name
33
54
  self.is_sub_agent = is_sub_agent
34
55
  self.prompt = ""
35
56
  self.conversation_length = 0 # Use length counter instead
36
57
  self.system_prompt = system_prompt
58
+ self.need_summary = need_summary
37
59
  # Load configuration from environment variables
38
- self.embedding_dimension = 1536 # Default for many embedding models
60
+ self.output_filter = output_filter if output_filter else []
61
+
62
+ self.summary_prompt = summary_prompt if summary_prompt else f"""Please generate a concise summary report of the task execution, including:
63
+
64
+ 1. Task Objective: Task restatement
65
+ 2. Execution Result: Success/Failure
66
+ 3. Key Information: Important information extracted during execution
67
+ 4. Important Findings: Any noteworthy discoveries
68
+ 5. Follow-up Suggestions: If any
69
+
70
+ Please describe in concise bullet points, highlighting important information.
71
+ """
72
+
39
73
  self.max_context_length = get_max_context_length()
74
+
75
+ self.auto_complete = auto_complete
76
+
77
+
40
78
 
41
- # Initialize embedding model
42
- try:
43
- self.embedding_model = load_embedding_model()
44
-
45
- # Warm up model and get correct dimension
46
- test_text = "This is a test text to ensure the model is fully loaded."
47
- test_embedding = self.embedding_model.encode(
48
- test_text,
49
- convert_to_tensor=True,
50
- normalize_embeddings=True
51
- )
52
- self.embedding_dimension = len(test_embedding)
53
- PrettyOutput.print("Successfully loaded embedding model", OutputType.SUCCESS)
54
-
55
- # Initialize HNSW index (use correct dimension)
56
-
57
-
58
- except Exception as e:
59
- PrettyOutput.print(f"Failed to load embedding model: {str(e)}", OutputType.ERROR)
60
- raise
61
79
 
62
80
  # Initialize methodology related attributes
63
81
  self.methodology_data = []
64
82
 
65
83
  PrettyOutput.section(f"Jarvis initialized - With {self.model.name()}", OutputType.SYSTEM)
84
+ tools = self.tool_registry.get_all_tools()
85
+ if tools:
86
+ PrettyOutput.section(f"Available tools: {', '.join([tool['name'] for tool in tools])}", OutputType.SYSTEM)
87
+
88
+
89
+ # Load methodology
90
+
91
+ tools_prompt = self.tool_registry.load_tools()
92
+ complete_prompt = """"""
93
+ if self.auto_complete:
94
+ complete_prompt = """
95
+ When the task is completed, you should print the following message:
96
+ <!!!COMPLETE!!!>
97
+ """
98
+
99
+ self.model.set_system_message(f"""
100
+ {self.system_prompt}
101
+
102
+ {tools_prompt}
103
+
104
+ {complete_prompt}
105
+ """)
106
+ self.first = True
66
107
 
67
108
  @staticmethod
68
109
  def extract_tool_calls(content: str) -> List[Dict]:
@@ -72,14 +113,6 @@ class Agent:
72
113
  tool_call_lines = []
73
114
  in_tool_call = False
74
115
 
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
116
 
84
117
  # Process line by line
85
118
  for line in lines:
@@ -88,27 +121,19 @@ arguments:
88
121
  continue
89
122
  elif '</TOOL_CALL>' in line:
90
123
  if in_tool_call and tool_call_lines:
91
- try:
92
- # Parse YAML directly
93
- tool_call_text = '\n'.join(tool_call_lines)
94
- tool_call_data = yaml.safe_load(tool_call_text)
95
-
96
- # Validate necessary fields
97
- if "name" in tool_call_data and "arguments" in tool_call_data:
98
- # Return content before tool call and tool call
99
- return [{
100
- "name": tool_call_data["name"],
101
- "arguments": tool_call_data["arguments"]
102
- }]
103
- else:
104
- PrettyOutput.print("Tool call missing necessary fields", OutputType.ERROR)
105
- raise Exception("Tool call missing necessary fields, " + tool_call_help)
106
- except yaml.YAMLError as e:
107
- PrettyOutput.print(f"YAML parsing error: {str(e)}", OutputType.ERROR)
108
- raise Exception(f"YAML parsing error: {str(e)}")
109
- except Exception as e:
110
- PrettyOutput.print(f"Error processing tool call: {str(e)}", OutputType.ERROR)
111
- raise Exception(f"Error processing tool call: {str(e)}")
124
+ # Parse YAML directly
125
+ tool_call_text = '\n'.join(tool_call_lines)
126
+ tool_call_data = yaml.safe_load(tool_call_text)
127
+
128
+ # Validate necessary fields
129
+ if "name" in tool_call_data and "arguments" in tool_call_data:
130
+ # Return content before tool call and tool call
131
+ return [{
132
+ "name": tool_call_data["name"],
133
+ "arguments": tool_call_data["arguments"]
134
+ }]
135
+ else:
136
+ raise Exception("Tool call missing necessary fields")
112
137
  in_tool_call = False
113
138
  continue
114
139
 
@@ -185,53 +210,39 @@ Please continue the task based on the above information.
185
210
  """
186
211
  PrettyOutput.section("Task completed", OutputType.SUCCESS)
187
212
 
188
- # 询问是否生成方法论,带输入验证
189
- while True:
190
- user_input = get_single_line_input("Generate methodology for this task? (y/n)").strip().lower()
191
- if user_input in ['y', 'n', '']:
192
- break
193
- PrettyOutput.print("Invalid input, please enter y or n", OutputType.WARNING)
194
-
195
- if user_input == 'y':
196
- try:
197
- # 让模型判断是否需要生成方法论
198
- analysis_prompt = """The current task has ended, please analyze whether a methodology needs to be generated.
199
- If you think a methodology should be generated, first determine whether to create a new methodology or update an existing one. If updating an existing methodology, use 'update', otherwise use 'add'.
200
- If you think a methodology is not needed, please explain why.
201
- The methodology should be applicable to general scenarios, do not include task-specific information such as code commit messages.
202
- The methodology should include: problem restatement, optimal solution, notes (as needed), and nothing else.
203
- Only output the methodology tool call instruction, or the explanation for not generating a methodology. Do not output anything else.
204
- """
205
- self.prompt = analysis_prompt
206
- response = self._call_model(self.prompt)
207
-
208
- # 检查是否包含工具调用
213
+ if not self.is_sub_agent:
214
+ if self.record_methodology:
215
+
209
216
  try:
210
- tool_calls = Agent.extract_tool_calls(response)
211
- if tool_calls:
212
- self.tool_registry.handle_tool_calls(tool_calls)
217
+ # 让模型判断是否需要生成方法论
218
+ analysis_prompt = """The current task has ended, please analyze whether a methodology needs to be generated.
219
+ If you think a methodology should be generated, first determine whether to create a new methodology or update an existing one. If updating an existing methodology, use 'update', otherwise use 'add'.
220
+ If you think a methodology is not needed, please explain why.
221
+ The methodology should be applicable to general scenarios, do not include task-specific information such as code commit messages.
222
+ The methodology should include: problem restatement, optimal solution, notes (as needed), and nothing else.
223
+ Only output the methodology tool call instruction, or the explanation for not generating a methodology. Do not output anything else.
224
+ """
225
+ self.prompt = analysis_prompt
226
+ response = self._call_model(self.prompt)
227
+
228
+ # 检查是否包含工具调用
229
+ try:
230
+ tool_calls = Agent.extract_tool_calls(response)
231
+ if tool_calls:
232
+ self.tool_registry.handle_tool_calls(tool_calls)
233
+ except Exception as e:
234
+ PrettyOutput.print(f"Failed to handle methodology generation: {str(e)}", OutputType.ERROR)
235
+
213
236
  except Exception as e:
214
- PrettyOutput.print(f"Failed to handle methodology generation: {str(e)}", OutputType.ERROR)
215
-
216
- except Exception as e:
217
- PrettyOutput.print(f"Error generating methodology: {str(e)}", OutputType.ERROR)
218
-
219
- if not self.is_sub_agent:
237
+ PrettyOutput.print(f"Error generating methodology: {str(e)}", OutputType.ERROR)
238
+
220
239
  return "Task completed"
221
240
 
222
- # 生成任务总结
223
- summary_prompt = f"""Please generate a concise summary report of the task execution, including:
224
-
225
- 1. Task Objective: Task restatement
226
- 2. Execution Result: Success/Failure
227
- 3. Key Information: Important information extracted during execution
228
- 4. Important Findings: Any noteworthy discoveries
229
- 5. Follow-up Suggestions: If any
230
-
231
- Please describe in concise bullet points, highlighting important information.
232
- """
233
- self.prompt = summary_prompt
234
- return self._call_model(self.prompt)
241
+ if self.need_summary:
242
+ self.prompt = self.summary_prompt
243
+ return self._call_model(self.prompt)
244
+
245
+ return "Task completed"
235
246
 
236
247
 
237
248
  def run(self, user_input: str, file_list: Optional[List[str]] = None) -> str:
@@ -244,28 +255,22 @@ Please describe in concise bullet points, highlighting important information.
244
255
  Returns:
245
256
  str: Task summary report
246
257
  """
258
+
259
+
260
+
247
261
  try:
248
262
  PrettyOutput.section("Preparing environment", OutputType.PLANNING)
249
263
  if file_list:
250
264
  self.model.upload_files(file_list)
251
265
 
252
- # Load methodology
253
- methodology_prompt = load_methodology(user_input)
254
- tools_prompt = load_tools()
255
-
256
266
  # 显示任务开始
257
267
  PrettyOutput.section(f"Starting new task: {self.name}", OutputType.PLANNING)
258
268
 
259
- self.clear_history()
260
-
261
- self.model.set_system_message(f"""
262
- {self.system_prompt}
263
-
264
- {tools_prompt}
265
-
266
- {methodology_prompt}
267
- """)
268
- self.prompt = f"{user_input}"
269
+ if self.first:
270
+ self.prompt = f"{user_input}\n\n{load_methodology(user_input)}"
271
+ self.first = False
272
+ else:
273
+ self.prompt = f"{user_input}"
269
274
 
270
275
  while True:
271
276
  try:
@@ -281,25 +286,32 @@ Please describe in concise bullet points, highlighting important information.
281
286
  continue
282
287
  else:
283
288
  current_response = self._call_model(self.prompt)
284
- self.conversation_length += len(current_response) # Add response length
289
+ self.prompt = ""
290
+ self.conversation_length += len(current_response)
291
+
292
+ for filter in self.output_filter:
293
+ self.prompt += filter(current_response)
294
+
285
295
  try:
286
296
  result = Agent.extract_tool_calls(current_response)
287
297
  except Exception as e:
288
298
  PrettyOutput.print(f"Tool call error: {str(e)}", OutputType.ERROR)
289
- self.prompt = f"Tool call error: {str(e)}"
299
+ self.prompt += f"Tool call error: {str(e)}"
290
300
  continue
291
301
 
292
302
  if len(result) > 0:
293
303
  PrettyOutput.print("Executing tool call...", OutputType.PROGRESS)
294
304
  tool_result = self.tool_registry.handle_tool_calls(result)
295
- self.prompt = tool_result
305
+ self.prompt += tool_result
306
+
307
+ if self.prompt:
296
308
  continue
309
+
310
+ if self.auto_complete and "<!!!COMPLETE!!!>" in current_response:
311
+ return self._complete_task()
297
312
 
298
313
  # 获取用户输入
299
314
  user_input = get_multiline_input(f"{self.name}: You can continue to input, or enter an empty line to end the current task")
300
- if user_input == "__interrupt__":
301
- PrettyOutput.print("Task cancelled by user", OutputType.WARNING)
302
- return "Task cancelled by user"
303
315
 
304
316
  if user_input:
305
317
  self.prompt = user_input
@@ -382,10 +394,11 @@ def select_task(tasks: dict) -> str:
382
394
  # Convert tasks to list for ordered display
383
395
  task_names = list(tasks.keys())
384
396
 
385
- PrettyOutput.print("\nAvailable tasks:", OutputType.INFO)
397
+ task_list = ["Available tasks:"]
386
398
  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)
399
+ task_list.append(f"[{i}] {name}")
400
+ task_list.append("[0] Skip predefined tasks")
401
+ PrettyOutput.print("\n".join(task_list), OutputType.INFO)
389
402
 
390
403
 
391
404
  while True:
@@ -426,26 +439,13 @@ When users need to execute tasks, you will strictly follow these steps to handle
426
439
  7. Execute Action Plan: Execute one step at a time, **use at most one tool** (wait for tool execution results before proceeding)
427
440
  8. Monitor and Adjust: If execution results don't match expectations, reflect and adjust the action plan, iterate previous steps
428
441
  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
442
+ 10. Auto check the task goal completion status: If the task goal is completed, use the task completion command to end the task
443
+ 11. Task Completion: End the task using task completion command when finished
430
444
 
431
445
  Methodology Template:
432
446
  1. Problem Restatement
433
447
  2. Optimal Solution
434
448
  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
449
 
450
450
  -------------------------------------------------------------"""
451
451
 
@@ -459,7 +459,7 @@ def main():
459
459
 
460
460
  try:
461
461
  # 获取全局模型实例
462
- agent = Agent(system_prompt=origin_agent_system_prompt)
462
+ agent = Agent(system_prompt=origin_agent_system_prompt, tool_registry=ToolRegistry())
463
463
 
464
464
  # 加载预定义任务
465
465
  tasks = load_tasks()
@@ -474,7 +474,7 @@ def main():
474
474
  while True:
475
475
  try:
476
476
  user_input = get_multiline_input("Please enter your task (input empty line to exit):")
477
- if not user_input or user_input == "__interrupt__":
477
+ if not user_input:
478
478
  break
479
479
  agent.run(user_input, args.files)
480
480
  except Exception as e:
@@ -0,0 +1,234 @@
1
+ from enum import auto
2
+ import os
3
+ import re
4
+ from typing import List
5
+
6
+ import yaml
7
+ from jarvis.agent import Agent
8
+ from jarvis.jarvis_code_agent.patch import apply_patch
9
+ from jarvis.jarvis_code_agent.file_select import select_files
10
+ from jarvis.jarvis_code_agent.relevant_files import find_relevant_files
11
+ from jarvis.models.registry import PlatformRegistry
12
+ from jarvis.tools.git_commiter import GitCommitTool
13
+ from jarvis.tools.registry import ToolRegistry
14
+ from jarvis.utils import OutputType, PrettyOutput, get_file_line_count, get_multiline_input, get_single_line_input, has_uncommitted_changes, init_env, find_git_root, is_disable_codebase, make_choice_input, user_confirm
15
+
16
+
17
+
18
+
19
+
20
+ class CodeAgent:
21
+ def __init__(self):
22
+ self.root_dir = os.getcwd()
23
+ tool_registry = ToolRegistry()
24
+ tool_registry.use_tools(["read_code", "execute_shell", "search", "ask_user", "ask_codebase"])
25
+ code_system_prompt = """
26
+ You are a code agent, you are responsible for modifying the code.
27
+
28
+ You should read the code and analyze the code, and then provide a plan for the code modification.
29
+
30
+ ## Workflow Steps
31
+
32
+ 1. ANALYSIS
33
+ - Understand the requirement thoroughly
34
+ - Identify which files need to be modified
35
+ - Review the current implementation
36
+ - Consider potential impacts
37
+
38
+ 2. PLANNING
39
+ - Break down the changes into logical steps
40
+ - Consider dependencies between changes
41
+ - Plan the implementation sequence
42
+ - Think about potential risks
43
+
44
+ 3. IMPLEMENTATION
45
+ For each file that needs changes:
46
+ a. Read and understand the current code
47
+ b. Plan the specific modifications
48
+ c. Write the patch in the required format
49
+ d. Review the patch for correctness
50
+
51
+ ## File Reading Guidelines
52
+
53
+ 1. For Large Files (>200 lines):
54
+ - Do NOT read the entire file at once using 'read_code'
55
+ - First use 'execute_shell' with grep/find to locate relevant sections
56
+ - Then use 'read_code' with specific line ranges to read only necessary portions
57
+ - Example:
58
+ * Use: execute_shell("grep -n 'function_name' path/to/file")
59
+ * Then: read_code("path/to/file", start_line=found_line-10, end_line=found_line+20)
60
+
61
+ 2. For Small Files:
62
+ - Can read entire file using 'read_code' directly
63
+
64
+ ## Patch Format and Guidelines
65
+
66
+ 1. Basic Format:
67
+ <PATCH>
68
+ > /path/to/file start_line,end_line
69
+ new_content_line1
70
+ new_content_line2
71
+ </PATCH>
72
+
73
+ 2. Rules:
74
+ - Each <PATCH> block MUST contain exactly ONE patch for ONE location
75
+ - Multiple changes to different locations require separate <PATCH> blocks
76
+ - Line Numbers Behavior:
77
+ * start_line (first number): This line WILL be replaced
78
+ * end_line (second number): This line will NOT be replaced
79
+ * The patch replaces content from start_line (inclusive) to end_line (exclusive)
80
+ - Use absolute paths relative to the project root
81
+ - Maintain consistent indentation
82
+ - Include enough context for precise location
83
+
84
+ 3. Multiple Changes Example:
85
+ Before:
86
+ ```
87
+ Line 0: first line
88
+ Line 1: second line
89
+ Line 2: third line
90
+ Line 3: fourth line
91
+ ```
92
+
93
+ For multiple changes, use separate patches:
94
+ ```
95
+ <PATCH>
96
+ > /path/to/file 0,1
97
+ new first line
98
+ </PATCH>
99
+
100
+ <PATCH>
101
+ > /path/to/file 2,3
102
+ new third line
103
+ </PATCH>
104
+ ```
105
+
106
+ After:
107
+ ```
108
+ new first line
109
+ Line 1: second line
110
+ new third line
111
+ Line 3: fourth line
112
+ ```
113
+
114
+ Note: In this example:
115
+ - Each change is in its own <PATCH> block
116
+ - Changes are applied sequentially
117
+ - Line numbers are based on the original file
118
+
119
+ ## Implementation Guidelines
120
+
121
+ 1. Code Quality:
122
+ - Keep changes minimal and focused
123
+ - Maintain consistent style
124
+ - Add clear comments for complex logic
125
+ - Follow project patterns
126
+ - Ensure proper error handling
127
+
128
+ 2. Tools Available:
129
+ - Use 'read_code/ask_codebase' to examine file contents
130
+ - Use 'execute_shell' for grep/find/ctags operations
131
+ - Use 'search' to search on web
132
+ - Use 'ask_user' when clarification is needed
133
+
134
+ Please proceed with the analysis and implementation following this workflow.
135
+ Start by examining the files and planning your changes.
136
+ Then provide the necessary patches in the specified format.
137
+ """
138
+ self.agent = Agent(system_prompt=code_system_prompt,
139
+ name="CodeAgent",
140
+ auto_complete=False,
141
+ is_sub_agent=False,
142
+ tool_registry=tool_registry,
143
+ platform=PlatformRegistry().get_codegen_platform(),
144
+ record_methodology=False,
145
+ output_filter=[apply_patch],
146
+ need_summary=False)
147
+
148
+
149
+
150
+ def _init_env(self):
151
+ curr_dir = os.getcwd()
152
+ git_dir = find_git_root(curr_dir)
153
+ self.root_dir = git_dir
154
+ if has_uncommitted_changes():
155
+ git_commiter = GitCommitTool()
156
+ git_commiter.execute({})
157
+
158
+
159
+ def make_files_prompt(self, files: List[str]) -> str:
160
+ """Make the files prompt.
161
+
162
+ Args:
163
+ files: The files to be modified
164
+
165
+ """
166
+ return "\n".join(
167
+ f"- {file} ({get_file_line_count(file)} lines)"
168
+ for file in files
169
+ )
170
+
171
+ def run(self, user_input: str) :
172
+ """Run the code agent with the given user input.
173
+
174
+ Args:
175
+ user_input: The user's requirement/request
176
+
177
+ Returns:
178
+ str: Output describing the execution result
179
+ """
180
+ try:
181
+ self._init_env()
182
+ files = find_relevant_files(user_input, self.root_dir)
183
+ self.agent.run(self._build_first_edit_prompt(user_input, self.make_files_prompt(files)))
184
+
185
+ except Exception as e:
186
+ return f"Error during execution: {str(e)}"
187
+
188
+
189
+
190
+ def _build_first_edit_prompt(self, user_input: str, files_prompt: str) -> str:
191
+ """Build the initial prompt for the agent.
192
+
193
+ Args:
194
+ user_input: The user's requirement
195
+ files_prompt: The formatted list of relevant files
196
+
197
+ Returns:
198
+ str: The formatted prompt
199
+ """
200
+ return f"""# Code Modification Task
201
+
202
+ ## User Requirement
203
+ {user_input}
204
+
205
+ ## Available Files
206
+ {files_prompt}
207
+ """
208
+ def main():
209
+ """Jarvis main entry point"""
210
+ # Add argument parser
211
+ init_env()
212
+
213
+
214
+ try:
215
+ # Interactive mode
216
+ while True:
217
+ try:
218
+ user_input = get_multiline_input("Please enter your requirement (input empty line to exit):")
219
+ if not user_input:
220
+ break
221
+ agent = CodeAgent()
222
+ agent.run(user_input)
223
+
224
+ except Exception as e:
225
+ PrettyOutput.print(f"Error: {str(e)}", OutputType.ERROR)
226
+
227
+ except Exception as e:
228
+ PrettyOutput.print(f"Initialization error: {str(e)}", OutputType.ERROR)
229
+ return 1
230
+
231
+ return 0
232
+
233
+ if __name__ == "__main__":
234
+ exit(main())