jarvis-ai-assistant 0.1.110__py3-none-any.whl → 0.1.112__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.
- jarvis/__init__.py +1 -1
- jarvis/agent.py +51 -39
- jarvis/jarvis_code_agent/code_agent.py +89 -53
- jarvis/jarvis_code_agent/file_select.py +20 -20
- jarvis/jarvis_code_agent/patch.py +20 -11
- jarvis/jarvis_code_agent/relevant_files.py +68 -16
- jarvis/jarvis_codebase/main.py +82 -88
- jarvis/jarvis_lsp/cpp.py +1 -1
- jarvis/jarvis_lsp/go.py +1 -1
- jarvis/jarvis_lsp/python.py +0 -2
- jarvis/jarvis_lsp/registry.py +13 -13
- jarvis/jarvis_lsp/rust.py +1 -1
- jarvis/jarvis_platform/ai8.py +14 -14
- jarvis/jarvis_platform/base.py +1 -1
- jarvis/jarvis_platform/kimi.py +17 -17
- jarvis/jarvis_platform/ollama.py +14 -14
- jarvis/jarvis_platform/openai.py +8 -8
- jarvis/jarvis_platform/oyi.py +19 -19
- jarvis/jarvis_platform/registry.py +6 -6
- jarvis/jarvis_platform_manager/main.py +17 -17
- jarvis/jarvis_rag/main.py +25 -25
- jarvis/jarvis_smart_shell/main.py +6 -6
- jarvis/jarvis_tools/ask_codebase.py +4 -4
- jarvis/jarvis_tools/ask_user.py +2 -2
- jarvis/jarvis_tools/create_code_agent.py +8 -8
- jarvis/jarvis_tools/create_sub_agent.py +2 -2
- jarvis/jarvis_tools/execute_shell.py +2 -2
- jarvis/jarvis_tools/file_operation.py +1 -1
- jarvis/jarvis_tools/git_commiter.py +4 -6
- jarvis/jarvis_tools/methodology.py +3 -3
- jarvis/jarvis_tools/rag.py +3 -3
- jarvis/jarvis_tools/read_code.py +4 -3
- jarvis/jarvis_tools/read_webpage.py +19 -6
- jarvis/jarvis_tools/registry.py +11 -11
- jarvis/jarvis_tools/search.py +88 -27
- jarvis/jarvis_tools/select_code_files.py +1 -1
- jarvis/jarvis_tools/tool_generator.py +182 -0
- jarvis/utils/date_utils.py +19 -0
- jarvis/utils.py +31 -25
- jarvis_ai_assistant-0.1.112.dist-info/METADATA +460 -0
- jarvis_ai_assistant-0.1.112.dist-info/RECORD +64 -0
- jarvis_ai_assistant-0.1.110.dist-info/METADATA +0 -462
- jarvis_ai_assistant-0.1.110.dist-info/RECORD +0 -62
- {jarvis_ai_assistant-0.1.110.dist-info → jarvis_ai_assistant-0.1.112.dist-info}/LICENSE +0 -0
- {jarvis_ai_assistant-0.1.110.dist-info → jarvis_ai_assistant-0.1.112.dist-info}/WHEEL +0 -0
- {jarvis_ai_assistant-0.1.110.dist-info → jarvis_ai_assistant-0.1.112.dist-info}/entry_points.txt +0 -0
- {jarvis_ai_assistant-0.1.110.dist-info → jarvis_ai_assistant-0.1.112.dist-info}/top_level.txt +0 -0
jarvis/__init__.py
CHANGED
jarvis/agent.py
CHANGED
|
@@ -8,7 +8,7 @@ import yaml
|
|
|
8
8
|
from jarvis.jarvis_platform.base import BasePlatform
|
|
9
9
|
from jarvis.jarvis_platform.registry import PlatformRegistry
|
|
10
10
|
from jarvis.jarvis_tools.registry import ToolRegistry, tool_call_help
|
|
11
|
-
from jarvis.utils import PrettyOutput, OutputType, get_context_token_count, is_auto_complete, is_need_summary, is_record_methodology, load_methodology, add_agent, delete_current_agent, get_max_token_count, get_multiline_input, init_env, is_use_methodology
|
|
11
|
+
from jarvis.utils import PrettyOutput, OutputType, get_context_token_count, is_auto_complete, is_execute_tool_confirm, is_need_summary, is_record_methodology, load_methodology, add_agent, delete_current_agent, get_max_token_count, get_multiline_input, init_env, is_use_methodology, user_confirm
|
|
12
12
|
import os
|
|
13
13
|
|
|
14
14
|
class Agent:
|
|
@@ -39,10 +39,12 @@ class Agent:
|
|
|
39
39
|
auto_complete: Optional[bool] = None,
|
|
40
40
|
output_handler_before_tool: Optional[List[Callable]] = None,
|
|
41
41
|
output_handler_after_tool: Optional[List[Callable]] = None,
|
|
42
|
+
input_handler: Optional[List[Callable]] = None,
|
|
42
43
|
use_methodology: Optional[bool] = None,
|
|
43
44
|
record_methodology: Optional[bool] = None,
|
|
44
45
|
need_summary: Optional[bool] = None,
|
|
45
|
-
max_context_length: Optional[int] = None
|
|
46
|
+
max_context_length: Optional[int] = None,
|
|
47
|
+
execute_tool_confirm: Optional[bool] = None):
|
|
46
48
|
"""Initialize an Agent instance.
|
|
47
49
|
|
|
48
50
|
Args:
|
|
@@ -60,7 +62,7 @@ class Agent:
|
|
|
60
62
|
need_summary: Whether to generate summaries
|
|
61
63
|
max_context_length: Maximum context length
|
|
62
64
|
"""
|
|
63
|
-
PrettyOutput.print(f"
|
|
65
|
+
PrettyOutput.print(f"欢迎使用Jarvis,你的AI助手,正在初始化...", OutputType.SYSTEM)
|
|
64
66
|
if platform is not None:
|
|
65
67
|
self.model = platform
|
|
66
68
|
else:
|
|
@@ -74,10 +76,13 @@ class Agent:
|
|
|
74
76
|
self.conversation_length = 0 # Use length counter instead
|
|
75
77
|
self.system_prompt = system_prompt
|
|
76
78
|
self.need_summary = need_summary if need_summary is not None else is_need_summary()
|
|
79
|
+
self.input_handler = input_handler if input_handler is not None else []
|
|
77
80
|
# Load configuration from environment variables
|
|
78
81
|
self.output_handler_before_tool = output_handler_before_tool if output_handler_before_tool else []
|
|
79
82
|
self.output_handler_after_tool = output_handler_after_tool if output_handler_after_tool else []
|
|
80
83
|
|
|
84
|
+
self.execute_tool_confirm = execute_tool_confirm if execute_tool_confirm is not None else is_execute_tool_confirm()
|
|
85
|
+
|
|
81
86
|
self.summary_prompt = summary_prompt if summary_prompt else f"""Please generate a concise summary report of the task execution, including:
|
|
82
87
|
|
|
83
88
|
1. Task Objective: Task restatement
|
|
@@ -93,11 +98,11 @@ Please describe in concise bullet points, highlighting important information.
|
|
|
93
98
|
|
|
94
99
|
self.auto_complete = auto_complete if auto_complete is not None else is_auto_complete()
|
|
95
100
|
|
|
96
|
-
PrettyOutput.section(f"Jarvis
|
|
101
|
+
PrettyOutput.section(f"Jarvis 初始化完成 - 使用 {self.model.name()} 模型", OutputType.SYSTEM)
|
|
97
102
|
|
|
98
103
|
tools = self.tool_registry.get_all_tools()
|
|
99
104
|
if tools:
|
|
100
|
-
PrettyOutput.section(f"
|
|
105
|
+
PrettyOutput.section(f"可用工具: {', '.join([tool['name'] for tool in tools])}", OutputType.SYSTEM)
|
|
101
106
|
|
|
102
107
|
|
|
103
108
|
tools_prompt = self.tool_registry.load_tools()
|
|
@@ -178,12 +183,16 @@ Please describe in concise bullet points, highlighting important information.
|
|
|
178
183
|
Will retry with exponential backoff up to 30 seconds between retries
|
|
179
184
|
"""
|
|
180
185
|
sleep_time = 5
|
|
186
|
+
|
|
187
|
+
for handler in self.input_handler:
|
|
188
|
+
message = handler(message)
|
|
189
|
+
|
|
181
190
|
while True:
|
|
182
191
|
ret = self.model.chat_until_success(message)
|
|
183
192
|
if ret:
|
|
184
193
|
return ret
|
|
185
194
|
else:
|
|
186
|
-
PrettyOutput.print(f"
|
|
195
|
+
PrettyOutput.print(f"模型调用失败,正在重试... 等待 {sleep_time}s", OutputType.INFO)
|
|
187
196
|
time.sleep(sleep_time)
|
|
188
197
|
sleep_time *= 2
|
|
189
198
|
if sleep_time > 30:
|
|
@@ -206,7 +215,7 @@ Please describe in concise bullet points, highlighting important information.
|
|
|
206
215
|
"""
|
|
207
216
|
# Create a new model instance to summarize, avoid affecting the main conversation
|
|
208
217
|
|
|
209
|
-
PrettyOutput.print("
|
|
218
|
+
PrettyOutput.print("总结对话历史,准备生成摘要,开始新对话...", OutputType.PROGRESS)
|
|
210
219
|
|
|
211
220
|
prompt = """Please summarize the key information from the previous conversation, including:
|
|
212
221
|
1. Current task objective
|
|
@@ -219,7 +228,7 @@ Please describe in concise bullet points, highlighting important information. Do
|
|
|
219
228
|
"""
|
|
220
229
|
|
|
221
230
|
try:
|
|
222
|
-
summary = self.
|
|
231
|
+
summary = self._call_model(self.prompt + "\n" + prompt)
|
|
223
232
|
|
|
224
233
|
# 清空当前对话历史,但保留系统消息
|
|
225
234
|
self.conversation_length = 0 # Reset conversation length
|
|
@@ -234,7 +243,7 @@ Please continue the task based on the above information.
|
|
|
234
243
|
self.conversation_length = len(self.prompt) # 设置新的起始长度
|
|
235
244
|
|
|
236
245
|
except Exception as e:
|
|
237
|
-
PrettyOutput.print(f"
|
|
246
|
+
PrettyOutput.print(f"总结对话历史失败: {str(e)}", OutputType.ERROR)
|
|
238
247
|
|
|
239
248
|
def _complete_task(self) -> str:
|
|
240
249
|
"""Complete the current task and generate summary if needed.
|
|
@@ -246,7 +255,7 @@ Please continue the task based on the above information.
|
|
|
246
255
|
- For main agent: May generate methodology if enabled
|
|
247
256
|
- For sub-agent: May generate summary if enabled
|
|
248
257
|
"""
|
|
249
|
-
PrettyOutput.section("
|
|
258
|
+
PrettyOutput.section("任务完成", OutputType.SUCCESS)
|
|
250
259
|
|
|
251
260
|
if not self.is_sub_agent:
|
|
252
261
|
if self.record_methodology:
|
|
@@ -269,18 +278,18 @@ Please continue the task based on the above information.
|
|
|
269
278
|
if tool_calls:
|
|
270
279
|
self.tool_registry.handle_tool_calls(tool_calls)
|
|
271
280
|
except Exception as e:
|
|
272
|
-
PrettyOutput.print(f"
|
|
281
|
+
PrettyOutput.print(f"处理方法论生成失败: {str(e)}", OutputType.ERROR)
|
|
273
282
|
|
|
274
283
|
except Exception as e:
|
|
275
|
-
PrettyOutput.print(f"
|
|
284
|
+
PrettyOutput.print(f"生成方法论失败: {str(e)}", OutputType.ERROR)
|
|
276
285
|
|
|
277
|
-
return "
|
|
286
|
+
return "任务完成"
|
|
278
287
|
|
|
279
288
|
if self.need_summary:
|
|
280
289
|
self.prompt = self.summary_prompt
|
|
281
290
|
return self._call_model(self.prompt)
|
|
282
291
|
|
|
283
|
-
return "
|
|
292
|
+
return "任务完成"
|
|
284
293
|
|
|
285
294
|
|
|
286
295
|
def run(self, user_input: str, file_list: Optional[List[str]] = None) -> str:
|
|
@@ -303,12 +312,12 @@ Please continue the task based on the above information.
|
|
|
303
312
|
add_agent(self.name)
|
|
304
313
|
|
|
305
314
|
try:
|
|
306
|
-
PrettyOutput.section("
|
|
315
|
+
PrettyOutput.section("准备环境", OutputType.PLANNING)
|
|
307
316
|
if file_list:
|
|
308
317
|
self.model.upload_files(file_list)
|
|
309
318
|
|
|
310
319
|
# 显示任务开始
|
|
311
|
-
PrettyOutput.section(f"
|
|
320
|
+
PrettyOutput.section(f"开始新任务: {self.name}", OutputType.PLANNING)
|
|
312
321
|
|
|
313
322
|
if self.first and self.use_methodology:
|
|
314
323
|
self.prompt = f"{user_input}\n\n{load_methodology(user_input)}"
|
|
@@ -319,7 +328,7 @@ Please continue the task based on the above information.
|
|
|
319
328
|
while True:
|
|
320
329
|
try:
|
|
321
330
|
# 显示思考状态
|
|
322
|
-
PrettyOutput.print("
|
|
331
|
+
PrettyOutput.print("正在分析任务...", OutputType.PROGRESS)
|
|
323
332
|
|
|
324
333
|
# 累加对话长度
|
|
325
334
|
self.conversation_length += get_context_token_count(self.prompt)
|
|
@@ -339,15 +348,16 @@ Please continue the task based on the above information.
|
|
|
339
348
|
try:
|
|
340
349
|
result = Agent._extract_tool_calls(current_response)
|
|
341
350
|
except Exception as e:
|
|
342
|
-
PrettyOutput.print(f"
|
|
351
|
+
PrettyOutput.print(f"工具调用错误: {str(e)}", OutputType.ERROR)
|
|
343
352
|
self.prompt += f"Tool call error: {str(e)}"
|
|
344
353
|
continue
|
|
345
354
|
|
|
346
355
|
if len(result) > 0:
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
356
|
+
if not self.execute_tool_confirm or user_confirm(f"执行工具调用: {result[0]['name']}?"):
|
|
357
|
+
PrettyOutput.print("正在执行工具调用...", OutputType.PROGRESS)
|
|
358
|
+
tool_result = self.tool_registry.handle_tool_calls(result)
|
|
359
|
+
self.prompt += tool_result
|
|
360
|
+
|
|
351
361
|
for handler in self.output_handler_after_tool:
|
|
352
362
|
self.prompt += handler(current_response)
|
|
353
363
|
|
|
@@ -358,7 +368,7 @@ Please continue the task based on the above information.
|
|
|
358
368
|
return self._complete_task()
|
|
359
369
|
|
|
360
370
|
# 获取用户输入
|
|
361
|
-
user_input = get_multiline_input(f"{self.name}:
|
|
371
|
+
user_input = get_multiline_input(f"{self.name}: 您可以继续输入,或输入空行来结束当前任务:")
|
|
362
372
|
|
|
363
373
|
if user_input:
|
|
364
374
|
self.prompt = user_input
|
|
@@ -368,11 +378,11 @@ Please continue the task based on the above information.
|
|
|
368
378
|
return self._complete_task()
|
|
369
379
|
|
|
370
380
|
except Exception as e:
|
|
371
|
-
PrettyOutput.print(str(e), OutputType.ERROR)
|
|
381
|
+
PrettyOutput.print(f"任务失败: {str(e)}", OutputType.ERROR)
|
|
372
382
|
return f"Task failed: {str(e)}"
|
|
373
383
|
|
|
374
384
|
except Exception as e:
|
|
375
|
-
PrettyOutput.print(str(e), OutputType.ERROR)
|
|
385
|
+
PrettyOutput.print(f"任务失败: {str(e)}", OutputType.ERROR)
|
|
376
386
|
return f"Task failed: {str(e)}"
|
|
377
387
|
|
|
378
388
|
finally:
|
|
@@ -410,9 +420,9 @@ def _load_tasks() -> dict:
|
|
|
410
420
|
if desc: # Ensure description is not empty
|
|
411
421
|
tasks[str(name)] = str(desc)
|
|
412
422
|
else:
|
|
413
|
-
PrettyOutput.print("
|
|
423
|
+
PrettyOutput.print("警告: ~/.jarvis/pre-command 文件应该包含一个字典,键为任务名称,值为任务描述", OutputType.ERROR)
|
|
414
424
|
except Exception as e:
|
|
415
|
-
PrettyOutput.print(f"
|
|
425
|
+
PrettyOutput.print(f"加载 ~/.jarvis/pre-command 文件失败: {str(e)}", OutputType.ERROR)
|
|
416
426
|
|
|
417
427
|
# Check .jarvis/pre-command in current directory
|
|
418
428
|
if os.path.exists(".jarvis/pre-command"):
|
|
@@ -426,9 +436,9 @@ def _load_tasks() -> dict:
|
|
|
426
436
|
if desc: # Ensure description is not empty
|
|
427
437
|
tasks[str(name)] = str(desc)
|
|
428
438
|
else:
|
|
429
|
-
PrettyOutput.print("
|
|
439
|
+
PrettyOutput.print("警告: .jarvis/pre-command 文件应该包含一个字典,键为任务名称,值为任务描述", OutputType.ERROR)
|
|
430
440
|
except Exception as e:
|
|
431
|
-
PrettyOutput.print(f"
|
|
441
|
+
PrettyOutput.print(f"加载 .jarvis/pre-command 文件失败: {str(e)}", OutputType.ERROR)
|
|
432
442
|
|
|
433
443
|
|
|
434
444
|
if is_use_methodology():
|
|
@@ -451,17 +461,17 @@ def _select_task(tasks: dict) -> str:
|
|
|
451
461
|
# Convert tasks to list for ordered display
|
|
452
462
|
task_names = list(tasks.keys())
|
|
453
463
|
|
|
454
|
-
task_list = ["
|
|
464
|
+
task_list = ["可用任务:"]
|
|
455
465
|
for i, name in enumerate(task_names, 1):
|
|
456
466
|
task_list.append(f"[{i}] {name}")
|
|
457
|
-
task_list.append("[0]
|
|
467
|
+
task_list.append("[0] 跳过预定义任务")
|
|
458
468
|
PrettyOutput.print("\n".join(task_list), OutputType.INFO)
|
|
459
469
|
|
|
460
470
|
|
|
461
471
|
while True:
|
|
462
472
|
try:
|
|
463
473
|
choice = prompt(
|
|
464
|
-
"\
|
|
474
|
+
"\n请选择一个任务编号(0 跳过预定义任务):",
|
|
465
475
|
).strip()
|
|
466
476
|
|
|
467
477
|
if not choice:
|
|
@@ -474,14 +484,14 @@ def _select_task(tasks: dict) -> str:
|
|
|
474
484
|
selected_name = task_names[choice - 1]
|
|
475
485
|
return tasks[selected_name] # Return the task description
|
|
476
486
|
else:
|
|
477
|
-
PrettyOutput.print("
|
|
487
|
+
PrettyOutput.print("无效的选择。请选择列表中的一个号码。", OutputType.ERROR)
|
|
478
488
|
|
|
479
489
|
except KeyboardInterrupt:
|
|
480
490
|
return "" # Return empty on Ctrl+C
|
|
481
491
|
except EOFError:
|
|
482
492
|
return "" # Return empty on Ctrl+D
|
|
483
493
|
except Exception as e:
|
|
484
|
-
PrettyOutput.print(f"
|
|
494
|
+
PrettyOutput.print(f"选择任务失败: {str(e)}", OutputType.ERROR)
|
|
485
495
|
continue
|
|
486
496
|
|
|
487
497
|
origin_agent_system_prompt = """You are Jarvis, an AI assistant with powerful problem-solving capabilities.
|
|
@@ -499,6 +509,8 @@ When users need to execute tasks, you will strictly follow these steps to handle
|
|
|
499
509
|
10. Auto check the task goal completion status: If the task goal is completed, use the task completion command to end the task
|
|
500
510
|
11. Task Completion: End the task using task completion command when finished
|
|
501
511
|
|
|
512
|
+
Tip: Chat in user's language
|
|
513
|
+
|
|
502
514
|
Methodology Template:
|
|
503
515
|
1. Problem Restatement
|
|
504
516
|
2. Optimal Solution
|
|
@@ -516,29 +528,29 @@ def main():
|
|
|
516
528
|
|
|
517
529
|
try:
|
|
518
530
|
# 获取全局模型实例
|
|
519
|
-
agent = Agent(system_prompt=origin_agent_system_prompt
|
|
531
|
+
agent = Agent(system_prompt=origin_agent_system_prompt)
|
|
520
532
|
|
|
521
533
|
# 加载预定义任务
|
|
522
534
|
tasks = _load_tasks()
|
|
523
535
|
if tasks:
|
|
524
536
|
selected_task = _select_task(tasks)
|
|
525
537
|
if selected_task:
|
|
526
|
-
PrettyOutput.print(f"
|
|
538
|
+
PrettyOutput.print(f"执行任务: {selected_task}", OutputType.INFO)
|
|
527
539
|
agent.run(selected_task, args.files)
|
|
528
540
|
return 0
|
|
529
541
|
|
|
530
542
|
# 如果没有选择预定义任务,进入交互模式
|
|
531
543
|
while True:
|
|
532
544
|
try:
|
|
533
|
-
user_input = get_multiline_input("
|
|
545
|
+
user_input = get_multiline_input("请输入你的任务(输入空行退出):")
|
|
534
546
|
if not user_input:
|
|
535
547
|
break
|
|
536
548
|
agent.run(user_input, args.files)
|
|
537
549
|
except Exception as e:
|
|
538
|
-
PrettyOutput.print(f"
|
|
550
|
+
PrettyOutput.print(f"错误: {str(e)}", OutputType.ERROR)
|
|
539
551
|
|
|
540
552
|
except Exception as e:
|
|
541
|
-
PrettyOutput.print(f"
|
|
553
|
+
PrettyOutput.print(f"初始化错误: {str(e)}", OutputType.ERROR)
|
|
542
554
|
return 1
|
|
543
555
|
|
|
544
556
|
return 0
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import os
|
|
2
|
-
from typing import List
|
|
2
|
+
from typing import Dict, List
|
|
3
3
|
|
|
4
4
|
from jarvis.agent import Agent
|
|
5
5
|
from jarvis.jarvis_code_agent.patch import apply_patch
|
|
6
|
-
from jarvis.jarvis_code_agent.relevant_files import
|
|
6
|
+
from jarvis.jarvis_code_agent.relevant_files import find_relevant_information
|
|
7
7
|
from jarvis.jarvis_platform.registry import PlatformRegistry
|
|
8
8
|
from jarvis.jarvis_tools.git_commiter import GitCommitTool
|
|
9
9
|
from jarvis.jarvis_tools.registry import ToolRegistry
|
|
10
|
-
from jarvis.utils import OutputType, PrettyOutput,
|
|
10
|
+
from jarvis.utils import OutputType, PrettyOutput, get_multiline_input, has_uncommitted_changes, init_env, find_git_root
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
class CodeAgent:
|
|
@@ -26,11 +26,32 @@ class CodeAgent:
|
|
|
26
26
|
"lsp_find_definition",
|
|
27
27
|
"lsp_prepare_rename",
|
|
28
28
|
"lsp_validate_edit"])
|
|
29
|
-
code_system_prompt = """You are a code agent responsible for modifying code.
|
|
29
|
+
code_system_prompt = """You are a code agent responsible for modifying code. Your primary task is to understand existing code first and ensure compatibility with the current system.
|
|
30
|
+
|
|
31
|
+
# Critical First Steps
|
|
32
|
+
1. READ and UNDERSTAND existing code thoroughly
|
|
33
|
+
2. Identify current patterns and conventions
|
|
34
|
+
3. Map out affected components and their interactions
|
|
35
|
+
4. Plan changes that maintain system integrity
|
|
36
|
+
|
|
37
|
+
# Code Completeness Requirements
|
|
38
|
+
1. Implementation Must Be Complete
|
|
39
|
+
• NO TODOs or placeholder comments
|
|
40
|
+
• NO unfinished functions
|
|
41
|
+
• NO stub implementations
|
|
42
|
+
• All error cases must be handled
|
|
43
|
+
• All edge cases must be covered
|
|
44
|
+
|
|
45
|
+
2. Documentation Must Be Complete
|
|
46
|
+
• All functions must have docstrings
|
|
47
|
+
• All parameters must be documented
|
|
48
|
+
• Return values must be specified
|
|
49
|
+
• Exceptions must be documented
|
|
50
|
+
• Complex logic must be explained
|
|
30
51
|
|
|
31
52
|
# Patch Format
|
|
32
53
|
<PATCH>
|
|
33
|
-
>
|
|
54
|
+
> path/file start,end
|
|
34
55
|
new_content
|
|
35
56
|
</PATCH>
|
|
36
57
|
|
|
@@ -41,40 +62,44 @@ Key Rules:
|
|
|
41
62
|
• Same start/end number: insert before that line
|
|
42
63
|
• Start=0, end=0: create new file with content
|
|
43
64
|
|
|
44
|
-
# Code Compatibility
|
|
65
|
+
# Code Compatibility Requirements
|
|
45
66
|
1. System Integration
|
|
46
|
-
•
|
|
47
|
-
•
|
|
48
|
-
•
|
|
49
|
-
•
|
|
67
|
+
• MUST preserve existing API contracts
|
|
68
|
+
• MUST maintain current function signatures
|
|
69
|
+
• MUST keep data structure compatibility
|
|
70
|
+
• MUST follow error handling patterns
|
|
50
71
|
|
|
51
72
|
2. Style Consistency
|
|
52
|
-
• Match naming conventions
|
|
53
|
-
• Follow
|
|
54
|
-
• Use
|
|
55
|
-
•
|
|
73
|
+
• Match existing naming conventions exactly
|
|
74
|
+
• Follow established code organization
|
|
75
|
+
• Use current import style and order
|
|
76
|
+
• Maintain comment style and level of detail
|
|
56
77
|
|
|
57
78
|
3. Pattern Alignment
|
|
58
|
-
•
|
|
59
|
-
• Follow
|
|
60
|
-
•
|
|
61
|
-
• Keep configuration
|
|
79
|
+
• Reuse existing error handling approaches
|
|
80
|
+
• Follow established design patterns
|
|
81
|
+
• Use current logging conventions
|
|
82
|
+
• Keep configuration consistency
|
|
62
83
|
|
|
63
84
|
# Development Process
|
|
64
|
-
1. ANALYZE
|
|
65
|
-
•
|
|
66
|
-
•
|
|
67
|
-
•
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
•
|
|
72
|
-
•
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
•
|
|
85
|
+
1. ANALYZE (Current Code)
|
|
86
|
+
• Read and understand existing implementations
|
|
87
|
+
• Map out current code structure
|
|
88
|
+
• Identify established patterns
|
|
89
|
+
• Note key dependencies
|
|
90
|
+
|
|
91
|
+
2. ASSESS (Changes)
|
|
92
|
+
• Evaluate impact on existing code
|
|
93
|
+
• Check all dependencies
|
|
94
|
+
• Verify API compatibility
|
|
95
|
+
• Consider side effects
|
|
96
|
+
|
|
97
|
+
3. IMPLEMENT (Carefully)
|
|
98
|
+
• Make minimal necessary changes
|
|
99
|
+
• Follow existing patterns exactly
|
|
100
|
+
• Preserve all interfaces
|
|
101
|
+
• Maintain backward compatibility
|
|
102
|
+
• Implement completely - no TODOs
|
|
78
103
|
|
|
79
104
|
# File Handling
|
|
80
105
|
Large Files (>200 lines):
|
|
@@ -84,26 +109,28 @@ Large Files (>200 lines):
|
|
|
84
109
|
|
|
85
110
|
# Available Tools
|
|
86
111
|
Primary:
|
|
112
|
+
• read_code - MUST use to understand existing code
|
|
87
113
|
• LSP tools for code analysis
|
|
88
|
-
• read_code with line ranges
|
|
89
114
|
• execute_shell for searches
|
|
90
|
-
• ask_user when
|
|
115
|
+
• ask_user when uncertain
|
|
91
116
|
|
|
92
117
|
# Quality Requirements
|
|
93
|
-
|
|
94
|
-
✓
|
|
95
|
-
✓
|
|
118
|
+
Every Change Must:
|
|
119
|
+
✓ Be based on thorough code reading
|
|
120
|
+
✓ Preserve all interfaces
|
|
121
|
+
✓ Match existing style exactly
|
|
96
122
|
✓ Handle errors consistently
|
|
97
123
|
✓ Maintain documentation
|
|
98
|
-
✓
|
|
99
|
-
✓
|
|
124
|
+
✓ Follow project patterns
|
|
125
|
+
✓ Be completely implemented
|
|
126
|
+
✓ Have no TODOs or stubs"""
|
|
100
127
|
self.agent = Agent(system_prompt=code_system_prompt,
|
|
101
128
|
name="CodeAgent",
|
|
102
129
|
auto_complete=False,
|
|
103
130
|
is_sub_agent=False,
|
|
104
131
|
use_methodology=False,
|
|
105
132
|
tool_registry=tool_registry,
|
|
106
|
-
platform=PlatformRegistry().
|
|
133
|
+
platform=PlatformRegistry().get_codegen_platform(),
|
|
107
134
|
record_methodology=False,
|
|
108
135
|
output_handler_after_tool=[apply_patch],
|
|
109
136
|
need_summary=False)
|
|
@@ -119,17 +146,22 @@ Code Changes Must:
|
|
|
119
146
|
git_commiter.execute({})
|
|
120
147
|
|
|
121
148
|
|
|
122
|
-
def make_files_prompt(self, files: List[str]) -> str:
|
|
123
|
-
"""Make the files prompt.
|
|
149
|
+
def make_files_prompt(self, files: List[Dict[str, str]]) -> str:
|
|
150
|
+
"""Make the files prompt with content that fits within token limit.
|
|
124
151
|
|
|
125
152
|
Args:
|
|
126
153
|
files: The files to be modified
|
|
127
154
|
|
|
155
|
+
Returns:
|
|
156
|
+
str: A prompt containing file paths and contents within token limit
|
|
128
157
|
"""
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
158
|
+
prompt_parts = []
|
|
159
|
+
|
|
160
|
+
# Then try to add file contents
|
|
161
|
+
for file in files:
|
|
162
|
+
prompt_parts.append(f'''- {file['file']} ({file['reason']})''')
|
|
163
|
+
|
|
164
|
+
return "\n".join(prompt_parts)
|
|
133
165
|
|
|
134
166
|
def run(self, user_input: str) :
|
|
135
167
|
"""Run the code agent with the given user input.
|
|
@@ -142,15 +174,15 @@ Code Changes Must:
|
|
|
142
174
|
"""
|
|
143
175
|
try:
|
|
144
176
|
self._init_env()
|
|
145
|
-
files =
|
|
146
|
-
self.agent.run(self._build_first_edit_prompt(user_input, self.make_files_prompt(files)))
|
|
177
|
+
files, information = find_relevant_information(user_input, self.root_dir)
|
|
178
|
+
self.agent.run(self._build_first_edit_prompt(user_input, self.make_files_prompt(files), information))
|
|
147
179
|
|
|
148
180
|
except Exception as e:
|
|
149
181
|
return f"Error during execution: {str(e)}"
|
|
150
182
|
|
|
151
183
|
|
|
152
184
|
|
|
153
|
-
def _build_first_edit_prompt(self, user_input: str, files_prompt: str) -> str:
|
|
185
|
+
def _build_first_edit_prompt(self, user_input: str, files_prompt: str, information: str) -> str:
|
|
154
186
|
"""Build the initial prompt for the agent.
|
|
155
187
|
|
|
156
188
|
Args:
|
|
@@ -160,13 +192,17 @@ Code Changes Must:
|
|
|
160
192
|
Returns:
|
|
161
193
|
str: The formatted prompt
|
|
162
194
|
"""
|
|
195
|
+
|
|
163
196
|
return f"""# Code Modification Task
|
|
164
197
|
|
|
165
198
|
## User Requirement
|
|
166
199
|
{user_input}
|
|
167
200
|
|
|
168
|
-
##
|
|
201
|
+
## Maybe Relevant Files
|
|
169
202
|
{files_prompt}
|
|
203
|
+
|
|
204
|
+
## Some Information
|
|
205
|
+
{information}
|
|
170
206
|
"""
|
|
171
207
|
def main():
|
|
172
208
|
"""Jarvis main entry point"""
|
|
@@ -178,17 +214,17 @@ def main():
|
|
|
178
214
|
# Interactive mode
|
|
179
215
|
while True:
|
|
180
216
|
try:
|
|
181
|
-
user_input = get_multiline_input("
|
|
217
|
+
user_input = get_multiline_input("请输入你的需求(输入空行退出):")
|
|
182
218
|
if not user_input:
|
|
183
219
|
break
|
|
184
220
|
agent = CodeAgent()
|
|
185
221
|
agent.run(user_input)
|
|
186
222
|
|
|
187
223
|
except Exception as e:
|
|
188
|
-
PrettyOutput.print(f"
|
|
224
|
+
PrettyOutput.print(f"错误: {str(e)}", OutputType.ERROR)
|
|
189
225
|
|
|
190
226
|
except Exception as e:
|
|
191
|
-
PrettyOutput.print(f"
|
|
227
|
+
PrettyOutput.print(f"初始化错误: {str(e)}", OutputType.ERROR)
|
|
192
228
|
return 1
|
|
193
229
|
|
|
194
230
|
return 0
|