jarvis-ai-assistant 0.7.16__py3-none-any.whl → 1.0.2__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.
Files changed (279) hide show
  1. jarvis/__init__.py +1 -1
  2. jarvis/jarvis_agent/__init__.py +567 -222
  3. jarvis/jarvis_agent/agent_manager.py +19 -12
  4. jarvis/jarvis_agent/builtin_input_handler.py +79 -11
  5. jarvis/jarvis_agent/config_editor.py +7 -2
  6. jarvis/jarvis_agent/event_bus.py +24 -13
  7. jarvis/jarvis_agent/events.py +19 -1
  8. jarvis/jarvis_agent/file_context_handler.py +67 -64
  9. jarvis/jarvis_agent/file_methodology_manager.py +38 -24
  10. jarvis/jarvis_agent/jarvis.py +186 -114
  11. jarvis/jarvis_agent/language_extractors/__init__.py +8 -1
  12. jarvis/jarvis_agent/language_extractors/c_extractor.py +7 -4
  13. jarvis/jarvis_agent/language_extractors/cpp_extractor.py +9 -4
  14. jarvis/jarvis_agent/language_extractors/go_extractor.py +7 -4
  15. jarvis/jarvis_agent/language_extractors/java_extractor.py +27 -20
  16. jarvis/jarvis_agent/language_extractors/javascript_extractor.py +22 -17
  17. jarvis/jarvis_agent/language_extractors/python_extractor.py +7 -4
  18. jarvis/jarvis_agent/language_extractors/rust_extractor.py +7 -4
  19. jarvis/jarvis_agent/language_extractors/typescript_extractor.py +22 -17
  20. jarvis/jarvis_agent/language_support_info.py +250 -219
  21. jarvis/jarvis_agent/main.py +19 -23
  22. jarvis/jarvis_agent/memory_manager.py +9 -6
  23. jarvis/jarvis_agent/methodology_share_manager.py +21 -15
  24. jarvis/jarvis_agent/output_handler.py +4 -2
  25. jarvis/jarvis_agent/prompt_builder.py +7 -6
  26. jarvis/jarvis_agent/prompt_manager.py +113 -8
  27. jarvis/jarvis_agent/prompts.py +317 -85
  28. jarvis/jarvis_agent/protocols.py +5 -2
  29. jarvis/jarvis_agent/run_loop.py +192 -32
  30. jarvis/jarvis_agent/session_manager.py +7 -3
  31. jarvis/jarvis_agent/share_manager.py +23 -13
  32. jarvis/jarvis_agent/shell_input_handler.py +12 -8
  33. jarvis/jarvis_agent/stdio_redirect.py +25 -26
  34. jarvis/jarvis_agent/task_analyzer.py +29 -23
  35. jarvis/jarvis_agent/task_list.py +869 -0
  36. jarvis/jarvis_agent/task_manager.py +26 -23
  37. jarvis/jarvis_agent/tool_executor.py +6 -5
  38. jarvis/jarvis_agent/tool_share_manager.py +24 -14
  39. jarvis/jarvis_agent/user_interaction.py +3 -3
  40. jarvis/jarvis_agent/utils.py +9 -1
  41. jarvis/jarvis_agent/web_bridge.py +37 -17
  42. jarvis/jarvis_agent/web_output_sink.py +5 -2
  43. jarvis/jarvis_agent/web_server.py +165 -36
  44. jarvis/jarvis_c2rust/__init__.py +1 -1
  45. jarvis/jarvis_c2rust/cli.py +260 -141
  46. jarvis/jarvis_c2rust/collector.py +37 -18
  47. jarvis/jarvis_c2rust/constants.py +60 -0
  48. jarvis/jarvis_c2rust/library_replacer.py +242 -1010
  49. jarvis/jarvis_c2rust/library_replacer_checkpoint.py +133 -0
  50. jarvis/jarvis_c2rust/library_replacer_llm.py +287 -0
  51. jarvis/jarvis_c2rust/library_replacer_loader.py +191 -0
  52. jarvis/jarvis_c2rust/library_replacer_output.py +134 -0
  53. jarvis/jarvis_c2rust/library_replacer_prompts.py +124 -0
  54. jarvis/jarvis_c2rust/library_replacer_utils.py +188 -0
  55. jarvis/jarvis_c2rust/llm_module_agent.py +98 -1044
  56. jarvis/jarvis_c2rust/llm_module_agent_apply.py +170 -0
  57. jarvis/jarvis_c2rust/llm_module_agent_executor.py +288 -0
  58. jarvis/jarvis_c2rust/llm_module_agent_loader.py +170 -0
  59. jarvis/jarvis_c2rust/llm_module_agent_prompts.py +268 -0
  60. jarvis/jarvis_c2rust/llm_module_agent_types.py +57 -0
  61. jarvis/jarvis_c2rust/llm_module_agent_utils.py +150 -0
  62. jarvis/jarvis_c2rust/llm_module_agent_validator.py +119 -0
  63. jarvis/jarvis_c2rust/loaders.py +28 -10
  64. jarvis/jarvis_c2rust/models.py +5 -2
  65. jarvis/jarvis_c2rust/optimizer.py +192 -1974
  66. jarvis/jarvis_c2rust/optimizer_build_fix.py +286 -0
  67. jarvis/jarvis_c2rust/optimizer_clippy.py +766 -0
  68. jarvis/jarvis_c2rust/optimizer_config.py +49 -0
  69. jarvis/jarvis_c2rust/optimizer_docs.py +183 -0
  70. jarvis/jarvis_c2rust/optimizer_options.py +48 -0
  71. jarvis/jarvis_c2rust/optimizer_progress.py +469 -0
  72. jarvis/jarvis_c2rust/optimizer_report.py +52 -0
  73. jarvis/jarvis_c2rust/optimizer_unsafe.py +309 -0
  74. jarvis/jarvis_c2rust/optimizer_utils.py +469 -0
  75. jarvis/jarvis_c2rust/optimizer_visibility.py +185 -0
  76. jarvis/jarvis_c2rust/scanner.py +229 -166
  77. jarvis/jarvis_c2rust/transpiler.py +531 -2732
  78. jarvis/jarvis_c2rust/transpiler_agents.py +503 -0
  79. jarvis/jarvis_c2rust/transpiler_build.py +1294 -0
  80. jarvis/jarvis_c2rust/transpiler_codegen.py +204 -0
  81. jarvis/jarvis_c2rust/transpiler_compile.py +146 -0
  82. jarvis/jarvis_c2rust/transpiler_config.py +178 -0
  83. jarvis/jarvis_c2rust/transpiler_context.py +122 -0
  84. jarvis/jarvis_c2rust/transpiler_executor.py +516 -0
  85. jarvis/jarvis_c2rust/transpiler_generation.py +278 -0
  86. jarvis/jarvis_c2rust/transpiler_git.py +163 -0
  87. jarvis/jarvis_c2rust/transpiler_mod_utils.py +225 -0
  88. jarvis/jarvis_c2rust/transpiler_modules.py +336 -0
  89. jarvis/jarvis_c2rust/transpiler_planning.py +394 -0
  90. jarvis/jarvis_c2rust/transpiler_review.py +1196 -0
  91. jarvis/jarvis_c2rust/transpiler_symbols.py +176 -0
  92. jarvis/jarvis_c2rust/utils.py +269 -79
  93. jarvis/jarvis_code_agent/after_change.py +233 -0
  94. jarvis/jarvis_code_agent/build_validation_config.py +37 -30
  95. jarvis/jarvis_code_agent/builtin_rules.py +68 -0
  96. jarvis/jarvis_code_agent/code_agent.py +976 -1517
  97. jarvis/jarvis_code_agent/code_agent_build.py +227 -0
  98. jarvis/jarvis_code_agent/code_agent_diff.py +246 -0
  99. jarvis/jarvis_code_agent/code_agent_git.py +525 -0
  100. jarvis/jarvis_code_agent/code_agent_impact.py +177 -0
  101. jarvis/jarvis_code_agent/code_agent_lint.py +283 -0
  102. jarvis/jarvis_code_agent/code_agent_llm.py +159 -0
  103. jarvis/jarvis_code_agent/code_agent_postprocess.py +105 -0
  104. jarvis/jarvis_code_agent/code_agent_prompts.py +46 -0
  105. jarvis/jarvis_code_agent/code_agent_rules.py +305 -0
  106. jarvis/jarvis_code_agent/code_analyzer/__init__.py +52 -48
  107. jarvis/jarvis_code_agent/code_analyzer/base_language.py +12 -10
  108. jarvis/jarvis_code_agent/code_analyzer/build_validator/__init__.py +12 -11
  109. jarvis/jarvis_code_agent/code_analyzer/build_validator/base.py +16 -12
  110. jarvis/jarvis_code_agent/code_analyzer/build_validator/cmake.py +26 -17
  111. jarvis/jarvis_code_agent/code_analyzer/build_validator/detector.py +558 -104
  112. jarvis/jarvis_code_agent/code_analyzer/build_validator/fallback.py +27 -16
  113. jarvis/jarvis_code_agent/code_analyzer/build_validator/go.py +22 -18
  114. jarvis/jarvis_code_agent/code_analyzer/build_validator/java_gradle.py +21 -16
  115. jarvis/jarvis_code_agent/code_analyzer/build_validator/java_maven.py +20 -16
  116. jarvis/jarvis_code_agent/code_analyzer/build_validator/makefile.py +27 -16
  117. jarvis/jarvis_code_agent/code_analyzer/build_validator/nodejs.py +47 -23
  118. jarvis/jarvis_code_agent/code_analyzer/build_validator/python.py +71 -37
  119. jarvis/jarvis_code_agent/code_analyzer/build_validator/rust.py +162 -35
  120. jarvis/jarvis_code_agent/code_analyzer/build_validator/validator.py +111 -57
  121. jarvis/jarvis_code_agent/code_analyzer/build_validator.py +18 -12
  122. jarvis/jarvis_code_agent/code_analyzer/context_manager.py +185 -183
  123. jarvis/jarvis_code_agent/code_analyzer/context_recommender.py +2 -1
  124. jarvis/jarvis_code_agent/code_analyzer/dependency_analyzer.py +24 -15
  125. jarvis/jarvis_code_agent/code_analyzer/file_ignore.py +227 -141
  126. jarvis/jarvis_code_agent/code_analyzer/impact_analyzer.py +321 -247
  127. jarvis/jarvis_code_agent/code_analyzer/language_registry.py +37 -29
  128. jarvis/jarvis_code_agent/code_analyzer/language_support.py +21 -13
  129. jarvis/jarvis_code_agent/code_analyzer/languages/__init__.py +15 -9
  130. jarvis/jarvis_code_agent/code_analyzer/languages/c_cpp_language.py +75 -45
  131. jarvis/jarvis_code_agent/code_analyzer/languages/go_language.py +87 -52
  132. jarvis/jarvis_code_agent/code_analyzer/languages/java_language.py +84 -51
  133. jarvis/jarvis_code_agent/code_analyzer/languages/javascript_language.py +94 -64
  134. jarvis/jarvis_code_agent/code_analyzer/languages/python_language.py +109 -71
  135. jarvis/jarvis_code_agent/code_analyzer/languages/rust_language.py +97 -63
  136. jarvis/jarvis_code_agent/code_analyzer/languages/typescript_language.py +103 -69
  137. jarvis/jarvis_code_agent/code_analyzer/llm_context_recommender.py +271 -268
  138. jarvis/jarvis_code_agent/code_analyzer/symbol_extractor.py +76 -64
  139. jarvis/jarvis_code_agent/code_analyzer/tree_sitter_extractor.py +92 -19
  140. jarvis/jarvis_code_agent/diff_visualizer.py +998 -0
  141. jarvis/jarvis_code_agent/lint.py +223 -524
  142. jarvis/jarvis_code_agent/rule_share_manager.py +158 -0
  143. jarvis/jarvis_code_agent/rules/clean_code.md +144 -0
  144. jarvis/jarvis_code_agent/rules/code_review.md +115 -0
  145. jarvis/jarvis_code_agent/rules/documentation.md +165 -0
  146. jarvis/jarvis_code_agent/rules/generate_rules.md +52 -0
  147. jarvis/jarvis_code_agent/rules/performance.md +158 -0
  148. jarvis/jarvis_code_agent/rules/refactoring.md +139 -0
  149. jarvis/jarvis_code_agent/rules/security.md +160 -0
  150. jarvis/jarvis_code_agent/rules/tdd.md +78 -0
  151. jarvis/jarvis_code_agent/test_rules/cpp_test.md +118 -0
  152. jarvis/jarvis_code_agent/test_rules/go_test.md +98 -0
  153. jarvis/jarvis_code_agent/test_rules/java_test.md +99 -0
  154. jarvis/jarvis_code_agent/test_rules/javascript_test.md +113 -0
  155. jarvis/jarvis_code_agent/test_rules/php_test.md +117 -0
  156. jarvis/jarvis_code_agent/test_rules/python_test.md +91 -0
  157. jarvis/jarvis_code_agent/test_rules/ruby_test.md +102 -0
  158. jarvis/jarvis_code_agent/test_rules/rust_test.md +86 -0
  159. jarvis/jarvis_code_agent/utils.py +36 -26
  160. jarvis/jarvis_code_analysis/checklists/loader.py +21 -21
  161. jarvis/jarvis_code_analysis/code_review.py +64 -33
  162. jarvis/jarvis_data/config_schema.json +285 -192
  163. jarvis/jarvis_git_squash/main.py +8 -6
  164. jarvis/jarvis_git_utils/git_commiter.py +53 -76
  165. jarvis/jarvis_mcp/__init__.py +5 -2
  166. jarvis/jarvis_mcp/sse_mcp_client.py +40 -30
  167. jarvis/jarvis_mcp/stdio_mcp_client.py +27 -19
  168. jarvis/jarvis_mcp/streamable_mcp_client.py +35 -26
  169. jarvis/jarvis_memory_organizer/memory_organizer.py +78 -55
  170. jarvis/jarvis_methodology/main.py +48 -39
  171. jarvis/jarvis_multi_agent/__init__.py +56 -23
  172. jarvis/jarvis_multi_agent/main.py +15 -18
  173. jarvis/jarvis_platform/base.py +179 -111
  174. jarvis/jarvis_platform/human.py +27 -16
  175. jarvis/jarvis_platform/kimi.py +52 -45
  176. jarvis/jarvis_platform/openai.py +101 -40
  177. jarvis/jarvis_platform/registry.py +51 -33
  178. jarvis/jarvis_platform/tongyi.py +68 -38
  179. jarvis/jarvis_platform/yuanbao.py +59 -43
  180. jarvis/jarvis_platform_manager/main.py +68 -76
  181. jarvis/jarvis_platform_manager/service.py +24 -14
  182. jarvis/jarvis_rag/README_CONFIG.md +314 -0
  183. jarvis/jarvis_rag/README_DYNAMIC_LOADING.md +311 -0
  184. jarvis/jarvis_rag/README_ONLINE_MODELS.md +230 -0
  185. jarvis/jarvis_rag/__init__.py +57 -4
  186. jarvis/jarvis_rag/cache.py +3 -1
  187. jarvis/jarvis_rag/cli.py +48 -68
  188. jarvis/jarvis_rag/embedding_interface.py +39 -0
  189. jarvis/jarvis_rag/embedding_manager.py +7 -230
  190. jarvis/jarvis_rag/embeddings/__init__.py +41 -0
  191. jarvis/jarvis_rag/embeddings/base.py +114 -0
  192. jarvis/jarvis_rag/embeddings/cohere.py +66 -0
  193. jarvis/jarvis_rag/embeddings/edgefn.py +117 -0
  194. jarvis/jarvis_rag/embeddings/local.py +260 -0
  195. jarvis/jarvis_rag/embeddings/openai.py +62 -0
  196. jarvis/jarvis_rag/embeddings/registry.py +293 -0
  197. jarvis/jarvis_rag/llm_interface.py +8 -6
  198. jarvis/jarvis_rag/query_rewriter.py +8 -9
  199. jarvis/jarvis_rag/rag_pipeline.py +61 -52
  200. jarvis/jarvis_rag/reranker.py +7 -75
  201. jarvis/jarvis_rag/reranker_interface.py +32 -0
  202. jarvis/jarvis_rag/rerankers/__init__.py +41 -0
  203. jarvis/jarvis_rag/rerankers/base.py +109 -0
  204. jarvis/jarvis_rag/rerankers/cohere.py +67 -0
  205. jarvis/jarvis_rag/rerankers/edgefn.py +140 -0
  206. jarvis/jarvis_rag/rerankers/jina.py +79 -0
  207. jarvis/jarvis_rag/rerankers/local.py +89 -0
  208. jarvis/jarvis_rag/rerankers/registry.py +293 -0
  209. jarvis/jarvis_rag/retriever.py +58 -43
  210. jarvis/jarvis_sec/__init__.py +66 -141
  211. jarvis/jarvis_sec/agents.py +21 -17
  212. jarvis/jarvis_sec/analysis.py +80 -33
  213. jarvis/jarvis_sec/checkers/__init__.py +7 -13
  214. jarvis/jarvis_sec/checkers/c_checker.py +356 -164
  215. jarvis/jarvis_sec/checkers/rust_checker.py +47 -29
  216. jarvis/jarvis_sec/cli.py +43 -21
  217. jarvis/jarvis_sec/clustering.py +430 -272
  218. jarvis/jarvis_sec/file_manager.py +99 -55
  219. jarvis/jarvis_sec/parsers.py +9 -6
  220. jarvis/jarvis_sec/prompts.py +4 -3
  221. jarvis/jarvis_sec/report.py +44 -22
  222. jarvis/jarvis_sec/review.py +180 -107
  223. jarvis/jarvis_sec/status.py +50 -41
  224. jarvis/jarvis_sec/types.py +3 -0
  225. jarvis/jarvis_sec/utils.py +160 -83
  226. jarvis/jarvis_sec/verification.py +411 -181
  227. jarvis/jarvis_sec/workflow.py +132 -21
  228. jarvis/jarvis_smart_shell/main.py +28 -41
  229. jarvis/jarvis_stats/cli.py +14 -12
  230. jarvis/jarvis_stats/stats.py +28 -19
  231. jarvis/jarvis_stats/storage.py +14 -8
  232. jarvis/jarvis_stats/visualizer.py +12 -7
  233. jarvis/jarvis_tools/base.py +5 -2
  234. jarvis/jarvis_tools/clear_memory.py +13 -9
  235. jarvis/jarvis_tools/cli/main.py +23 -18
  236. jarvis/jarvis_tools/edit_file.py +572 -873
  237. jarvis/jarvis_tools/execute_script.py +10 -7
  238. jarvis/jarvis_tools/file_analyzer.py +7 -8
  239. jarvis/jarvis_tools/meta_agent.py +287 -0
  240. jarvis/jarvis_tools/methodology.py +5 -3
  241. jarvis/jarvis_tools/read_code.py +305 -1438
  242. jarvis/jarvis_tools/read_symbols.py +50 -17
  243. jarvis/jarvis_tools/read_webpage.py +19 -18
  244. jarvis/jarvis_tools/registry.py +435 -156
  245. jarvis/jarvis_tools/retrieve_memory.py +16 -11
  246. jarvis/jarvis_tools/save_memory.py +8 -6
  247. jarvis/jarvis_tools/search_web.py +31 -31
  248. jarvis/jarvis_tools/sub_agent.py +32 -28
  249. jarvis/jarvis_tools/sub_code_agent.py +44 -60
  250. jarvis/jarvis_tools/task_list_manager.py +1811 -0
  251. jarvis/jarvis_tools/virtual_tty.py +29 -19
  252. jarvis/jarvis_utils/__init__.py +4 -0
  253. jarvis/jarvis_utils/builtin_replace_map.py +2 -1
  254. jarvis/jarvis_utils/clipboard.py +9 -8
  255. jarvis/jarvis_utils/collections.py +331 -0
  256. jarvis/jarvis_utils/config.py +699 -194
  257. jarvis/jarvis_utils/dialogue_recorder.py +294 -0
  258. jarvis/jarvis_utils/embedding.py +6 -3
  259. jarvis/jarvis_utils/file_processors.py +7 -1
  260. jarvis/jarvis_utils/fzf.py +9 -3
  261. jarvis/jarvis_utils/git_utils.py +71 -42
  262. jarvis/jarvis_utils/globals.py +116 -32
  263. jarvis/jarvis_utils/http.py +6 -2
  264. jarvis/jarvis_utils/input.py +318 -83
  265. jarvis/jarvis_utils/jsonnet_compat.py +119 -104
  266. jarvis/jarvis_utils/methodology.py +37 -28
  267. jarvis/jarvis_utils/output.py +201 -44
  268. jarvis/jarvis_utils/utils.py +986 -628
  269. {jarvis_ai_assistant-0.7.16.dist-info → jarvis_ai_assistant-1.0.2.dist-info}/METADATA +49 -33
  270. jarvis_ai_assistant-1.0.2.dist-info/RECORD +304 -0
  271. jarvis/jarvis_code_agent/code_analyzer/structured_code.py +0 -556
  272. jarvis/jarvis_tools/generate_new_tool.py +0 -205
  273. jarvis/jarvis_tools/lsp_client.py +0 -1552
  274. jarvis/jarvis_tools/rewrite_file.py +0 -105
  275. jarvis_ai_assistant-0.7.16.dist-info/RECORD +0 -218
  276. {jarvis_ai_assistant-0.7.16.dist-info → jarvis_ai_assistant-1.0.2.dist-info}/WHEEL +0 -0
  277. {jarvis_ai_assistant-0.7.16.dist-info → jarvis_ai_assistant-1.0.2.dist-info}/entry_points.txt +0 -0
  278. {jarvis_ai_assistant-0.7.16.dist-info → jarvis_ai_assistant-1.0.2.dist-info}/licenses/LICENSE +0 -0
  279. {jarvis_ai_assistant-0.7.16.dist-info → jarvis_ai_assistant-1.0.2.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,309 @@
1
+ # -*- coding: utf-8 -*-
2
+ """Unsafe 清理优化模块。"""
3
+
4
+ import os
5
+ from pathlib import Path
6
+ from typing import Callable
7
+ from typing import Dict
8
+ from typing import List
9
+
10
+ from jarvis.jarvis_utils.output import PrettyOutput
11
+
12
+ from jarvis.jarvis_agent.events import AFTER_TOOL_CALL
13
+ from jarvis.jarvis_agent.events import BEFORE_TOOL_CALL
14
+ from jarvis.jarvis_c2rust.optimizer_options import OptimizeOptions
15
+ from jarvis.jarvis_c2rust.optimizer_options import OptimizeStats
16
+ from jarvis.jarvis_c2rust.optimizer_progress import ProgressManager
17
+ from jarvis.jarvis_c2rust.optimizer_utils import cargo_check_full
18
+ from jarvis.jarvis_c2rust.optimizer_utils import check_missing_safety_doc_warnings
19
+ from jarvis.jarvis_c2rust.optimizer_utils import run_cargo_fmt
20
+ from jarvis.jarvis_code_agent.code_agent import CodeAgent
21
+
22
+
23
+ class UnsafeOptimizer:
24
+ """Unsafe 清理优化器。"""
25
+
26
+ def __init__(
27
+ self,
28
+ crate_dir: Path,
29
+ options: OptimizeOptions,
30
+ stats: OptimizeStats,
31
+ progress_manager: ProgressManager,
32
+ append_additional_notes_func: Callable[[str], str],
33
+ extract_warnings_by_file_func: Callable[[str], Dict[str, List[Dict]]],
34
+ format_warnings_for_prompt_func: Callable[[List[Dict], int], str],
35
+ ):
36
+ self.crate_dir = crate_dir
37
+ self.options = options
38
+ self.stats = stats
39
+ self.progress_manager = progress_manager
40
+ self.append_additional_notes = append_additional_notes_func
41
+ self.extract_warnings_by_file = extract_warnings_by_file_func
42
+ self.format_warnings_for_prompt = format_warnings_for_prompt_func
43
+
44
+ def codeagent_opt_unsafe_cleanup(self, target_files: List[Path]) -> None:
45
+ """
46
+ 使用 CodeAgent 进行 unsafe 清理优化。
47
+ 使用 clippy 的 missing_safety_doc checker 来查找 unsafe 告警,按文件处理,每次处理一个文件的所有告警。
48
+
49
+ 注意:CodeAgent 必须在 crate 目录下创建和执行,以确保所有文件操作和命令执行都在正确的上下文中进行。
50
+ """
51
+ crate = self.crate_dir.resolve()
52
+ file_list: List[str] = []
53
+ for p in target_files:
54
+ try:
55
+ rel = p.resolve().relative_to(crate).as_posix()
56
+ except Exception:
57
+ rel = p.as_posix()
58
+ file_list.append(rel)
59
+ self.stats.files_scanned += 1
60
+
61
+ # 切换到 crate 目录,确保 CodeAgent 在正确的上下文中创建和执行
62
+ prev_cwd = os.getcwd()
63
+ iteration = 0
64
+
65
+ try:
66
+ os.chdir(str(crate))
67
+
68
+ # 循环修复 unsafe 告警,按文件处理
69
+ while True:
70
+ iteration += 1
71
+
72
+ # 检查当前 missing_safety_doc 告警
73
+ has_warnings, current_clippy_output = check_missing_safety_doc_warnings(
74
+ crate
75
+ )
76
+ if not has_warnings:
77
+ PrettyOutput.auto_print(
78
+ f"[c2rust-optimizer][codeagent][unsafe-cleanup] 所有 missing_safety_doc 告警已消除(共迭代 {iteration - 1} 次)"
79
+ )
80
+ return # 所有告警已消除
81
+
82
+ # 按文件提取告警
83
+ warnings_by_file = self.extract_warnings_by_file(current_clippy_output)
84
+ if not warnings_by_file:
85
+ PrettyOutput.auto_print(
86
+ "[c2rust-optimizer][codeagent][unsafe-cleanup] 无法提取告警,停止修复"
87
+ )
88
+ return # 仍有告警未消除
89
+
90
+ # 找到第一个有告警的文件(优先处理目标文件列表中的文件)
91
+ target_file_path = None
92
+ target_warnings = None
93
+
94
+ # 优先处理目标文件列表中的文件
95
+ for file_rel in file_list:
96
+ # 尝试匹配文件路径(可能是相对路径或绝对路径)
97
+ for file_path, warnings in warnings_by_file.items():
98
+ if file_rel in file_path or file_path.endswith(file_rel):
99
+ target_file_path = file_path
100
+ target_warnings = warnings
101
+ break
102
+ if target_file_path:
103
+ break
104
+
105
+ # 如果目标文件列表中没有告警,选择第一个有告警的文件
106
+ if not target_file_path:
107
+ target_file_path = next(iter(warnings_by_file.keys()))
108
+ target_warnings = warnings_by_file[target_file_path]
109
+
110
+ # 获取该文件的所有告警(一次处理一个文件的所有告警)
111
+ warnings_to_fix = target_warnings
112
+ warning_count = (
113
+ len(warnings_to_fix) if warnings_to_fix is not None else 0
114
+ )
115
+
116
+ PrettyOutput.auto_print(
117
+ f"[c2rust-optimizer][codeagent][unsafe-cleanup] 第 {iteration} 次迭代:修复文件 {target_file_path} 的 {warning_count} 个 missing_safety_doc 告警"
118
+ )
119
+
120
+ # 格式化告警信息
121
+ formatted_warnings = self.format_warnings_for_prompt(
122
+ warnings_to_fix or [], warning_count
123
+ )
124
+
125
+ # 构建提示词,修复该文件的所有 missing_safety_doc 告警
126
+ prompt_lines: List[str] = [
127
+ "你是资深 Rust 代码工程师。请在当前 crate 下修复指定文件中的 missing_safety_doc 告警,并以补丁形式输出修改:",
128
+ f"- crate 根目录:{crate}",
129
+ "",
130
+ "本次优化仅允许修改以下文件(严格限制,只处理这一个文件):",
131
+ f"- {target_file_path}",
132
+ "",
133
+ f"重要:本次修复仅修复该文件中的 {warning_count} 个 missing_safety_doc 告警。",
134
+ "",
135
+ "优化目标:",
136
+ f"1) 修复文件 {target_file_path} 中的 {warning_count} 个 missing_safety_doc 告警:",
137
+ " **修复原则:能消除就消除,不能消除才增加 SAFETY 注释**",
138
+ "",
139
+ " 优先级 1(优先尝试):消除 unsafe",
140
+ " - 如果 unsafe 函数或方法实际上不需要是 unsafe 的,应该移除 unsafe 关键字;",
141
+ " - 如果 unsafe 块可以移除,应该移除整个 unsafe 块;",
142
+ " - 如果 unsafe 块可以缩小范围,应该缩小范围;",
143
+ " - 仔细分析代码,判断是否真的需要 unsafe,如果可以通过安全的方式实现,优先使用安全的方式。",
144
+ "",
145
+ " 优先级 2(无法消除时):添加 SAFETY 注释",
146
+ " - 只有在确认无法消除 unsafe 的情况下,才为 unsafe 函数或方法添加 `/// SAFETY: ...` 文档注释;",
147
+ " - SAFETY 注释必须详细说明为什么该函数或方法是 unsafe 的,包括:",
148
+ " * 哪些不变量必须由调用者维护;",
149
+ " * 哪些前提条件必须满足;",
150
+ " * 可能导致未定义行为的情况;",
151
+ " * 为什么不能使用安全的替代方案;",
152
+ " - 如果 unsafe 块无法移除但可以缩小范围,应该缩小范围并在紧邻位置添加 `/// SAFETY: ...` 注释。",
153
+ "",
154
+ "2) 修复已有实现的问题:",
155
+ " - 如果在修复 missing_safety_doc 告警的过程中,发现代码已有的实现有问题(如逻辑错误、潜在 bug、性能问题、内存安全问题等),也需要一并修复;",
156
+ " - 这些问题可能包括但不限于:不正确的 unsafe 使用、未检查的边界条件、资源泄漏、竞态条件、数据竞争等;",
157
+ " - 修复时应该保持最小改动原则,优先修复最严重的问题。",
158
+ "",
159
+ "约束与范围:",
160
+ f"- **仅修改文件 {target_file_path},不要修改其他文件**;除非必须(如修复引用路径),否则不要修改其他文件。",
161
+ "- 保持最小改动,不要进行与修复 missing_safety_doc 告警无关的重构或格式化。",
162
+ f"- **只修复该文件中的 {warning_count} 个 missing_safety_doc 告警,不要修复其他告警**。",
163
+ "- 修改后需保证 `cargo test` 可以通过;如需引入少量配套改动,请一并包含在补丁中以确保通过。",
164
+ "- 输出仅为补丁,不要输出解释或多余文本。",
165
+ "",
166
+ "优先级说明:",
167
+ "- **修复 unsafe 的优先级:能消除就消除,不能消除才增加 SAFETY 注释**;",
168
+ "- 对于每个 unsafe,首先尝试分析是否可以安全地移除,只有在确认无法移除时才添加 SAFETY 注释;",
169
+ "- **如果优化过程中出现了测试不通过或编译错误,必须优先解决这些问题**;",
170
+ "- 在修复告警之前,先确保代码能够正常编译和通过测试;",
171
+ "- 如果修复告警导致了编译错误或测试失败,必须立即修复这些错误,然后再继续优化。",
172
+ "",
173
+ "自检要求:在每次输出补丁后,请使用 execute_script 工具在 crate 根目录执行 `cargo test -q` 进行验证;",
174
+ "若出现编译错误或测试失败,请优先修复这些问题,然后再继续修复告警;",
175
+ "若未通过,请继续输出新的补丁进行最小修复并再次自检,直至 `cargo test` 通过为止。",
176
+ "",
177
+ f"文件 {target_file_path} 中的 missing_safety_doc 告警信息如下:",
178
+ "<WARNINGS>",
179
+ formatted_warnings,
180
+ "</WARNINGS>",
181
+ ]
182
+ prompt = "\n".join(prompt_lines)
183
+ prompt = self.append_additional_notes(prompt)
184
+
185
+ # 修复前执行 cargo fmt
186
+ run_cargo_fmt(crate)
187
+
188
+ # 记录运行前的 commit id
189
+ commit_before = self.progress_manager.get_crate_commit_hash()
190
+
191
+ # CodeAgent 在 crate 目录下创建和执行
192
+ agent = CodeAgent(
193
+ name=f"UnsafeCleanupAgent-iter{iteration}",
194
+ need_summary=False,
195
+ non_interactive=self.options.non_interactive,
196
+ model_group=self.options.llm_group,
197
+ enable_task_list_manager=False,
198
+ disable_review=True,
199
+ )
200
+ # 订阅 BEFORE_TOOL_CALL 和 AFTER_TOOL_CALL 事件,用于细粒度检测测试代码删除
201
+ agent.event_bus.subscribe(
202
+ BEFORE_TOOL_CALL, self.progress_manager.on_before_tool_call
203
+ )
204
+ agent.event_bus.subscribe(
205
+ AFTER_TOOL_CALL, self.progress_manager.on_after_tool_call
206
+ )
207
+ # 记录 Agent 创建时的 commit id(作为初始值)
208
+ agent_id = id(agent)
209
+ agent_key = f"agent_{agent_id}"
210
+ initial_commit = self.progress_manager.get_crate_commit_hash()
211
+ if initial_commit:
212
+ self.progress_manager._agent_before_commits[agent_key] = (
213
+ initial_commit
214
+ )
215
+ agent.run(
216
+ prompt,
217
+ prefix=f"[c2rust-optimizer][codeagent][unsafe-cleanup][iter{iteration}]",
218
+ suffix="",
219
+ )
220
+
221
+ # 检测并处理测试代码删除
222
+ if self.progress_manager.check_and_handle_test_deletion(
223
+ commit_before, agent
224
+ ):
225
+ # 如果回退了,需要重新运行 agent
226
+ PrettyOutput.auto_print(
227
+ f"[c2rust-optimizer][codeagent][unsafe-cleanup] 检测到测试代码删除问题,已回退,重新运行 agent (iter={iteration})"
228
+ )
229
+ commit_before = self.progress_manager.get_crate_commit_hash()
230
+ agent.run(
231
+ prompt,
232
+ prefix=f"[c2rust-optimizer][codeagent][unsafe-cleanup][iter{iteration}][retry]",
233
+ suffix="",
234
+ )
235
+ # 再次检测
236
+ if self.progress_manager.check_and_handle_test_deletion(
237
+ commit_before, agent
238
+ ):
239
+ PrettyOutput.auto_print(
240
+ f"[c2rust-optimizer][codeagent][unsafe-cleanup] 再次检测到测试代码删除问题,已回退 (iter={iteration})"
241
+ )
242
+
243
+ # 验证修复是否成功(通过 cargo test)
244
+ ok, _ = cargo_check_full(
245
+ crate,
246
+ self.stats,
247
+ self.options.max_checks,
248
+ timeout=self.options.cargo_test_timeout,
249
+ )
250
+ if ok:
251
+ # 修复成功,保存进度和 commit id
252
+ try:
253
+ # 确保 target_file_path 是 Path 对象
254
+ target_file_path_obj = Path(target_file_path)
255
+ file_path_to_save: Path = (
256
+ crate / target_file_path_obj
257
+ if not target_file_path_obj.is_absolute()
258
+ else target_file_path_obj
259
+ )
260
+ if file_path_to_save.exists():
261
+ self.progress_manager.save_fix_progress(
262
+ "unsafe_cleanup",
263
+ f"{target_file_path}-iter{iteration}",
264
+ [file_path_to_save],
265
+ )
266
+ else:
267
+ self.progress_manager.save_fix_progress(
268
+ "unsafe_cleanup",
269
+ f"{target_file_path}-iter{iteration}",
270
+ None,
271
+ )
272
+ except Exception:
273
+ self.progress_manager.save_fix_progress(
274
+ "unsafe_cleanup",
275
+ f"{target_file_path}-iter{iteration}",
276
+ None,
277
+ )
278
+ PrettyOutput.auto_print(
279
+ f"[c2rust-optimizer][codeagent][unsafe-cleanup] 文件 {target_file_path} 的 {warning_count} 个告警修复成功,已保存进度"
280
+ )
281
+ else:
282
+ # 测试失败,回退到运行前的 commit
283
+ if commit_before:
284
+ PrettyOutput.auto_print(
285
+ f"[c2rust-optimizer][codeagent][unsafe-cleanup] 文件 {target_file_path} 修复后测试失败,回退到运行前的 commit: {commit_before[:8]}"
286
+ )
287
+ if self.progress_manager.reset_to_commit(commit_before):
288
+ PrettyOutput.auto_print(
289
+ f"[c2rust-optimizer][codeagent][unsafe-cleanup] 已成功回退到 commit: {commit_before[:8]}"
290
+ )
291
+ else:
292
+ PrettyOutput.auto_print(
293
+ "[c2rust-optimizer][codeagent][unsafe-cleanup] 回退失败,请手动检查代码状态"
294
+ )
295
+ else:
296
+ PrettyOutput.auto_print(
297
+ f"[c2rust-optimizer][codeagent][unsafe-cleanup] 文件 {target_file_path} 修复后测试失败,但无法获取运行前的 commit,继续修复"
298
+ )
299
+
300
+ # 修复后再次检查告警
301
+ has_warnings_after, _ = check_missing_safety_doc_warnings(crate)
302
+ if not has_warnings_after:
303
+ PrettyOutput.auto_print(
304
+ f"[c2rust-optimizer][codeagent][unsafe-cleanup] 所有 missing_safety_doc 告警已消除(共迭代 {iteration} 次)"
305
+ )
306
+ return # 所有告警已消除
307
+
308
+ finally:
309
+ os.chdir(prev_cwd)