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
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""构建修复循环模块。"""
|
|
3
|
+
|
|
4
|
+
import os
|
|
5
|
+
import subprocess
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from typing import Callable
|
|
8
|
+
from typing import List
|
|
9
|
+
|
|
10
|
+
from jarvis.jarvis_utils.output import PrettyOutput
|
|
11
|
+
|
|
12
|
+
from jarvis.jarvis_agent.events import AFTER_TOOL_CALL
|
|
13
|
+
from jarvis.jarvis_agent.events import BEFORE_TOOL_CALL
|
|
14
|
+
from jarvis.jarvis_c2rust.optimizer_options import OptimizeOptions
|
|
15
|
+
from jarvis.jarvis_c2rust.optimizer_options import OptimizeStats
|
|
16
|
+
from jarvis.jarvis_c2rust.optimizer_progress import ProgressManager
|
|
17
|
+
from jarvis.jarvis_c2rust.optimizer_utils import cargo_check_full
|
|
18
|
+
from jarvis.jarvis_c2rust.optimizer_utils import run_cargo_fmt
|
|
19
|
+
from jarvis.jarvis_code_agent.code_agent import CodeAgent
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class BuildFixOptimizer:
|
|
23
|
+
"""构建修复循环优化器。"""
|
|
24
|
+
|
|
25
|
+
def __init__(
|
|
26
|
+
self,
|
|
27
|
+
crate_dir: Path,
|
|
28
|
+
options: OptimizeOptions,
|
|
29
|
+
stats: OptimizeStats,
|
|
30
|
+
progress_manager: ProgressManager,
|
|
31
|
+
append_additional_notes_func: Callable[[str], str],
|
|
32
|
+
):
|
|
33
|
+
self.crate_dir = crate_dir
|
|
34
|
+
self.options = options
|
|
35
|
+
self.stats = stats
|
|
36
|
+
self.progress_manager = progress_manager
|
|
37
|
+
self.append_additional_notes = append_additional_notes_func
|
|
38
|
+
|
|
39
|
+
def build_fix_loop(self, scope_files: List[Path]) -> bool:
|
|
40
|
+
"""
|
|
41
|
+
循环执行 cargo check 并用 CodeAgent 进行最小修复,直到通过或达到重试上限或检查预算耗尽。
|
|
42
|
+
仅允许(优先)修改 scope_files(除非确有必要),以支持分批优化。
|
|
43
|
+
返回 True 表示修复成功构建通过;False 表示未能在限制内修复。
|
|
44
|
+
|
|
45
|
+
注意:CodeAgent 必须在 crate 目录下创建和执行,以确保所有文件操作和命令执行都在正确的上下文中进行。
|
|
46
|
+
"""
|
|
47
|
+
maxr = int(self.options.build_fix_retries or 0)
|
|
48
|
+
if maxr <= 0:
|
|
49
|
+
return False
|
|
50
|
+
crate = self.crate_dir.resolve()
|
|
51
|
+
allowed: List[str] = []
|
|
52
|
+
for p in scope_files:
|
|
53
|
+
try:
|
|
54
|
+
rel = p.resolve().relative_to(crate).as_posix()
|
|
55
|
+
except Exception:
|
|
56
|
+
rel = p.as_posix()
|
|
57
|
+
allowed.append(rel)
|
|
58
|
+
|
|
59
|
+
attempt = 0
|
|
60
|
+
while True:
|
|
61
|
+
# 检查预算
|
|
62
|
+
if (
|
|
63
|
+
self.options.max_checks
|
|
64
|
+
and self.stats.cargo_checks >= self.options.max_checks
|
|
65
|
+
):
|
|
66
|
+
return False
|
|
67
|
+
# 执行构建
|
|
68
|
+
output = ""
|
|
69
|
+
try:
|
|
70
|
+
res = subprocess.run(
|
|
71
|
+
["cargo", "test", "-q"],
|
|
72
|
+
capture_output=True,
|
|
73
|
+
text=True,
|
|
74
|
+
check=False,
|
|
75
|
+
cwd=str(crate),
|
|
76
|
+
timeout=self.options.cargo_test_timeout
|
|
77
|
+
if self.options.cargo_test_timeout > 0
|
|
78
|
+
else None,
|
|
79
|
+
)
|
|
80
|
+
self.stats.cargo_checks += 1
|
|
81
|
+
if res.returncode == 0:
|
|
82
|
+
PrettyOutput.auto_print(
|
|
83
|
+
"✅ [c2rust-optimizer][build-fix] 构建修复成功。"
|
|
84
|
+
)
|
|
85
|
+
return True
|
|
86
|
+
output = ((res.stdout or "") + ("\n" + (res.stderr or ""))).strip()
|
|
87
|
+
except subprocess.TimeoutExpired as e:
|
|
88
|
+
self.stats.cargo_checks += 1
|
|
89
|
+
out_s = e.stdout.decode("utf-8", errors="ignore") if e.stdout else ""
|
|
90
|
+
err_s = e.stderr.decode("utf-8", errors="ignore") if e.stderr else ""
|
|
91
|
+
output = f"cargo test timed out after {self.options.cargo_test_timeout} seconds"
|
|
92
|
+
full_output = (out_s + ("\n" + err_s if err_s else "")).strip()
|
|
93
|
+
if full_output:
|
|
94
|
+
output += f"\nOutput:\n{full_output}"
|
|
95
|
+
except Exception as e:
|
|
96
|
+
self.stats.cargo_checks += 1
|
|
97
|
+
output = f"cargo test exception: {e}"
|
|
98
|
+
|
|
99
|
+
# 达到重试上限则失败
|
|
100
|
+
attempt += 1
|
|
101
|
+
if attempt > maxr:
|
|
102
|
+
PrettyOutput.auto_print(
|
|
103
|
+
"❌ [c2rust-optimizer][build-fix] 构建修复重试次数已用尽。"
|
|
104
|
+
)
|
|
105
|
+
return False
|
|
106
|
+
|
|
107
|
+
PrettyOutput.auto_print(
|
|
108
|
+
f"⚠️ [c2rust-optimizer][build-fix] 构建失败。正在尝试使用 CodeAgent 进行修复 (第 {attempt}/{maxr} 次尝试)..."
|
|
109
|
+
)
|
|
110
|
+
# 生成最小修复提示
|
|
111
|
+
prompt_lines = [
|
|
112
|
+
"请根据以下测试/构建错误对 crate 进行最小必要的修复以通过 `cargo test`:",
|
|
113
|
+
f"- crate 根目录:{crate}",
|
|
114
|
+
"",
|
|
115
|
+
"本次修复优先且仅允许修改以下文件(除非确有必要,否则不要修改范围外文件):",
|
|
116
|
+
*[f"- {rel}" for rel in allowed],
|
|
117
|
+
"",
|
|
118
|
+
"约束与范围:",
|
|
119
|
+
"- 保持最小改动,不要进行与错误无关的重构或格式化;",
|
|
120
|
+
"- 仅输出补丁,不要输出解释或多余文本。",
|
|
121
|
+
"",
|
|
122
|
+
"优化目标:",
|
|
123
|
+
"1) 修复构建/测试错误:",
|
|
124
|
+
" - 必须优先解决所有编译错误和测试失败问题;",
|
|
125
|
+
" - 修复时应该先解决编译错误,然后再解决测试失败;",
|
|
126
|
+
" - 如果修复过程中引入了新的错误,必须立即修复这些新错误。",
|
|
127
|
+
"",
|
|
128
|
+
"2) 修复已有实现的问题:",
|
|
129
|
+
" - 如果在修复构建/测试错误的过程中,发现代码已有的实现有问题(如逻辑错误、潜在 bug、性能问题、内存安全问题等),也需要一并修复;",
|
|
130
|
+
" - 这些问题可能包括但不限于:不正确的算法实现、未检查的边界条件、资源泄漏、竞态条件、数据竞争等;",
|
|
131
|
+
" - 修复时应该保持最小改动原则,优先修复最严重的问题。",
|
|
132
|
+
"",
|
|
133
|
+
"优先级说明:",
|
|
134
|
+
"- **必须优先解决所有编译错误和测试失败问题**;",
|
|
135
|
+
"- 修复时应该先解决编译错误,然后再解决测试失败;",
|
|
136
|
+
"- 如果修复过程中引入了新的错误,必须立即修复这些新错误。",
|
|
137
|
+
"",
|
|
138
|
+
"自检要求:在每次输出补丁后,请使用 execute_script 工具在 crate 根目录执行 `cargo test -q` 进行验证;",
|
|
139
|
+
"若出现编译错误或测试失败,请优先修复这些问题;",
|
|
140
|
+
"若未通过,请继续输出新的补丁进行最小修复并再次自检,直至 `cargo test` 通过为止。",
|
|
141
|
+
"",
|
|
142
|
+
"构建错误如下:",
|
|
143
|
+
"<BUILD_ERROR>",
|
|
144
|
+
output,
|
|
145
|
+
"</BUILD_ERROR>",
|
|
146
|
+
]
|
|
147
|
+
prompt = "\n".join(prompt_lines)
|
|
148
|
+
prompt = self.append_additional_notes(prompt)
|
|
149
|
+
# 切换到 crate 目录,确保 CodeAgent 在正确的上下文中创建和执行
|
|
150
|
+
prev_cwd = os.getcwd()
|
|
151
|
+
try:
|
|
152
|
+
os.chdir(str(crate))
|
|
153
|
+
# 修复前执行 cargo fmt
|
|
154
|
+
run_cargo_fmt(crate)
|
|
155
|
+
|
|
156
|
+
# 记录运行前的 commit id
|
|
157
|
+
commit_before = self.progress_manager.get_crate_commit_hash()
|
|
158
|
+
|
|
159
|
+
# CodeAgent 在 crate 目录下创建和执行
|
|
160
|
+
agent = CodeAgent(
|
|
161
|
+
name=f"BuildFixAgent-iter{attempt}",
|
|
162
|
+
need_summary=False,
|
|
163
|
+
non_interactive=self.options.non_interactive,
|
|
164
|
+
model_group=self.options.llm_group,
|
|
165
|
+
enable_task_list_manager=False,
|
|
166
|
+
disable_review=True,
|
|
167
|
+
)
|
|
168
|
+
# 订阅 BEFORE_TOOL_CALL 和 AFTER_TOOL_CALL 事件,用于细粒度检测测试代码删除
|
|
169
|
+
agent.event_bus.subscribe(
|
|
170
|
+
BEFORE_TOOL_CALL, self.progress_manager.on_before_tool_call
|
|
171
|
+
)
|
|
172
|
+
agent.event_bus.subscribe(
|
|
173
|
+
AFTER_TOOL_CALL, self.progress_manager.on_after_tool_call
|
|
174
|
+
)
|
|
175
|
+
# 记录 Agent 创建时的 commit id(作为初始值)
|
|
176
|
+
agent_id = id(agent)
|
|
177
|
+
agent_key = f"agent_{agent_id}"
|
|
178
|
+
initial_commit = self.progress_manager.get_crate_commit_hash()
|
|
179
|
+
if initial_commit:
|
|
180
|
+
self.progress_manager._agent_before_commits[agent_key] = (
|
|
181
|
+
initial_commit
|
|
182
|
+
)
|
|
183
|
+
agent.run(
|
|
184
|
+
prompt,
|
|
185
|
+
prefix=f"[c2rust-optimizer][build-fix iter={attempt}]",
|
|
186
|
+
suffix="",
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
# 检测并处理测试代码删除
|
|
190
|
+
if self.progress_manager.check_and_handle_test_deletion(
|
|
191
|
+
commit_before, agent
|
|
192
|
+
):
|
|
193
|
+
# 如果回退了,需要重新运行 agent
|
|
194
|
+
PrettyOutput.auto_print(
|
|
195
|
+
f"⚠️ [c2rust-optimizer][build-fix] 检测到测试代码删除问题,已回退,重新运行 agent (iter={attempt})"
|
|
196
|
+
)
|
|
197
|
+
commit_before = self.progress_manager.get_crate_commit_hash()
|
|
198
|
+
agent.run(
|
|
199
|
+
prompt,
|
|
200
|
+
prefix=f"[c2rust-optimizer][build-fix iter={attempt}][retry]",
|
|
201
|
+
suffix="",
|
|
202
|
+
)
|
|
203
|
+
# 再次检测
|
|
204
|
+
if self.progress_manager.check_and_handle_test_deletion(
|
|
205
|
+
commit_before, agent
|
|
206
|
+
):
|
|
207
|
+
PrettyOutput.auto_print(
|
|
208
|
+
f"❌ [c2rust-optimizer][build-fix] 再次检测到测试代码删除问题,已回退 (iter={attempt})"
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
# 验证修复是否成功(通过 cargo test)
|
|
212
|
+
ok, _ = cargo_check_full(
|
|
213
|
+
crate,
|
|
214
|
+
self.stats,
|
|
215
|
+
self.options.max_checks,
|
|
216
|
+
timeout=self.options.cargo_test_timeout,
|
|
217
|
+
)
|
|
218
|
+
if ok:
|
|
219
|
+
# 修复成功,保存进度和 commit id
|
|
220
|
+
file_paths = [crate / f for f in allowed if (crate / f).exists()]
|
|
221
|
+
self.progress_manager.save_fix_progress(
|
|
222
|
+
"build_fix",
|
|
223
|
+
f"iter{attempt}",
|
|
224
|
+
file_paths if file_paths else None,
|
|
225
|
+
)
|
|
226
|
+
PrettyOutput.auto_print(
|
|
227
|
+
f"✅ [c2rust-optimizer][build-fix] 第 {attempt} 次修复成功,已保存进度"
|
|
228
|
+
)
|
|
229
|
+
# 返回 True 表示修复成功
|
|
230
|
+
return True
|
|
231
|
+
else:
|
|
232
|
+
# 测试失败,回退到运行前的 commit
|
|
233
|
+
if commit_before:
|
|
234
|
+
PrettyOutput.auto_print(
|
|
235
|
+
f"⚠️ [c2rust-optimizer][build-fix] 第 {attempt} 次修复后测试失败,回退到运行前的 commit: {commit_before[:8]}"
|
|
236
|
+
)
|
|
237
|
+
if self.progress_manager.reset_to_commit(commit_before):
|
|
238
|
+
PrettyOutput.auto_print(
|
|
239
|
+
f"ℹ️ [c2rust-optimizer][build-fix] 已成功回退到 commit: {commit_before[:8]}"
|
|
240
|
+
)
|
|
241
|
+
else:
|
|
242
|
+
PrettyOutput.auto_print(
|
|
243
|
+
"❌ [c2rust-optimizer][build-fix] 回退失败,请手动检查代码状态"
|
|
244
|
+
)
|
|
245
|
+
else:
|
|
246
|
+
PrettyOutput.auto_print(
|
|
247
|
+
f"⚠️ [c2rust-optimizer][build-fix] 第 {attempt} 次修复后测试失败,但无法获取运行前的 commit,继续尝试"
|
|
248
|
+
)
|
|
249
|
+
finally:
|
|
250
|
+
os.chdir(prev_cwd)
|
|
251
|
+
|
|
252
|
+
def verify_and_fix_after_step(
|
|
253
|
+
self, step_name: str, target_files: List[Path]
|
|
254
|
+
) -> bool:
|
|
255
|
+
"""
|
|
256
|
+
验证步骤执行后的测试,如果失败则尝试修复。
|
|
257
|
+
|
|
258
|
+
Args:
|
|
259
|
+
step_name: 步骤名称(用于错误消息)
|
|
260
|
+
target_files: 目标文件列表(用于修复范围)
|
|
261
|
+
|
|
262
|
+
Returns:
|
|
263
|
+
True: 测试通过或修复成功
|
|
264
|
+
False: 测试失败且修复失败(已回滚)
|
|
265
|
+
"""
|
|
266
|
+
ok, diag_full = cargo_check_full(
|
|
267
|
+
self.crate_dir,
|
|
268
|
+
self.stats,
|
|
269
|
+
self.options.max_checks,
|
|
270
|
+
timeout=self.options.cargo_test_timeout,
|
|
271
|
+
)
|
|
272
|
+
if not ok:
|
|
273
|
+
fixed = self.build_fix_loop(target_files)
|
|
274
|
+
if not fixed:
|
|
275
|
+
first = (
|
|
276
|
+
diag_full.splitlines()[0]
|
|
277
|
+
if isinstance(diag_full, str) and diag_full
|
|
278
|
+
else "failed"
|
|
279
|
+
)
|
|
280
|
+
if self.stats.errors is not None:
|
|
281
|
+
self.stats.errors.append(f"test after {step_name} failed: {first}")
|
|
282
|
+
try:
|
|
283
|
+
self.progress_manager.reset_to_snapshot()
|
|
284
|
+
finally:
|
|
285
|
+
return False
|
|
286
|
+
return True
|