jarvis-ai-assistant 0.1.102__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 (55) hide show
  1. jarvis/__init__.py +1 -1
  2. jarvis/agent.py +138 -117
  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 +878 -0
  8. jarvis/jarvis_platform/main.py +5 -3
  9. jarvis/jarvis_rag/main.py +818 -0
  10. jarvis/jarvis_smart_shell/main.py +2 -2
  11. jarvis/models/ai8.py +3 -1
  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 +24 -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 +141 -0
  32. jarvis/tools/read_code.py +147 -0
  33. jarvis/tools/read_webpage.py +1 -1
  34. jarvis/tools/registry.py +47 -31
  35. jarvis/tools/search.py +8 -6
  36. jarvis/tools/select_code_files.py +4 -4
  37. jarvis/utils.py +374 -84
  38. {jarvis_ai_assistant-0.1.102.dist-info → jarvis_ai_assistant-0.1.103.dist-info}/METADATA +52 -2
  39. jarvis_ai_assistant-0.1.103.dist-info/RECORD +51 -0
  40. jarvis_ai_assistant-0.1.103.dist-info/entry_points.txt +11 -0
  41. jarvis/jarvis_code_agent/main.py +0 -200
  42. jarvis/jarvis_coder/git_utils.py +0 -123
  43. jarvis/jarvis_coder/patch_handler.py +0 -340
  44. jarvis/jarvis_github/main.py +0 -232
  45. jarvis/tools/execute_code_modification.py +0 -70
  46. jarvis/tools/find_files.py +0 -119
  47. jarvis/tools/generate_tool.py +0 -174
  48. jarvis/tools/thinker.py +0 -151
  49. jarvis_ai_assistant-0.1.102.dist-info/RECORD +0 -46
  50. jarvis_ai_assistant-0.1.102.dist-info/entry_points.txt +0 -6
  51. /jarvis/{jarvis_coder → jarvis_codebase}/__init__.py +0 -0
  52. /jarvis/{jarvis_github → jarvis_rag}/__init__.py +0 -0
  53. {jarvis_ai_assistant-0.1.102.dist-info → jarvis_ai_assistant-0.1.103.dist-info}/LICENSE +0 -0
  54. {jarvis_ai_assistant-0.1.102.dist-info → jarvis_ai_assistant-0.1.103.dist-info}/WHEEL +0 -0
  55. {jarvis_ai_assistant-0.1.102.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.102"
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, 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,25 +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
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
+ """
38
72
 
39
73
  self.max_context_length = get_max_context_length()
74
+
75
+ self.auto_complete = auto_complete
76
+
77
+
40
78
 
41
79
 
42
80
  # Initialize methodology related attributes
43
81
  self.methodology_data = []
44
82
 
45
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
46
107
 
47
108
  @staticmethod
48
109
  def extract_tool_calls(content: str) -> List[Dict]:
@@ -52,14 +113,6 @@ class Agent:
52
113
  tool_call_lines = []
53
114
  in_tool_call = False
54
115
 
55
- tool_call_help = """Tool Usage Format:
56
-
57
- <TOOL_CALL>
58
- name: tool_name
59
- arguments:
60
- param1: value1
61
- param2: value2
62
- </TOOL_CALL>"""
63
116
 
64
117
  # Process line by line
65
118
  for line in lines:
@@ -68,27 +121,19 @@ arguments:
68
121
  continue
69
122
  elif '</TOOL_CALL>' in line:
70
123
  if in_tool_call and tool_call_lines:
71
- try:
72
- # Parse YAML directly
73
- tool_call_text = '\n'.join(tool_call_lines)
74
- tool_call_data = yaml.safe_load(tool_call_text)
75
-
76
- # Validate necessary fields
77
- if "name" in tool_call_data and "arguments" in tool_call_data:
78
- # Return content before tool call and tool call
79
- return [{
80
- "name": tool_call_data["name"],
81
- "arguments": tool_call_data["arguments"]
82
- }]
83
- else:
84
- PrettyOutput.print("Tool call missing necessary fields", OutputType.ERROR)
85
- raise Exception("Tool call missing necessary fields, " + tool_call_help)
86
- except yaml.YAMLError as e:
87
- PrettyOutput.print(f"YAML parsing error: {str(e)}", OutputType.ERROR)
88
- raise Exception(f"YAML parsing error: {str(e)}")
89
- except Exception as e:
90
- PrettyOutput.print(f"Error processing tool call: {str(e)}", OutputType.ERROR)
91
- 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")
92
137
  in_tool_call = False
93
138
  continue
94
139
 
@@ -165,53 +210,39 @@ Please continue the task based on the above information.
165
210
  """
166
211
  PrettyOutput.section("Task completed", OutputType.SUCCESS)
167
212
 
168
- # 询问是否生成方法论,带输入验证
169
- while True:
170
- user_input = get_single_line_input("Generate methodology for this task? (y/n)").strip().lower()
171
- if user_input in ['y', 'n', '']:
172
- break
173
- PrettyOutput.print("Invalid input, please enter y or n", OutputType.WARNING)
174
-
175
- if user_input == 'y':
176
- try:
177
- # 让模型判断是否需要生成方法论
178
- analysis_prompt = """The current task has ended, please analyze whether a methodology needs to be generated.
179
- 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'.
180
- If you think a methodology is not needed, please explain why.
181
- The methodology should be applicable to general scenarios, do not include task-specific information such as code commit messages.
182
- The methodology should include: problem restatement, optimal solution, notes (as needed), and nothing else.
183
- Only output the methodology tool call instruction, or the explanation for not generating a methodology. Do not output anything else.
184
- """
185
- self.prompt = analysis_prompt
186
- response = self._call_model(self.prompt)
187
-
188
- # 检查是否包含工具调用
213
+ if not self.is_sub_agent:
214
+ if self.record_methodology:
215
+
189
216
  try:
190
- tool_calls = Agent.extract_tool_calls(response)
191
- if tool_calls:
192
- 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
+
193
236
  except Exception as e:
194
- PrettyOutput.print(f"Failed to handle methodology generation: {str(e)}", OutputType.ERROR)
195
-
196
- except Exception as e:
197
- PrettyOutput.print(f"Error generating methodology: {str(e)}", OutputType.ERROR)
198
-
199
- if not self.is_sub_agent:
237
+ PrettyOutput.print(f"Error generating methodology: {str(e)}", OutputType.ERROR)
238
+
200
239
  return "Task completed"
201
240
 
202
- # 生成任务总结
203
- summary_prompt = f"""Please generate a concise summary report of the task execution, including:
204
-
205
- 1. Task Objective: Task restatement
206
- 2. Execution Result: Success/Failure
207
- 3. Key Information: Important information extracted during execution
208
- 4. Important Findings: Any noteworthy discoveries
209
- 5. Follow-up Suggestions: If any
210
-
211
- Please describe in concise bullet points, highlighting important information.
212
- """
213
- self.prompt = summary_prompt
214
- 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"
215
246
 
216
247
 
217
248
  def run(self, user_input: str, file_list: Optional[List[str]] = None) -> str:
@@ -224,28 +255,22 @@ Please describe in concise bullet points, highlighting important information.
224
255
  Returns:
225
256
  str: Task summary report
226
257
  """
258
+
259
+
260
+
227
261
  try:
228
262
  PrettyOutput.section("Preparing environment", OutputType.PLANNING)
229
263
  if file_list:
230
264
  self.model.upload_files(file_list)
231
265
 
232
- # Load methodology
233
- methodology_prompt = load_methodology(user_input)
234
- tools_prompt = load_tools()
235
-
236
266
  # 显示任务开始
237
267
  PrettyOutput.section(f"Starting new task: {self.name}", OutputType.PLANNING)
238
268
 
239
- self.clear_history()
240
-
241
- self.model.set_system_message(f"""
242
- {self.system_prompt}
243
-
244
- {tools_prompt}
245
-
246
- {methodology_prompt}
247
- """)
248
- 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}"
249
274
 
250
275
  while True:
251
276
  try:
@@ -261,25 +286,32 @@ Please describe in concise bullet points, highlighting important information.
261
286
  continue
262
287
  else:
263
288
  current_response = self._call_model(self.prompt)
264
- 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
+
265
295
  try:
266
296
  result = Agent.extract_tool_calls(current_response)
267
297
  except Exception as e:
268
298
  PrettyOutput.print(f"Tool call error: {str(e)}", OutputType.ERROR)
269
- self.prompt = f"Tool call error: {str(e)}"
299
+ self.prompt += f"Tool call error: {str(e)}"
270
300
  continue
271
301
 
272
302
  if len(result) > 0:
273
303
  PrettyOutput.print("Executing tool call...", OutputType.PROGRESS)
274
304
  tool_result = self.tool_registry.handle_tool_calls(result)
275
- self.prompt = tool_result
305
+ self.prompt += tool_result
306
+
307
+ if self.prompt:
276
308
  continue
309
+
310
+ if self.auto_complete and "<!!!COMPLETE!!!>" in current_response:
311
+ return self._complete_task()
277
312
 
278
313
  # 获取用户输入
279
314
  user_input = get_multiline_input(f"{self.name}: You can continue to input, or enter an empty line to end the current task")
280
- if user_input == "__interrupt__":
281
- PrettyOutput.print("Task cancelled by user", OutputType.WARNING)
282
- return "Task cancelled by user"
283
315
 
284
316
  if user_input:
285
317
  self.prompt = user_input
@@ -362,10 +394,11 @@ def select_task(tasks: dict) -> str:
362
394
  # Convert tasks to list for ordered display
363
395
  task_names = list(tasks.keys())
364
396
 
365
- PrettyOutput.print("\nAvailable tasks:", OutputType.INFO)
397
+ task_list = ["Available tasks:"]
366
398
  for i, name in enumerate(task_names, 1):
367
- PrettyOutput.print(f"[{i}] {name}", OutputType.INFO)
368
- 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)
369
402
 
370
403
 
371
404
  while True:
@@ -406,25 +439,13 @@ When users need to execute tasks, you will strictly follow these steps to handle
406
439
  7. Execute Action Plan: Execute one step at a time, **use at most one tool** (wait for tool execution results before proceeding)
407
440
  8. Monitor and Adjust: If execution results don't match expectations, reflect and adjust the action plan, iterate previous steps
408
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
409
- 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
410
444
 
411
445
  Methodology Template:
412
446
  1. Problem Restatement
413
447
  2. Optimal Solution
414
448
  3. Optimal Solution Steps (exclude failed actions)
415
-
416
- Strict Rules:
417
- - Execute only one tool at a time
418
- - Tool execution must strictly follow the tool usage format
419
- - Wait for user to provide execution results
420
- - Don't assume or imagine results
421
- - Don't create fake dialogues
422
- - If current information is insufficient, you may ask the user
423
- - Not all problem-solving steps are mandatory, skip as appropriate
424
- - Request user guidance when multiple iterations show no progress
425
- - If yaml string contains colons, wrap the entire string in quotes to avoid yaml parsing errors
426
- - Use | syntax for multi-line strings in yaml
427
- - If you can start executing the task, please start directly without asking the user if you can begin.
428
449
 
429
450
  -------------------------------------------------------------"""
430
451
 
@@ -453,7 +474,7 @@ def main():
453
474
  while True:
454
475
  try:
455
476
  user_input = get_multiline_input("Please enter your task (input empty line to exit):")
456
- if not user_input or user_input == "__interrupt__":
477
+ if not user_input:
457
478
  break
458
479
  agent.run(user_input, args.files)
459
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())