jarvis-ai-assistant 0.7.0__py3-none-any.whl → 0.7.6__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 (159) hide show
  1. jarvis/__init__.py +1 -1
  2. jarvis/jarvis_agent/__init__.py +243 -139
  3. jarvis/jarvis_agent/agent_manager.py +5 -10
  4. jarvis/jarvis_agent/builtin_input_handler.py +2 -6
  5. jarvis/jarvis_agent/config_editor.py +2 -7
  6. jarvis/jarvis_agent/event_bus.py +82 -12
  7. jarvis/jarvis_agent/file_context_handler.py +265 -15
  8. jarvis/jarvis_agent/file_methodology_manager.py +3 -4
  9. jarvis/jarvis_agent/jarvis.py +113 -98
  10. jarvis/jarvis_agent/language_extractors/__init__.py +57 -0
  11. jarvis/jarvis_agent/language_extractors/c_extractor.py +21 -0
  12. jarvis/jarvis_agent/language_extractors/cpp_extractor.py +21 -0
  13. jarvis/jarvis_agent/language_extractors/go_extractor.py +21 -0
  14. jarvis/jarvis_agent/language_extractors/java_extractor.py +84 -0
  15. jarvis/jarvis_agent/language_extractors/javascript_extractor.py +79 -0
  16. jarvis/jarvis_agent/language_extractors/python_extractor.py +21 -0
  17. jarvis/jarvis_agent/language_extractors/rust_extractor.py +21 -0
  18. jarvis/jarvis_agent/language_extractors/typescript_extractor.py +84 -0
  19. jarvis/jarvis_agent/language_support_info.py +486 -0
  20. jarvis/jarvis_agent/main.py +6 -12
  21. jarvis/jarvis_agent/memory_manager.py +7 -16
  22. jarvis/jarvis_agent/methodology_share_manager.py +10 -16
  23. jarvis/jarvis_agent/prompt_manager.py +1 -1
  24. jarvis/jarvis_agent/prompts.py +193 -171
  25. jarvis/jarvis_agent/protocols.py +8 -12
  26. jarvis/jarvis_agent/run_loop.py +77 -14
  27. jarvis/jarvis_agent/session_manager.py +2 -3
  28. jarvis/jarvis_agent/share_manager.py +12 -21
  29. jarvis/jarvis_agent/shell_input_handler.py +1 -2
  30. jarvis/jarvis_agent/task_analyzer.py +26 -4
  31. jarvis/jarvis_agent/task_manager.py +11 -27
  32. jarvis/jarvis_agent/tool_executor.py +2 -3
  33. jarvis/jarvis_agent/tool_share_manager.py +12 -24
  34. jarvis/jarvis_agent/web_server.py +55 -20
  35. jarvis/jarvis_c2rust/__init__.py +5 -5
  36. jarvis/jarvis_c2rust/cli.py +461 -499
  37. jarvis/jarvis_c2rust/collector.py +45 -53
  38. jarvis/jarvis_c2rust/constants.py +26 -0
  39. jarvis/jarvis_c2rust/library_replacer.py +264 -132
  40. jarvis/jarvis_c2rust/llm_module_agent.py +162 -190
  41. jarvis/jarvis_c2rust/loaders.py +207 -0
  42. jarvis/jarvis_c2rust/models.py +28 -0
  43. jarvis/jarvis_c2rust/optimizer.py +1592 -395
  44. jarvis/jarvis_c2rust/transpiler.py +1722 -1064
  45. jarvis/jarvis_c2rust/utils.py +385 -0
  46. jarvis/jarvis_code_agent/build_validation_config.py +2 -3
  47. jarvis/jarvis_code_agent/code_agent.py +394 -320
  48. jarvis/jarvis_code_agent/code_analyzer/__init__.py +3 -0
  49. jarvis/jarvis_code_agent/code_analyzer/build_validator/base.py +4 -0
  50. jarvis/jarvis_code_agent/code_analyzer/build_validator/cmake.py +17 -2
  51. jarvis/jarvis_code_agent/code_analyzer/build_validator/fallback.py +3 -0
  52. jarvis/jarvis_code_agent/code_analyzer/build_validator/go.py +36 -4
  53. jarvis/jarvis_code_agent/code_analyzer/build_validator/java_gradle.py +9 -0
  54. jarvis/jarvis_code_agent/code_analyzer/build_validator/java_maven.py +9 -0
  55. jarvis/jarvis_code_agent/code_analyzer/build_validator/makefile.py +12 -1
  56. jarvis/jarvis_code_agent/code_analyzer/build_validator/nodejs.py +22 -5
  57. jarvis/jarvis_code_agent/code_analyzer/build_validator/python.py +57 -32
  58. jarvis/jarvis_code_agent/code_analyzer/build_validator/rust.py +62 -6
  59. jarvis/jarvis_code_agent/code_analyzer/build_validator/validator.py +8 -9
  60. jarvis/jarvis_code_agent/code_analyzer/context_manager.py +290 -5
  61. jarvis/jarvis_code_agent/code_analyzer/language_support.py +21 -0
  62. jarvis/jarvis_code_agent/code_analyzer/languages/__init__.py +21 -3
  63. jarvis/jarvis_code_agent/code_analyzer/languages/c_cpp_language.py +72 -4
  64. jarvis/jarvis_code_agent/code_analyzer/languages/go_language.py +35 -3
  65. jarvis/jarvis_code_agent/code_analyzer/languages/java_language.py +212 -0
  66. jarvis/jarvis_code_agent/code_analyzer/languages/javascript_language.py +254 -0
  67. jarvis/jarvis_code_agent/code_analyzer/languages/python_language.py +52 -2
  68. jarvis/jarvis_code_agent/code_analyzer/languages/rust_language.py +73 -1
  69. jarvis/jarvis_code_agent/code_analyzer/languages/typescript_language.py +280 -0
  70. jarvis/jarvis_code_agent/code_analyzer/llm_context_recommender.py +306 -152
  71. jarvis/jarvis_code_agent/code_analyzer/structured_code.py +556 -0
  72. jarvis/jarvis_code_agent/code_analyzer/symbol_extractor.py +193 -18
  73. jarvis/jarvis_code_agent/code_analyzer/tree_sitter_extractor.py +18 -8
  74. jarvis/jarvis_code_agent/lint.py +258 -27
  75. jarvis/jarvis_code_agent/utils.py +0 -1
  76. jarvis/jarvis_code_analysis/code_review.py +19 -24
  77. jarvis/jarvis_data/config_schema.json +53 -26
  78. jarvis/jarvis_git_squash/main.py +4 -5
  79. jarvis/jarvis_git_utils/git_commiter.py +44 -49
  80. jarvis/jarvis_mcp/sse_mcp_client.py +20 -27
  81. jarvis/jarvis_mcp/stdio_mcp_client.py +11 -12
  82. jarvis/jarvis_mcp/streamable_mcp_client.py +15 -14
  83. jarvis/jarvis_memory_organizer/memory_organizer.py +55 -74
  84. jarvis/jarvis_methodology/main.py +32 -48
  85. jarvis/jarvis_multi_agent/__init__.py +79 -61
  86. jarvis/jarvis_multi_agent/main.py +3 -7
  87. jarvis/jarvis_platform/base.py +469 -199
  88. jarvis/jarvis_platform/human.py +7 -8
  89. jarvis/jarvis_platform/kimi.py +30 -36
  90. jarvis/jarvis_platform/openai.py +65 -27
  91. jarvis/jarvis_platform/registry.py +26 -10
  92. jarvis/jarvis_platform/tongyi.py +24 -25
  93. jarvis/jarvis_platform/yuanbao.py +31 -42
  94. jarvis/jarvis_platform_manager/main.py +66 -77
  95. jarvis/jarvis_platform_manager/service.py +8 -13
  96. jarvis/jarvis_rag/cli.py +49 -51
  97. jarvis/jarvis_rag/embedding_manager.py +13 -18
  98. jarvis/jarvis_rag/llm_interface.py +8 -9
  99. jarvis/jarvis_rag/query_rewriter.py +10 -21
  100. jarvis/jarvis_rag/rag_pipeline.py +24 -27
  101. jarvis/jarvis_rag/reranker.py +4 -5
  102. jarvis/jarvis_rag/retriever.py +28 -30
  103. jarvis/jarvis_sec/__init__.py +220 -3520
  104. jarvis/jarvis_sec/agents.py +143 -0
  105. jarvis/jarvis_sec/analysis.py +276 -0
  106. jarvis/jarvis_sec/cli.py +29 -6
  107. jarvis/jarvis_sec/clustering.py +1439 -0
  108. jarvis/jarvis_sec/file_manager.py +427 -0
  109. jarvis/jarvis_sec/parsers.py +73 -0
  110. jarvis/jarvis_sec/prompts.py +268 -0
  111. jarvis/jarvis_sec/report.py +83 -4
  112. jarvis/jarvis_sec/review.py +453 -0
  113. jarvis/jarvis_sec/utils.py +499 -0
  114. jarvis/jarvis_sec/verification.py +848 -0
  115. jarvis/jarvis_sec/workflow.py +7 -0
  116. jarvis/jarvis_smart_shell/main.py +38 -87
  117. jarvis/jarvis_stats/cli.py +1 -1
  118. jarvis/jarvis_stats/stats.py +7 -7
  119. jarvis/jarvis_stats/storage.py +15 -21
  120. jarvis/jarvis_tools/clear_memory.py +3 -20
  121. jarvis/jarvis_tools/cli/main.py +20 -23
  122. jarvis/jarvis_tools/edit_file.py +1066 -0
  123. jarvis/jarvis_tools/execute_script.py +42 -21
  124. jarvis/jarvis_tools/file_analyzer.py +6 -9
  125. jarvis/jarvis_tools/generate_new_tool.py +11 -20
  126. jarvis/jarvis_tools/lsp_client.py +1552 -0
  127. jarvis/jarvis_tools/methodology.py +2 -3
  128. jarvis/jarvis_tools/read_code.py +1525 -87
  129. jarvis/jarvis_tools/read_symbols.py +2 -3
  130. jarvis/jarvis_tools/read_webpage.py +7 -10
  131. jarvis/jarvis_tools/registry.py +370 -181
  132. jarvis/jarvis_tools/retrieve_memory.py +20 -19
  133. jarvis/jarvis_tools/rewrite_file.py +105 -0
  134. jarvis/jarvis_tools/save_memory.py +3 -15
  135. jarvis/jarvis_tools/search_web.py +3 -7
  136. jarvis/jarvis_tools/sub_agent.py +17 -6
  137. jarvis/jarvis_tools/sub_code_agent.py +14 -16
  138. jarvis/jarvis_tools/virtual_tty.py +54 -32
  139. jarvis/jarvis_utils/clipboard.py +7 -10
  140. jarvis/jarvis_utils/config.py +98 -63
  141. jarvis/jarvis_utils/embedding.py +5 -5
  142. jarvis/jarvis_utils/fzf.py +8 -8
  143. jarvis/jarvis_utils/git_utils.py +81 -67
  144. jarvis/jarvis_utils/input.py +24 -49
  145. jarvis/jarvis_utils/jsonnet_compat.py +465 -0
  146. jarvis/jarvis_utils/methodology.py +33 -35
  147. jarvis/jarvis_utils/utils.py +245 -202
  148. {jarvis_ai_assistant-0.7.0.dist-info → jarvis_ai_assistant-0.7.6.dist-info}/METADATA +205 -70
  149. jarvis_ai_assistant-0.7.6.dist-info/RECORD +218 -0
  150. jarvis/jarvis_agent/edit_file_handler.py +0 -584
  151. jarvis/jarvis_agent/rewrite_file_handler.py +0 -141
  152. jarvis/jarvis_agent/task_planner.py +0 -496
  153. jarvis/jarvis_platform/ai8.py +0 -332
  154. jarvis/jarvis_tools/ask_user.py +0 -54
  155. jarvis_ai_assistant-0.7.0.dist-info/RECORD +0 -192
  156. {jarvis_ai_assistant-0.7.0.dist-info → jarvis_ai_assistant-0.7.6.dist-info}/WHEEL +0 -0
  157. {jarvis_ai_assistant-0.7.0.dist-info → jarvis_ai_assistant-0.7.6.dist-info}/entry_points.txt +0 -0
  158. {jarvis_ai_assistant-0.7.0.dist-info → jarvis_ai_assistant-0.7.6.dist-info}/licenses/LICENSE +0 -0
  159. {jarvis_ai_assistant-0.7.0.dist-info → jarvis_ai_assistant-0.7.6.dist-info}/top_level.txt +0 -0
@@ -22,6 +22,7 @@ from .impact_analyzer import (
22
22
  TestDiscoverer,
23
23
  parse_git_diff_to_edits,
24
24
  )
25
+ from .structured_code import StructuredCodeExtractor
25
26
 
26
27
  __all__ = [
27
28
  # Symbol extraction
@@ -58,5 +59,7 @@ __all__ = [
58
59
  'Edit',
59
60
  'TestDiscoverer',
60
61
  'parse_git_diff_to_edits',
62
+ # Structured code extraction
63
+ 'StructuredCodeExtractor',
61
64
  ]
62
65
 
@@ -41,6 +41,10 @@ class BuildResult:
41
41
  class BuildValidatorBase(ABC):
42
42
  """构建验证器基类"""
43
43
 
44
+ # 子类需要定义的类变量
45
+ BUILD_SYSTEM_NAME: str = "" # 构建系统名称,如 "CMake", "Makefile", "Cargo"
46
+ SUPPORTED_LANGUAGES: List[str] = [] # 支持的语言列表,如 ["c", "cpp"]
47
+
44
48
  def __init__(self, project_root: str, timeout: int = 30):
45
49
  self.project_root = project_root
46
50
  self.timeout = timeout
@@ -18,6 +18,9 @@ from .base import BuildValidatorBase, BuildResult, BuildSystem
18
18
  class CMakeBuildValidator(BuildValidatorBase):
19
19
  """CMake构建验证器"""
20
20
 
21
+ BUILD_SYSTEM_NAME = "CMake"
22
+ SUPPORTED_LANGUAGES = ["c", "cpp"]
23
+
21
24
  def validate(self, modified_files: Optional[List[str]] = None) -> BuildResult:
22
25
  start_time = time.time()
23
26
 
@@ -32,9 +35,15 @@ class CMakeBuildValidator(BuildValidatorBase):
32
35
  )
33
36
  duration = time.time() - start_time
34
37
  success = returncode == 0
38
+ output = stdout + stderr
39
+ if success:
40
+ print(f"✅ CMake 构建验证成功(耗时 {duration:.2f} 秒)")
41
+ else:
42
+ print(f"❌ CMake 构建验证失败(耗时 {duration:.2f} 秒)")
43
+ print(f"错误信息:CMake构建失败\n{output[:500]}")
35
44
  return BuildResult(
36
45
  success=success,
37
- output=stdout + stderr,
46
+ output=output,
38
47
  error_message=None if success else "CMake构建失败",
39
48
  build_system=BuildSystem.C_CMAKE,
40
49
  duration=duration,
@@ -49,9 +58,15 @@ class CMakeBuildValidator(BuildValidatorBase):
49
58
  duration = time.time() - start_time
50
59
 
51
60
  success = returncode == 0
61
+ output = stdout + stderr
62
+ if success:
63
+ print(f"✅ CMake 配置验证成功(耗时 {duration:.2f} 秒)")
64
+ else:
65
+ print(f"❌ CMake 配置验证失败(耗时 {duration:.2f} 秒)")
66
+ print(f"错误信息:CMake配置失败\n{output[:500]}")
52
67
  return BuildResult(
53
68
  success=success,
54
- output=stdout + stderr,
69
+ output=output,
55
70
  error_message=None if success else "CMake配置失败",
56
71
  build_system=BuildSystem.C_CMAKE,
57
72
  duration=duration,
@@ -50,6 +50,8 @@ class FallbackBuildValidator(BuildValidatorBase):
50
50
 
51
51
  if errors:
52
52
  duration = time.time() - start_time
53
+ print(f"❌ 基础语法检查失败(耗时 {duration:.2f} 秒)")
54
+ print(f"错误信息:语法检查失败\n{chr(10).join(errors[:5])}")
53
55
  return BuildResult(
54
56
  success=False,
55
57
  output="\n".join(errors),
@@ -59,6 +61,7 @@ class FallbackBuildValidator(BuildValidatorBase):
59
61
  )
60
62
 
61
63
  duration = time.time() - start_time
64
+ print(f"✅ 基础语法检查通过(耗时 {duration:.2f} 秒,未检测到构建系统)")
62
65
  return BuildResult(
63
66
  success=True,
64
67
  output="基础语法检查通过(未检测到构建系统)",
@@ -14,13 +14,16 @@ from .base import BuildValidatorBase, BuildResult, BuildSystem
14
14
 
15
15
 
16
16
  class GoBuildValidator(BuildValidatorBase):
17
- """Go构建验证器"""
17
+ """Go构建验证器(使用go test,包括编译和测试)"""
18
+
19
+ BUILD_SYSTEM_NAME = "Go Build"
20
+ SUPPORTED_LANGUAGES = ["go"]
18
21
 
19
22
  def validate(self, modified_files: Optional[List[str]] = None) -> BuildResult:
20
23
  start_time = time.time()
21
24
 
22
- # 使用 go build 进行构建验证
23
- cmd = ["go", "build", "./..."]
25
+ # 使用 go test 进行构建和测试验证(会自动编译并运行测试)
26
+ cmd = ["go", "test", "./..."]
24
27
 
25
28
  returncode, stdout, stderr = self._run_command(cmd, timeout=30)
26
29
  duration = time.time() - start_time
@@ -28,11 +31,40 @@ class GoBuildValidator(BuildValidatorBase):
28
31
  success = returncode == 0
29
32
  output = stdout + stderr
30
33
 
34
+ if not success:
35
+ # 尝试解析错误信息(包括编译错误和测试失败)
36
+ error_message = self._parse_go_errors(output)
37
+ print(f"❌ Go 构建验证失败(耗时 {duration:.2f} 秒)")
38
+ if error_message:
39
+ print(f"错误信息:\n{error_message}")
40
+ else:
41
+ print(f"输出:\n{output[:500]}")
42
+ else:
43
+ error_message = None
44
+ print(f"✅ Go 构建验证成功(耗时 {duration:.2f} 秒)")
45
+
31
46
  return BuildResult(
32
47
  success=success,
33
48
  output=output,
34
- error_message=None if success else "Go构建失败",
49
+ error_message=error_message,
35
50
  build_system=BuildSystem.GO,
36
51
  duration=duration,
37
52
  )
53
+
54
+ def _parse_go_errors(self, output: str) -> str:
55
+ """解析Go的错误输出(包括编译错误和测试失败)"""
56
+ # 简化处理:提取关键错误信息
57
+ lines = output.split("\n")
58
+ errors = []
59
+ for line in lines:
60
+ # 匹配编译错误
61
+ if "error:" in line.lower() or "cannot" in line.lower():
62
+ errors.append(line.strip())
63
+ # 匹配测试失败
64
+ elif "--- FAIL:" in line or "FAIL" in line:
65
+ errors.append(line.strip())
66
+ # 匹配断言失败
67
+ elif "got" in line.lower() and "want" in line.lower():
68
+ errors.append(line.strip())
69
+ return "\n".join(errors[:10]) if errors else output[:500] # 限制长度
38
70
 
@@ -17,6 +17,9 @@ from .base import BuildValidatorBase, BuildResult, BuildSystem
17
17
  class JavaGradleBuildValidator(BuildValidatorBase):
18
18
  """Java Gradle构建验证器"""
19
19
 
20
+ BUILD_SYSTEM_NAME = "Gradle"
21
+ SUPPORTED_LANGUAGES = ["java"]
22
+
20
23
  def validate(self, modified_files: Optional[List[str]] = None) -> BuildResult:
21
24
  start_time = time.time()
22
25
 
@@ -34,6 +37,12 @@ class JavaGradleBuildValidator(BuildValidatorBase):
34
37
  success = returncode == 0
35
38
  output = stdout + stderr
36
39
 
40
+ if success:
41
+ print(f"✅ Gradle 构建验证成功(耗时 {duration:.2f} 秒)")
42
+ else:
43
+ print(f"❌ Gradle 构建验证失败(耗时 {duration:.2f} 秒)")
44
+ print(f"错误信息:Gradle编译失败\n{output[:500]}")
45
+
37
46
  return BuildResult(
38
47
  success=success,
39
48
  output=output,
@@ -16,6 +16,9 @@ from .base import BuildValidatorBase, BuildResult, BuildSystem
16
16
  class JavaMavenBuildValidator(BuildValidatorBase):
17
17
  """Java Maven构建验证器"""
18
18
 
19
+ BUILD_SYSTEM_NAME = "Maven"
20
+ SUPPORTED_LANGUAGES = ["java"]
21
+
19
22
  def validate(self, modified_files: Optional[List[str]] = None) -> BuildResult:
20
23
  start_time = time.time()
21
24
 
@@ -28,6 +31,12 @@ class JavaMavenBuildValidator(BuildValidatorBase):
28
31
  success = returncode == 0
29
32
  output = stdout + stderr
30
33
 
34
+ if success:
35
+ print(f"✅ Maven 构建验证成功(耗时 {duration:.2f} 秒)")
36
+ else:
37
+ print(f"❌ Maven 构建验证失败(耗时 {duration:.2f} 秒)")
38
+ print(f"错误信息:Maven编译失败\n{output[:500]}")
39
+
31
40
  return BuildResult(
32
41
  success=success,
33
42
  output=output,
@@ -17,6 +17,9 @@ from .base import BuildValidatorBase, BuildResult, BuildSystem
17
17
  class MakefileBuildValidator(BuildValidatorBase):
18
18
  """Makefile构建验证器"""
19
19
 
20
+ BUILD_SYSTEM_NAME = "Makefile"
21
+ SUPPORTED_LANGUAGES = ["c", "cpp"]
22
+
20
23
  def validate(self, modified_files: Optional[List[str]] = None) -> BuildResult:
21
24
  start_time = time.time()
22
25
 
@@ -24,6 +27,8 @@ class MakefileBuildValidator(BuildValidatorBase):
24
27
  makefile = os.path.join(self.project_root, "Makefile")
25
28
  if not os.path.exists(makefile):
26
29
  duration = time.time() - start_time
30
+ print(f"❌ Makefile 构建验证失败(耗时 {duration:.2f} 秒)")
31
+ print("错误信息:Makefile不存在")
27
32
  return BuildResult(
28
33
  success=False,
29
34
  output="Makefile不存在",
@@ -40,9 +45,15 @@ class MakefileBuildValidator(BuildValidatorBase):
40
45
  duration = time.time() - start_time
41
46
 
42
47
  success = returncode == 0
48
+ output = stdout + stderr
49
+ if success:
50
+ print(f"✅ Makefile 构建验证成功(耗时 {duration:.2f} 秒)")
51
+ else:
52
+ print(f"❌ Makefile 构建验证失败(耗时 {duration:.2f} 秒)")
53
+ print(f"错误信息:Makefile语法检查失败\n{output[:500]}")
43
54
  return BuildResult(
44
55
  success=success,
45
- output=stdout + stderr,
56
+ output=output,
46
57
  error_message=None if success else "Makefile语法检查失败",
47
58
  build_system=BuildSystem.C_MAKEFILE,
48
59
  duration=duration,
@@ -12,13 +12,15 @@ import os
12
12
  import time
13
13
  from typing import List, Optional
14
14
 
15
- from jarvis.jarvis_utils.output import OutputType, PrettyOutput
16
15
  from .base import BuildValidatorBase, BuildResult, BuildSystem
17
16
 
18
17
 
19
18
  class NodeJSBuildValidator(BuildValidatorBase):
20
19
  """Node.js构建验证器"""
21
20
 
21
+ BUILD_SYSTEM_NAME = "npm/Node.js"
22
+ SUPPORTED_LANGUAGES = ["javascript", "typescript"]
23
+
22
24
  def validate(self, modified_files: Optional[List[str]] = None) -> BuildResult:
23
25
  start_time = time.time()
24
26
 
@@ -31,9 +33,15 @@ class NodeJSBuildValidator(BuildValidatorBase):
31
33
  )
32
34
  duration = time.time() - start_time
33
35
  success = returncode == 0
36
+ output = stdout + stderr
37
+ if success:
38
+ print(f"✅ Node.js (TypeScript) 构建验证成功(耗时 {duration:.2f} 秒)")
39
+ else:
40
+ print(f"❌ Node.js (TypeScript) 构建验证失败(耗时 {duration:.2f} 秒)")
41
+ print(f"错误信息:TypeScript类型检查失败\n{output[:500]}")
34
42
  return BuildResult(
35
43
  success=success,
36
- output=stdout + stderr,
44
+ output=output,
37
45
  error_message=None if success else "TypeScript类型检查失败",
38
46
  build_system=BuildSystem.NODEJS,
39
47
  duration=duration,
@@ -53,15 +61,21 @@ class NodeJSBuildValidator(BuildValidatorBase):
53
61
  )
54
62
  duration = time.time() - start_time
55
63
  success = returncode == 0
64
+ output = stdout + stderr
65
+ if success:
66
+ print(f"✅ Node.js (npm build) 构建验证成功(耗时 {duration:.2f} 秒)")
67
+ else:
68
+ print(f"❌ Node.js (npm build) 构建验证失败(耗时 {duration:.2f} 秒)")
69
+ print(f"错误信息:npm build失败\n{output[:500]}")
56
70
  return BuildResult(
57
71
  success=success,
58
- output=stdout + stderr,
72
+ output=output,
59
73
  error_message=None if success else "npm build失败",
60
74
  build_system=BuildSystem.NODEJS,
61
75
  duration=duration,
62
76
  )
63
77
  except Exception as e:
64
- PrettyOutput.print(f"读取package.json失败: {e}", OutputType.WARNING)
78
+ print(f"⚠️ 读取package.json失败: {e}")
65
79
 
66
80
  # 策略3: 使用 eslint 进行语法检查(如果存在)
67
81
  if modified_files:
@@ -73,16 +87,19 @@ class NodeJSBuildValidator(BuildValidatorBase):
73
87
  timeout=15,
74
88
  )
75
89
  duration = time.time() - start_time
90
+ output = stdout + stderr
76
91
  # eslint返回非0可能是警告,不算失败
92
+ print(f"✅ Node.js (eslint) 构建验证成功(耗时 {duration:.2f} 秒)")
77
93
  return BuildResult(
78
94
  success=True, # 仅检查语法,警告不算失败
79
- output=stdout + stderr,
95
+ output=output,
80
96
  error_message=None,
81
97
  build_system=BuildSystem.NODEJS,
82
98
  duration=duration,
83
99
  )
84
100
 
85
101
  duration = time.time() - start_time
102
+ print(f"✅ Node.js 构建验证成功(耗时 {duration:.2f} 秒,无构建脚本)")
86
103
  return BuildResult(
87
104
  success=True,
88
105
  output="Node.js项目验证通过(无构建脚本)",
@@ -15,10 +15,13 @@ from .base import BuildValidatorBase, BuildResult, BuildSystem
15
15
 
16
16
 
17
17
  class PythonBuildValidator(BuildValidatorBase):
18
- """Python构建验证器"""
18
+ """Python构建验证器(包括编译和测试)"""
19
+
20
+ BUILD_SYSTEM_NAME = "Python"
21
+ SUPPORTED_LANGUAGES = ["python"]
19
22
 
20
23
  def _extract_python_errors(self, output: str) -> str:
21
- """提取Python错误信息"""
24
+ """提取Python错误信息(包括编译错误和测试失败)"""
22
25
  if not output:
23
26
  return ""
24
27
 
@@ -28,17 +31,21 @@ class PythonBuildValidator(BuildValidatorBase):
28
31
 
29
32
  for line in lines:
30
33
  line_lower = line.lower()
31
- # 检测错误关键词
32
- if any(keyword in line_lower for keyword in ["error", "failed", "exception", "traceback", "syntaxerror", "indentationerror"]):
34
+ # 检测错误关键词(包括编译错误和测试失败)
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
+ ]):
33
40
  in_error = True
34
41
  errors.append(line.strip())
35
42
  elif in_error and line.strip():
36
43
  # 继续收集错误相关的行
37
- if line.strip().startswith(("File", " File", " ", "E ", "FAILED")):
44
+ if line.strip().startswith(("File", " File", " ", "E ", "FAILED", "FAILURES", "assert")):
38
45
  errors.append(line.strip())
39
46
  elif not line.strip().startswith("="):
40
47
  # 如果遇到非错误相关的行,停止收集
41
- if len(errors) > 0 and not any(keyword in line_lower for keyword in ["error", "failed", "exception"]):
48
+ if len(errors) > 0 and not any(keyword in line_lower for keyword in ["error", "failed", "exception", "assert", "test"]):
42
49
  break
43
50
 
44
51
  # 如果收集到错误,返回前20行(限制长度)
@@ -84,6 +91,8 @@ class PythonBuildValidator(BuildValidatorBase):
84
91
  error_message = "\n".join(errors[:5]) # 最多显示5个文件的错误
85
92
  if len(errors) > 5:
86
93
  error_message += f"\n... 还有 {len(errors) - 5} 个文件存在错误"
94
+ print(f"❌ Python 构建验证失败(耗时 {duration:.2f} 秒)")
95
+ print(f"错误信息:\n{error_message}")
87
96
  return BuildResult(
88
97
  success=False,
89
98
  output=full_output,
@@ -92,37 +101,53 @@ class PythonBuildValidator(BuildValidatorBase):
92
101
  duration=duration,
93
102
  )
94
103
 
95
- # 策略2: 尝试运行 pytest --collect-only(如果存在)
96
- if os.path.exists(os.path.join(self.project_root, "pytest.ini")) or \
97
- os.path.exists(os.path.join(self.project_root, "setup.py")):
104
+ # 策略2: 尝试运行 pytest(会自动编译并运行测试,即使没有配置文件也会自动发现测试)
105
+ # 首先尝试 pytest
106
+ returncode, stdout, stderr = self._run_command(
107
+ ["python", "-m", "pytest", "-v"],
108
+ timeout=30,
109
+ )
110
+ # 如果 pytest 命令本身失败(如未安装),尝试 unittest
111
+ if returncode == 1 and "No module named pytest" in stderr:
112
+ # pytest 未安装,尝试使用 unittest
98
113
  returncode, stdout, stderr = self._run_command(
99
- ["python", "-m", "pytest", "--collect-only", "-q"],
100
- timeout=10,
101
- )
102
- duration = time.time() - start_time
103
- success = returncode == 0
104
- output = stdout + stderr
105
- # 如果失败,提取关键错误信息
106
- if not success:
107
- error_msg = self._extract_python_errors(output)
108
- if not error_msg:
109
- error_msg = "Python项目验证失败"
110
- else:
111
- error_msg = None
112
- return BuildResult(
113
- success=success,
114
- output=output,
115
- error_message=error_msg,
116
- build_system=BuildSystem.PYTHON,
117
- duration=duration,
114
+ ["python", "-m", "unittest", "discover", "-v"],
115
+ timeout=30,
118
116
  )
119
117
 
120
- # 策略3: 如果没有测试框架,仅验证语法(已在上面的策略1中完成)
121
118
  duration = time.time() - start_time
119
+ success = returncode == 0
120
+ output = stdout + stderr
121
+
122
+ # 如果失败,提取关键错误信息(包括编译错误和测试失败)
123
+ if not success:
124
+ error_msg = self._extract_python_errors(output)
125
+ if not error_msg:
126
+ # 检查是否是"没有找到测试"的情况(这不算失败)
127
+ if "no tests ran" in output.lower() or "no tests found" in output.lower():
128
+ # 没有测试文件,但语法检查通过,视为成功
129
+ print(f"✅ Python 构建验证成功(耗时 {duration:.2f} 秒,未发现测试文件)")
130
+ return BuildResult(
131
+ success=True,
132
+ output="Python语法检查通过(未发现测试文件)",
133
+ error_message=None,
134
+ build_system=BuildSystem.PYTHON,
135
+ duration=duration,
136
+ )
137
+ error_msg = "Python项目验证失败(编译或测试失败)"
138
+ print(f"❌ Python 构建验证失败(耗时 {duration:.2f} 秒)")
139
+ if error_msg:
140
+ print(f"错误信息:\n{error_msg}")
141
+ else:
142
+ print(f"输出:\n{output[:500]}")
143
+ else:
144
+ error_msg = None
145
+ print(f"✅ Python 构建验证成功(耗时 {duration:.2f} 秒)")
146
+
122
147
  return BuildResult(
123
- success=True,
124
- output="Python语法检查通过",
125
- error_message=None,
148
+ success=success,
149
+ output=output,
150
+ error_message=error_msg,
126
151
  build_system=BuildSystem.PYTHON,
127
152
  duration=duration,
128
153
  )
@@ -7,6 +7,8 @@ Rust构建验证器模块
7
7
  提供Rust项目的构建验证功能。
8
8
  """
9
9
 
10
+ import os
11
+ import subprocess
10
12
  import time
11
13
  from typing import List, Optional
12
14
 
@@ -14,25 +16,72 @@ from .base import BuildValidatorBase, BuildResult, BuildSystem
14
16
 
15
17
 
16
18
  class RustBuildValidator(BuildValidatorBase):
17
- """Rust构建验证器(使用cargo check)"""
19
+ """Rust构建验证器(使用cargo test,包括编译和测试)"""
20
+
21
+ BUILD_SYSTEM_NAME = "Cargo"
22
+ SUPPORTED_LANGUAGES = ["rust"]
18
23
 
19
24
  def validate(self, modified_files: Optional[List[str]] = None) -> BuildResult:
20
25
  start_time = time.time()
21
26
 
22
- # 使用 cargo check 进行增量检查(比 cargo build 更快)
23
- cmd = ["cargo", "check", "--message-format=json"]
27
+ # 使用 cargo test 进行构建和测试验证(会自动编译并运行测试)
28
+ # 设置 RUST_BACKTRACE=1 以启用调用链回溯
29
+ # 设置 RUSTFLAGS="-A warnings" 以屏蔽警告,只显示错误
30
+ cmd = ["cargo", "test", "--", "--nocapture"]
31
+
32
+ # 准备环境变量(继承当前环境并设置 RUST_BACKTRACE 和 RUSTFLAGS)
33
+ env = os.environ.copy()
34
+ env["RUST_BACKTRACE"] = "1"
35
+ # 如果已存在 RUSTFLAGS,则追加;否则新建
36
+ if "RUSTFLAGS" in env:
37
+ env["RUSTFLAGS"] = env["RUSTFLAGS"] + " -A warnings"
38
+ else:
39
+ env["RUSTFLAGS"] = "-A warnings"
40
+
41
+ # 直接使用 subprocess.run 以支持环境变量
42
+ try:
43
+ result = subprocess.run(
44
+ cmd,
45
+ cwd=self.project_root,
46
+ timeout=self.timeout,
47
+ capture_output=True,
48
+ text=True,
49
+ encoding="utf-8",
50
+ errors="replace",
51
+ env=env,
52
+ )
53
+ returncode = result.returncode
54
+ stdout = result.stdout
55
+ stderr = result.stderr
56
+ except subprocess.TimeoutExpired:
57
+ returncode = -1
58
+ stdout = ""
59
+ stderr = f"命令执行超时({self.timeout}秒)"
60
+ except FileNotFoundError:
61
+ returncode = -1
62
+ stdout = ""
63
+ stderr = f"命令未找到: {cmd[0]}"
64
+ except Exception as e:
65
+ returncode = -1
66
+ stdout = ""
67
+ stderr = f"执行命令时出错: {str(e)}"
24
68
 
25
- returncode, stdout, stderr = self._run_command(cmd)
26
69
  duration = time.time() - start_time
27
70
 
28
71
  success = returncode == 0
29
72
  output = stdout + stderr
30
73
 
31
74
  if not success:
32
- # 尝试解析JSON格式的错误信息
75
+ # 尝试解析错误信息(包括编译错误和测试失败)
33
76
  error_message = self._parse_cargo_errors(output)
77
+ print(f"❌ Rust 构建验证失败(耗时 {duration:.2f} 秒)")
78
+ if error_message:
79
+ print(f"错误信息:\n{error_message}")
80
+ else:
81
+ print(f"输出:\n{output[:500]}")
34
82
  else:
35
83
  error_message = None
84
+ print(f"✅ Rust 构建验证成功(耗时 {duration:.2f} 秒)")
36
85
 
37
86
  return BuildResult(
38
87
  success=success,
@@ -43,12 +92,19 @@ class RustBuildValidator(BuildValidatorBase):
43
92
  )
44
93
 
45
94
  def _parse_cargo_errors(self, output: str) -> str:
46
- """解析cargo的错误输出"""
95
+ """解析cargo的错误输出(包括编译错误和测试失败)"""
47
96
  # 简化处理:提取关键错误信息
48
97
  lines = output.split("\n")
49
98
  errors = []
50
99
  for line in lines:
100
+ # 匹配编译错误
51
101
  if "error[" in line or "error:" in line.lower():
52
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())
53
109
  return "\n".join(errors[:10]) if errors else output[:500] # 限制长度
54
110
 
@@ -9,7 +9,6 @@
9
9
 
10
10
  from typing import Dict, List, Optional
11
11
 
12
- from jarvis.jarvis_utils.output import OutputType, PrettyOutput
13
12
 
14
13
  from .base import BuildSystem, BuildValidatorBase, BuildResult
15
14
  from .detector import BuildSystemDetector
@@ -74,7 +73,7 @@ class BuildValidator:
74
73
  try:
75
74
  saved_enum = BuildSystem(saved_system)
76
75
  if saved_enum in detected_systems:
77
- PrettyOutput.print(f"使用配置文件中保存的构建系统: {saved_system}", OutputType.INFO)
76
+ print(f"ℹ️ 使用配置文件中保存的构建系统: {saved_system}")
78
77
  return saved_enum
79
78
  except ValueError:
80
79
  # 配置文件中保存的构建系统无效,忽略
@@ -95,10 +94,10 @@ class BuildValidator:
95
94
  selected = detected_systems[choice_num - 1]
96
95
  # 保存用户选择
97
96
  self.config.set_selected_build_system(selected.value)
98
- PrettyOutput.print(f"用户选择构建系统: {selected.value}", OutputType.INFO)
97
+ print(f"ℹ️ 用户选择构建系统: {selected.value}")
99
98
  return selected
100
99
  elif choice_num == len(detected_systems) + 1:
101
- PrettyOutput.print("用户取消选择,使用兜底验证器", OutputType.INFO)
100
+ print("ℹ️ 用户取消选择,使用兜底验证器")
102
101
  return None
103
102
  else:
104
103
  print(f"无效选择,请输入 1-{len(detected_systems) + 1}")
@@ -122,7 +121,7 @@ class BuildValidator:
122
121
 
123
122
  if not detected_systems:
124
123
  # 未检测到构建系统,使用兜底验证器
125
- PrettyOutput.print("未检测到构建系统,使用兜底验证器", OutputType.INFO)
124
+ print("ℹ️ 未检测到构建系统,使用兜底验证器")
126
125
  return self._fallback_validator.validate(modified_files)
127
126
 
128
127
  # 让用户选择构建系统(如果多个)
@@ -130,16 +129,16 @@ class BuildValidator:
130
129
 
131
130
  if build_system and build_system in self._validators:
132
131
  validator = self._validators[build_system]
133
- PrettyOutput.print(f"使用构建系统: {build_system.value}, 验证器: {validator.__class__.__name__}", OutputType.INFO)
132
+ print(f"ℹ️ 使用构建系统: {build_system.value}, 验证器: {validator.__class__.__name__}")
134
133
  try:
135
134
  return validator.validate(modified_files)
136
135
  except Exception as e:
137
- PrettyOutput.print(f"验证器 {validator.__class__.__name__} 执行失败: {e}, 使用兜底验证器", OutputType.WARNING)
136
+ print(f"⚠️ 验证器 {validator.__class__.__name__} 执行失败: {e}, 使用兜底验证器")
138
137
  # 验证器执行失败时,使用兜底验证器
139
138
  return self._fallback_validator.validate(modified_files)
140
139
  else:
141
140
  # 用户取消或未选择,使用兜底验证器
142
- PrettyOutput.print("使用兜底验证器", OutputType.INFO)
141
+ print("ℹ️ 使用兜底验证器")
143
142
  return self._fallback_validator.validate(modified_files)
144
143
 
145
144
  def register_validator(self, build_system: BuildSystem, validator: BuildValidatorBase):
@@ -150,5 +149,5 @@ class BuildValidator:
150
149
  validator: 验证器实例
151
150
  """
152
151
  self._validators[build_system] = validator
153
- PrettyOutput.print(f"注册自定义验证器: {build_system.value} -> {validator.__class__.__name__}", OutputType.INFO)
152
+ print(f"ℹ️ 注册自定义验证器: {build_system.value} -> {validator.__class__.__name__}")
154
153