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,503 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ Agent 管理模块
4
+ """
5
+
6
+ import json
7
+ import time
8
+ from pathlib import Path
9
+ from typing import Any
10
+ from typing import Dict
11
+ from typing import Optional
12
+
13
+ from jarvis.jarvis_utils.output import PrettyOutput
14
+
15
+ from jarvis.jarvis_agent.events import AFTER_TOOL_CALL
16
+ from jarvis.jarvis_agent.events import BEFORE_TOOL_CALL
17
+ from jarvis.jarvis_c2rust.models import FnRecord
18
+ from jarvis.jarvis_c2rust.utils import dir_tree
19
+ from jarvis.jarvis_code_agent.code_agent import CodeAgent
20
+
21
+
22
+ class AgentManager:
23
+ """Agent 管理器"""
24
+
25
+ def __init__(
26
+ self,
27
+ crate_dir: Path,
28
+ project_root: Path,
29
+ llm_group: Optional[str],
30
+ non_interactive: bool,
31
+ fn_index_by_id: Dict[int, FnRecord],
32
+ get_crate_commit_hash_func,
33
+ agent_before_commits: Dict[str, Optional[str]],
34
+ ) -> None:
35
+ self.crate_dir = crate_dir
36
+ self.project_root = project_root
37
+ self.llm_group = llm_group
38
+ self.non_interactive = non_interactive
39
+ self.fn_index_by_id = fn_index_by_id
40
+ self.get_crate_commit_hash = get_crate_commit_hash_func
41
+ self.agent_before_commits = agent_before_commits
42
+ self._current_function_id: Optional[int] = None
43
+ self._current_context_full_header: str = ""
44
+ self._current_context_compact_header: str = ""
45
+ self._current_context_full_sent: bool = False
46
+ # 存储当前函数的 C 代码,供修复 Agent 使用
47
+ self._current_c_code: str = ""
48
+
49
+ def get_generation_agent(self) -> CodeAgent:
50
+ """
51
+ 获取代码生成Agent(CodeAgent)。每次调用都重新创建,不复用。
52
+ 用于代码生成。
53
+ 注意:Agent 必须在 crate 根目录下创建,以确保工具(如 read_symbols)能正确获取符号表。
54
+ 提示:代码生成遵循 TDD(测试驱动开发)方法,通过提示词指导 Agent 先写测试再写实现。
55
+ """
56
+ fid = self._current_function_id
57
+ # 注意:Agent 必须在 crate 根目录下创建,以确保工具(如 read_symbols)能正确获取符号表
58
+ # 由于 transpile() 开始时已切换到 crate 目录,此处无需再次切换
59
+ # 统一启用方法论和分析功能,提供更好的代码生成能力
60
+ # 获取函数信息用于 Agent name
61
+ fn_name = ""
62
+ if fid is not None:
63
+ rec = self.fn_index_by_id.get(fid)
64
+ if rec:
65
+ fn_name = rec.qname or rec.name or f"fn_{fid}"
66
+ agent_name = "C2Rust-GenerationAgent" + (f"({fn_name})" if fn_name else "")
67
+ agent = CodeAgent(
68
+ name=agent_name,
69
+ need_summary=False,
70
+ non_interactive=self.non_interactive,
71
+ model_group=self.llm_group,
72
+ append_tools="read_symbols,methodology",
73
+ use_methodology=True,
74
+ use_analysis=True,
75
+ force_save_memory=False,
76
+ enable_task_list_manager=False,
77
+ disable_review=True,
78
+ )
79
+ # 订阅 BEFORE_TOOL_CALL 和 AFTER_TOOL_CALL 事件,用于细粒度检测测试代码删除
80
+ agent.event_bus.subscribe(BEFORE_TOOL_CALL, self.on_before_tool_call)
81
+ agent.event_bus.subscribe(AFTER_TOOL_CALL, self.on_after_tool_call)
82
+ # 记录 Agent 创建时的 commit id(作为初始值)
83
+ agent_id = id(agent)
84
+ agent_key = f"agent_{agent_id}"
85
+ initial_commit = self.get_crate_commit_hash()
86
+ if initial_commit:
87
+ self.agent_before_commits[agent_key] = initial_commit
88
+ return agent
89
+
90
+ def get_fix_agent(
91
+ self, c_code: Optional[str] = None, need_summary: bool = False
92
+ ) -> CodeAgent:
93
+ """
94
+ 获取修复Agent(CodeAgent)。每次调用都重新创建,不复用。
95
+ 用于修复构建错误和测试失败,启用方法论和分析功能以提供更好的修复能力。
96
+ 注意:Agent 必须在 crate 根目录下创建,以确保工具(如 read_symbols)能正确获取符号表。
97
+
98
+ 参数:
99
+ c_code: 原 C 实现的代码,将添加到 Agent 的上下文中
100
+ need_summary: 是否需要生成总结,默认为 False(构建修复阶段不需要总结)
101
+ """
102
+ # 每次重新创建,不复用
103
+ # 获取函数信息用于 Agent name
104
+ fn_name = ""
105
+ if self._current_function_id is not None:
106
+ rec = self.fn_index_by_id.get(self._current_function_id)
107
+ if rec:
108
+ fn_name = rec.qname or rec.name or f"fn_{self._current_function_id}"
109
+
110
+ # 使用当前 C 代码(如果提供了参数则使用参数,否则使用缓存的)
111
+ current_c_code = c_code if c_code is not None else self._current_c_code
112
+
113
+ agent_name = "C2Rust-FixAgent" + (f"({fn_name})" if fn_name else "")
114
+
115
+ # 只有在需要总结时才设置 summary_prompt
116
+ summary_prompt = None
117
+ if need_summary:
118
+ summary_prompt = """请总结本次修复的流程和结果。总结应包含以下内容:
119
+ 1. **修复流程**:
120
+ - 遇到的问题类型(编译错误、测试失败、警告等)
121
+ - 问题定位过程(如何找到问题根源)
122
+ - 修复步骤(具体做了哪些修改)
123
+ - 使用的工具和方法
124
+ 2. **修复结果**:
125
+ - 修复是否成功
126
+ - 修复了哪些问题
127
+ - 修改了哪些文件
128
+ - 是否引入了新的问题
129
+ - 验证结果(编译、测试是否通过)
130
+ 3. **注意事项**:
131
+ - 如果修复过程中遇到困难,说明原因
132
+ - 如果修复不完整,说明遗留问题
133
+ - 如果修复可能影响其他代码,说明影响范围
134
+
135
+ 请使用清晰的结构和简洁的语言,确保总结信息完整且易于理解。"""
136
+
137
+ agent = CodeAgent(
138
+ name=agent_name,
139
+ need_summary=need_summary,
140
+ summary_prompt=summary_prompt,
141
+ non_interactive=self.non_interactive,
142
+ model_group=self.llm_group,
143
+ append_tools="read_symbols,methodology",
144
+ use_methodology=True,
145
+ use_analysis=True,
146
+ force_save_memory=False,
147
+ disable_review=True,
148
+ )
149
+ # 订阅 BEFORE_TOOL_CALL 和 AFTER_TOOL_CALL 事件,用于细粒度检测测试代码删除
150
+ agent.event_bus.subscribe(BEFORE_TOOL_CALL, self.on_before_tool_call)
151
+ agent.event_bus.subscribe(AFTER_TOOL_CALL, self.on_after_tool_call)
152
+ # 记录 Agent 创建时的 commit id(作为初始值)
153
+ agent_id = id(agent)
154
+ agent_key = f"agent_{agent_id}"
155
+ initial_commit = self.get_crate_commit_hash()
156
+ if initial_commit:
157
+ self.agent_before_commits[agent_key] = initial_commit
158
+
159
+ # 为修复 Agent 添加包含原 C 代码的上下文
160
+ if current_c_code:
161
+ # 在 Agent 的 session 中添加 C 代码上下文
162
+ if hasattr(agent, "session") and hasattr(agent.session, "prompt"):
163
+ c_code_context = (
164
+ "\n\n【原始 C 实现代码(修复参考)】\n"
165
+ "以下是当前函数对应的原始 C 实现代码,修复时请参考:\n"
166
+ "<C_SOURCE>\n"
167
+ f"{current_c_code}\n"
168
+ "</C_SOURCE>\n"
169
+ )
170
+ agent.session.prompt = c_code_context + agent.session.prompt
171
+
172
+ return agent
173
+
174
+ def get_code_agent(self) -> CodeAgent:
175
+ """
176
+ 获取代码生成/修复Agent(CodeAgent)。每次调用都重新创建,不复用。
177
+ 统一用于代码生成和修复,启用方法论和分析功能以提供更好的代码质量。
178
+ 注意:Agent 必须在 crate 根目录下创建,以确保工具(如 read_symbols)能正确获取符号表。
179
+ 提示:代码生成遵循 TDD(测试驱动开发)方法,通过提示词指导 Agent 先写测试再写实现。
180
+ """
181
+ fid = self._current_function_id
182
+ # 注意:Agent 必须在 crate 根目录下创建,以确保工具(如 read_symbols)能正确获取符号表
183
+ # 由于 transpile() 开始时已切换到 crate 目录,此处无需再次切换
184
+ # 统一启用方法论和分析功能,提供更好的代码生成和修复能力
185
+ # 获取函数信息用于 Agent name
186
+ fn_name = ""
187
+ if fid is not None:
188
+ rec = self.fn_index_by_id.get(fid)
189
+ if rec:
190
+ fn_name = rec.qname or rec.name or f"fn_{fid}"
191
+ agent_name = "C2Rust-CodeAgent" + (f"({fn_name})" if fn_name else "")
192
+ agent = CodeAgent(
193
+ name=agent_name,
194
+ need_summary=False,
195
+ non_interactive=self.non_interactive,
196
+ model_group=self.llm_group,
197
+ append_tools="read_symbols,methodology",
198
+ use_methodology=True,
199
+ use_analysis=True,
200
+ force_save_memory=False,
201
+ enable_task_list_manager=False,
202
+ disable_review=True,
203
+ )
204
+ # 订阅 BEFORE_TOOL_CALL 和 AFTER_TOOL_CALL 事件,用于细粒度检测测试代码删除
205
+ agent.event_bus.subscribe(BEFORE_TOOL_CALL, self.on_before_tool_call)
206
+ agent.event_bus.subscribe(AFTER_TOOL_CALL, self.on_after_tool_call)
207
+ # 记录 Agent 创建时的 commit id(作为初始值)
208
+ agent_id = id(agent)
209
+ agent_key = f"agent_{agent_id}"
210
+ initial_commit = self.get_crate_commit_hash()
211
+ if initial_commit:
212
+ self.agent_before_commits[agent_key] = initial_commit
213
+ return agent
214
+
215
+ def compose_prompt_with_context(self, prompt: str, for_fix: bool = False) -> str:
216
+ """
217
+ 在复用Agent时,将此前构建的函数上下文头部拼接到当前提示词前,确保连续性。
218
+ 策略:
219
+ - 每个函数生命周期内,首次调用拼接"全量头部";
220
+ - 后续调用仅拼接"精简头部";
221
+ - 如头部缺失则直接返回原提示。
222
+
223
+ 参数:
224
+ for_fix: 如果为 True,表示这是用于修复 Agent 的提示词,会在上下文中添加原 C 代码
225
+ """
226
+ # 如果是修复 Agent,添加原 C 代码上下文
227
+ if for_fix and self._current_c_code:
228
+ c_code_header = (
229
+ "\n【原始 C 实现代码(修复参考)】\n"
230
+ "以下是当前函数对应的原始 C 实现代码,修复时请参考:\n"
231
+ "<C_SOURCE>\n"
232
+ f"{self._current_c_code}\n"
233
+ "</C_SOURCE>\n"
234
+ )
235
+ # 首次发送全量上下文
236
+ if (
237
+ not self._current_context_full_sent
238
+ ) and self._current_context_full_header:
239
+ self._current_context_full_sent = True
240
+ return (
241
+ self._current_context_full_header + c_code_header + "\n\n" + prompt
242
+ )
243
+ # 后续拼接精简上下文
244
+ if self._current_context_compact_header:
245
+ return (
246
+ self._current_context_compact_header
247
+ + c_code_header
248
+ + "\n\n"
249
+ + prompt
250
+ )
251
+ return c_code_header + "\n\n" + prompt
252
+
253
+ # 首次发送全量上下文
254
+ if (not self._current_context_full_sent) and self._current_context_full_header:
255
+ self._current_context_full_sent = True
256
+ return self._current_context_full_header + "\n\n" + prompt
257
+ # 后续拼接精简上下文
258
+ if self._current_context_compact_header:
259
+ return self._current_context_compact_header + "\n\n" + prompt
260
+ return prompt
261
+
262
+ def reset_function_context(
263
+ self,
264
+ rec: FnRecord,
265
+ module: str,
266
+ rust_sig: str,
267
+ c_code: str,
268
+ collect_callees_context_func,
269
+ extract_compile_flags_func,
270
+ ) -> None:
271
+ """
272
+ 初始化当前函数的上下文。
273
+ 在单个函数实现开始时调用一次。
274
+ 注意:所有 Agent 每次调用都重新创建,不复用。
275
+ """
276
+ self._current_function_id = rec.id
277
+ # 保存当前函数的 C 代码,供修复 Agent 使用
278
+ self._current_c_code = c_code or ""
279
+
280
+ # 汇总上下文头部,供后续复用时拼接
281
+ callees_ctx = collect_callees_context_func(rec)
282
+ crate_tree = dir_tree(self.crate_dir)
283
+ librep_ctx = (
284
+ rec.lib_replacement if isinstance(rec.lib_replacement, dict) else None
285
+ )
286
+ # 提取编译参数
287
+ compile_flags = extract_compile_flags_func(rec.file)
288
+
289
+ header_lines = [
290
+ "【当前函数上下文(复用Agent专用)】",
291
+ f"- 函数: {rec.qname or rec.name} (id={rec.id})",
292
+ f"- 源位置: {rec.file}:{rec.start_line}-{rec.end_line}",
293
+ f"- 原 C 工程目录: {self.project_root.resolve()}",
294
+ f"- 目标模块: {module}",
295
+ f"- 建议/当前签名: {rust_sig}",
296
+ f"- crate 根目录: {self.crate_dir.resolve()}",
297
+ "",
298
+ "原始C函数源码片段(只读参考):",
299
+ "<C_SOURCE>",
300
+ c_code or "",
301
+ "</C_SOURCE>",
302
+ "",
303
+ "被引用符号上下文:",
304
+ json.dumps(callees_ctx, ensure_ascii=False, indent=2),
305
+ "",
306
+ "库替代上下文(若有):",
307
+ json.dumps(librep_ctx, ensure_ascii=False, indent=2),
308
+ ]
309
+ # 添加编译参数(如果存在)
310
+ if compile_flags:
311
+ header_lines.extend(
312
+ [
313
+ "",
314
+ "C文件编译参数(来自 compile_commands.json):",
315
+ compile_flags,
316
+ ]
317
+ )
318
+ header_lines.extend(
319
+ [
320
+ "",
321
+ "crate 目录结构(部分):",
322
+ "<CRATE_TREE>",
323
+ crate_tree,
324
+ "</CRATE_TREE>",
325
+ ]
326
+ )
327
+ # 精简头部(后续复用)
328
+ compact_lines = [
329
+ "【函数上下文简要(复用)】",
330
+ f"- 函数: {rec.qname or rec.name} (id={rec.id})",
331
+ f"- 原 C 工程目录: {self.project_root.resolve()}",
332
+ f"- 模块: {module}",
333
+ f"- 签名: {rust_sig}",
334
+ f"- crate: {self.crate_dir.resolve()}",
335
+ ]
336
+ self._current_context_full_header = "\n".join(header_lines)
337
+ self._current_context_compact_header = "\n".join(compact_lines)
338
+ self._current_context_full_sent = False
339
+
340
+ def refresh_compact_context(
341
+ self, rec: FnRecord, module: str, rust_sig: str
342
+ ) -> None:
343
+ """
344
+ 刷新精简上下文头部(在 sig-fix/ensure-impl 后调用,保证后续提示一致)。
345
+ 仅更新精简头部,不影响已发送的全量头部。
346
+ """
347
+ try:
348
+ compact_lines = [
349
+ "【函数上下文简要(复用)】",
350
+ f"- 函数: {rec.qname or rec.name} (id={rec.id})",
351
+ f"- 模块: {module}",
352
+ f"- 签名: {rust_sig}",
353
+ f"- crate: {self.crate_dir.resolve()}",
354
+ ]
355
+ self._current_context_compact_header = "\n".join(compact_lines)
356
+ except Exception:
357
+ pass
358
+
359
+ def on_before_tool_call(self, agent: Any, current_response=None, **kwargs) -> None:
360
+ """
361
+ 工具调用前的事件处理器,用于记录工具调用前的 commit id。
362
+
363
+ 在每次工具调用前记录当前的 commit,以便在工具调用后检测到问题时能够回退。
364
+ """
365
+ try:
366
+ # 只关注可能修改代码的工具
367
+ # 注意:在 BEFORE_TOOL_CALL 时,工具还未执行,无法获取工具名称
368
+ # 但我们可以在 AFTER_TOOL_CALL 时检查工具名称,这里先记录 commit
369
+ agent_id = id(agent)
370
+ agent_key = f"agent_{agent_id}"
371
+ current_commit = self.get_crate_commit_hash()
372
+ if current_commit:
373
+ # 记录工具调用前的 commit(如果之前没有记录,或者 commit 已变化)
374
+ if (
375
+ agent_key not in self.agent_before_commits
376
+ or self.agent_before_commits[agent_key] != current_commit
377
+ ):
378
+ self.agent_before_commits[agent_key] = current_commit
379
+ except Exception as e:
380
+ # 事件处理器异常不应影响主流程
381
+ PrettyOutput.auto_print(
382
+ f"⚠️ [c2rust-transpiler][test-detection] BEFORE_TOOL_CALL 事件处理器异常: {e}"
383
+ )
384
+
385
+ def on_after_tool_call(
386
+ self,
387
+ agent: Any,
388
+ current_response=None,
389
+ need_return=None,
390
+ tool_prompt=None,
391
+ **kwargs,
392
+ ) -> None:
393
+ """
394
+ 工具调用后的事件处理器,用于细粒度检测测试代码删除。
395
+
396
+ 在每次工具调用后立即检测,如果检测到测试代码被错误删除,立即回退。
397
+ """
398
+ try:
399
+ # 只检测编辑文件的工具调用
400
+ last_tool = (
401
+ agent.get_user_data("__last_executed_tool__")
402
+ if hasattr(agent, "get_user_data")
403
+ else None
404
+ )
405
+ if not last_tool:
406
+ return
407
+
408
+ # 只关注可能修改代码的工具
409
+ edit_tools = {
410
+ "edit_file",
411
+ "apply_patch",
412
+ }
413
+ if last_tool not in edit_tools:
414
+ return
415
+
416
+ # 获取该 Agent 对应的工具调用前的 commit id
417
+ agent_id = id(agent)
418
+ agent_key = f"agent_{agent_id}"
419
+ before_commit = self.agent_before_commits.get(agent_key)
420
+
421
+ # 如果没有 commit 信息,无法检测
422
+ if not before_commit:
423
+ return
424
+
425
+ # 检测测试代码删除
426
+ from jarvis.jarvis_c2rust.utils import ask_llm_about_test_deletion
427
+ from jarvis.jarvis_c2rust.utils import detect_test_deletion
428
+
429
+ detection_result = detect_test_deletion("[c2rust-transpiler]")
430
+ if not detection_result:
431
+ # 没有检测到删除,更新 commit 记录
432
+ current_commit = self.get_crate_commit_hash()
433
+ if current_commit and current_commit != before_commit:
434
+ self.agent_before_commits[agent_key] = current_commit
435
+ return
436
+
437
+ PrettyOutput.auto_print(
438
+ "⚠️ [c2rust-transpiler][test-detection] 检测到可能错误删除了测试代码标记(工具调用后检测)"
439
+ )
440
+
441
+ # 询问 LLM 是否合理
442
+ need_reset = ask_llm_about_test_deletion(
443
+ detection_result, agent, "[c2rust-transpiler]"
444
+ )
445
+
446
+ if need_reset:
447
+ PrettyOutput.auto_print(
448
+ f"❌ [c2rust-transpiler][test-detection] LLM 确认删除不合理,正在回退到 commit: {before_commit}"
449
+ )
450
+ # 需要调用 reset_to_commit 函数,但这里需要通过回调传递
451
+ # 暂时先记录,由调用方处理
452
+ if hasattr(self, "_reset_to_commit_func"):
453
+ if self._reset_to_commit_func(before_commit):
454
+ PrettyOutput.auto_print(
455
+ "✅ [c2rust-transpiler][test-detection] 已回退到之前的 commit(工具调用后检测)"
456
+ )
457
+ # 回退后,保持之前的 commit 记录
458
+ self.agent_before_commits[agent_key] = before_commit
459
+ # 在 agent 的 session 中添加提示,告知修改被撤销
460
+ if hasattr(agent, "session") and hasattr(
461
+ agent.session, "prompt"
462
+ ):
463
+ agent.session.prompt += "\n\n⚠️ 修改被撤销:检测到测试代码被错误删除,已回退到之前的版本。\n"
464
+ else:
465
+ PrettyOutput.auto_print(
466
+ "❌ [c2rust-transpiler][test-detection] 回退失败"
467
+ )
468
+ else:
469
+ # LLM 认为删除合理,更新 commit 记录
470
+ current_commit = self.get_crate_commit_hash()
471
+ if current_commit and current_commit != before_commit:
472
+ self.agent_before_commits[agent_key] = current_commit
473
+ except Exception as e:
474
+ # 事件处理器异常不应影响主流程
475
+ PrettyOutput.auto_print(
476
+ f"⚠️ [c2rust-transpiler][test-detection] AFTER_TOOL_CALL 事件处理器异常: {e}"
477
+ )
478
+
479
+ def set_reset_to_commit_func(self, reset_func) -> None:
480
+ """设置回退 commit 的函数"""
481
+ self._reset_to_commit_func = reset_func
482
+
483
+ def update_progress_current(
484
+ self,
485
+ rec: FnRecord,
486
+ module: str,
487
+ rust_sig: str,
488
+ progress: Dict[str, Any],
489
+ save_progress_func,
490
+ ) -> None:
491
+ """更新当前进度"""
492
+ progress["current"] = {
493
+ "time": time.strftime("%Y-%m-%dT%H:%M:%S", time.localtime()),
494
+ "id": rec.id,
495
+ "name": rec.name,
496
+ "qualified_name": rec.qname,
497
+ "file": rec.file,
498
+ "start_line": rec.start_line,
499
+ "end_line": rec.end_line,
500
+ "module": module,
501
+ "rust_signature": rust_sig,
502
+ }
503
+ save_progress_func()