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.
- jarvis/__init__.py +1 -1
- jarvis/jarvis_agent/__init__.py +567 -222
- jarvis/jarvis_agent/agent_manager.py +19 -12
- jarvis/jarvis_agent/builtin_input_handler.py +79 -11
- jarvis/jarvis_agent/config_editor.py +7 -2
- jarvis/jarvis_agent/event_bus.py +24 -13
- jarvis/jarvis_agent/events.py +19 -1
- jarvis/jarvis_agent/file_context_handler.py +67 -64
- jarvis/jarvis_agent/file_methodology_manager.py +38 -24
- jarvis/jarvis_agent/jarvis.py +186 -114
- jarvis/jarvis_agent/language_extractors/__init__.py +8 -1
- jarvis/jarvis_agent/language_extractors/c_extractor.py +7 -4
- jarvis/jarvis_agent/language_extractors/cpp_extractor.py +9 -4
- jarvis/jarvis_agent/language_extractors/go_extractor.py +7 -4
- jarvis/jarvis_agent/language_extractors/java_extractor.py +27 -20
- jarvis/jarvis_agent/language_extractors/javascript_extractor.py +22 -17
- jarvis/jarvis_agent/language_extractors/python_extractor.py +7 -4
- jarvis/jarvis_agent/language_extractors/rust_extractor.py +7 -4
- jarvis/jarvis_agent/language_extractors/typescript_extractor.py +22 -17
- jarvis/jarvis_agent/language_support_info.py +250 -219
- jarvis/jarvis_agent/main.py +19 -23
- jarvis/jarvis_agent/memory_manager.py +9 -6
- jarvis/jarvis_agent/methodology_share_manager.py +21 -15
- jarvis/jarvis_agent/output_handler.py +4 -2
- jarvis/jarvis_agent/prompt_builder.py +7 -6
- jarvis/jarvis_agent/prompt_manager.py +113 -8
- jarvis/jarvis_agent/prompts.py +317 -85
- jarvis/jarvis_agent/protocols.py +5 -2
- jarvis/jarvis_agent/run_loop.py +192 -32
- jarvis/jarvis_agent/session_manager.py +7 -3
- jarvis/jarvis_agent/share_manager.py +23 -13
- jarvis/jarvis_agent/shell_input_handler.py +12 -8
- jarvis/jarvis_agent/stdio_redirect.py +25 -26
- jarvis/jarvis_agent/task_analyzer.py +29 -23
- jarvis/jarvis_agent/task_list.py +869 -0
- jarvis/jarvis_agent/task_manager.py +26 -23
- jarvis/jarvis_agent/tool_executor.py +6 -5
- jarvis/jarvis_agent/tool_share_manager.py +24 -14
- jarvis/jarvis_agent/user_interaction.py +3 -3
- jarvis/jarvis_agent/utils.py +9 -1
- jarvis/jarvis_agent/web_bridge.py +37 -17
- jarvis/jarvis_agent/web_output_sink.py +5 -2
- jarvis/jarvis_agent/web_server.py +165 -36
- jarvis/jarvis_c2rust/__init__.py +1 -1
- jarvis/jarvis_c2rust/cli.py +260 -141
- jarvis/jarvis_c2rust/collector.py +37 -18
- jarvis/jarvis_c2rust/constants.py +60 -0
- jarvis/jarvis_c2rust/library_replacer.py +242 -1010
- jarvis/jarvis_c2rust/library_replacer_checkpoint.py +133 -0
- jarvis/jarvis_c2rust/library_replacer_llm.py +287 -0
- jarvis/jarvis_c2rust/library_replacer_loader.py +191 -0
- jarvis/jarvis_c2rust/library_replacer_output.py +134 -0
- jarvis/jarvis_c2rust/library_replacer_prompts.py +124 -0
- jarvis/jarvis_c2rust/library_replacer_utils.py +188 -0
- jarvis/jarvis_c2rust/llm_module_agent.py +98 -1044
- jarvis/jarvis_c2rust/llm_module_agent_apply.py +170 -0
- jarvis/jarvis_c2rust/llm_module_agent_executor.py +288 -0
- jarvis/jarvis_c2rust/llm_module_agent_loader.py +170 -0
- jarvis/jarvis_c2rust/llm_module_agent_prompts.py +268 -0
- jarvis/jarvis_c2rust/llm_module_agent_types.py +57 -0
- jarvis/jarvis_c2rust/llm_module_agent_utils.py +150 -0
- jarvis/jarvis_c2rust/llm_module_agent_validator.py +119 -0
- jarvis/jarvis_c2rust/loaders.py +28 -10
- jarvis/jarvis_c2rust/models.py +5 -2
- jarvis/jarvis_c2rust/optimizer.py +192 -1974
- jarvis/jarvis_c2rust/optimizer_build_fix.py +286 -0
- jarvis/jarvis_c2rust/optimizer_clippy.py +766 -0
- jarvis/jarvis_c2rust/optimizer_config.py +49 -0
- jarvis/jarvis_c2rust/optimizer_docs.py +183 -0
- jarvis/jarvis_c2rust/optimizer_options.py +48 -0
- jarvis/jarvis_c2rust/optimizer_progress.py +469 -0
- jarvis/jarvis_c2rust/optimizer_report.py +52 -0
- jarvis/jarvis_c2rust/optimizer_unsafe.py +309 -0
- jarvis/jarvis_c2rust/optimizer_utils.py +469 -0
- jarvis/jarvis_c2rust/optimizer_visibility.py +185 -0
- jarvis/jarvis_c2rust/scanner.py +229 -166
- jarvis/jarvis_c2rust/transpiler.py +531 -2732
- jarvis/jarvis_c2rust/transpiler_agents.py +503 -0
- jarvis/jarvis_c2rust/transpiler_build.py +1294 -0
- jarvis/jarvis_c2rust/transpiler_codegen.py +204 -0
- jarvis/jarvis_c2rust/transpiler_compile.py +146 -0
- jarvis/jarvis_c2rust/transpiler_config.py +178 -0
- jarvis/jarvis_c2rust/transpiler_context.py +122 -0
- jarvis/jarvis_c2rust/transpiler_executor.py +516 -0
- jarvis/jarvis_c2rust/transpiler_generation.py +278 -0
- jarvis/jarvis_c2rust/transpiler_git.py +163 -0
- jarvis/jarvis_c2rust/transpiler_mod_utils.py +225 -0
- jarvis/jarvis_c2rust/transpiler_modules.py +336 -0
- jarvis/jarvis_c2rust/transpiler_planning.py +394 -0
- jarvis/jarvis_c2rust/transpiler_review.py +1196 -0
- jarvis/jarvis_c2rust/transpiler_symbols.py +176 -0
- jarvis/jarvis_c2rust/utils.py +269 -79
- jarvis/jarvis_code_agent/after_change.py +233 -0
- jarvis/jarvis_code_agent/build_validation_config.py +37 -30
- jarvis/jarvis_code_agent/builtin_rules.py +68 -0
- jarvis/jarvis_code_agent/code_agent.py +976 -1517
- jarvis/jarvis_code_agent/code_agent_build.py +227 -0
- jarvis/jarvis_code_agent/code_agent_diff.py +246 -0
- jarvis/jarvis_code_agent/code_agent_git.py +525 -0
- jarvis/jarvis_code_agent/code_agent_impact.py +177 -0
- jarvis/jarvis_code_agent/code_agent_lint.py +283 -0
- jarvis/jarvis_code_agent/code_agent_llm.py +159 -0
- jarvis/jarvis_code_agent/code_agent_postprocess.py +105 -0
- jarvis/jarvis_code_agent/code_agent_prompts.py +46 -0
- jarvis/jarvis_code_agent/code_agent_rules.py +305 -0
- jarvis/jarvis_code_agent/code_analyzer/__init__.py +52 -48
- jarvis/jarvis_code_agent/code_analyzer/base_language.py +12 -10
- jarvis/jarvis_code_agent/code_analyzer/build_validator/__init__.py +12 -11
- jarvis/jarvis_code_agent/code_analyzer/build_validator/base.py +16 -12
- jarvis/jarvis_code_agent/code_analyzer/build_validator/cmake.py +26 -17
- jarvis/jarvis_code_agent/code_analyzer/build_validator/detector.py +558 -104
- jarvis/jarvis_code_agent/code_analyzer/build_validator/fallback.py +27 -16
- jarvis/jarvis_code_agent/code_analyzer/build_validator/go.py +22 -18
- jarvis/jarvis_code_agent/code_analyzer/build_validator/java_gradle.py +21 -16
- jarvis/jarvis_code_agent/code_analyzer/build_validator/java_maven.py +20 -16
- jarvis/jarvis_code_agent/code_analyzer/build_validator/makefile.py +27 -16
- jarvis/jarvis_code_agent/code_analyzer/build_validator/nodejs.py +47 -23
- jarvis/jarvis_code_agent/code_analyzer/build_validator/python.py +71 -37
- jarvis/jarvis_code_agent/code_analyzer/build_validator/rust.py +162 -35
- jarvis/jarvis_code_agent/code_analyzer/build_validator/validator.py +111 -57
- jarvis/jarvis_code_agent/code_analyzer/build_validator.py +18 -12
- jarvis/jarvis_code_agent/code_analyzer/context_manager.py +185 -183
- jarvis/jarvis_code_agent/code_analyzer/context_recommender.py +2 -1
- jarvis/jarvis_code_agent/code_analyzer/dependency_analyzer.py +24 -15
- jarvis/jarvis_code_agent/code_analyzer/file_ignore.py +227 -141
- jarvis/jarvis_code_agent/code_analyzer/impact_analyzer.py +321 -247
- jarvis/jarvis_code_agent/code_analyzer/language_registry.py +37 -29
- jarvis/jarvis_code_agent/code_analyzer/language_support.py +21 -13
- jarvis/jarvis_code_agent/code_analyzer/languages/__init__.py +15 -9
- jarvis/jarvis_code_agent/code_analyzer/languages/c_cpp_language.py +75 -45
- jarvis/jarvis_code_agent/code_analyzer/languages/go_language.py +87 -52
- jarvis/jarvis_code_agent/code_analyzer/languages/java_language.py +84 -51
- jarvis/jarvis_code_agent/code_analyzer/languages/javascript_language.py +94 -64
- jarvis/jarvis_code_agent/code_analyzer/languages/python_language.py +109 -71
- jarvis/jarvis_code_agent/code_analyzer/languages/rust_language.py +97 -63
- jarvis/jarvis_code_agent/code_analyzer/languages/typescript_language.py +103 -69
- jarvis/jarvis_code_agent/code_analyzer/llm_context_recommender.py +271 -268
- jarvis/jarvis_code_agent/code_analyzer/symbol_extractor.py +76 -64
- jarvis/jarvis_code_agent/code_analyzer/tree_sitter_extractor.py +92 -19
- jarvis/jarvis_code_agent/diff_visualizer.py +998 -0
- jarvis/jarvis_code_agent/lint.py +223 -524
- jarvis/jarvis_code_agent/rule_share_manager.py +158 -0
- jarvis/jarvis_code_agent/rules/clean_code.md +144 -0
- jarvis/jarvis_code_agent/rules/code_review.md +115 -0
- jarvis/jarvis_code_agent/rules/documentation.md +165 -0
- jarvis/jarvis_code_agent/rules/generate_rules.md +52 -0
- jarvis/jarvis_code_agent/rules/performance.md +158 -0
- jarvis/jarvis_code_agent/rules/refactoring.md +139 -0
- jarvis/jarvis_code_agent/rules/security.md +160 -0
- jarvis/jarvis_code_agent/rules/tdd.md +78 -0
- jarvis/jarvis_code_agent/test_rules/cpp_test.md +118 -0
- jarvis/jarvis_code_agent/test_rules/go_test.md +98 -0
- jarvis/jarvis_code_agent/test_rules/java_test.md +99 -0
- jarvis/jarvis_code_agent/test_rules/javascript_test.md +113 -0
- jarvis/jarvis_code_agent/test_rules/php_test.md +117 -0
- jarvis/jarvis_code_agent/test_rules/python_test.md +91 -0
- jarvis/jarvis_code_agent/test_rules/ruby_test.md +102 -0
- jarvis/jarvis_code_agent/test_rules/rust_test.md +86 -0
- jarvis/jarvis_code_agent/utils.py +36 -26
- jarvis/jarvis_code_analysis/checklists/loader.py +21 -21
- jarvis/jarvis_code_analysis/code_review.py +64 -33
- jarvis/jarvis_data/config_schema.json +285 -192
- jarvis/jarvis_git_squash/main.py +8 -6
- jarvis/jarvis_git_utils/git_commiter.py +53 -76
- jarvis/jarvis_mcp/__init__.py +5 -2
- jarvis/jarvis_mcp/sse_mcp_client.py +40 -30
- jarvis/jarvis_mcp/stdio_mcp_client.py +27 -19
- jarvis/jarvis_mcp/streamable_mcp_client.py +35 -26
- jarvis/jarvis_memory_organizer/memory_organizer.py +78 -55
- jarvis/jarvis_methodology/main.py +48 -39
- jarvis/jarvis_multi_agent/__init__.py +56 -23
- jarvis/jarvis_multi_agent/main.py +15 -18
- jarvis/jarvis_platform/base.py +179 -111
- jarvis/jarvis_platform/human.py +27 -16
- jarvis/jarvis_platform/kimi.py +52 -45
- jarvis/jarvis_platform/openai.py +101 -40
- jarvis/jarvis_platform/registry.py +51 -33
- jarvis/jarvis_platform/tongyi.py +68 -38
- jarvis/jarvis_platform/yuanbao.py +59 -43
- jarvis/jarvis_platform_manager/main.py +68 -76
- jarvis/jarvis_platform_manager/service.py +24 -14
- jarvis/jarvis_rag/README_CONFIG.md +314 -0
- jarvis/jarvis_rag/README_DYNAMIC_LOADING.md +311 -0
- jarvis/jarvis_rag/README_ONLINE_MODELS.md +230 -0
- jarvis/jarvis_rag/__init__.py +57 -4
- jarvis/jarvis_rag/cache.py +3 -1
- jarvis/jarvis_rag/cli.py +48 -68
- jarvis/jarvis_rag/embedding_interface.py +39 -0
- jarvis/jarvis_rag/embedding_manager.py +7 -230
- jarvis/jarvis_rag/embeddings/__init__.py +41 -0
- jarvis/jarvis_rag/embeddings/base.py +114 -0
- jarvis/jarvis_rag/embeddings/cohere.py +66 -0
- jarvis/jarvis_rag/embeddings/edgefn.py +117 -0
- jarvis/jarvis_rag/embeddings/local.py +260 -0
- jarvis/jarvis_rag/embeddings/openai.py +62 -0
- jarvis/jarvis_rag/embeddings/registry.py +293 -0
- jarvis/jarvis_rag/llm_interface.py +8 -6
- jarvis/jarvis_rag/query_rewriter.py +8 -9
- jarvis/jarvis_rag/rag_pipeline.py +61 -52
- jarvis/jarvis_rag/reranker.py +7 -75
- jarvis/jarvis_rag/reranker_interface.py +32 -0
- jarvis/jarvis_rag/rerankers/__init__.py +41 -0
- jarvis/jarvis_rag/rerankers/base.py +109 -0
- jarvis/jarvis_rag/rerankers/cohere.py +67 -0
- jarvis/jarvis_rag/rerankers/edgefn.py +140 -0
- jarvis/jarvis_rag/rerankers/jina.py +79 -0
- jarvis/jarvis_rag/rerankers/local.py +89 -0
- jarvis/jarvis_rag/rerankers/registry.py +293 -0
- jarvis/jarvis_rag/retriever.py +58 -43
- jarvis/jarvis_sec/__init__.py +66 -141
- jarvis/jarvis_sec/agents.py +21 -17
- jarvis/jarvis_sec/analysis.py +80 -33
- jarvis/jarvis_sec/checkers/__init__.py +7 -13
- jarvis/jarvis_sec/checkers/c_checker.py +356 -164
- jarvis/jarvis_sec/checkers/rust_checker.py +47 -29
- jarvis/jarvis_sec/cli.py +43 -21
- jarvis/jarvis_sec/clustering.py +430 -272
- jarvis/jarvis_sec/file_manager.py +99 -55
- jarvis/jarvis_sec/parsers.py +9 -6
- jarvis/jarvis_sec/prompts.py +4 -3
- jarvis/jarvis_sec/report.py +44 -22
- jarvis/jarvis_sec/review.py +180 -107
- jarvis/jarvis_sec/status.py +50 -41
- jarvis/jarvis_sec/types.py +3 -0
- jarvis/jarvis_sec/utils.py +160 -83
- jarvis/jarvis_sec/verification.py +411 -181
- jarvis/jarvis_sec/workflow.py +132 -21
- jarvis/jarvis_smart_shell/main.py +28 -41
- jarvis/jarvis_stats/cli.py +14 -12
- jarvis/jarvis_stats/stats.py +28 -19
- jarvis/jarvis_stats/storage.py +14 -8
- jarvis/jarvis_stats/visualizer.py +12 -7
- jarvis/jarvis_tools/base.py +5 -2
- jarvis/jarvis_tools/clear_memory.py +13 -9
- jarvis/jarvis_tools/cli/main.py +23 -18
- jarvis/jarvis_tools/edit_file.py +572 -873
- jarvis/jarvis_tools/execute_script.py +10 -7
- jarvis/jarvis_tools/file_analyzer.py +7 -8
- jarvis/jarvis_tools/meta_agent.py +287 -0
- jarvis/jarvis_tools/methodology.py +5 -3
- jarvis/jarvis_tools/read_code.py +305 -1438
- jarvis/jarvis_tools/read_symbols.py +50 -17
- jarvis/jarvis_tools/read_webpage.py +19 -18
- jarvis/jarvis_tools/registry.py +435 -156
- jarvis/jarvis_tools/retrieve_memory.py +16 -11
- jarvis/jarvis_tools/save_memory.py +8 -6
- jarvis/jarvis_tools/search_web.py +31 -31
- jarvis/jarvis_tools/sub_agent.py +32 -28
- jarvis/jarvis_tools/sub_code_agent.py +44 -60
- jarvis/jarvis_tools/task_list_manager.py +1811 -0
- jarvis/jarvis_tools/virtual_tty.py +29 -19
- jarvis/jarvis_utils/__init__.py +4 -0
- jarvis/jarvis_utils/builtin_replace_map.py +2 -1
- jarvis/jarvis_utils/clipboard.py +9 -8
- jarvis/jarvis_utils/collections.py +331 -0
- jarvis/jarvis_utils/config.py +699 -194
- jarvis/jarvis_utils/dialogue_recorder.py +294 -0
- jarvis/jarvis_utils/embedding.py +6 -3
- jarvis/jarvis_utils/file_processors.py +7 -1
- jarvis/jarvis_utils/fzf.py +9 -3
- jarvis/jarvis_utils/git_utils.py +71 -42
- jarvis/jarvis_utils/globals.py +116 -32
- jarvis/jarvis_utils/http.py +6 -2
- jarvis/jarvis_utils/input.py +318 -83
- jarvis/jarvis_utils/jsonnet_compat.py +119 -104
- jarvis/jarvis_utils/methodology.py +37 -28
- jarvis/jarvis_utils/output.py +201 -44
- jarvis/jarvis_utils/utils.py +986 -628
- {jarvis_ai_assistant-0.7.8.dist-info → jarvis_ai_assistant-1.0.2.dist-info}/METADATA +49 -33
- jarvis_ai_assistant-1.0.2.dist-info/RECORD +304 -0
- jarvis/jarvis_code_agent/code_analyzer/structured_code.py +0 -556
- jarvis/jarvis_tools/generate_new_tool.py +0 -205
- jarvis/jarvis_tools/lsp_client.py +0 -1552
- jarvis/jarvis_tools/rewrite_file.py +0 -105
- jarvis_ai_assistant-0.7.8.dist-info/RECORD +0 -218
- {jarvis_ai_assistant-0.7.8.dist-info → jarvis_ai_assistant-1.0.2.dist-info}/WHEEL +0 -0
- {jarvis_ai_assistant-0.7.8.dist-info → jarvis_ai_assistant-1.0.2.dist-info}/entry_points.txt +0 -0
- {jarvis_ai_assistant-0.7.8.dist-info → jarvis_ai_assistant-1.0.2.dist-info}/licenses/LICENSE +0 -0
- {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
|
|
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
|
|
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(
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
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(
|
|
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(
|
|
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
|
-
|
|
80
|
-
errors.append(
|
|
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
|
-
|
|
95
|
-
|
|
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
|
|
158
|
+
if (
|
|
159
|
+
"no tests ran" in output.lower()
|
|
160
|
+
or "no tests found" in output.lower()
|
|
161
|
+
):
|
|
128
162
|
# 没有测试文件,但语法检查通过,视为成功
|
|
129
|
-
|
|
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
|
-
|
|
174
|
+
PrettyOutput.auto_print(f"❌ Python 构建验证失败(耗时 {duration:.2f} 秒)")
|
|
139
175
|
if error_msg:
|
|
140
|
-
|
|
176
|
+
PrettyOutput.auto_print(f"错误信息:\n{error_msg}")
|
|
141
177
|
else:
|
|
142
|
-
|
|
178
|
+
PrettyOutput.auto_print(f"输出:\n{output[:500]}")
|
|
143
179
|
else:
|
|
144
|
-
|
|
145
|
-
|
|
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 .
|
|
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
|
-
|
|
83
|
+
PrettyOutput.auto_print(f"❌ Rust 构建验证失败(耗时 {duration:.2f} 秒)")
|
|
78
84
|
if error_message:
|
|
79
|
-
|
|
85
|
+
PrettyOutput.auto_print(f"错误信息:\n{error_message}")
|
|
80
86
|
else:
|
|
81
|
-
|
|
87
|
+
PrettyOutput.auto_print(f"输出:\n{output[:500]}")
|
|
82
88
|
else:
|
|
83
89
|
error_message = None
|
|
84
|
-
|
|
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
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
#
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
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字符
|