jarvis-ai-assistant 0.7.8__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.8.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.8.dist-info/RECORD +0 -218
  276. {jarvis_ai_assistant-0.7.8.dist-info → jarvis_ai_assistant-1.0.2.dist-info}/WHEEL +0 -0
  277. {jarvis_ai_assistant-0.7.8.dist-info → jarvis_ai_assistant-1.0.2.dist-info}/entry_points.txt +0 -0
  278. {jarvis_ai_assistant-0.7.8.dist-info → jarvis_ai_assistant-1.0.2.dist-info}/licenses/LICENSE +0 -0
  279. {jarvis_ai_assistant-0.7.8.dist-info → jarvis_ai_assistant-1.0.2.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,516 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ 转译执行器模块
4
+
5
+ 负责执行转译的主流程,包括:
6
+ - 初始化 crate 目录和配置
7
+ - 加载和处理 order 文件
8
+ - 遍历函数并执行转译流程
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ import os
14
+ from pathlib import Path
15
+ from typing import Any
16
+ from typing import Dict
17
+ from typing import List
18
+ from typing import Set
19
+
20
+
21
+ from jarvis.jarvis_c2rust.constants import MAX_FUNCTION_RETRIES
22
+ from jarvis.jarvis_c2rust.library_replacer_utils import is_entry_function
23
+ from jarvis.jarvis_c2rust.models import FnRecord
24
+ from jarvis.jarvis_c2rust.utils import ensure_order_file
25
+ from jarvis.jarvis_c2rust.utils import iter_order_steps
26
+ from jarvis.jarvis_utils.output import PrettyOutput
27
+
28
+
29
+ class TranspilerExecutor:
30
+ """转译执行器,负责执行转译的主流程"""
31
+
32
+ def __init__(
33
+ self,
34
+ project_root: Path,
35
+ crate_dir: Path,
36
+ progress: Dict[str, Any],
37
+ resume: bool,
38
+ fn_index_by_id: Dict[int, FnRecord],
39
+ # 依赖注入的方法
40
+ load_order_index_func,
41
+ should_skip_func,
42
+ read_source_span_func,
43
+ plan_module_and_signature_func,
44
+ update_progress_current_func,
45
+ mark_converted_func,
46
+ reset_function_context_func,
47
+ ensure_mod_chain_for_module_func,
48
+ ensure_top_level_pub_mod_func,
49
+ get_crate_commit_hash_func,
50
+ reset_to_commit_func,
51
+ run_cargo_fmt_func,
52
+ untranslated_callee_symbols_func,
53
+ codeagent_generate_impl_func,
54
+ refresh_compact_context_func,
55
+ cargo_build_loop_func,
56
+ review_and_optimize_func,
57
+ extract_rust_fn_name_from_sig_func,
58
+ resolve_pending_todos_for_symbol_func,
59
+ save_progress_func,
60
+ consecutive_fix_failures_getter,
61
+ consecutive_fix_failures_setter,
62
+ current_function_start_commit_getter,
63
+ current_function_start_commit_setter,
64
+ get_build_loop_has_fixes_func,
65
+ ensure_cargo_toml_bin_func,
66
+ ) -> None:
67
+ self.project_root = project_root
68
+ self.crate_dir = crate_dir
69
+ self.progress = progress
70
+ self.resume = resume
71
+ self.fn_index_by_id = fn_index_by_id
72
+
73
+ # 注入的方法
74
+ self.load_order_index = load_order_index_func
75
+ self.should_skip = should_skip_func
76
+ self.read_source_span = read_source_span_func
77
+ self.plan_module_and_signature = plan_module_and_signature_func
78
+ self.update_progress_current = update_progress_current_func
79
+ self.mark_converted = mark_converted_func
80
+ self.reset_function_context = reset_function_context_func
81
+ self.ensure_mod_chain_for_module = ensure_mod_chain_for_module_func
82
+ self.ensure_top_level_pub_mod = ensure_top_level_pub_mod_func
83
+ self.get_crate_commit_hash = get_crate_commit_hash_func
84
+ self.reset_to_commit = reset_to_commit_func
85
+ self.run_cargo_fmt = run_cargo_fmt_func
86
+ self.untranslated_callee_symbols = untranslated_callee_symbols_func
87
+ self.codeagent_generate_impl = codeagent_generate_impl_func
88
+ self.refresh_compact_context = refresh_compact_context_func
89
+ self.cargo_build_loop = cargo_build_loop_func
90
+ self.review_and_optimize = review_and_optimize_func
91
+ self.extract_rust_fn_name_from_sig = extract_rust_fn_name_from_sig_func
92
+ self.resolve_pending_todos_for_symbol = resolve_pending_todos_for_symbol_func
93
+ self.save_progress = save_progress_func
94
+ self.consecutive_fix_failures_getter = consecutive_fix_failures_getter
95
+ self.consecutive_fix_failures_setter = consecutive_fix_failures_setter
96
+ self.current_function_start_commit_getter = current_function_start_commit_getter
97
+ self.current_function_start_commit_setter = current_function_start_commit_setter
98
+ self.get_build_loop_has_fixes = get_build_loop_has_fixes_func
99
+ self.ensure_cargo_toml_bin = ensure_cargo_toml_bin_func
100
+
101
+ def execute(self) -> None:
102
+ """执行转译主流程"""
103
+ PrettyOutput.auto_print("🚀 [c2rust-transpiler][start] 开始转译")
104
+ # 切换到 crate 根目录,整个转译过程都在此目录下执行
105
+ prev_cwd = os.getcwd()
106
+ try:
107
+ os.chdir(str(self.crate_dir))
108
+ PrettyOutput.auto_print(
109
+ f"📁 [c2rust-transpiler][start] 已切换到 crate 目录: {os.getcwd()}"
110
+ )
111
+ # 准确性兜底:在未执行 prepare 的情况下,确保 crate 目录与最小 Cargo 配置存在
112
+ self._ensure_crate_structure()
113
+
114
+ order_path = ensure_order_file(self.project_root)
115
+ steps = iter_order_steps(order_path)
116
+ if not steps:
117
+ PrettyOutput.auto_print("⚠️ [c2rust-transpiler] 未找到翻译步骤。")
118
+ return
119
+
120
+ # 构建自包含 order 索引(id -> FnRecord,name/qname -> id)
121
+ self.load_order_index(order_path)
122
+
123
+ # 扁平化顺序,按单个函数处理(保持原有顺序)
124
+ seq: List[int] = []
125
+ for grp in steps:
126
+ seq.extend(grp)
127
+
128
+ # 若支持 resume,则跳过 progress['converted'] 中已完成的
129
+ done: Set[int] = set(self.progress.get("converted") or [])
130
+ # 计算需要处理的函数总数(排除已完成的)
131
+ total_to_process = len([fid for fid in seq if fid not in done])
132
+ current_index = 0
133
+
134
+ # 恢复时,reset 到最后一个已转换函数的 commit id
135
+ self._handle_resume(seq, done)
136
+
137
+ PrettyOutput.auto_print(
138
+ f"📊 [c2rust-transpiler][order] 顺序信息: 步骤数={len(steps)} 总ID={sum(len(g) for g in steps)} 已转换={len(done)} 待处理={total_to_process}"
139
+ )
140
+
141
+ for fid in seq:
142
+ if fid in done:
143
+ continue
144
+ rec = self.fn_index_by_id.get(fid)
145
+ if not rec:
146
+ continue
147
+ if self.should_skip(rec):
148
+ PrettyOutput.auto_print(
149
+ f"⏭️ [c2rust-transpiler][skip] 跳过 {rec.qname or rec.name} (id={rec.id}) 位于 {rec.file}:{rec.start_line}-{rec.end_line}"
150
+ )
151
+ continue
152
+
153
+ # 更新进度索引
154
+ current_index += 1
155
+ progress_info = (
156
+ f"({current_index}/{total_to_process})"
157
+ if total_to_process > 0
158
+ else ""
159
+ )
160
+
161
+ # 处理单个函数
162
+ if not self._process_function(rec, progress_info):
163
+ # 处理失败,保留当前状态,便于下次 resume
164
+ return
165
+
166
+ PrettyOutput.auto_print(
167
+ "📋 [c2rust-transpiler] 所有符合条件的函数均已处理完毕。"
168
+ )
169
+ finally:
170
+ os.chdir(prev_cwd)
171
+ PrettyOutput.auto_print(
172
+ f"🏁 [c2rust-transpiler][end] 已恢复工作目录: {os.getcwd()}"
173
+ )
174
+
175
+ def _ensure_crate_structure(self) -> None:
176
+ """确保 crate 目录和最小 Cargo 配置存在"""
177
+ try:
178
+ cd = self.crate_dir.resolve()
179
+ cd.mkdir(parents=True, exist_ok=True)
180
+ cargo = cd / "Cargo.toml"
181
+ src_dir = cd / "src"
182
+ lib_rs = src_dir / "lib.rs"
183
+ # 最小 Cargo.toml(不覆盖已有),edition 使用 2021 以兼容更广环境
184
+ if not cargo.exists():
185
+ pkg_name = cd.name
186
+ content = (
187
+ f'[package]\nname = "{pkg_name}"\nversion = "0.1.0"\nedition = "2021"\n\n'
188
+ '[lib]\npath = "src/lib.rs"\n'
189
+ )
190
+ try:
191
+ cargo.write_text(content, encoding="utf-8")
192
+ PrettyOutput.auto_print(
193
+ f"✅ [c2rust-transpiler][init] created Cargo.toml at {cargo}"
194
+ )
195
+ except Exception:
196
+ pass
197
+ # 确保 src/lib.rs 存在
198
+ src_dir.mkdir(parents=True, exist_ok=True)
199
+ if not lib_rs.exists():
200
+ try:
201
+ lib_rs.write_text(
202
+ "// Auto-created by c2rust transpiler\n", encoding="utf-8"
203
+ )
204
+ PrettyOutput.auto_print(
205
+ f"✅ [c2rust-transpiler][init] created src/lib.rs at {lib_rs}"
206
+ )
207
+ except Exception:
208
+ pass
209
+ except Exception:
210
+ # 保持稳健,失败不阻塞主流程
211
+ pass
212
+
213
+ def _handle_resume(self, seq: List[int], done: Set[int]) -> None:
214
+ """处理恢复逻辑:reset 到最后一个已转换函数的 commit id"""
215
+ if not (self.resume and done):
216
+ return
217
+
218
+ converted_commits = self.progress.get("converted_commits") or {}
219
+ if not converted_commits:
220
+ return
221
+
222
+ # 找到最后一个已转换函数的 commit id
223
+ last_commit = None
224
+ for fid in reversed(seq):
225
+ if fid in done:
226
+ commit_id = converted_commits.get(str(fid))
227
+ if commit_id:
228
+ last_commit = commit_id
229
+ break
230
+
231
+ if not last_commit:
232
+ return
233
+
234
+ current_commit = self.get_crate_commit_hash()
235
+ if current_commit != last_commit:
236
+ PrettyOutput.auto_print(
237
+ f"🔄 [c2rust-transpiler][resume] 检测到代码状态不一致,正在 reset 到最后一个已转换函数的 commit: {last_commit}"
238
+ )
239
+ if self.reset_to_commit(last_commit):
240
+ PrettyOutput.auto_print(
241
+ f"✅ [c2rust-transpiler][resume] 已 reset 到 commit: {last_commit}"
242
+ )
243
+ else:
244
+ PrettyOutput.auto_print(
245
+ "⚠️ [c2rust-transpiler][resume] reset 失败,继续使用当前代码状态"
246
+ )
247
+ else:
248
+ PrettyOutput.auto_print(
249
+ "✅ [c2rust-transpiler][resume] 代码状态一致,无需 reset"
250
+ )
251
+
252
+ def _process_function(self, rec: FnRecord, progress_info: str) -> bool:
253
+ """处理单个函数的转译流程
254
+
255
+ 返回:
256
+ bool: True 表示成功,False 表示需要停止(失败或达到重试上限)
257
+ """
258
+ # 在每个函数开始转译前执行 cargo fmt
259
+ workspace_root = str(self.crate_dir)
260
+ self.run_cargo_fmt(workspace_root)
261
+
262
+ # 读取C函数源码
263
+ PrettyOutput.auto_print(
264
+ f"📖 [c2rust-transpiler][read] {progress_info} 读取 C 源码: {rec.qname or rec.name} (id={rec.id}) 来自 {rec.file}:{rec.start_line}-{rec.end_line}"
265
+ )
266
+ c_code = self.read_source_span(rec)
267
+ PrettyOutput.auto_print(
268
+ f"📊 [c2rust-transpiler][read] 已加载 {len(c_code.splitlines()) if c_code else 0} 行"
269
+ )
270
+
271
+ # 若缺少源码片段且缺乏签名/参数信息,则跳过本函数,记录进度以便后续处理
272
+ if not c_code and not (
273
+ getattr(rec, "signature", "") or getattr(rec, "params", None)
274
+ ):
275
+ skipped = self.progress.get("skipped_missing_source") or []
276
+ if rec.id not in skipped:
277
+ skipped.append(rec.id)
278
+ self.progress["skipped_missing_source"] = skipped
279
+ PrettyOutput.auto_print(
280
+ f"⚠️ [c2rust-transpiler] {progress_info} 跳过:缺少源码与签名信息 -> {rec.qname or rec.name} (id={rec.id})"
281
+ )
282
+ self.save_progress()
283
+ return True # 跳过不算失败
284
+
285
+ # 1) 规划:模块路径与Rust签名
286
+ PrettyOutput.auto_print(
287
+ f"📝 [c2rust-transpiler][plan] {progress_info} 正在规划模块与签名: {rec.qname or rec.name} (id={rec.id})"
288
+ )
289
+ module, rust_sig, skip_implementation = self.plan_module_and_signature(
290
+ rec, c_code
291
+ )
292
+ PrettyOutput.auto_print(
293
+ f"✅ [c2rust-transpiler][plan] 已选择 模块={module}, 签名={rust_sig}"
294
+ )
295
+
296
+ # 记录当前进度
297
+ self.update_progress_current(rec, module, rust_sig)
298
+ PrettyOutput.auto_print(
299
+ f"📝 [c2rust-transpiler][progress] 已更新当前进度记录 id={rec.id}"
300
+ )
301
+
302
+ # 检测 main 函数并更新 Cargo.toml
303
+ if is_entry_function(rec.__dict__):
304
+ # 检查模块路径是否在 src/bin/ 下
305
+ module_path_clean = module.replace("\\", "/")
306
+ if module_path_clean.startswith("src/bin/") or "/bin/" in module_path_clean:
307
+ # 提取相对于 crate 根目录的路径
308
+ if not module_path_clean.startswith("src/"):
309
+ # 如果是绝对路径,需要转换为相对路径
310
+ try:
311
+ mp = Path(module)
312
+ if mp.is_absolute():
313
+ rel = mp.relative_to(self.crate_dir.resolve())
314
+ module_path_clean = str(rel).replace("\\", "/")
315
+ except Exception:
316
+ pass
317
+ # 确保路径以 src/ 开头
318
+ if module_path_clean.startswith("src/"):
319
+ PrettyOutput.auto_print(
320
+ f"⚙️ [c2rust-transpiler][main] 检测到 main 函数,更新 Cargo.toml 添加 [[bin]] 配置: {module_path_clean}"
321
+ )
322
+ self.ensure_cargo_toml_bin(module_path_clean)
323
+
324
+ # 如果标记为跳过实现,则直接标记为已转换
325
+ if skip_implementation:
326
+ PrettyOutput.auto_print(
327
+ f"⏭️ [c2rust-transpiler][skip-impl] 函数 {rec.qname or rec.name} 评估为不需要实现,跳过实现阶段"
328
+ )
329
+ # 直接标记为已转换,跳过代码生成、构建和审查阶段
330
+ self.mark_converted(rec, module, rust_sig)
331
+ PrettyOutput.auto_print(
332
+ f"✅ [c2rust-transpiler][mark] 已标记并建立映射: {rec.qname or rec.name} -> {module} (跳过实现,视为已实现)"
333
+ )
334
+ return True
335
+
336
+ # 初始化函数上下文与代码编写与修复Agent复用缓存(只在当前函数开始时执行一次)
337
+ self.reset_function_context(rec, module, rust_sig, c_code)
338
+
339
+ # 1.5) 确保模块声明链(提前到生成实现之前,避免生成的代码无法被正确引用)
340
+ self._ensure_module_structure(module)
341
+
342
+ # 在处理函数前,记录当前的 commit id(用于失败回退)
343
+ self.current_function_start_commit_setter(self.get_crate_commit_hash())
344
+ if self.current_function_start_commit_getter():
345
+ PrettyOutput.auto_print(
346
+ f"🔖 [c2rust-transpiler][commit] 记录函数开始时的 commit: {self.current_function_start_commit_getter()}"
347
+ )
348
+ else:
349
+ PrettyOutput.auto_print(
350
+ "⚠️ [c2rust-transpiler][commit] 警告:无法获取 commit id,将无法在失败时回退"
351
+ )
352
+
353
+ # 重置连续失败计数(每个新函数开始时重置)
354
+ self.consecutive_fix_failures_setter(0)
355
+
356
+ # 使用循环来处理函数,支持失败回退后重新开始
357
+ function_retry_count = 0
358
+ max_function_retries = MAX_FUNCTION_RETRIES
359
+ build_has_fixes = False # 在循环外定义,确保在 break 后仍可使用
360
+ while function_retry_count <= max_function_retries:
361
+ if function_retry_count > 0:
362
+ PrettyOutput.auto_print(
363
+ f"🔁 [c2rust-transpiler][retry] 重新开始处理函数 (第 {function_retry_count} 次重试)"
364
+ )
365
+ # 重新记录 commit id(回退后的新 commit)
366
+ self.current_function_start_commit_setter(self.get_crate_commit_hash())
367
+ if self.current_function_start_commit_getter():
368
+ PrettyOutput.auto_print(
369
+ f"📝 [c2rust-transpiler][commit] 重新记录函数开始时的 commit: {self.current_function_start_commit_getter()}"
370
+ )
371
+ # 重置连续失败计数(重新开始时重置)
372
+ self.consecutive_fix_failures_setter(0)
373
+
374
+ # 2) 生成实现
375
+ unresolved = self.untranslated_callee_symbols(rec)
376
+ PrettyOutput.auto_print(
377
+ f"⚠️ [c2rust-transpiler][deps] {progress_info} 未解析的被调符号: {', '.join(unresolved) if unresolved else '(none)'}"
378
+ )
379
+ PrettyOutput.auto_print(
380
+ f"📋 [c2rust-transpiler][gen] {progress_info} 正在为 {rec.qname or rec.name} 生成 Rust 实现"
381
+ )
382
+ self.codeagent_generate_impl(rec, c_code, module, rust_sig, unresolved)
383
+ PrettyOutput.auto_print(
384
+ f"📋 [c2rust-transpiler][gen] 已在 {module} 生成或更新实现"
385
+ )
386
+ # 刷新精简上下文(防止签名/模块调整后提示不同步)
387
+ try:
388
+ self.refresh_compact_context(rec, module, rust_sig)
389
+ except Exception:
390
+ pass
391
+
392
+ # 3) 构建与修复
393
+ PrettyOutput.auto_print("📋 [c2rust-transpiler][build] 开始 cargo 测试循环")
394
+ ok = self.cargo_build_loop()
395
+
396
+ # 检查构建循环中是否进行了修复(累积修复标记,不要重置)
397
+ current_build_has_fixes = (
398
+ self.get_build_loop_has_fixes()
399
+ if hasattr(self, "get_build_loop_has_fixes")
400
+ else False
401
+ )
402
+ # 累积修复标记:如果本次或之前有修复,都标记为有修复
403
+ build_has_fixes = build_has_fixes or current_build_has_fixes
404
+
405
+ # 检查是否需要重新开始(回退后)
406
+ if ok is None:
407
+ # 需要重新开始
408
+ function_retry_count += 1
409
+ if function_retry_count > max_function_retries:
410
+ PrettyOutput.auto_print(
411
+ f"🔄 [c2rust-transpiler] 函数重新开始次数已达上限({max_function_retries}),停止处理该函数"
412
+ )
413
+ # 保留当前状态,便于下次 resume
414
+ return False
415
+ # 重置连续失败计数
416
+ self.consecutive_fix_failures_setter(0)
417
+ # 继续循环,重新开始处理
418
+ continue
419
+
420
+ PrettyOutput.auto_print(
421
+ f"📊 [c2rust-transpiler][build] 构建结果: {'通过' if ok else '失败'}"
422
+ )
423
+ if not ok:
424
+ PrettyOutput.auto_print(
425
+ "🔁 [c2rust-transpiler] 在重试次数限制内未能成功构建,已停止。"
426
+ )
427
+ # 保留当前状态,便于下次 resume
428
+ return False
429
+
430
+ # 构建成功,跳出循环继续后续流程
431
+ # 如果构建过程中进行了修复,需要重新进行 review
432
+ if build_has_fixes:
433
+ PrettyOutput.auto_print(
434
+ "👀 [c2rust-transpiler][build] 构建过程中进行了修复,需要重新进行代码审查"
435
+ )
436
+ break
437
+
438
+ # 4) 审查与优化(复用 Review Agent)
439
+ # 如果构建过程中进行了修复,需要重新进行 review 以确保修复没有引入新问题
440
+ if build_has_fixes:
441
+ PrettyOutput.auto_print(
442
+ f"🔄 [c2rust-transpiler][review] {progress_info} 构建修复后重新开始代码审查: {rec.qname or rec.name}"
443
+ )
444
+ else:
445
+ PrettyOutput.auto_print(
446
+ f"👀 [c2rust-transpiler][review] {progress_info} 开始代码审查: {rec.qname or rec.name}"
447
+ )
448
+ self.review_and_optimize(rec, module, rust_sig)
449
+ PrettyOutput.auto_print("🔍 [c2rust-transpiler][review] 代码审查完成")
450
+
451
+ # 5) 标记已转换与映射记录(JSONL)
452
+ self.mark_converted(rec, module, rust_sig)
453
+ PrettyOutput.auto_print(
454
+ f"📋 [c2rust-transpiler][mark] {progress_info} 已标记并建立映射: {rec.qname or rec.name} -> {module}"
455
+ )
456
+
457
+ # 6) 若此前有其它函数因依赖当前符号而在源码中放置了 todo!("<symbol>"),则立即回头消除(复用代码编写与修复Agent)
458
+ current_rust_fn = self.extract_rust_fn_name_from_sig(rust_sig)
459
+ # 收集需要处理的符号(去重,避免 qname 和 name 相同时重复处理)
460
+ symbols_to_resolve = []
461
+ if rec.qname:
462
+ symbols_to_resolve.append(rec.qname)
463
+ if rec.name and rec.name != rec.qname: # 如果 name 与 qname 不同,才添加
464
+ symbols_to_resolve.append(rec.name)
465
+ # 处理每个符号(去重后)
466
+ for sym in symbols_to_resolve:
467
+ PrettyOutput.auto_print(
468
+ f"📋 [c2rust-transpiler][todo] 清理 todo!('{sym}') 的出现位置"
469
+ )
470
+ self.resolve_pending_todos_for_symbol(
471
+ sym, module, current_rust_fn, rust_sig
472
+ )
473
+ # 如果有处理任何符号,统一运行一次 cargo test(避免重复运行)
474
+ if symbols_to_resolve:
475
+ PrettyOutput.auto_print(
476
+ "📋 [c2rust-transpiler][build] 处理 todo 后重新运行 cargo test"
477
+ )
478
+ self.cargo_build_loop()
479
+
480
+ return True
481
+
482
+ def _ensure_module_structure(self, module: str) -> None:
483
+ """确保模块声明链和顶层模块导出"""
484
+ try:
485
+ self.ensure_mod_chain_for_module(module)
486
+ PrettyOutput.auto_print(
487
+ f"📋 [c2rust-transpiler][mod] 已补齐 {module} 的 mod.rs 声明链"
488
+ )
489
+ # 确保顶层模块在 src/lib.rs 中被公开
490
+ mp = Path(module)
491
+ crate_root = self.crate_dir.resolve()
492
+ rel = (
493
+ mp.resolve().relative_to(crate_root)
494
+ if mp.is_absolute()
495
+ else Path(module)
496
+ )
497
+ rel_s = str(rel).replace("\\", "/")
498
+ if rel_s.startswith("./"):
499
+ rel_s = rel_s[2:]
500
+ if rel_s.startswith("src/"):
501
+ parts = rel_s[len("src/") :].strip("/").split("/")
502
+ if parts and parts[0]:
503
+ top_mod = parts[0]
504
+ # 过滤掉 "mod"、"bin" 关键字和 .rs 文件
505
+ if top_mod not in ("mod", "bin") and not top_mod.endswith(".rs"):
506
+ self.ensure_top_level_pub_mod(top_mod)
507
+ PrettyOutput.auto_print(
508
+ f"📋 [c2rust-transpiler][mod] 已在 src/lib.rs 确保顶层 pub mod {top_mod}"
509
+ )
510
+ cur = self.progress.get("current") or {}
511
+ cur["mod_chain_fixed"] = True
512
+ cur["mod_visibility_fixed"] = True
513
+ self.progress["current"] = cur
514
+ self.save_progress()
515
+ except Exception:
516
+ pass