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,394 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ 模块和签名规划模块
4
+ """
5
+
6
+ import json
7
+ from pathlib import Path
8
+ from typing import Any
9
+ from typing import Dict
10
+ from typing import List
11
+ from typing import Optional
12
+ from typing import Tuple
13
+
14
+ from jarvis.jarvis_agent import Agent
15
+ from jarvis.jarvis_utils.output import PrettyOutput
16
+ from jarvis.jarvis_agent.events import AFTER_TOOL_CALL
17
+ from jarvis.jarvis_agent.events import BEFORE_TOOL_CALL
18
+ from jarvis.jarvis_c2rust.models import FnRecord
19
+ from jarvis.jarvis_c2rust.utils import dir_tree
20
+ from jarvis.jarvis_c2rust.utils import extract_json_from_summary
21
+
22
+
23
+ class PlanningManager:
24
+ """模块和签名规划管理器"""
25
+
26
+ def __init__(
27
+ self,
28
+ project_root: Path,
29
+ crate_dir: Path,
30
+ data_dir: Path,
31
+ llm_group: Optional[str],
32
+ plan_max_retries: int,
33
+ non_interactive: bool,
34
+ disabled_libraries: List[str],
35
+ root_symbols: List[str],
36
+ extract_compile_flags_func,
37
+ collect_callees_context_func,
38
+ append_additional_notes_func,
39
+ is_root_symbol_func,
40
+ get_crate_commit_hash_func,
41
+ on_before_tool_call_func,
42
+ on_after_tool_call_func,
43
+ agent_before_commits: Dict[str, Optional[str]],
44
+ ) -> None:
45
+ self.project_root = project_root
46
+ self.crate_dir = crate_dir
47
+ self.data_dir = data_dir
48
+ self.llm_group = llm_group
49
+ self.plan_max_retries = plan_max_retries
50
+ self.non_interactive = non_interactive
51
+ self.disabled_libraries = disabled_libraries
52
+ self.root_symbols = root_symbols
53
+ self.extract_compile_flags = extract_compile_flags_func
54
+ self.collect_callees_context = collect_callees_context_func
55
+ self.append_additional_notes = append_additional_notes_func
56
+ self.is_root_symbol = is_root_symbol_func
57
+ self.get_crate_commit_hash = get_crate_commit_hash_func
58
+ self.on_before_tool_call = on_before_tool_call_func
59
+ self.on_after_tool_call = on_after_tool_call_func
60
+ self.agent_before_commits = agent_before_commits
61
+
62
+ def build_module_selection_prompts(
63
+ self,
64
+ rec: FnRecord,
65
+ c_code: str,
66
+ callees_ctx: List[Dict[str, Any]],
67
+ crate_tree: str,
68
+ ) -> Tuple[str, str, str]:
69
+ """
70
+ 返回 (system_prompt, user_prompt, summary_prompt)
71
+ 要求 summary 输出 JSON:
72
+ {
73
+ "module": "src/<path>.rs or module path (e.g., src/foo/mod.rs or src/foo/bar.rs)",
74
+ "rust_signature": "pub fn ...",
75
+ "notes": "optional"
76
+ }
77
+ """
78
+ is_root = self.is_root_symbol(rec)
79
+ system_prompt = (
80
+ "你是资深Rust工程师,擅长为C/C++函数选择合适的Rust模块位置并产出对应的Rust函数签名。\n"
81
+ "目标:根据提供的C源码、调用者上下文与crate目录结构,为该函数选择合适的Rust模块文件并给出Rust函数签名(不实现)。\n"
82
+ "原则:\n"
83
+ "- 按功能内聚与依赖方向选择模块,避免循环依赖;\n"
84
+ "- 模块路径必须落在 crate 的 src/ 下,优先放置到已存在的模块中;必要时可建议创建新的子模块文件;\n"
85
+ "- 函数接口设计应遵循 Rust 最佳实践,不需要兼容 C 的数据类型;优先使用 Rust 原生类型(如 i32/u32/usize、&[T]/&mut [T]、String、Result<T, E> 等),而不是 C 风格类型(如 core::ffi::c_*、libc::c_*);\n"
86
+ '- 禁止使用 extern "C";函数应使用标准的 Rust 调用约定,不需要 C ABI;\n'
87
+ "- 参数个数与顺序可以保持与 C 一致,但类型设计应优先考虑 Rust 的惯用法和安全性;\n"
88
+ + (
89
+ "- **根符号要求**:此函数是根符号,必须使用 `pub` 关键字对外暴露,确保可以从 crate 外部访问。同时,该函数所在的模块必须在 src/lib.rs 中被导出(使用 `pub mod <模块名>;`)。\n"
90
+ if is_root
91
+ else ""
92
+ )
93
+ + "- **评估是否需要实现**:在规划阶段,请评估此函数是否真的需要实现。以下情况可以跳过实现(设置 skip_implementation 为 true),但**必须确保功能一致性**:\n"
94
+ + " * **已实现的函数**:如果函数已经在目标模块(module)中实现,可以使用 read_code 工具检查目标文件,确认函数已存在且**功能与 C 实现一致**,则无需重复实现。**重要**:如果已实现的函数功能不一致(如参数处理不同、返回值不同、行为不同等),则不能跳过,需要重新实现或修正\n"
95
+ + " * **资源释放类函数**:如文件关闭 fclose、内存释放 free、句柄释放、锁释放等,在 Rust 中通常通过 RAII(Drop trait)自动管理,无需显式实现\n"
96
+ + " * **已被库替代**:如果函数已被标准库或第三方 crate 替代(lib_replacement 字段已设置),且**库的功能与 C 实现完全一致**,不需要兼容层,可以跳过实现。**重要**:如果库的功能与 C 实现不一致(如 API 行为不同、参数要求不同、返回值不同等),则需要实现兼容层或重新实现,不能跳过\n"
97
+ + " * **空实现或无意义函数**:如果 C 函数本身是空实现、简单返回常量、或仅用于兼容性占位,在 Rust 中可能不需要实现\n"
98
+ + " * **内联函数或宏**:如果函数在 C 中是内联函数或宏,在 Rust 中可能不需要单独实现\n"
99
+ + " * **其他不需要实现的情况**:根据具体情况判断,如果函数在 Rust 转译中确实不需要实现,可以跳过\n"
100
+ + " * **功能一致性检查原则**:在判断是否跳过实现时,必须仔细对比 C 实现与 Rust 实现(或库替代)的功能一致性,包括但不限于:输入参数处理、返回值、副作用、错误处理、边界条件处理等。如果存在任何不一致,则不能跳过实现\n"
101
+ + " * 如果设置 skip_implementation 为 true,请在 notes 字段中详细说明原因,并确认已进行功能一致性检查\n"
102
+ + "- 仅输出必要信息,避免冗余解释。"
103
+ )
104
+ # 提取编译参数
105
+ compile_flags = self.extract_compile_flags(rec.file)
106
+ compile_flags_section = ""
107
+ if compile_flags:
108
+ compile_flags_section = "\n".join(
109
+ [
110
+ "",
111
+ "C文件编译参数(来自 compile_commands.json):",
112
+ compile_flags,
113
+ ]
114
+ )
115
+
116
+ user_prompt = "\n".join(
117
+ [
118
+ "请阅读以下上下文并准备总结:",
119
+ f"- 函数标识: id={rec.id}, name={rec.name}, qualified={rec.qname}",
120
+ f"- 源文件位置: {rec.file}:{rec.start_line}-{rec.end_line}",
121
+ f"- crate 根目录路径: {self.crate_dir.resolve()}",
122
+ "",
123
+ "C函数源码片段:",
124
+ "<C_SOURCE>",
125
+ c_code,
126
+ "</C_SOURCE>",
127
+ "",
128
+ "符号表签名与参数(只读参考):",
129
+ json.dumps(
130
+ {
131
+ "signature": getattr(rec, "signature", ""),
132
+ "params": getattr(rec, "params", None),
133
+ },
134
+ ensure_ascii=False,
135
+ indent=2,
136
+ ),
137
+ "",
138
+ "被引用符号上下文(如已转译则包含Rust模块信息):",
139
+ json.dumps(callees_ctx, ensure_ascii=False, indent=2),
140
+ "",
141
+ "库替代上下文(若存在):",
142
+ json.dumps(
143
+ getattr(rec, "lib_replacement", None), ensure_ascii=False, indent=2
144
+ ),
145
+ compile_flags_section,
146
+ "",
147
+ *(
148
+ [
149
+ f"禁用库列表(禁止在实现中使用这些库):{', '.join(self.disabled_libraries)}"
150
+ ]
151
+ if self.disabled_libraries
152
+ else []
153
+ ),
154
+ *([""] if self.disabled_libraries else []),
155
+ "当前crate目录结构(部分):",
156
+ "<CRATE_TREE>",
157
+ crate_tree,
158
+ "</CRATE_TREE>",
159
+ "",
160
+ "为避免完整读取体积较大的符号表,你也可以使用工具 read_symbols 按需获取指定符号记录:",
161
+ "- 工具: read_symbols",
162
+ "- 参数示例(JSON):",
163
+ f' {{"symbols_file": "{(self.data_dir / "symbols.jsonl").resolve()}", "symbols": ["符号1", "符号2"]}}',
164
+ "",
165
+ "**重要:检查函数是否已实现及功能一致性**",
166
+ "在确定目标模块(module)后,请使用 read_code 工具检查该模块文件,确认函数是否已经实现:",
167
+ "- 工具: read_code",
168
+ "- 参数示例(JSON):",
169
+ ' {"file_path": "<目标模块路径>"}',
170
+ '- 如果函数已经在目标模块中实现,**必须仔细对比 C 实现与 Rust 实现的功能一致性**(包括参数处理、返回值、副作用、错误处理、边界条件等),只有功能完全一致时才能设置 skip_implementation 为 true,并在 notes 中说明 "函数已在目标模块中实现,且功能与 C 实现一致"。如果功能不一致,则不能跳过,需要重新实现或修正',
171
+ "",
172
+ "如果理解完毕,请进入总结阶段。",
173
+ ]
174
+ )
175
+ summary_prompt = (
176
+ "请仅输出一个 <SUMMARY> 块,块内必须且只包含一个 JSON 对象,不得包含其它内容。\n"
177
+ "允许字段(JSON 对象):\n"
178
+ '- "module": "<绝对路径>/src/xxx.rs 或 <绝对路径>/src/xxx/mod.rs;或相对路径 src/xxx.rs / src/xxx/mod.rs"\n'
179
+ '- "rust_signature": "pub fn xxx(...)->..."\n'
180
+ '- "skip_implementation": bool // 可选,如果为 true,表示此函数不需要实现,可以直接标记为已实现\n'
181
+ '- "notes": "可选说明(若有上下文缺失或风险点,请在此列出;如果 skip_implementation 为 true,必须在此说明原因)"\n'
182
+ "注意:\n"
183
+ "- module 必须位于 crate 的 src/ 目录下,接受绝对路径或以 src/ 开头的相对路径;尽量选择已有文件;如需新建文件,给出合理路径;\n"
184
+ "- rust_signature 应遵循 Rust 最佳实践,不需要兼容 C 的数据类型;优先使用 Rust 原生类型和惯用法,而不是 C 风格类型。\n"
185
+ "- **评估是否需要实现**:请仔细评估此函数是否真的需要实现。以下情况可以设置 skip_implementation 为 true,但**必须确保功能一致性**:\n"
186
+ + " * **已实现的函数**:如果函数已经在目标模块(module)中实现,可以使用 read_code 工具检查目标文件,确认函数已存在且**功能与 C 实现一致**,则无需重复实现。**重要**:如果已实现的函数功能不一致(如参数处理不同、返回值不同、行为不同等),则不能跳过,需要重新实现或修正\n"
187
+ + " * **资源释放类函数**:如文件关闭 fclose、内存释放 free、句柄释放、锁释放等,在 Rust 中通常通过 RAII(Drop trait)自动管理,无需显式实现\n"
188
+ + " * **已被库替代**:如果函数已被标准库或第三方 crate 替代(lib_replacement 字段已设置),且**库的功能与 C 实现完全一致**,不需要兼容层,可以跳过实现。**重要**:如果库的功能与 C 实现不一致(如 API 行为不同、参数要求不同、返回值不同等),则需要实现兼容层或重新实现,不能跳过\n"
189
+ + " * **空实现或无意义函数**:如果 C 函数本身是空实现、简单返回常量、或仅用于兼容性占位,在 Rust 中可能不需要实现\n"
190
+ + " * **内联函数或宏**:如果函数在 C 中是内联函数或宏,在 Rust 中可能不需要单独实现\n"
191
+ + " * **其他不需要实现的情况**:根据具体情况判断,如果函数在 Rust 转译中确实不需要实现,可以跳过\n"
192
+ + " * **功能一致性检查原则**:在判断是否跳过实现时,必须仔细对比 C 实现与 Rust 实现(或库替代)的功能一致性,包括但不限于:输入参数处理、返回值、副作用、错误处理、边界条件处理等。如果存在任何不一致,则不能跳过实现\n"
193
+ + " * **重要**:如果设置 skip_implementation 为 true,必须在 notes 字段中详细说明原因,并确认已进行功能一致性检查,例如:\n"
194
+ + ' - "函数已在目标模块中实现,且功能与 C 实现一致"\n'
195
+ + ' - "通过 RAII 自动管理,无需显式实现"\n'
196
+ + ' - "已被标准库 std::xxx 替代,且功能完全一致,无需实现"\n'
197
+ + ' - "空实现函数,在 Rust 中不需要"\n'
198
+ + ' - "内联函数,已在调用处展开,无需单独实现"\n'
199
+ + "- 如果函数确实需要实现,或功能不一致需要修正,则不要设置 skip_implementation 或设置为 false\n"
200
+ + "- 类型设计原则:\n"
201
+ + " * 基本类型:优先使用 i32/u32/i64/u64/isize/usize/f32/f64 等原生 Rust 类型,而不是 core::ffi::c_* 或 libc::c_*;\n"
202
+ + " * 指针/引用:优先使用引用 &T/&mut T 或切片 &[T]/&mut [T],而非原始指针 *const T/*mut T;仅在必要时使用原始指针;\n"
203
+ + " * 字符串:优先使用 String、&str 而非 *const c_char/*mut c_char;\n"
204
+ + " * 错误处理:考虑使用 Result<T, E> 而非 C 风格的错误码;\n"
205
+ + " * 参数个数与顺序可以保持与 C 一致,但类型应优先考虑 Rust 的惯用法、安全性和可读性;\n"
206
+ + (
207
+ "- **根符号要求**:此函数是根符号,rust_signature 必须包含 `pub` 关键字,确保可以从 crate 外部访问。同时,该函数所在的模块必须在 src/lib.rs 中被导出(使用 `pub mod <模块名>;`)。\n"
208
+ if is_root
209
+ else ""
210
+ )
211
+ + "- 函数签名应包含可见性修饰(pub)与函数名;类型应为 Rust 最佳实践的选择,而非简单映射 C 类型。\n"
212
+ + '- 禁止使用 extern "C";函数应使用标准的 Rust 调用约定,不需要 C ABI。\n'
213
+ + "请严格按以下格式输出(JSON格式,支持jsonnet语法如尾随逗号、注释、|||分隔符多行字符串等):\n"
214
+ + "示例1(正常函数):\n"
215
+ + '<SUMMARY>\n{\n "module": "...",\n "rust_signature": "...",\n "notes": "..."\n}\n</SUMMARY>\n'
216
+ + "示例2(已实现的函数,且功能一致,可跳过实现):\n"
217
+ + '<SUMMARY>\n{\n "module": "...",\n "rust_signature": "...",\n "skip_implementation": true,\n "notes": "函数已在目标模块中实现,且功能与 C 实现一致(参数处理、返回值、副作用均一致)"\n}\n</SUMMARY>\n'
218
+ + "示例3(不需要实现的函数,可跳过实现):\n"
219
+ + '<SUMMARY>\n{\n "module": "...",\n "rust_signature": "...",\n "skip_implementation": true,\n "notes": "通过 RAII 自动管理,无需显式实现"\n}\n</SUMMARY>\n'
220
+ + "示例4(已被库替代,且功能一致,可跳过实现):\n"
221
+ + '<SUMMARY>\n{\n "module": "...",\n "rust_signature": "...",\n "skip_implementation": true,\n "notes": "已被标准库 std::xxx 替代,且功能与 C 实现完全一致(API 行为、参数要求、返回值均一致),无需实现"\n}\n</SUMMARY>\n'
222
+ + "示例5(空实现函数,可跳过实现):\n"
223
+ + '<SUMMARY>\n{\n "module": "...",\n "rust_signature": "...",\n "skip_implementation": true,\n "notes": "C 函数为空实现,在 Rust 中不需要"\n}\n</SUMMARY>'
224
+ )
225
+ # 在 user_prompt 和 summary_prompt 中追加附加说明(system_prompt 通常不需要)
226
+ user_prompt = self.append_additional_notes(user_prompt)
227
+ summary_prompt = self.append_additional_notes(summary_prompt)
228
+ return system_prompt, user_prompt, summary_prompt
229
+
230
+ def plan_module_and_signature(
231
+ self, rec: FnRecord, c_code: str
232
+ ) -> Tuple[str, str, bool]:
233
+ """调用 Agent 选择模块与签名,返回 (module_path, rust_signature, skip_implementation),若格式不满足将自动重试直到满足"""
234
+ crate_tree = dir_tree(self.crate_dir)
235
+ callees_ctx = self.collect_callees_context(rec)
236
+ sys_p, usr_p, base_sum_p = self.build_module_selection_prompts(
237
+ rec, c_code, callees_ctx, crate_tree
238
+ )
239
+
240
+ def _validate(meta: Any) -> Tuple[bool, str]:
241
+ """基本格式检查,仅验证字段存在性,不做硬编码规则校验"""
242
+ if not isinstance(meta, dict) or not meta:
243
+ return False, "未解析到有效的 <SUMMARY> 中的 JSON 对象"
244
+ module = meta.get("module")
245
+ rust_sig = meta.get("rust_signature")
246
+ if not isinstance(module, str) or not module.strip():
247
+ return False, "缺少必填字段 module"
248
+ if not isinstance(rust_sig, str) or not rust_sig.strip():
249
+ return False, "缺少必填字段 rust_signature"
250
+ # 路径归一化:容忍相对/简略路径,最终归一为 crate_dir 下的绝对路径(不做硬编码校验)
251
+ try:
252
+ raw = str(module).strip().replace("\\", "/")
253
+ crate_root = self.crate_dir.resolve()
254
+ mp: Path
255
+ p = Path(raw)
256
+ if p.is_absolute():
257
+ mp = p.resolve()
258
+ else:
259
+ # 规范化相对路径:若不以 src/ 开头,自动补全为 src/<raw>
260
+ if raw.startswith("./"):
261
+ raw = raw[2:]
262
+ if not raw.startswith("src/"):
263
+ raw = f"src/{raw}"
264
+ mp = (crate_root / raw).resolve()
265
+ # 将归一化后的绝对路径回写到 meta,避免后续流程二次解析歧义
266
+ meta["module"] = str(mp)
267
+ except Exception:
268
+ # 路径归一化失败不影响,保留原始值
269
+ pass
270
+ return True, ""
271
+
272
+ def _retry_sum_prompt(reason: str) -> str:
273
+ return (
274
+ base_sum_p
275
+ + "\n\n[格式检查失败,必须重试]\n"
276
+ + f"- 失败原因:{reason}\n"
277
+ + "- 仅输出一个 <SUMMARY> 块;块内直接包含 JSON 对象(不需要额外的标签);\n"
278
+ + "- JSON 对象必须包含字段:module、rust_signature。\n"
279
+ )
280
+
281
+ attempt = 0
282
+ last_reason = "未知错误"
283
+ plan_max_retries_val = self.plan_max_retries
284
+ # 如果 plan_max_retries 为 0,表示无限重试
285
+ use_direct_model = False # 标记是否使用直接模型调用
286
+ agent = None # 在循环外声明,以便重试时复用
287
+
288
+ # 注意:Agent 必须在 crate 根目录下创建,以确保工具(如 read_symbols)能正确获取符号表
289
+ # 由于 transpile() 开始时已切换到 crate 目录,此处无需再次切换
290
+ while plan_max_retries_val == 0 or attempt < plan_max_retries_val:
291
+ attempt += 1
292
+ sum_p = base_sum_p if attempt == 1 else _retry_sum_prompt(last_reason)
293
+
294
+ # 第一次创建 Agent,后续重试时复用(如果使用直接模型调用)
295
+ # 注意:Agent 必须在 crate 根目录下创建,以确保工具(如 read_symbols)能正确获取符号表
296
+ if agent is None or not use_direct_model:
297
+ # 获取函数信息用于 Agent name
298
+ fn_name = rec.qname or rec.name or f"fn_{rec.id}"
299
+ agent_name = f"C2Rust-Function-Planner({fn_name})"
300
+ agent = Agent(
301
+ system_prompt=sys_p,
302
+ name=agent_name,
303
+ model_group=self.llm_group,
304
+ summary_prompt=sum_p,
305
+ need_summary=True,
306
+ auto_complete=True,
307
+ use_tools=["execute_script", "read_code", "read_symbols"],
308
+ non_interactive=self.non_interactive,
309
+ use_methodology=False,
310
+ use_analysis=False,
311
+ )
312
+ # 订阅 BEFORE_TOOL_CALL 和 AFTER_TOOL_CALL 事件,用于细粒度检测测试代码删除
313
+ agent.event_bus.subscribe(BEFORE_TOOL_CALL, self.on_before_tool_call)
314
+ agent.event_bus.subscribe(AFTER_TOOL_CALL, self.on_after_tool_call)
315
+ # 记录 Agent 创建时的 commit id(作为初始值)
316
+ agent_id = id(agent)
317
+ agent_key = f"agent_{agent_id}"
318
+ initial_commit = self.get_crate_commit_hash()
319
+ if initial_commit:
320
+ self.agent_before_commits[agent_key] = initial_commit
321
+
322
+ if use_direct_model:
323
+ # 格式校验失败后,直接调用模型接口
324
+ # 构造包含摘要提示词和具体错误信息的完整提示
325
+ error_guidance = ""
326
+ if last_reason and last_reason != "未知错误":
327
+ if "JSON解析失败" in last_reason:
328
+ error_guidance = f"\n\n**格式错误详情(请根据以下错误修复输出格式):**\n- {last_reason}\n\n请确保输出的JSON格式正确,包括正确的引号、逗号、大括号等。JSON 对象必须包含字段:module(字符串)、rust_signature(字符串)。支持jsonnet语法(如尾随逗号、注释、||| 或 ``` 分隔符多行字符串等)。"
329
+ else:
330
+ error_guidance = f"\n\n**格式错误详情(请根据以下错误修复输出格式):**\n- {last_reason}\n\n请确保输出格式正确:仅输出一个 <SUMMARY> 块,块内直接包含 JSON 对象(不需要额外的标签);JSON 对象必须包含字段:module(字符串)、rust_signature(字符串)。支持jsonnet语法(如尾随逗号、注释、||| 或 ``` 分隔符多行字符串等)。"
331
+
332
+ full_prompt = f"{usr_p}{error_guidance}\n\n{sum_p}"
333
+ try:
334
+ response = agent.model.chat_until_success(full_prompt)
335
+ summary = response
336
+ except Exception as e:
337
+ PrettyOutput.auto_print(
338
+ f"⚠️ [c2rust-transpiler][plan] 直接模型调用失败: {e},回退到 run()"
339
+ )
340
+ summary = agent.run(usr_p)
341
+ else:
342
+ # 第一次使用 run(),让 Agent 完整运行(可能使用工具)
343
+ summary = agent.run(usr_p)
344
+
345
+ meta, parse_error = extract_json_from_summary(str(summary or ""))
346
+ if parse_error:
347
+ # JSON解析失败,将错误信息反馈给模型
348
+ PrettyOutput.auto_print(
349
+ f"⚠️ [c2rust-transpiler][plan] JSON解析失败: {parse_error}"
350
+ )
351
+ last_reason = f"JSON解析失败: {parse_error}"
352
+ use_direct_model = True
353
+ # 解析失败,继续重试
354
+ continue
355
+ else:
356
+ ok, reason = _validate(meta)
357
+ if ok:
358
+ module = str(meta.get("module") or "").strip()
359
+ rust_sig = str(meta.get("rust_signature") or "").strip()
360
+ skip_impl = bool(meta.get("skip_implementation") is True)
361
+ if skip_impl:
362
+ notes = str(meta.get("notes") or "")
363
+ PrettyOutput.auto_print(
364
+ f"✅ [c2rust-transpiler][plan] 第 {attempt} 次尝试成功: 模块={module}, 签名={rust_sig}, 跳过实现={skip_impl}"
365
+ )
366
+ if notes:
367
+ PrettyOutput.auto_print(
368
+ f"ℹ️ [c2rust-transpiler][plan] 跳过实现原因: {notes}"
369
+ )
370
+ else:
371
+ PrettyOutput.auto_print(
372
+ f"✅ [c2rust-transpiler][plan] 第 {attempt} 次尝试成功: 模块={module}, 签名={rust_sig}"
373
+ )
374
+ return module, rust_sig, skip_impl
375
+ else:
376
+ PrettyOutput.auto_print(
377
+ f"⚠️ [c2rust-transpiler][plan] 第 {attempt} 次尝试失败: {reason}"
378
+ )
379
+ last_reason = reason
380
+ # 格式校验失败,后续重试使用直接模型调用
381
+ use_direct_model = True
382
+
383
+ # 规划超出重试上限:回退到兜底方案(默认模块 src/ffi.rs + 简单占位签名)
384
+ # 注意:如果 plan_max_retries_val == 0(无限重试),理论上不应该到达这里
385
+ try:
386
+ crate_root = self.crate_dir.resolve()
387
+ fallback_module = str((crate_root / "src" / "ffi.rs").resolve())
388
+ except Exception:
389
+ fallback_module = "src/ffi.rs"
390
+ fallback_sig = f"pub fn {rec.name or ('fn_' + str(rec.id))}()"
391
+ PrettyOutput.auto_print(
392
+ f"⚠️ [c2rust-transpiler][plan] 超出规划重试上限({plan_max_retries_val if plan_max_retries_val > 0 else '无限'}),回退到兜底: module={fallback_module}, signature={fallback_sig}"
393
+ )
394
+ return fallback_module, fallback_sig, False