jarvis-ai-assistant 0.7.16__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.16.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.16.dist-info/RECORD +0 -218
- {jarvis_ai_assistant-0.7.16.dist-info → jarvis_ai_assistant-1.0.2.dist-info}/WHEEL +0 -0
- {jarvis_ai_assistant-0.7.16.dist-info → jarvis_ai_assistant-1.0.2.dist-info}/entry_points.txt +0 -0
- {jarvis_ai_assistant-0.7.16.dist-info → jarvis_ai_assistant-1.0.2.dist-info}/licenses/LICENSE +0 -0
- {jarvis_ai_assistant-0.7.16.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
|
构建系统检测器模块
|
|
6
3
|
|
|
@@ -8,118 +5,575 @@
|
|
|
8
5
|
"""
|
|
9
6
|
|
|
10
7
|
import os
|
|
11
|
-
|
|
8
|
+
import re
|
|
9
|
+
import subprocess
|
|
10
|
+
|
|
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
|
+
from typing import Tuple
|
|
12
19
|
|
|
13
20
|
from .base import BuildSystem
|
|
14
21
|
|
|
15
22
|
|
|
16
23
|
class BuildSystemDetector:
|
|
17
24
|
"""构建系统检测器"""
|
|
18
|
-
|
|
25
|
+
|
|
19
26
|
def __init__(self, project_root: str):
|
|
20
27
|
self.project_root = project_root
|
|
21
|
-
|
|
22
|
-
def
|
|
23
|
-
"""
|
|
24
|
-
|
|
28
|
+
|
|
29
|
+
def _get_file_statistics(self) -> str:
|
|
30
|
+
"""获取文件数量统计信息
|
|
31
|
+
|
|
32
|
+
使用loc工具获取文件统计信息。
|
|
33
|
+
|
|
25
34
|
Returns:
|
|
26
|
-
|
|
35
|
+
loc工具输出的原始字符串,失败时返回空字符串
|
|
27
36
|
"""
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
37
|
+
try:
|
|
38
|
+
# 调用loc工具获取统计信息
|
|
39
|
+
result = subprocess.run(
|
|
40
|
+
["loc"],
|
|
41
|
+
cwd=self.project_root,
|
|
42
|
+
capture_output=True,
|
|
43
|
+
text=True,
|
|
44
|
+
encoding="utf-8",
|
|
45
|
+
errors="replace",
|
|
46
|
+
check=False,
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
if result.returncode == 0 and result.stdout:
|
|
50
|
+
return result.stdout.strip()
|
|
51
|
+
else:
|
|
52
|
+
return ""
|
|
53
|
+
except FileNotFoundError:
|
|
54
|
+
# loc工具未安装,返回空字符串
|
|
55
|
+
PrettyOutput.auto_print("⚠️ loc工具未安装,无法获取文件统计信息")
|
|
56
|
+
return ""
|
|
57
|
+
except Exception as e:
|
|
58
|
+
# 其他错误,返回空字符串
|
|
59
|
+
PrettyOutput.auto_print(f"⚠️ 调用loc工具失败: {e}")
|
|
60
|
+
return ""
|
|
61
|
+
|
|
62
|
+
def _get_git_root_file_list(self, max_files: int = 100) -> str:
|
|
63
|
+
"""获取git根目录的文件列表(限制数量)
|
|
64
|
+
|
|
65
|
+
先识别git根目录,然后列出根目录下的文件列表。
|
|
66
|
+
|
|
67
|
+
Args:
|
|
68
|
+
max_files: 最大返回文件数量
|
|
69
|
+
|
|
34
70
|
Returns:
|
|
35
|
-
|
|
71
|
+
文件列表的字符串表示,每行一个文件,失败时返回空字符串
|
|
36
72
|
"""
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
"
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
73
|
+
try:
|
|
74
|
+
# 先识别git根目录
|
|
75
|
+
git_root_result = subprocess.run(
|
|
76
|
+
["git", "rev-parse", "--show-toplevel"],
|
|
77
|
+
cwd=self.project_root,
|
|
78
|
+
capture_output=True,
|
|
79
|
+
text=True,
|
|
80
|
+
check=False,
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
if git_root_result.returncode != 0:
|
|
84
|
+
# 如果不是git仓库,尝试直接读取当前目录
|
|
85
|
+
git_root = self.project_root
|
|
86
|
+
else:
|
|
87
|
+
git_root = git_root_result.stdout.strip()
|
|
88
|
+
|
|
89
|
+
# 列出git根目录下的文件
|
|
90
|
+
file_list: List[str] = []
|
|
91
|
+
|
|
92
|
+
# 使用git ls-files获取git跟踪的文件列表
|
|
93
|
+
result = subprocess.run(
|
|
94
|
+
["git", "ls-files"],
|
|
95
|
+
cwd=git_root,
|
|
96
|
+
capture_output=True,
|
|
97
|
+
text=True,
|
|
98
|
+
check=False,
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
if result.returncode == 0:
|
|
102
|
+
files = result.stdout.strip().split("\n")
|
|
103
|
+
# 只取根目录下的文件(不包含子目录)
|
|
104
|
+
for file_path in files:
|
|
105
|
+
if not file_path.strip():
|
|
106
|
+
continue
|
|
107
|
+
# 只取根目录下的文件(不包含路径分隔符)
|
|
108
|
+
if "/" not in file_path:
|
|
109
|
+
file_list.append(file_path)
|
|
110
|
+
if len(file_list) >= max_files:
|
|
111
|
+
break
|
|
112
|
+
else:
|
|
113
|
+
# 如果git命令失败,尝试直接读取根目录
|
|
114
|
+
try:
|
|
115
|
+
for item in os.listdir(git_root):
|
|
116
|
+
item_path = os.path.join(git_root, item)
|
|
117
|
+
if os.path.isfile(item_path) and not item.startswith("."):
|
|
118
|
+
file_list.append(item)
|
|
119
|
+
if len(file_list) >= max_files:
|
|
120
|
+
break
|
|
121
|
+
except Exception:
|
|
122
|
+
pass
|
|
123
|
+
|
|
124
|
+
# 返回格式化的字符串
|
|
125
|
+
if file_list:
|
|
126
|
+
return "\n".join(file_list)
|
|
127
|
+
else:
|
|
128
|
+
return ""
|
|
129
|
+
except Exception as e:
|
|
130
|
+
# 发生错误时返回空字符串
|
|
131
|
+
PrettyOutput.auto_print(f"⚠️ 获取git根目录文件列表失败: {e}")
|
|
132
|
+
return ""
|
|
133
|
+
|
|
134
|
+
def _get_supported_build_systems(self) -> List[str]:
|
|
135
|
+
"""获取当前支持的构建系统列表
|
|
136
|
+
|
|
137
|
+
Returns:
|
|
138
|
+
构建系统名称列表
|
|
139
|
+
"""
|
|
140
|
+
return [
|
|
141
|
+
"rust (Cargo.toml)",
|
|
142
|
+
"go (go.mod)",
|
|
143
|
+
"java_maven (pom.xml)",
|
|
144
|
+
"java_gradle (build.gradle/build.gradle.kts)",
|
|
145
|
+
"nodejs (package.json)",
|
|
146
|
+
"python (setup.py/pyproject.toml/requirements.txt等)",
|
|
147
|
+
"c_cmake (CMakeLists.txt)",
|
|
148
|
+
"c_makefile (Makefile)",
|
|
149
|
+
"unknown (未知/未识别)",
|
|
102
150
|
]
|
|
103
|
-
for indicator in indicators:
|
|
104
|
-
if os.path.exists(os.path.join(self.project_root, indicator)):
|
|
105
|
-
return BuildSystem.PYTHON
|
|
106
|
-
return None
|
|
107
|
-
|
|
108
|
-
def _detect_c_cmake(self) -> Optional[BuildSystem]:
|
|
109
|
-
"""检测CMake项目(CMakeLists.txt)"""
|
|
110
|
-
cmake_lists = os.path.join(self.project_root, "CMakeLists.txt")
|
|
111
|
-
if os.path.exists(cmake_lists):
|
|
112
|
-
# 检查是否同时存在Makefile
|
|
113
|
-
makefile = os.path.join(self.project_root, "Makefile")
|
|
114
|
-
if os.path.exists(makefile):
|
|
115
|
-
return BuildSystem.C_MAKEFILE_CMAKE
|
|
116
|
-
return BuildSystem.C_CMAKE
|
|
117
|
-
return None
|
|
118
|
-
|
|
119
|
-
def _detect_c_makefile(self) -> Optional[BuildSystem]:
|
|
120
|
-
"""检测Makefile项目"""
|
|
121
|
-
makefile = os.path.join(self.project_root, "Makefile")
|
|
122
|
-
if os.path.exists(makefile):
|
|
123
|
-
return BuildSystem.C_MAKEFILE
|
|
124
|
-
return None
|
|
125
151
|
|
|
152
|
+
def detect_with_llm(self) -> Optional[List[Tuple[BuildSystem, float]]]:
|
|
153
|
+
"""使用LLM检测构建系统(基于文件统计和文件列表)
|
|
154
|
+
|
|
155
|
+
Returns:
|
|
156
|
+
检测到的构建系统列表(带概率),按概率从大到小排序,如果无法检测则返回None
|
|
157
|
+
格式: [(BuildSystem, probability), ...]
|
|
158
|
+
"""
|
|
159
|
+
# 检查配置文件中是否已有保存的构建系统
|
|
160
|
+
from jarvis.jarvis_code_agent.build_validation_config import (
|
|
161
|
+
BuildValidationConfig,
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
config = BuildValidationConfig(self.project_root)
|
|
165
|
+
saved_system = config.get_selected_build_system()
|
|
166
|
+
if saved_system:
|
|
167
|
+
try:
|
|
168
|
+
saved_enum = BuildSystem(saved_system)
|
|
169
|
+
PrettyOutput.auto_print(
|
|
170
|
+
f"ℹ️ 使用配置文件中保存的构建系统: {saved_system}"
|
|
171
|
+
)
|
|
172
|
+
return [(saved_enum, 1.0)]
|
|
173
|
+
except ValueError:
|
|
174
|
+
# 配置文件中保存的构建系统无效,继续检测
|
|
175
|
+
pass
|
|
176
|
+
|
|
177
|
+
# 获取文件统计信息
|
|
178
|
+
file_stats = self._get_file_statistics()
|
|
179
|
+
|
|
180
|
+
# 获取git根目录文件列表
|
|
181
|
+
root_files = self._get_git_root_file_list(max_files=50)
|
|
182
|
+
|
|
183
|
+
# 获取支持的构建系统列表
|
|
184
|
+
supported_systems = self._get_supported_build_systems()
|
|
185
|
+
|
|
186
|
+
# 构建上下文
|
|
187
|
+
stats_text = file_stats if file_stats else " (无统计信息)"
|
|
188
|
+
# 格式化文件列表,每行前面加 " - "
|
|
189
|
+
if root_files:
|
|
190
|
+
files_lines = root_files.split("\n")[:30] # 限制前30个文件
|
|
191
|
+
files_text = "\n".join([f" - {f}" for f in files_lines])
|
|
192
|
+
else:
|
|
193
|
+
files_text = " (无文件列表)"
|
|
194
|
+
systems_text = "\n".join([f" - {sys}" for sys in supported_systems])
|
|
195
|
+
|
|
196
|
+
context = f"""请根据以下信息判断项目的构建系统:
|
|
197
|
+
|
|
198
|
+
文件数量统计(按扩展名,前20项):
|
|
199
|
+
{stats_text}
|
|
200
|
+
|
|
201
|
+
Git根目录文件列表(前30项):
|
|
202
|
+
{files_text}
|
|
203
|
+
|
|
204
|
+
当前支持的构建系统:
|
|
205
|
+
{systems_text}
|
|
206
|
+
|
|
207
|
+
请仔细分析文件统计信息和文件列表,判断项目使用的构建系统。
|
|
208
|
+
对于每个可能的构建系统,请给出一个概率值(0.0-1.0之间),表示该构建系统的可能性。
|
|
209
|
+
如果无法确定,可以返回 "unknown"。
|
|
210
|
+
|
|
211
|
+
请使用以下格式回答(必须包含且仅包含以下标记,多个构建系统用换行分隔):
|
|
212
|
+
- 如果判断为Rust项目,回答: <BUILD_SYSTEM>rust:0.95</BUILD_SYSTEM>
|
|
213
|
+
- 如果判断为Go项目,回答: <BUILD_SYSTEM>go:0.90</BUILD_SYSTEM>
|
|
214
|
+
- 如果判断为Java Maven项目,回答: <BUILD_SYSTEM>java_maven:0.85</BUILD_SYSTEM>
|
|
215
|
+
- 如果判断为Java Gradle项目,回答: <BUILD_SYSTEM>java_gradle:0.80</BUILD_SYSTEM>
|
|
216
|
+
- 如果判断为Node.js项目,回答: <BUILD_SYSTEM>nodejs:0.75</BUILD_SYSTEM>
|
|
217
|
+
- 如果判断为Python项目,回答: <BUILD_SYSTEM>python:0.70</BUILD_SYSTEM>
|
|
218
|
+
- 如果判断为CMake项目,回答: <BUILD_SYSTEM>c_cmake:0.65</BUILD_SYSTEM>
|
|
219
|
+
- 如果判断为Makefile项目,回答: <BUILD_SYSTEM>c_makefile:0.60</BUILD_SYSTEM>
|
|
220
|
+
- 如果无法确定,回答: <BUILD_SYSTEM>unknown:0.50</BUILD_SYSTEM>
|
|
221
|
+
|
|
222
|
+
格式说明:
|
|
223
|
+
- 每个构建系统一行,格式为 <BUILD_SYSTEM>系统名称:概率值</BUILD_SYSTEM>
|
|
224
|
+
- 概率值范围:0.0-1.0,数值越大表示可能性越高
|
|
225
|
+
- 可以返回多个构建系统,每个一行,按概率从高到低排序
|
|
226
|
+
- 示例:
|
|
227
|
+
<BUILD_SYSTEM>python:0.85</BUILD_SYSTEM>
|
|
228
|
+
<BUILD_SYSTEM>nodejs:0.30</BUILD_SYSTEM>
|
|
229
|
+
|
|
230
|
+
请严格按照协议格式回答,不要添加其他内容。
|
|
231
|
+
"""
|
|
232
|
+
|
|
233
|
+
try:
|
|
234
|
+
# 使用cheap平台进行判断
|
|
235
|
+
from jarvis.jarvis_platform.registry import PlatformRegistry
|
|
236
|
+
|
|
237
|
+
platform = PlatformRegistry().get_cheap_platform()
|
|
238
|
+
|
|
239
|
+
PrettyOutput.auto_print("🤖 正在使用LLM判断构建系统...")
|
|
240
|
+
response = platform.chat_until_success(context)
|
|
241
|
+
|
|
242
|
+
# 解析响应
|
|
243
|
+
detected_systems_with_prob: List[Tuple[BuildSystem, float]] = []
|
|
244
|
+
unknown_probabilities: List[float] = [] # 收集无效构建系统的概率
|
|
245
|
+
|
|
246
|
+
# 提取所有BUILD_SYSTEM标记
|
|
247
|
+
matches = re.findall(r"<BUILD_SYSTEM>(.*?)</BUILD_SYSTEM>", response)
|
|
248
|
+
|
|
249
|
+
for match in matches:
|
|
250
|
+
match = match.strip()
|
|
251
|
+
# 解析格式:系统名称:概率值
|
|
252
|
+
if ":" in match:
|
|
253
|
+
parts = match.split(":", 1)
|
|
254
|
+
system_str = parts[0].strip()
|
|
255
|
+
try:
|
|
256
|
+
prob_str = parts[1].strip()
|
|
257
|
+
probability = float(prob_str)
|
|
258
|
+
# 确保概率在0.0-1.0之间
|
|
259
|
+
probability = max(0.0, min(1.0, probability))
|
|
260
|
+
|
|
261
|
+
try:
|
|
262
|
+
system_enum = BuildSystem(system_str)
|
|
263
|
+
detected_systems_with_prob.append(
|
|
264
|
+
(system_enum, probability)
|
|
265
|
+
)
|
|
266
|
+
except ValueError:
|
|
267
|
+
# 无效的构建系统名称,转换为unknown
|
|
268
|
+
unknown_probabilities.append(probability)
|
|
269
|
+
except (ValueError, IndexError):
|
|
270
|
+
# 如果解析失败,尝试不带概率的格式(向后兼容)
|
|
271
|
+
try:
|
|
272
|
+
system_enum = BuildSystem(system_str)
|
|
273
|
+
# 默认概率为0.5
|
|
274
|
+
detected_systems_with_prob.append((system_enum, 0.5))
|
|
275
|
+
except ValueError:
|
|
276
|
+
# 无效的构建系统名称,转换为unknown(默认概率0.5)
|
|
277
|
+
unknown_probabilities.append(0.5)
|
|
278
|
+
else:
|
|
279
|
+
# 不带概率的格式(向后兼容)
|
|
280
|
+
try:
|
|
281
|
+
system_enum = BuildSystem(match)
|
|
282
|
+
# 默认概率为0.5
|
|
283
|
+
detected_systems_with_prob.append((system_enum, 0.5))
|
|
284
|
+
except ValueError:
|
|
285
|
+
# 无效的构建系统名称,转换为unknown(默认概率0.5)
|
|
286
|
+
unknown_probabilities.append(0.5)
|
|
287
|
+
|
|
288
|
+
# 如果有无效的构建系统,将它们合并为unknown
|
|
289
|
+
if unknown_probabilities:
|
|
290
|
+
# 使用平均概率,或者如果只有一个,直接使用
|
|
291
|
+
avg_prob = (
|
|
292
|
+
sum(unknown_probabilities) / len(unknown_probabilities)
|
|
293
|
+
if unknown_probabilities
|
|
294
|
+
else 0.5
|
|
295
|
+
)
|
|
296
|
+
# 检查是否已经有unknown,如果有则取最大概率
|
|
297
|
+
existing_unknown = None
|
|
298
|
+
for i, (sys, prob) in enumerate(detected_systems_with_prob):
|
|
299
|
+
if sys == BuildSystem.UNKNOWN:
|
|
300
|
+
existing_unknown = i
|
|
301
|
+
break
|
|
302
|
+
|
|
303
|
+
if existing_unknown is not None:
|
|
304
|
+
# 如果已有unknown,取最大概率
|
|
305
|
+
max_prob = max(
|
|
306
|
+
detected_systems_with_prob[existing_unknown][1], avg_prob
|
|
307
|
+
)
|
|
308
|
+
detected_systems_with_prob[existing_unknown] = (
|
|
309
|
+
BuildSystem.UNKNOWN,
|
|
310
|
+
max_prob,
|
|
311
|
+
)
|
|
312
|
+
else:
|
|
313
|
+
# 如果没有unknown,添加一个
|
|
314
|
+
detected_systems_with_prob.append((BuildSystem.UNKNOWN, avg_prob))
|
|
315
|
+
|
|
316
|
+
if detected_systems_with_prob:
|
|
317
|
+
# 按概率从大到小排序
|
|
318
|
+
detected_systems_with_prob.sort(key=lambda x: x[1], reverse=True)
|
|
319
|
+
return detected_systems_with_prob
|
|
320
|
+
else:
|
|
321
|
+
# 如果没有找到有效的构建系统,返回unknown
|
|
322
|
+
return [(BuildSystem.UNKNOWN, 0.5)]
|
|
323
|
+
|
|
324
|
+
except Exception as e:
|
|
325
|
+
PrettyOutput.auto_print(f"⚠️ LLM判断构建系统失败: {e},使用unknown")
|
|
326
|
+
return [(BuildSystem.UNKNOWN, 0.5)]
|
|
327
|
+
|
|
328
|
+
def detect_with_llm_and_confirm(self) -> Optional[List[BuildSystem]]:
|
|
329
|
+
"""使用LLM检测构建系统,并让用户确认
|
|
330
|
+
|
|
331
|
+
Returns:
|
|
332
|
+
用户确认后的构建系统列表,如果用户取消则返回None
|
|
333
|
+
"""
|
|
334
|
+
|
|
335
|
+
# 检查是否处于非交互模式
|
|
336
|
+
def _is_non_interactive() -> bool:
|
|
337
|
+
try:
|
|
338
|
+
from jarvis.jarvis_utils.config import is_non_interactive
|
|
339
|
+
|
|
340
|
+
return bool(is_non_interactive())
|
|
341
|
+
except Exception:
|
|
342
|
+
return False
|
|
343
|
+
|
|
344
|
+
detected_systems_with_prob = self.detect_with_llm()
|
|
345
|
+
|
|
346
|
+
if not detected_systems_with_prob:
|
|
347
|
+
return None
|
|
348
|
+
|
|
349
|
+
# 提取构建系统列表(按概率排序)
|
|
350
|
+
detected_systems = [sys for sys, _ in detected_systems_with_prob]
|
|
351
|
+
|
|
352
|
+
# 非交互模式:直接选择概率最高的构建系统
|
|
353
|
+
if _is_non_interactive():
|
|
354
|
+
system, prob = detected_systems_with_prob[0]
|
|
355
|
+
PrettyOutput.auto_print(
|
|
356
|
+
f"ℹ️ 非交互模式:自动选择概率最高的构建系统: {system.value} (概率: {prob:.2%})"
|
|
357
|
+
)
|
|
358
|
+
from jarvis.jarvis_code_agent.build_validation_config import (
|
|
359
|
+
BuildValidationConfig,
|
|
360
|
+
)
|
|
361
|
+
|
|
362
|
+
config = BuildValidationConfig(self.project_root)
|
|
363
|
+
config.set_selected_build_system(system.value)
|
|
364
|
+
return detected_systems
|
|
365
|
+
|
|
366
|
+
# 如果检测到unknown,直接使用,不询问用户
|
|
367
|
+
if len(detected_systems) == 1 and detected_systems[0] == BuildSystem.UNKNOWN:
|
|
368
|
+
prob = detected_systems_with_prob[0][1]
|
|
369
|
+
PrettyOutput.auto_print(
|
|
370
|
+
f"ℹ️ LLM判断:无法确定构建系统(unknown,概率: {prob:.2%}),直接使用unknown"
|
|
371
|
+
)
|
|
372
|
+
from jarvis.jarvis_code_agent.build_validation_config import (
|
|
373
|
+
BuildValidationConfig,
|
|
374
|
+
)
|
|
375
|
+
|
|
376
|
+
config = BuildValidationConfig(self.project_root)
|
|
377
|
+
config.set_selected_build_system("unknown")
|
|
378
|
+
return detected_systems
|
|
379
|
+
|
|
380
|
+
# 显示检测结果(按概率从大到小排序)
|
|
381
|
+
PrettyOutput.auto_print("\n🤖 LLM判断结果(按概率从大到小排序):")
|
|
382
|
+
for idx, (system, prob) in enumerate(detected_systems_with_prob, start=1):
|
|
383
|
+
PrettyOutput.auto_print(f" {idx}. {system.value} (概率: {prob:.2%})")
|
|
384
|
+
|
|
385
|
+
# 显示检测结果
|
|
386
|
+
if len(detected_systems) == 1:
|
|
387
|
+
system, prob = detected_systems_with_prob[0]
|
|
388
|
+
from jarvis.jarvis_code_agent.build_validation_config import (
|
|
389
|
+
BuildValidationConfig,
|
|
390
|
+
)
|
|
391
|
+
from jarvis.jarvis_utils.input import user_confirm
|
|
392
|
+
|
|
393
|
+
config = BuildValidationConfig(self.project_root)
|
|
394
|
+
|
|
395
|
+
if user_confirm(
|
|
396
|
+
f"是否确认使用 {system.value} 作为构建系统?(概率: {prob:.2%})",
|
|
397
|
+
default=True,
|
|
398
|
+
):
|
|
399
|
+
config.set_selected_build_system(system.value)
|
|
400
|
+
return detected_systems
|
|
401
|
+
else:
|
|
402
|
+
# 用户不确认,让用户选择(传入带概率的信息以保持排序)
|
|
403
|
+
return self._let_user_select_build_system_with_prob(
|
|
404
|
+
detected_systems_with_prob
|
|
405
|
+
)
|
|
406
|
+
else:
|
|
407
|
+
# 检测到多个构建系统,让用户选择(传入带概率的信息以保持排序)
|
|
408
|
+
return self._let_user_select_build_system_with_prob(
|
|
409
|
+
detected_systems_with_prob
|
|
410
|
+
)
|
|
411
|
+
|
|
412
|
+
def _let_user_select_build_system_with_prob(
|
|
413
|
+
self, detected_systems_with_prob: List[Tuple[BuildSystem, float]]
|
|
414
|
+
) -> Optional[List[BuildSystem]]:
|
|
415
|
+
"""让用户选择构建系统(带概率信息,按概率排序)
|
|
416
|
+
|
|
417
|
+
Args:
|
|
418
|
+
detected_systems_with_prob: 检测到的构建系统列表(带概率),已按概率排序
|
|
419
|
+
|
|
420
|
+
Returns:
|
|
421
|
+
用户选择的构建系统列表,如果用户取消则返回None
|
|
422
|
+
"""
|
|
423
|
+
|
|
424
|
+
# 检查是否处于非交互模式
|
|
425
|
+
def _is_non_interactive() -> bool:
|
|
426
|
+
try:
|
|
427
|
+
from jarvis.jarvis_utils.config import is_non_interactive
|
|
428
|
+
|
|
429
|
+
return bool(is_non_interactive())
|
|
430
|
+
except Exception:
|
|
431
|
+
return False
|
|
432
|
+
|
|
433
|
+
from jarvis.jarvis_code_agent.build_validation_config import (
|
|
434
|
+
BuildValidationConfig,
|
|
435
|
+
)
|
|
436
|
+
|
|
437
|
+
config = BuildValidationConfig(self.project_root)
|
|
438
|
+
|
|
439
|
+
# 非交互模式:直接选择概率最高的构建系统
|
|
440
|
+
if _is_non_interactive():
|
|
441
|
+
if detected_systems_with_prob:
|
|
442
|
+
selected, prob = detected_systems_with_prob[0]
|
|
443
|
+
PrettyOutput.auto_print(
|
|
444
|
+
f"ℹ️ 非交互模式:自动选择概率最高的构建系统: {selected.value} (概率: {prob:.2%})"
|
|
445
|
+
)
|
|
446
|
+
config.set_selected_build_system(selected.value)
|
|
447
|
+
return [selected]
|
|
448
|
+
else:
|
|
449
|
+
PrettyOutput.auto_print("ℹ️ 非交互模式:未检测到构建系统,使用unknown")
|
|
450
|
+
config.set_selected_build_system("unknown")
|
|
451
|
+
return [BuildSystem.UNKNOWN]
|
|
452
|
+
|
|
453
|
+
PrettyOutput.auto_print("\n请选择构建系统(按概率从大到小排序):")
|
|
454
|
+
for idx, (system, prob) in enumerate(detected_systems_with_prob, start=1):
|
|
455
|
+
PrettyOutput.auto_print(f" {idx}. {system.value} (概率: {prob:.2%})")
|
|
456
|
+
PrettyOutput.auto_print(
|
|
457
|
+
f" {len(detected_systems_with_prob) + 1}. 取消(使用unknown)"
|
|
458
|
+
)
|
|
459
|
+
|
|
460
|
+
while True:
|
|
461
|
+
try:
|
|
462
|
+
choice = input(
|
|
463
|
+
f"\n请选择 (1-{len(detected_systems_with_prob) + 1}): "
|
|
464
|
+
).strip()
|
|
465
|
+
choice_num = int(choice)
|
|
466
|
+
|
|
467
|
+
if 1 <= choice_num <= len(detected_systems_with_prob):
|
|
468
|
+
selected, prob = detected_systems_with_prob[choice_num - 1]
|
|
469
|
+
# 保存用户选择
|
|
470
|
+
config.set_selected_build_system(selected.value)
|
|
471
|
+
PrettyOutput.auto_print(
|
|
472
|
+
f"ℹ️ 用户选择构建系统: {selected.value} (概率: {prob:.2%})"
|
|
473
|
+
)
|
|
474
|
+
return [selected]
|
|
475
|
+
elif choice_num == len(detected_systems_with_prob) + 1:
|
|
476
|
+
PrettyOutput.auto_print("ℹ️ 用户取消选择,使用unknown")
|
|
477
|
+
config.set_selected_build_system("unknown")
|
|
478
|
+
return [BuildSystem.UNKNOWN]
|
|
479
|
+
else:
|
|
480
|
+
PrettyOutput.auto_print(
|
|
481
|
+
f"无效选择,请输入 1-{len(detected_systems_with_prob) + 1}"
|
|
482
|
+
)
|
|
483
|
+
except ValueError:
|
|
484
|
+
PrettyOutput.auto_print("请输入有效的数字")
|
|
485
|
+
except (KeyboardInterrupt, EOFError):
|
|
486
|
+
PrettyOutput.auto_print("\n用户取消,使用unknown")
|
|
487
|
+
config.set_selected_build_system("unknown")
|
|
488
|
+
return [BuildSystem.UNKNOWN]
|
|
489
|
+
|
|
490
|
+
def _let_user_select_build_system(
|
|
491
|
+
self, detected_systems: Optional[List[BuildSystem]] = None
|
|
492
|
+
) -> Optional[List[BuildSystem]]:
|
|
493
|
+
"""让用户选择构建系统(兼容旧接口)
|
|
494
|
+
|
|
495
|
+
Args:
|
|
496
|
+
detected_systems: 检测到的构建系统列表,如果为None则显示所有支持的构建系统
|
|
497
|
+
|
|
498
|
+
Returns:
|
|
499
|
+
用户选择的构建系统列表,如果用户取消则返回None
|
|
500
|
+
"""
|
|
501
|
+
|
|
502
|
+
# 检查是否处于非交互模式
|
|
503
|
+
def _is_non_interactive() -> bool:
|
|
504
|
+
try:
|
|
505
|
+
from jarvis.jarvis_utils.config import is_non_interactive
|
|
506
|
+
|
|
507
|
+
return bool(is_non_interactive())
|
|
508
|
+
except Exception:
|
|
509
|
+
return False
|
|
510
|
+
|
|
511
|
+
from jarvis.jarvis_code_agent.build_validation_config import (
|
|
512
|
+
BuildValidationConfig,
|
|
513
|
+
)
|
|
514
|
+
|
|
515
|
+
config = BuildValidationConfig(self.project_root)
|
|
516
|
+
|
|
517
|
+
if detected_systems is None:
|
|
518
|
+
# 显示所有支持的构建系统
|
|
519
|
+
all_systems = [
|
|
520
|
+
BuildSystem.RUST,
|
|
521
|
+
BuildSystem.GO,
|
|
522
|
+
BuildSystem.JAVA_MAVEN,
|
|
523
|
+
BuildSystem.JAVA_GRADLE,
|
|
524
|
+
BuildSystem.NODEJS,
|
|
525
|
+
BuildSystem.PYTHON,
|
|
526
|
+
BuildSystem.C_CMAKE,
|
|
527
|
+
BuildSystem.C_MAKEFILE,
|
|
528
|
+
BuildSystem.UNKNOWN,
|
|
529
|
+
]
|
|
530
|
+
detected_systems = all_systems
|
|
531
|
+
|
|
532
|
+
# 非交互模式:直接选择第一个构建系统(或unknown)
|
|
533
|
+
if _is_non_interactive():
|
|
534
|
+
if detected_systems and detected_systems[0] != BuildSystem.UNKNOWN:
|
|
535
|
+
selected_system: BuildSystem = detected_systems[0]
|
|
536
|
+
PrettyOutput.auto_print(
|
|
537
|
+
f"ℹ️ 非交互模式:自动选择构建系统: {selected_system.value}"
|
|
538
|
+
)
|
|
539
|
+
config.set_selected_build_system(selected_system.value)
|
|
540
|
+
return [selected_system]
|
|
541
|
+
else:
|
|
542
|
+
PrettyOutput.auto_print("ℹ️ 非交互模式:未检测到构建系统,使用unknown")
|
|
543
|
+
config.set_selected_build_system("unknown")
|
|
544
|
+
return [BuildSystem.UNKNOWN]
|
|
545
|
+
|
|
546
|
+
PrettyOutput.auto_print("\n请选择构建系统:")
|
|
547
|
+
for idx, system in enumerate(detected_systems, start=1):
|
|
548
|
+
PrettyOutput.auto_print(f" {idx}. {system.value}")
|
|
549
|
+
PrettyOutput.auto_print(f" {len(detected_systems) + 1}. 取消(使用unknown)")
|
|
550
|
+
|
|
551
|
+
while True:
|
|
552
|
+
try:
|
|
553
|
+
choice = input(f"\n请选择 (1-{len(detected_systems) + 1}): ").strip()
|
|
554
|
+
choice_num = int(choice)
|
|
555
|
+
|
|
556
|
+
if 1 <= choice_num <= len(detected_systems):
|
|
557
|
+
selected_build_system: BuildSystem = detected_systems[
|
|
558
|
+
choice_num - 1
|
|
559
|
+
]
|
|
560
|
+
# 保存用户选择
|
|
561
|
+
config.set_selected_build_system(selected_build_system.value)
|
|
562
|
+
PrettyOutput.auto_print(
|
|
563
|
+
f"ℹ️ 用户选择构建系统: {selected_build_system.value}"
|
|
564
|
+
)
|
|
565
|
+
return [selected_build_system]
|
|
566
|
+
elif choice_num == len(detected_systems) + 1:
|
|
567
|
+
PrettyOutput.auto_print("ℹ️ 用户取消选择,使用unknown")
|
|
568
|
+
config.set_selected_build_system("unknown")
|
|
569
|
+
return [BuildSystem.UNKNOWN]
|
|
570
|
+
else:
|
|
571
|
+
PrettyOutput.auto_print(
|
|
572
|
+
f"无效选择,请输入 1-{len(detected_systems) + 1}"
|
|
573
|
+
)
|
|
574
|
+
except ValueError:
|
|
575
|
+
PrettyOutput.auto_print("请输入有效的数字")
|
|
576
|
+
except (KeyboardInterrupt, EOFError):
|
|
577
|
+
PrettyOutput.auto_print("\n用户取消,使用unknown")
|
|
578
|
+
config.set_selected_build_system("unknown")
|
|
579
|
+
return [BuildSystem.UNKNOWN]
|