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,286 @@
1
+ # -*- coding: utf-8 -*-
2
+ """构建修复循环模块。"""
3
+
4
+ import os
5
+ import subprocess
6
+ from pathlib import Path
7
+ from typing import Callable
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 run_cargo_fmt
19
+ from jarvis.jarvis_code_agent.code_agent import CodeAgent
20
+
21
+
22
+ class BuildFixOptimizer:
23
+ """构建修复循环优化器。"""
24
+
25
+ def __init__(
26
+ self,
27
+ crate_dir: Path,
28
+ options: OptimizeOptions,
29
+ stats: OptimizeStats,
30
+ progress_manager: ProgressManager,
31
+ append_additional_notes_func: Callable[[str], str],
32
+ ):
33
+ self.crate_dir = crate_dir
34
+ self.options = options
35
+ self.stats = stats
36
+ self.progress_manager = progress_manager
37
+ self.append_additional_notes = append_additional_notes_func
38
+
39
+ def build_fix_loop(self, scope_files: List[Path]) -> bool:
40
+ """
41
+ 循环执行 cargo check 并用 CodeAgent 进行最小修复,直到通过或达到重试上限或检查预算耗尽。
42
+ 仅允许(优先)修改 scope_files(除非确有必要),以支持分批优化。
43
+ 返回 True 表示修复成功构建通过;False 表示未能在限制内修复。
44
+
45
+ 注意:CodeAgent 必须在 crate 目录下创建和执行,以确保所有文件操作和命令执行都在正确的上下文中进行。
46
+ """
47
+ maxr = int(self.options.build_fix_retries or 0)
48
+ if maxr <= 0:
49
+ return False
50
+ crate = self.crate_dir.resolve()
51
+ allowed: List[str] = []
52
+ for p in scope_files:
53
+ try:
54
+ rel = p.resolve().relative_to(crate).as_posix()
55
+ except Exception:
56
+ rel = p.as_posix()
57
+ allowed.append(rel)
58
+
59
+ attempt = 0
60
+ while True:
61
+ # 检查预算
62
+ if (
63
+ self.options.max_checks
64
+ and self.stats.cargo_checks >= self.options.max_checks
65
+ ):
66
+ return False
67
+ # 执行构建
68
+ output = ""
69
+ try:
70
+ res = subprocess.run(
71
+ ["cargo", "test", "-q"],
72
+ capture_output=True,
73
+ text=True,
74
+ check=False,
75
+ cwd=str(crate),
76
+ timeout=self.options.cargo_test_timeout
77
+ if self.options.cargo_test_timeout > 0
78
+ else None,
79
+ )
80
+ self.stats.cargo_checks += 1
81
+ if res.returncode == 0:
82
+ PrettyOutput.auto_print(
83
+ "✅ [c2rust-optimizer][build-fix] 构建修复成功。"
84
+ )
85
+ return True
86
+ output = ((res.stdout or "") + ("\n" + (res.stderr or ""))).strip()
87
+ except subprocess.TimeoutExpired as e:
88
+ self.stats.cargo_checks += 1
89
+ out_s = e.stdout.decode("utf-8", errors="ignore") if e.stdout else ""
90
+ err_s = e.stderr.decode("utf-8", errors="ignore") if e.stderr else ""
91
+ output = f"cargo test timed out after {self.options.cargo_test_timeout} seconds"
92
+ full_output = (out_s + ("\n" + err_s if err_s else "")).strip()
93
+ if full_output:
94
+ output += f"\nOutput:\n{full_output}"
95
+ except Exception as e:
96
+ self.stats.cargo_checks += 1
97
+ output = f"cargo test exception: {e}"
98
+
99
+ # 达到重试上限则失败
100
+ attempt += 1
101
+ if attempt > maxr:
102
+ PrettyOutput.auto_print(
103
+ "❌ [c2rust-optimizer][build-fix] 构建修复重试次数已用尽。"
104
+ )
105
+ return False
106
+
107
+ PrettyOutput.auto_print(
108
+ f"⚠️ [c2rust-optimizer][build-fix] 构建失败。正在尝试使用 CodeAgent 进行修复 (第 {attempt}/{maxr} 次尝试)..."
109
+ )
110
+ # 生成最小修复提示
111
+ prompt_lines = [
112
+ "请根据以下测试/构建错误对 crate 进行最小必要的修复以通过 `cargo test`:",
113
+ f"- crate 根目录:{crate}",
114
+ "",
115
+ "本次修复优先且仅允许修改以下文件(除非确有必要,否则不要修改范围外文件):",
116
+ *[f"- {rel}" for rel in allowed],
117
+ "",
118
+ "约束与范围:",
119
+ "- 保持最小改动,不要进行与错误无关的重构或格式化;",
120
+ "- 仅输出补丁,不要输出解释或多余文本。",
121
+ "",
122
+ "优化目标:",
123
+ "1) 修复构建/测试错误:",
124
+ " - 必须优先解决所有编译错误和测试失败问题;",
125
+ " - 修复时应该先解决编译错误,然后再解决测试失败;",
126
+ " - 如果修复过程中引入了新的错误,必须立即修复这些新错误。",
127
+ "",
128
+ "2) 修复已有实现的问题:",
129
+ " - 如果在修复构建/测试错误的过程中,发现代码已有的实现有问题(如逻辑错误、潜在 bug、性能问题、内存安全问题等),也需要一并修复;",
130
+ " - 这些问题可能包括但不限于:不正确的算法实现、未检查的边界条件、资源泄漏、竞态条件、数据竞争等;",
131
+ " - 修复时应该保持最小改动原则,优先修复最严重的问题。",
132
+ "",
133
+ "优先级说明:",
134
+ "- **必须优先解决所有编译错误和测试失败问题**;",
135
+ "- 修复时应该先解决编译错误,然后再解决测试失败;",
136
+ "- 如果修复过程中引入了新的错误,必须立即修复这些新错误。",
137
+ "",
138
+ "自检要求:在每次输出补丁后,请使用 execute_script 工具在 crate 根目录执行 `cargo test -q` 进行验证;",
139
+ "若出现编译错误或测试失败,请优先修复这些问题;",
140
+ "若未通过,请继续输出新的补丁进行最小修复并再次自检,直至 `cargo test` 通过为止。",
141
+ "",
142
+ "构建错误如下:",
143
+ "<BUILD_ERROR>",
144
+ output,
145
+ "</BUILD_ERROR>",
146
+ ]
147
+ prompt = "\n".join(prompt_lines)
148
+ prompt = self.append_additional_notes(prompt)
149
+ # 切换到 crate 目录,确保 CodeAgent 在正确的上下文中创建和执行
150
+ prev_cwd = os.getcwd()
151
+ try:
152
+ os.chdir(str(crate))
153
+ # 修复前执行 cargo fmt
154
+ run_cargo_fmt(crate)
155
+
156
+ # 记录运行前的 commit id
157
+ commit_before = self.progress_manager.get_crate_commit_hash()
158
+
159
+ # CodeAgent 在 crate 目录下创建和执行
160
+ agent = CodeAgent(
161
+ name=f"BuildFixAgent-iter{attempt}",
162
+ need_summary=False,
163
+ non_interactive=self.options.non_interactive,
164
+ model_group=self.options.llm_group,
165
+ enable_task_list_manager=False,
166
+ disable_review=True,
167
+ )
168
+ # 订阅 BEFORE_TOOL_CALL 和 AFTER_TOOL_CALL 事件,用于细粒度检测测试代码删除
169
+ agent.event_bus.subscribe(
170
+ BEFORE_TOOL_CALL, self.progress_manager.on_before_tool_call
171
+ )
172
+ agent.event_bus.subscribe(
173
+ AFTER_TOOL_CALL, self.progress_manager.on_after_tool_call
174
+ )
175
+ # 记录 Agent 创建时的 commit id(作为初始值)
176
+ agent_id = id(agent)
177
+ agent_key = f"agent_{agent_id}"
178
+ initial_commit = self.progress_manager.get_crate_commit_hash()
179
+ if initial_commit:
180
+ self.progress_manager._agent_before_commits[agent_key] = (
181
+ initial_commit
182
+ )
183
+ agent.run(
184
+ prompt,
185
+ prefix=f"[c2rust-optimizer][build-fix iter={attempt}]",
186
+ suffix="",
187
+ )
188
+
189
+ # 检测并处理测试代码删除
190
+ if self.progress_manager.check_and_handle_test_deletion(
191
+ commit_before, agent
192
+ ):
193
+ # 如果回退了,需要重新运行 agent
194
+ PrettyOutput.auto_print(
195
+ f"⚠️ [c2rust-optimizer][build-fix] 检测到测试代码删除问题,已回退,重新运行 agent (iter={attempt})"
196
+ )
197
+ commit_before = self.progress_manager.get_crate_commit_hash()
198
+ agent.run(
199
+ prompt,
200
+ prefix=f"[c2rust-optimizer][build-fix iter={attempt}][retry]",
201
+ suffix="",
202
+ )
203
+ # 再次检测
204
+ if self.progress_manager.check_and_handle_test_deletion(
205
+ commit_before, agent
206
+ ):
207
+ PrettyOutput.auto_print(
208
+ f"❌ [c2rust-optimizer][build-fix] 再次检测到测试代码删除问题,已回退 (iter={attempt})"
209
+ )
210
+
211
+ # 验证修复是否成功(通过 cargo test)
212
+ ok, _ = cargo_check_full(
213
+ crate,
214
+ self.stats,
215
+ self.options.max_checks,
216
+ timeout=self.options.cargo_test_timeout,
217
+ )
218
+ if ok:
219
+ # 修复成功,保存进度和 commit id
220
+ file_paths = [crate / f for f in allowed if (crate / f).exists()]
221
+ self.progress_manager.save_fix_progress(
222
+ "build_fix",
223
+ f"iter{attempt}",
224
+ file_paths if file_paths else None,
225
+ )
226
+ PrettyOutput.auto_print(
227
+ f"✅ [c2rust-optimizer][build-fix] 第 {attempt} 次修复成功,已保存进度"
228
+ )
229
+ # 返回 True 表示修复成功
230
+ return True
231
+ else:
232
+ # 测试失败,回退到运行前的 commit
233
+ if commit_before:
234
+ PrettyOutput.auto_print(
235
+ f"⚠️ [c2rust-optimizer][build-fix] 第 {attempt} 次修复后测试失败,回退到运行前的 commit: {commit_before[:8]}"
236
+ )
237
+ if self.progress_manager.reset_to_commit(commit_before):
238
+ PrettyOutput.auto_print(
239
+ f"ℹ️ [c2rust-optimizer][build-fix] 已成功回退到 commit: {commit_before[:8]}"
240
+ )
241
+ else:
242
+ PrettyOutput.auto_print(
243
+ "❌ [c2rust-optimizer][build-fix] 回退失败,请手动检查代码状态"
244
+ )
245
+ else:
246
+ PrettyOutput.auto_print(
247
+ f"⚠️ [c2rust-optimizer][build-fix] 第 {attempt} 次修复后测试失败,但无法获取运行前的 commit,继续尝试"
248
+ )
249
+ finally:
250
+ os.chdir(prev_cwd)
251
+
252
+ def verify_and_fix_after_step(
253
+ self, step_name: str, target_files: List[Path]
254
+ ) -> bool:
255
+ """
256
+ 验证步骤执行后的测试,如果失败则尝试修复。
257
+
258
+ Args:
259
+ step_name: 步骤名称(用于错误消息)
260
+ target_files: 目标文件列表(用于修复范围)
261
+
262
+ Returns:
263
+ True: 测试通过或修复成功
264
+ False: 测试失败且修复失败(已回滚)
265
+ """
266
+ ok, diag_full = cargo_check_full(
267
+ self.crate_dir,
268
+ self.stats,
269
+ self.options.max_checks,
270
+ timeout=self.options.cargo_test_timeout,
271
+ )
272
+ if not ok:
273
+ fixed = self.build_fix_loop(target_files)
274
+ if not fixed:
275
+ first = (
276
+ diag_full.splitlines()[0]
277
+ if isinstance(diag_full, str) and diag_full
278
+ else "failed"
279
+ )
280
+ if self.stats.errors is not None:
281
+ self.stats.errors.append(f"test after {step_name} failed: {first}")
282
+ try:
283
+ self.progress_manager.reset_to_snapshot()
284
+ finally:
285
+ return False
286
+ return True