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
@@ -1,6 +1,3 @@
1
- #!/usr/bin/env python3
2
- # -*- coding: utf-8 -*-
3
-
4
1
  """
5
2
  Python构建验证器模块
6
3
 
@@ -9,45 +6,76 @@ Python构建验证器模块
9
6
 
10
7
  import os
11
8
  import time
12
- from typing import List, Optional
9
+ from typing import List
10
+
11
+ from jarvis.jarvis_utils.output import PrettyOutput
12
+
13
+ #!/usr/bin/env python3
14
+ # -*- coding: utf-8 -*-
15
+
16
+ from typing import Optional
13
17
 
14
- from .base import BuildValidatorBase, BuildResult, BuildSystem
18
+ from .base import BuildResult
19
+ from .base import BuildSystem
20
+ from .base import BuildValidatorBase
15
21
 
16
22
 
17
23
  class PythonBuildValidator(BuildValidatorBase):
18
24
  """Python构建验证器(包括编译和测试)"""
19
-
25
+
20
26
  BUILD_SYSTEM_NAME = "Python"
21
27
  SUPPORTED_LANGUAGES = ["python"]
22
-
28
+
23
29
  def _extract_python_errors(self, output: str) -> str:
24
30
  """提取Python错误信息(包括编译错误和测试失败)"""
25
31
  if not output:
26
32
  return ""
27
-
33
+
28
34
  lines = output.split("\n")
29
35
  errors = []
30
36
  in_error = False
31
-
37
+
32
38
  for line in lines:
33
39
  line_lower = line.lower()
34
40
  # 检测错误关键词(包括编译错误和测试失败)
35
- if any(keyword in line_lower for keyword in [
36
- "error", "failed", "exception", "traceback",
37
- "syntaxerror", "indentationerror", "assertionerror",
38
- "failed:", "failures:", "test", "assert"
39
- ]):
41
+ if any(
42
+ keyword in line_lower
43
+ for keyword in [
44
+ "error",
45
+ "failed",
46
+ "exception",
47
+ "traceback",
48
+ "syntaxerror",
49
+ "indentationerror",
50
+ "assertionerror",
51
+ "failed:",
52
+ "failures:",
53
+ "test",
54
+ "assert",
55
+ ]
56
+ ):
40
57
  in_error = True
41
58
  errors.append(line.strip())
42
59
  elif in_error and line.strip():
43
60
  # 继续收集错误相关的行
44
- if line.strip().startswith(("File", " File", " ", "E ", "FAILED", "FAILURES", "assert")):
61
+ if line.strip().startswith(
62
+ ("File", " File", " ", "E ", "FAILED", "FAILURES", "assert")
63
+ ):
45
64
  errors.append(line.strip())
46
65
  elif not line.strip().startswith("="):
47
66
  # 如果遇到非错误相关的行,停止收集
48
- if len(errors) > 0 and not any(keyword in line_lower for keyword in ["error", "failed", "exception", "assert", "test"]):
67
+ if len(errors) > 0 and not any(
68
+ keyword in line_lower
69
+ for keyword in [
70
+ "error",
71
+ "failed",
72
+ "exception",
73
+ "assert",
74
+ "test",
75
+ ]
76
+ ):
49
77
  break
50
-
78
+
51
79
  # 如果收集到错误,返回前20行(限制长度)
52
80
  if errors:
53
81
  error_text = "\n".join(errors[:20])
@@ -55,13 +83,13 @@ class PythonBuildValidator(BuildValidatorBase):
55
83
  if len(error_text) > 1000:
56
84
  error_text = error_text[:1000] + "\n... (错误信息已截断)"
57
85
  return error_text
58
-
86
+
59
87
  # 如果没有提取到结构化错误,返回原始输出的前500字符
60
88
  return output[:500] if output else ""
61
-
89
+
62
90
  def validate(self, modified_files: Optional[List[str]] = None) -> BuildResult:
63
91
  start_time = time.time()
64
-
92
+
65
93
  # 策略1: 尝试使用 py_compile 编译修改的文件
66
94
  if modified_files:
67
95
  errors = []
@@ -76,10 +104,10 @@ class PythonBuildValidator(BuildValidatorBase):
76
104
  timeout=5,
77
105
  )
78
106
  if returncode != 0:
79
- error_msg = f"{file_path}: {stderr}".strip()
80
- errors.append(error_msg)
107
+ file_error_msg = f"{file_path}: {stderr}".strip()
108
+ errors.append(file_error_msg)
81
109
  error_outputs.append(stdout + stderr)
82
-
110
+
83
111
  if errors:
84
112
  duration = time.time() - start_time
85
113
  # 合并所有错误输出
@@ -91,8 +119,10 @@ class PythonBuildValidator(BuildValidatorBase):
91
119
  error_message = "\n".join(errors[:5]) # 最多显示5个文件的错误
92
120
  if len(errors) > 5:
93
121
  error_message += f"\n... 还有 {len(errors) - 5} 个文件存在错误"
94
- print(f"❌ Python 构建验证失败(耗时 {duration:.2f} 秒)")
95
- print(f"错误信息:\n{error_message}")
122
+ PrettyOutput.auto_print(
123
+ f"❌ Python 构建验证失败(耗时 {duration:.2f} 秒)"
124
+ )
125
+ PrettyOutput.auto_print(f"错误信息:\n{error_message}")
96
126
  return BuildResult(
97
127
  success=False,
98
128
  output=full_output,
@@ -100,7 +130,7 @@ class PythonBuildValidator(BuildValidatorBase):
100
130
  build_system=BuildSystem.PYTHON,
101
131
  duration=duration,
102
132
  )
103
-
133
+
104
134
  # 策略2: 尝试运行 pytest(会自动编译并运行测试,即使没有配置文件也会自动发现测试)
105
135
  # 首先尝试 pytest
106
136
  returncode, stdout, stderr = self._run_command(
@@ -114,19 +144,25 @@ class PythonBuildValidator(BuildValidatorBase):
114
144
  ["python", "-m", "unittest", "discover", "-v"],
115
145
  timeout=30,
116
146
  )
117
-
147
+
118
148
  duration = time.time() - start_time
119
149
  success = returncode == 0
120
150
  output = stdout + stderr
121
-
151
+
122
152
  # 如果失败,提取关键错误信息(包括编译错误和测试失败)
153
+ error_msg: Optional[str] = None
123
154
  if not success:
124
155
  error_msg = self._extract_python_errors(output)
125
156
  if not error_msg:
126
157
  # 检查是否是"没有找到测试"的情况(这不算失败)
127
- if "no tests ran" in output.lower() or "no tests found" in output.lower():
158
+ if (
159
+ "no tests ran" in output.lower()
160
+ or "no tests found" in output.lower()
161
+ ):
128
162
  # 没有测试文件,但语法检查通过,视为成功
129
- print(f"✅ Python 构建验证成功(耗时 {duration:.2f} 秒,未发现测试文件)")
163
+ PrettyOutput.auto_print(
164
+ f"✅ Python 构建验证成功(耗时 {duration:.2f} 秒,未发现测试文件)"
165
+ )
130
166
  return BuildResult(
131
167
  success=True,
132
168
  output="Python语法检查通过(未发现测试文件)",
@@ -135,15 +171,14 @@ class PythonBuildValidator(BuildValidatorBase):
135
171
  duration=duration,
136
172
  )
137
173
  error_msg = "Python项目验证失败(编译或测试失败)"
138
- print(f"❌ Python 构建验证失败(耗时 {duration:.2f} 秒)")
174
+ PrettyOutput.auto_print(f"❌ Python 构建验证失败(耗时 {duration:.2f} 秒)")
139
175
  if error_msg:
140
- print(f"错误信息:\n{error_msg}")
176
+ PrettyOutput.auto_print(f"错误信息:\n{error_msg}")
141
177
  else:
142
- print(f"输出:\n{output[:500]}")
178
+ PrettyOutput.auto_print(f"输出:\n{output[:500]}")
143
179
  else:
144
- error_msg = None
145
- print(f"✅ Python 构建验证成功(耗时 {duration:.2f} 秒)")
146
-
180
+ PrettyOutput.auto_print(f"✅ Python 构建验证成功(耗时 {duration:.2f} 秒)")
181
+
147
182
  return BuildResult(
148
183
  success=success,
149
184
  output=output,
@@ -151,4 +186,3 @@ class PythonBuildValidator(BuildValidatorBase):
151
186
  build_system=BuildSystem.PYTHON,
152
187
  duration=duration,
153
188
  )
154
-
@@ -1,6 +1,3 @@
1
- #!/usr/bin/env python3
2
- # -*- coding: utf-8 -*-
3
-
4
1
  """
5
2
  Rust构建验证器模块
6
3
 
@@ -10,25 +7,34 @@ Rust构建验证器模块
10
7
  import os
11
8
  import subprocess
12
9
  import time
13
- from typing import List, Optional
14
10
 
15
- from .base import BuildValidatorBase, BuildResult, BuildSystem
11
+ from jarvis.jarvis_utils.output import PrettyOutput
12
+
13
+ #!/usr/bin/env python3
14
+ # -*- coding: utf-8 -*-
15
+
16
+ from typing import List
17
+ from typing import Optional
18
+
19
+ from .base import BuildResult
20
+ from .base import BuildSystem
21
+ from .base import BuildValidatorBase
16
22
 
17
23
 
18
24
  class RustBuildValidator(BuildValidatorBase):
19
25
  """Rust构建验证器(使用cargo test,包括编译和测试)"""
20
-
26
+
21
27
  BUILD_SYSTEM_NAME = "Cargo"
22
28
  SUPPORTED_LANGUAGES = ["rust"]
23
-
29
+
24
30
  def validate(self, modified_files: Optional[List[str]] = None) -> BuildResult:
25
31
  start_time = time.time()
26
-
27
- # 使用 cargo test 进行构建和测试验证(会自动编译并运行测试)
32
+
33
+ # 使用 cargo test 进行构建和测试验证(会自动编译并运行测试,包括文档测试)
28
34
  # 设置 RUST_BACKTRACE=1 以启用调用链回溯
29
35
  # 设置 RUSTFLAGS="-A warnings" 以屏蔽警告,只显示错误
30
36
  cmd = ["cargo", "test", "--", "--nocapture"]
31
-
37
+
32
38
  # 准备环境变量(继承当前环境并设置 RUST_BACKTRACE 和 RUSTFLAGS)
33
39
  env = os.environ.copy()
34
40
  env["RUST_BACKTRACE"] = "1"
@@ -37,7 +43,7 @@ class RustBuildValidator(BuildValidatorBase):
37
43
  env["RUSTFLAGS"] = env["RUSTFLAGS"] + " -A warnings"
38
44
  else:
39
45
  env["RUSTFLAGS"] = "-A warnings"
40
-
46
+
41
47
  # 直接使用 subprocess.run 以支持环境变量
42
48
  try:
43
49
  result = subprocess.run(
@@ -65,24 +71,24 @@ class RustBuildValidator(BuildValidatorBase):
65
71
  returncode = -1
66
72
  stdout = ""
67
73
  stderr = f"执行命令时出错: {str(e)}"
68
-
74
+
69
75
  duration = time.time() - start_time
70
-
76
+
71
77
  success = returncode == 0
72
78
  output = stdout + stderr
73
-
79
+
74
80
  if not success:
75
81
  # 尝试解析错误信息(包括编译错误和测试失败)
76
82
  error_message = self._parse_cargo_errors(output)
77
- print(f"❌ Rust 构建验证失败(耗时 {duration:.2f} 秒)")
83
+ PrettyOutput.auto_print(f"❌ Rust 构建验证失败(耗时 {duration:.2f} 秒)")
78
84
  if error_message:
79
- print(f"错误信息:\n{error_message}")
85
+ PrettyOutput.auto_print(f"错误信息:\n{error_message}")
80
86
  else:
81
- print(f"输出:\n{output[:500]}")
87
+ PrettyOutput.auto_print(f"输出:\n{output[:500]}")
82
88
  else:
83
89
  error_message = None
84
- print(f"✅ Rust 构建验证成功(耗时 {duration:.2f} 秒)")
85
-
90
+ PrettyOutput.auto_print(f"✅ Rust 构建验证成功(耗时 {duration:.2f} 秒)")
91
+
86
92
  return BuildResult(
87
93
  success=success,
88
94
  output=output,
@@ -90,21 +96,142 @@ class RustBuildValidator(BuildValidatorBase):
90
96
  build_system=BuildSystem.RUST,
91
97
  duration=duration,
92
98
  )
93
-
94
- def _parse_cargo_errors(self, output: str) -> str:
95
- """解析cargo的错误输出(包括编译错误和测试失败)"""
96
- # 简化处理:提取关键错误信息
99
+
100
+ def _parse_cargo_errors(self, output: str, context_lines: int = 20) -> str:
101
+ """解析cargo的错误输出(包括编译错误和测试失败)
102
+
103
+ Args:
104
+ output: cargo test 的完整输出
105
+ context_lines: 每个错误周围保留的上下文行数(默认20行)
106
+
107
+ Returns:
108
+ 提取的错误信息,包含失败测试用例及其上下文
109
+ """
97
110
  lines = output.split("\n")
98
- errors = []
99
- for line in lines:
100
- # 匹配编译错误
101
- if "error[" in line or "error:" in line.lower():
102
- errors.append(line.strip())
103
- # 匹配测试失败
104
- elif "test" in line.lower() and ("failed" in line.lower() or "panic" in line.lower()):
105
- errors.append(line.strip())
106
- # 匹配断言失败
107
- elif "assertion" in line.lower() and "failed" in line.lower():
108
- errors.append(line.strip())
109
- return "\n".join(errors[:10]) if errors else output[:500] # 限制长度
111
+ error_sections = []
112
+
113
+ # 1. 查找失败的测试用例
114
+ failed_tests = []
115
+ for i, line in enumerate(lines):
116
+ # 匹配失败的测试用例行,如 "test tests::test_name ... FAILED"
117
+ if "test" in line and "FAILED" in line:
118
+ # 提取测试名称
119
+ if "test " in line:
120
+ parts = line.split()
121
+ for j, part in enumerate(parts):
122
+ if part == "test" and j + 1 < len(parts):
123
+ test_name = parts[j + 1]
124
+ if "..." in test_name:
125
+ test_name = test_name.replace("...", "")
126
+ failed_tests.append((i, test_name, line))
127
+ break
128
+
129
+ # 2. 为每个失败的测试提取完整输出块
130
+ if failed_tests:
131
+ for test_idx, (line_idx, test_name, test_line) in enumerate(failed_tests):
132
+ # 找到这个测试的开始位置(向上查找,找到 "running" 或测试名称)
133
+ start_idx = max(0, line_idx - 10)
134
+ # 向上查找,找到测试开始标记
135
+ for i in range(line_idx - 1, max(0, line_idx - 100), -1):
136
+ # 查找 "running" 行,通常格式为 "running 1 test" 或包含测试名称
137
+ if "running" in lines[i].lower():
138
+ start_idx = i
139
+ break
140
+ # 或者找到前一个测试的结束标记
141
+ if (
142
+ i > 0
143
+ and "test " in lines[i]
144
+ and ("ok" in lines[i].lower() or "FAILED" in lines[i])
145
+ ):
146
+ start_idx = i + 1
147
+ break
148
+
149
+ # 找到这个测试的结束位置(向下查找,找到下一个测试或测试总结)
150
+ end_idx = min(len(lines), line_idx + context_lines)
151
+ # 向下查找,找到测试块的结束
152
+ for i in range(line_idx + 1, min(len(lines), line_idx + 500)):
153
+ # 遇到下一个测试用例行(格式:test xxx ... ok/FAILED)
154
+ if "test " in lines[i] and "..." in lines[i]:
155
+ end_idx = i
156
+ break
157
+ # 遇到测试总结行
158
+ if "test result:" in lines[i].lower():
159
+ end_idx = i
160
+ break
161
+ # 遇到新的 "running" 行,表示下一组测试开始
162
+ if "running" in lines[i].lower() and i > line_idx + 5:
163
+ end_idx = i
164
+ break
110
165
 
166
+ # 提取这个测试的完整输出
167
+ test_output = "\n".join(lines[start_idx:end_idx])
168
+ if test_output.strip():
169
+ error_sections.append(
170
+ f"=== 失败的测试: {test_name} ===\n{test_output}"
171
+ )
172
+
173
+ # 3. 如果没有找到失败的测试,查找编译错误
174
+ if not error_sections:
175
+ error_lines = []
176
+ in_error_block = False
177
+ error_start = -1
178
+
179
+ for i, line in enumerate(lines):
180
+ # 检测错误开始
181
+ if "error[" in line or (
182
+ "error:" in line.lower() and "error[" not in line
183
+ ):
184
+ if not in_error_block:
185
+ error_start = max(0, i - 2) # 包含错误前2行上下文
186
+ in_error_block = True
187
+ elif in_error_block:
188
+ # 错误块结束条件:空行后跟非错误行,或遇到新的错误
189
+ if line.strip() == "":
190
+ # 检查下一行是否是新的错误
191
+ if i + 1 < len(lines) and (
192
+ "error[" not in lines[i + 1]
193
+ and "error:" not in lines[i + 1].lower()
194
+ ):
195
+ # 结束当前错误块
196
+ error_lines.extend(lines[error_start : i + 1])
197
+ in_error_block = False
198
+ elif i - error_start > context_lines:
199
+ # 错误块太长,截断
200
+ error_lines.extend(lines[error_start:i])
201
+ in_error_block = False
202
+ if "error[" in line or "error:" in line.lower():
203
+ error_start = max(0, i - 2)
204
+ in_error_block = True
205
+
206
+ # 处理最后一个错误块
207
+ if in_error_block:
208
+ error_lines.extend(
209
+ lines[error_start : min(len(lines), error_start + context_lines)]
210
+ )
211
+
212
+ if error_lines:
213
+ error_sections.append("\n".join(error_lines))
214
+
215
+ # 4. 如果仍然没有找到错误,查找其他错误模式
216
+ if not error_sections:
217
+ for i, line in enumerate(lines):
218
+ if (
219
+ "panic" in line.lower()
220
+ or ("assertion" in line.lower() and "failed" in line.lower())
221
+ or "thread" in line.lower()
222
+ and "panicked" in line.lower()
223
+ ):
224
+ start = max(0, i - 3)
225
+ end = min(len(lines), i + context_lines)
226
+ error_sections.append("\n".join(lines[start:end]))
227
+ break
228
+
229
+ # 5. 如果找到了错误信息,返回;否则返回原始输出的前500字符
230
+ if error_sections:
231
+ result = "\n\n".join(error_sections)
232
+ # 限制总长度,避免过长
233
+ if len(result) > 5000:
234
+ result = result[:5000] + "\n... (输出已截断)"
235
+ return result
236
+ else:
237
+ return output[:500] # 如果没有找到特定错误,返回前500字符