jarvis-ai-assistant 0.1.160__tar.gz → 0.1.161__tar.gz

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 (104) hide show
  1. {jarvis_ai_assistant-0.1.160/src/jarvis_ai_assistant.egg-info → jarvis_ai_assistant-0.1.161}/PKG-INFO +1 -1
  2. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/pyproject.toml +1 -1
  3. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/setup.py +1 -1
  4. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/__init__.py +1 -1
  5. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_agent/jarvis.py +1 -1
  6. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_agent/patch.py +38 -18
  7. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_code_agent/code_agent.py +126 -15
  8. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_git_utils/git_commiter.py +7 -3
  9. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_utils/input.py +40 -37
  10. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161/src/jarvis_ai_assistant.egg-info}/PKG-INFO +1 -1
  11. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/LICENSE +0 -0
  12. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/MANIFEST.in +0 -0
  13. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/README.md +0 -0
  14. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/setup.cfg +0 -0
  15. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_agent/__init__.py +0 -0
  16. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_agent/builtin_input_handler.py +0 -0
  17. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_agent/file_input_handler.py +0 -0
  18. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_agent/main.py +0 -0
  19. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_agent/output_handler.py +0 -0
  20. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_agent/shell_input_handler.py +0 -0
  21. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_code_agent/__init__.py +0 -0
  22. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_code_analysis/checklists/__init__.py +0 -0
  23. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_code_analysis/checklists/c_cpp.py +0 -0
  24. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_code_analysis/checklists/csharp.py +0 -0
  25. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_code_analysis/checklists/data_format.py +0 -0
  26. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_code_analysis/checklists/devops.py +0 -0
  27. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_code_analysis/checklists/docs.py +0 -0
  28. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_code_analysis/checklists/go.py +0 -0
  29. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_code_analysis/checklists/infrastructure.py +0 -0
  30. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_code_analysis/checklists/java.py +0 -0
  31. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_code_analysis/checklists/javascript.py +0 -0
  32. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_code_analysis/checklists/kotlin.py +0 -0
  33. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_code_analysis/checklists/loader.py +0 -0
  34. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_code_analysis/checklists/php.py +0 -0
  35. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_code_analysis/checklists/python.py +0 -0
  36. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_code_analysis/checklists/ruby.py +0 -0
  37. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_code_analysis/checklists/rust.py +0 -0
  38. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_code_analysis/checklists/shell.py +0 -0
  39. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_code_analysis/checklists/sql.py +0 -0
  40. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_code_analysis/checklists/swift.py +0 -0
  41. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_code_analysis/checklists/web.py +0 -0
  42. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_code_analysis/code_review.py +0 -0
  43. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_dev/main.py +0 -0
  44. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_git_details/__init__.py +0 -0
  45. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_git_details/main.py +0 -0
  46. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_git_squash/__init__.py +0 -0
  47. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_git_squash/main.py +0 -0
  48. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_lsp/base.py +0 -0
  49. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_lsp/cpp.py +0 -0
  50. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_lsp/go.py +0 -0
  51. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_lsp/python.py +0 -0
  52. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_lsp/registry.py +0 -0
  53. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_lsp/rust.py +0 -0
  54. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_mcp/__init__.py +0 -0
  55. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_mcp/sse_mcp_client.py +0 -0
  56. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_mcp/stdio_mcp_client.py +0 -0
  57. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_methodology/main.py +0 -0
  58. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_multi_agent/__init__.py +0 -0
  59. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_multi_agent/main.py +0 -0
  60. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_platform/__init__.py +0 -0
  61. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_platform/base.py +0 -0
  62. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_platform/human.py +0 -0
  63. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_platform/kimi.py +0 -0
  64. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_platform/registry.py +0 -0
  65. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_platform/yuanbao.py +0 -0
  66. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_platform_manager/__init__.py +0 -0
  67. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_platform_manager/main.py +0 -0
  68. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_smart_shell/__init__.py +0 -0
  69. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_smart_shell/main.py +0 -0
  70. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_tools/__init__.py +0 -0
  71. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_tools/ask_codebase.py +0 -0
  72. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_tools/ask_user.py +0 -0
  73. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_tools/base.py +0 -0
  74. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_tools/chdir.py +0 -0
  75. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_tools/code_plan.py +0 -0
  76. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_tools/create_code_agent.py +0 -0
  77. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_tools/create_sub_agent.py +0 -0
  78. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_tools/execute_script.py +0 -0
  79. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_tools/file_analyzer.py +0 -0
  80. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_tools/file_operation.py +0 -0
  81. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_tools/find_methodology.py +0 -0
  82. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_tools/lsp_get_diagnostics.py +0 -0
  83. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_tools/methodology.py +0 -0
  84. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_tools/read_code.py +0 -0
  85. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_tools/read_webpage.py +0 -0
  86. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_tools/registry.py +0 -0
  87. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_tools/search_web.py +0 -0
  88. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_tools/virtual_tty.py +0 -0
  89. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_utils/__init__.py +0 -0
  90. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_utils/builtin_replace_map.py +0 -0
  91. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_utils/config.py +0 -0
  92. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_utils/embedding.py +0 -0
  93. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_utils/file_processors.py +0 -0
  94. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_utils/git_utils.py +0 -0
  95. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_utils/globals.py +0 -0
  96. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_utils/methodology.py +0 -0
  97. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_utils/output.py +0 -0
  98. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_utils/tag.py +0 -0
  99. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis/jarvis_utils/utils.py +0 -0
  100. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis_ai_assistant.egg-info/SOURCES.txt +0 -0
  101. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis_ai_assistant.egg-info/dependency_links.txt +0 -0
  102. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis_ai_assistant.egg-info/entry_points.txt +0 -0
  103. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis_ai_assistant.egg-info/requires.txt +0 -0
  104. {jarvis_ai_assistant-0.1.160 → jarvis_ai_assistant-0.1.161}/src/jarvis_ai_assistant.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: jarvis-ai-assistant
3
- Version: 0.1.160
3
+ Version: 0.1.161
4
4
  Summary: Jarvis: An AI assistant that uses tools to interact with the system
5
5
  Home-page: https://github.com/skyfireitdiy/Jarvis
6
6
  Author: skyfire
@@ -8,7 +8,7 @@ default = true
8
8
 
9
9
  [project]
10
10
  name = "jarvis-ai-assistant"
11
- version = "0.1.160"
11
+ version = "0.1.161"
12
12
  description = "Jarvis: An AI assistant that uses tools to interact with the system"
13
13
  readme = "README.md"
14
14
  authors = [{ name = "skyfire", email = "skyfireitdiy@hotmail.com" }]
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
2
2
 
3
3
  setup(
4
4
  name="jarvis-ai-assistant",
5
- version="0.1.160",
5
+ version="0.1.161",
6
6
  author="skyfire",
7
7
  author_email="skyfireitdiy@hotmail.com",
8
8
  description="An AI assistant that uses various tools to interact with the system",
@@ -1,3 +1,3 @@
1
1
  """Jarvis AI Assistant"""
2
2
 
3
- __version__ = "0.1.160"
3
+ __version__ = "0.1.161"
@@ -94,7 +94,7 @@ def _select_task(tasks: Dict[str, str]) -> str:
94
94
  # 询问是否需要补充信息
95
95
  need_additional = user_confirm("需要为此任务添加补充信息吗?", default=False)
96
96
  if need_additional:
97
- additional_input = get_multiline_input("请输入补充信息(输入空行结束):")
97
+ additional_input = get_multiline_input("请输入补充信息:")
98
98
  if additional_input:
99
99
  selected_task = f"{selected_task}\n\n补充信息:\n{additional_input}"
100
100
  return selected_task
@@ -210,12 +210,8 @@ def apply_patch(output_str: str, agent: Any) -> str:
210
210
  final_ret += f"# 应用补丁:\n```diff\n{diff}\n```"
211
211
 
212
212
  # 修改后的提示逻辑
213
- addon_prompt = "1. 请确认补丁是否已正确应用\n"
214
- addon_prompt += "2. 检查修改后的代码是否符合预期\n"
215
- addon_prompt += "3. 如果确认无误,请继续进行下一步修改\n"
216
- addon_prompt += "4. 如果发现问题,请立即开始修复\n"
217
- addon_prompt += f"如果用户的需求已经完成,请终止,不要输出新的 {ot('PATCH')},不要实现任何超出用户需求外的内容\n"
218
- addon_prompt += "如果有任何信息不清楚,调用工具获取信息\n"
213
+ addon_prompt = f"如果用户的需求未完成,请继续生成补丁,如果已经完成,请终止,不要输出新的 {ot('PATCH')},不要实现任何超出用户需求外的内容\n"
214
+ addon_prompt += "如果有任何信息不明确,调用工具获取信息\n"
219
215
  addon_prompt += "每次响应必须且只能包含一个操作\n"
220
216
 
221
217
  agent.set_addon_prompt(addon_prompt)
@@ -347,14 +343,36 @@ def handle_commit_workflow() -> bool:
347
343
  """Handle the git commit workflow and return the commit details.
348
344
 
349
345
  Returns:
350
- tuple[bool, str, str]: (continue_execution, commit_id, commit_message)
346
+ bool: 提交是否成功
351
347
  """
352
348
  if is_confirm_before_apply_patch() and not user_confirm("是否要提交代码?", default=True):
353
349
  revert_change()
354
350
  return False
355
- git_commiter = GitCommitTool()
356
- commit_result = git_commiter.execute({})
357
- return commit_result["success"]
351
+
352
+ import subprocess
353
+ try:
354
+ # 获取当前分支的提交总数
355
+ commit_count = subprocess.run(
356
+ ['git', 'rev-list', '--count', 'HEAD'],
357
+ capture_output=True,
358
+ text=True
359
+ )
360
+ if commit_count.returncode != 0:
361
+ return False
362
+
363
+ commit_count = int(commit_count.stdout.strip())
364
+
365
+ # 暂存所有修改
366
+ subprocess.run(['git', 'add', '.'], check=True)
367
+
368
+ # 提交变更
369
+ subprocess.run(
370
+ ['git', 'commit', '-m', f'CheckPoint #{commit_count + 1}'],
371
+ check=True
372
+ )
373
+ return True
374
+ except subprocess.CalledProcessError as e:
375
+ return False
358
376
 
359
377
 
360
378
  def handle_code_operation(filepath: str, patch_content: str) -> bool:
@@ -377,7 +395,7 @@ def handle_small_code_operation(filepath: str, patch_content: str) -> bool:
377
395
  model = PlatformRegistry().get_normal_platform()
378
396
  file_content = FileOperationTool().execute({"operation":"read", "files":[{"path":filepath}]})["stdout"]
379
397
 
380
- model.set_suppress_output(True)
398
+ model.set_suppress_output(False)
381
399
 
382
400
  prompt = f"""
383
401
  # 代码合并专家指南
@@ -419,7 +437,8 @@ def handle_small_code_operation(filepath: str, patch_content: str) -> bool:
419
437
  finished = False
420
438
  while count > 0:
421
439
  count -= 1
422
- response = model.chat_until_success(prompt).splitlines()
440
+ with spinner.hidden():
441
+ response = model.chat_until_success(prompt).splitlines()
423
442
  try:
424
443
  start_line = response.index(ot("MERGED_CODE")) + 1
425
444
  try:
@@ -481,7 +500,7 @@ def handle_large_code_operation(filepath: str, patch_content: str, model: BasePl
481
500
  upload_success = True
482
501
 
483
502
 
484
- model.set_suppress_output(True)
503
+ model.set_suppress_output(False)
485
504
 
486
505
  main_prompt = f"""
487
506
  # 代码补丁生成专家指南
@@ -536,12 +555,15 @@ def handle_large_code_operation(filepath: str, patch_content: str, model: BasePl
536
555
  # 原始代码
537
556
  {file_content}
538
557
  """
539
- response = model.chat_until_success(main_prompt + file_prompt)
558
+ with spinner.hidden():
559
+ response = model.chat_until_success(main_prompt + file_prompt)
540
560
  else:
541
561
  if upload_success:
542
- response = model.chat_until_success(main_prompt)
562
+ with spinner.hidden():
563
+ response = model.chat_until_success(main_prompt)
543
564
  else:
544
- response = model.chat_big_content(file_content, main_prompt)
565
+ with spinner.hidden():
566
+ response = model.chat_big_content(file_content, main_prompt)
545
567
 
546
568
  # 解析差异化补丁
547
569
  diff_blocks = re.finditer(ot("DIFF")+r'\s*>{4,} SEARCH\n?(.*?)\n?={4,}\n?(.*?)\s*<{4,} REPLACE\n?'+ct("DIFF"),
@@ -563,7 +585,6 @@ def handle_large_code_operation(filepath: str, patch_content: str, model: BasePl
563
585
  if search_text in modified_content:
564
586
  # 如果有多处,报错
565
587
  if modified_content.count(search_text) > 1:
566
- prompt = f"补丁 #{patch_count} 应用失败:找到多个匹配的代码段"
567
588
  spinner.write(f"❌ 补丁 #{patch_count} 应用失败:找到多个匹配的代码段")
568
589
  success = False
569
590
  break
@@ -573,7 +594,6 @@ def handle_large_code_operation(filepath: str, patch_content: str, model: BasePl
573
594
  spinner.write(f"✅ 补丁 #{patch_count} 应用成功")
574
595
  else:
575
596
  spinner.write(f"❌ 补丁 #{patch_count} 应用失败:无法找到匹配的代码段")
576
- prompt = f"补丁 #{patch_count} 应用失败:无法找到匹配的代码段"
577
597
  success = False
578
598
  break
579
599
  if not success:
@@ -7,7 +7,7 @@ import os
7
7
  import sys
8
8
  import subprocess
9
9
  import argparse
10
- from typing import Optional, List, Tuple
10
+ from typing import Any, Dict, Optional, List, Tuple
11
11
 
12
12
  # 忽略yaspin的类型检查
13
13
  from yaspin import yaspin # type: ignore
@@ -243,6 +243,83 @@ class CodeAgent:
243
243
  """
244
244
  return self.root_dir
245
245
 
246
+ def get_loc_stats(self) -> str:
247
+ """使用loc命令获取当前目录的代码统计信息
248
+
249
+ 返回:
250
+ str: loc命令输出的原始字符串,失败时返回空字符串
251
+ """
252
+ try:
253
+ result = subprocess.run(
254
+ ['loc'],
255
+ cwd=self.root_dir,
256
+ capture_output=True,
257
+ text=True
258
+ )
259
+ return result.stdout if result.returncode == 0 else ""
260
+ except FileNotFoundError:
261
+ return ""
262
+
263
+ def get_recent_commits_with_files(self) -> List[Dict[str, Any]]:
264
+ """获取最近5次提交的commit信息和文件清单
265
+
266
+ 返回:
267
+ List[Dict[str, Any]]: 包含commit信息和文件清单的字典列表,格式为:
268
+ [
269
+ {
270
+ 'hash': 提交hash,
271
+ 'message': 提交信息,
272
+ 'author': 作者,
273
+ 'date': 提交日期,
274
+ 'files': [修改的文件列表] (最多50个文件)
275
+ },
276
+ ...
277
+ ]
278
+ 失败时返回空列表
279
+ """
280
+ try:
281
+ # 获取最近5次提交的基本信息
282
+ result = subprocess.run(
283
+ ['git', 'log', '-5', '--pretty=format:%H%n%s%n%an%n%ad'],
284
+ cwd=self.root_dir,
285
+ capture_output=True,
286
+ text=True
287
+ )
288
+ if result.returncode != 0:
289
+ return []
290
+
291
+ # 解析提交信息
292
+ commits = []
293
+ lines = result.stdout.splitlines()
294
+ for i in range(0, len(lines), 4):
295
+ if i + 3 >= len(lines):
296
+ break
297
+ commit = {
298
+ 'hash': lines[i],
299
+ 'message': lines[i+1],
300
+ 'author': lines[i+2],
301
+ 'date': lines[i+3],
302
+ 'files': []
303
+ }
304
+ commits.append(commit)
305
+
306
+ # 获取每个提交的文件修改清单
307
+ for commit in commits:
308
+ files_result = subprocess.run(
309
+ ['git', 'show', '--name-only', '--pretty=format:', commit['hash']],
310
+ cwd=self.root_dir,
311
+ capture_output=True,
312
+ text=True
313
+ )
314
+ if files_result.returncode == 0:
315
+ files = list(set(filter(None, files_result.stdout.splitlines())))
316
+ commit['files'] = files[:50] # 限制最多50个文件
317
+
318
+ return commits
319
+
320
+ except subprocess.CalledProcessError:
321
+ return []
322
+
246
323
  def _init_env(self) -> None:
247
324
  """初始化环境"""
248
325
  with yaspin(text="正在初始化环境...", color="cyan") as spinner:
@@ -261,8 +338,29 @@ class CodeAgent:
261
338
  if has_uncommitted_changes():
262
339
  PrettyOutput.print("检测到未提交的修改,是否要提交?", OutputType.WARNING)
263
340
  if user_confirm("是否要提交?", True):
264
- git_commiter = GitCommitTool()
265
- git_commiter.execute({})
341
+ import subprocess
342
+ try:
343
+ # 获取当前分支的提交总数
344
+ commit_count = subprocess.run(
345
+ ['git', 'rev-list', '--count', 'HEAD'],
346
+ capture_output=True,
347
+ text=True
348
+ )
349
+ if commit_count.returncode != 0:
350
+ return
351
+
352
+ commit_count = int(commit_count.stdout.strip())
353
+
354
+ # 暂存所有修改
355
+ subprocess.run(['git', 'add', '.'], check=True)
356
+
357
+ # 提交变更
358
+ subprocess.run(
359
+ ['git', 'commit', '-m', f'CheckPoint #{commit_count + 1}'],
360
+ check=True
361
+ )
362
+ except subprocess.CalledProcessError as e:
363
+ PrettyOutput.print(f"提交失败: {str(e)}", OutputType.ERROR)
266
364
 
267
365
  def _show_commit_history(
268
366
  self,
@@ -301,17 +399,14 @@ class CodeAgent:
301
399
  ) -> None:
302
400
  """处理提交确认和可能的重置"""
303
401
  if commits and user_confirm("是否接受以上提交记录?", True):
304
- if len(commits) > 1 and user_confirm(
305
- "是否要合并为一个更清晰的提交记录?", True
306
- ):
307
- subprocess.run(
308
- ["git", "reset", "--mixed", str(start_commit)],
309
- stdout=subprocess.DEVNULL,
310
- stderr=subprocess.DEVNULL,
311
- check=True
312
- )
313
- git_commiter = GitCommitTool()
314
- git_commiter.execute({})
402
+ subprocess.run(
403
+ ["git", "reset", "--mixed", str(start_commit)],
404
+ stdout=subprocess.DEVNULL,
405
+ stderr=subprocess.DEVNULL,
406
+ check=True
407
+ )
408
+ git_commiter = GitCommitTool()
409
+ git_commiter.execute({})
315
410
  elif start_commit:
316
411
  os.system(f"git reset --hard {str(start_commit)}") # 确保转换为字符串
317
412
  PrettyOutput.print("已重置到初始提交", OutputType.INFO)
@@ -329,8 +424,24 @@ class CodeAgent:
329
424
  self._init_env()
330
425
  start_commit = get_latest_commit_hash()
331
426
 
427
+ # 获取项目统计信息并附加到用户输入
428
+ loc_stats = self.get_loc_stats()
429
+ commits_info = self.get_recent_commits_with_files()
430
+
431
+ project_info = []
432
+ if loc_stats:
433
+ project_info.append(f"代码统计:\n{loc_stats}")
434
+ if commits_info:
435
+ commits_str = "\n".join(
436
+ f"提交 {i+1}: {commit['hash'][:7]} - {commit['message']} ({len(commit['files'])}个文件)"
437
+ for i, commit in enumerate(commits_info)
438
+ )
439
+ project_info.append(f"最近提交:\n{commits_str}")
440
+
441
+ enhanced_input = f"{user_input}\n\n项目概况:\n" + "\n\n".join(project_info) if project_info else user_input
442
+
332
443
  try:
333
- self.agent.run(user_input)
444
+ self.agent.run(enhanced_input)
334
445
  except RuntimeError as e:
335
446
  PrettyOutput.print(f"执行失败: {str(e)}", OutputType.WARNING)
336
447
  return str(e)
@@ -164,6 +164,7 @@ class GitCommitTool:
164
164
 
165
165
  请详细分析已上传的代码差异文件,生成符合上述格式的提交信息。
166
166
  '''
167
+ commit_message = platform.chat_until_success(prompt)
167
168
  else:
168
169
  # 如果上传失败但内容较大,使用chat_big_content
169
170
  if is_large_content and hasattr(platform, 'chat_big_content'):
@@ -180,11 +181,13 @@ class GitCommitTool:
180
181
  # 尝试生成提交信息
181
182
  spinner.text = "正在生成提交消息..."
182
183
  while True:
183
- if not upload_success and not is_large_content:
184
+ # 只在特定情况下重新获取commit_message
185
+ if not upload_success and not is_large_content and not commit_message:
184
186
  commit_message = platform.chat_until_success(prompt)
185
- commit_message = self._extract_commit_message(commit_message)
187
+ extracted_message = self._extract_commit_message(commit_message)
186
188
  # 如果成功提取,就跳出循环
187
- if commit_message:
189
+ if extracted_message:
190
+ commit_message = extracted_message
188
191
  break
189
192
  prompt = f"""格式错误,请按照以下格式重新生成提交信息:
190
193
  {ot("COMMIT_MESSAGE")}
@@ -193,6 +196,7 @@ class GitCommitTool:
193
196
  [可选] 详细描述变更内容和原因
194
197
  {ct("COMMIT_MESSAGE")}
195
198
  """
199
+ commit_message = platform.chat_until_success(prompt)
196
200
  spinner.write("✅ 生成提交消息")
197
201
 
198
202
  # 执行提交
@@ -82,29 +82,20 @@ class FileCompleter(Completer):
82
82
  # 计算替换长度
83
83
  replace_length = len(text_after_at) + 1
84
84
 
85
- # 从replace_map获取建议列表
86
- default_suggestions = [
87
- (ot(tag), desc) for tag, desc in [
88
- (tag, self._get_description(tag))
89
- for tag in self.replace_map.keys()
90
- ]
91
- ]
92
- # 添加特殊标记
93
- default_suggestions.extend([
85
+ # 获取所有可能的补全项
86
+ all_completions = []
87
+
88
+ # 1. 添加特殊标记
89
+ all_completions.extend([
90
+ (ot(tag), self._get_description(tag))
91
+ for tag in self.replace_map.keys()
92
+ ])
93
+ all_completions.extend([
94
94
  (ot("Summary"), '总结'),
95
95
  (ot("Clear"), '清除历史'),
96
96
  ])
97
- for name, desc in default_suggestions:
98
- yield Completion(
99
- text=f"'{name}'",
100
- start_position=-replace_length,
101
- display=name,
102
- display_meta=desc
103
- ) # type: ignore
104
-
105
-
106
- # 使用git ls-files获取所有可能的文件
107
- all_files = []
97
+
98
+ # 2. 添加文件列表
108
99
  try:
109
100
  import subprocess
110
101
  result = subprocess.run(['git', 'ls-files'],
@@ -112,28 +103,40 @@ class FileCompleter(Completer):
112
103
  stderr=subprocess.PIPE,
113
104
  text=True)
114
105
  if result.returncode == 0:
115
- all_files = [line.strip() for line in result.stdout.splitlines() if line.strip()]
106
+ all_completions.extend([
107
+ (path, "File")
108
+ for path in result.stdout.splitlines()
109
+ if path.strip()
110
+ ])
116
111
  except Exception:
117
112
  pass
118
- # 生成补全建议
119
- if not file_path:
120
- scored_files = [(path, 100) for path in all_files[:self.max_suggestions]]
121
- else:
122
- scored_files_data = process.extract(file_path, all_files, limit=self.max_suggestions)
123
- scored_files = [(m[0], m[1]) for m in scored_files_data]
124
- scored_files.sort(key=lambda x: x[1], reverse=True)
125
- scored_files = scored_files[:self.max_suggestions]
126
- # 生成补全项
127
- for path, score in scored_files:
128
- if not file_path or score > self.min_score:
129
- display_text = path
130
- if file_path and score < 100:
131
- display_text = f"{path} ({score}%)"
113
+
114
+ # 统一过滤和排序
115
+ if file_path:
116
+ # 使用模糊匹配过滤
117
+ scored_items = process.extract(file_path, [item[0] for item in all_completions], limit=self.max_suggestions)
118
+ scored_items = [(item[0], item[1]) for item in scored_items if item[1] > self.min_score]
119
+ # 创建映射以便查找描述
120
+ completion_map = {item[0]: item[1] for item in all_completions}
121
+ # 生成补全项
122
+ for text, score in scored_items:
123
+ display_text = text
124
+ if score < 100:
125
+ display_text = f"{text} ({score}%)"
132
126
  yield Completion(
133
- text=f"'{path}'",
127
+ text=f"'{text}'",
134
128
  start_position=-replace_length,
135
129
  display=display_text,
136
- display_meta="File"
130
+ display_meta=completion_map.get(text, "")
131
+ ) # type: ignore
132
+ else:
133
+ # 没有输入时返回前max_suggestions个建议
134
+ for text, desc in all_completions[:self.max_suggestions]:
135
+ yield Completion(
136
+ text=f"'{text}'",
137
+ start_position=-replace_length,
138
+ display=text,
139
+ display_meta=desc
137
140
  ) # type: ignore
138
141
 
139
142
  def _get_description(self, tag: str) -> str:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: jarvis-ai-assistant
3
- Version: 0.1.160
3
+ Version: 0.1.161
4
4
  Summary: Jarvis: An AI assistant that uses tools to interact with the system
5
5
  Home-page: https://github.com/skyfireitdiy/Jarvis
6
6
  Author: skyfire