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
jarvis/jarvis_utils/config.py
CHANGED
|
@@ -1,21 +1,24 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
2
|
import os
|
|
3
3
|
from functools import lru_cache
|
|
4
|
-
from typing import Any
|
|
5
|
-
|
|
6
|
-
import
|
|
4
|
+
from typing import Any
|
|
5
|
+
from typing import Dict
|
|
6
|
+
from typing import List
|
|
7
|
+
from typing import Optional
|
|
8
|
+
from typing import cast
|
|
7
9
|
|
|
8
10
|
from jarvis.jarvis_utils.builtin_replace_map import BUILTIN_REPLACE_MAP
|
|
11
|
+
from jarvis.jarvis_utils.collections import CaseInsensitiveDict
|
|
9
12
|
|
|
10
13
|
# 全局环境变量存储
|
|
11
14
|
|
|
12
|
-
GLOBAL_CONFIG_DATA:
|
|
15
|
+
GLOBAL_CONFIG_DATA: CaseInsensitiveDict = CaseInsensitiveDict()
|
|
13
16
|
|
|
14
17
|
|
|
15
18
|
def set_global_env_data(env_data: Dict[str, Any]) -> None:
|
|
16
19
|
"""设置全局环境变量数据"""
|
|
17
20
|
global GLOBAL_CONFIG_DATA
|
|
18
|
-
GLOBAL_CONFIG_DATA = env_data
|
|
21
|
+
GLOBAL_CONFIG_DATA = CaseInsensitiveDict(env_data)
|
|
19
22
|
|
|
20
23
|
|
|
21
24
|
def set_config(key: str, value: Any) -> None:
|
|
@@ -37,7 +40,7 @@ def get_git_commit_prompt() -> str:
|
|
|
37
40
|
返回:
|
|
38
41
|
str: Git提交信息生成提示模板,如果未配置则返回空字符串
|
|
39
42
|
"""
|
|
40
|
-
return cast(str, GLOBAL_CONFIG_DATA.get("
|
|
43
|
+
return cast(str, GLOBAL_CONFIG_DATA.get("git_commit_prompt", ""))
|
|
41
44
|
|
|
42
45
|
|
|
43
46
|
# 输出窗口预留大小
|
|
@@ -49,25 +52,16 @@ def get_replace_map() -> dict:
|
|
|
49
52
|
"""
|
|
50
53
|
获取替换映射表。
|
|
51
54
|
|
|
52
|
-
优先使用GLOBAL_CONFIG_DATA['
|
|
53
|
-
|
|
54
|
-
如果文件不存在则返回内置替换映射表。
|
|
55
|
+
优先使用GLOBAL_CONFIG_DATA['replace_map']的配置,
|
|
56
|
+
如果未配置则返回内置替换映射表。
|
|
55
57
|
|
|
56
58
|
返回:
|
|
57
|
-
dict: 合并后的替换映射表字典(
|
|
59
|
+
dict: 合并后的替换映射表字典(内置+配置中的映射表)
|
|
58
60
|
"""
|
|
59
|
-
if "
|
|
60
|
-
return {**BUILTIN_REPLACE_MAP, **GLOBAL_CONFIG_DATA["
|
|
61
|
-
|
|
62
|
-
replace_map_path = os.path.join(get_data_dir(), "replace_map.yaml")
|
|
63
|
-
if not os.path.exists(replace_map_path):
|
|
64
|
-
return BUILTIN_REPLACE_MAP.copy()
|
|
61
|
+
if "replace_map" in GLOBAL_CONFIG_DATA:
|
|
62
|
+
return {**BUILTIN_REPLACE_MAP, **GLOBAL_CONFIG_DATA["replace_map"]}
|
|
65
63
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
with open(replace_map_path, "r", encoding="utf-8", errors="ignore") as file:
|
|
69
|
-
file_map = yaml.safe_load(file) or {}
|
|
70
|
-
return {**BUILTIN_REPLACE_MAP, **file_map}
|
|
64
|
+
return BUILTIN_REPLACE_MAP.copy()
|
|
71
65
|
|
|
72
66
|
|
|
73
67
|
def get_max_input_token_count(model_group_override: Optional[str] = None) -> int:
|
|
@@ -78,7 +72,35 @@ def get_max_input_token_count(model_group_override: Optional[str] = None) -> int
|
|
|
78
72
|
int: 模型能处理的最大输入token数量。
|
|
79
73
|
"""
|
|
80
74
|
config = _get_resolved_model_config(model_group_override)
|
|
81
|
-
return int(config.get("
|
|
75
|
+
return int(config.get("max_input_token_count", "128000"))
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def get_cheap_max_input_token_count(model_group_override: Optional[str] = None) -> int:
|
|
79
|
+
"""
|
|
80
|
+
获取廉价模型允许的最大输入token数量。
|
|
81
|
+
|
|
82
|
+
返回:
|
|
83
|
+
int: 模型能处理的最大输入token数量,如果未配置则回退到正常配置
|
|
84
|
+
"""
|
|
85
|
+
config = _get_resolved_model_config(model_group_override)
|
|
86
|
+
cheap_max_token = config.get("cheap_max_input_token_count")
|
|
87
|
+
if cheap_max_token:
|
|
88
|
+
return int(cheap_max_token)
|
|
89
|
+
return get_max_input_token_count(model_group_override)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def get_smart_max_input_token_count(model_group_override: Optional[str] = None) -> int:
|
|
93
|
+
"""
|
|
94
|
+
获取智能模型允许的最大输入token数量。
|
|
95
|
+
|
|
96
|
+
返回:
|
|
97
|
+
int: 模型能处理的最大输入token数量,如果未配置则回退到正常配置
|
|
98
|
+
"""
|
|
99
|
+
config = _get_resolved_model_config(model_group_override)
|
|
100
|
+
smart_max_token = config.get("smart_max_input_token_count")
|
|
101
|
+
if smart_max_token:
|
|
102
|
+
return int(smart_max_token)
|
|
103
|
+
return get_max_input_token_count(model_group_override)
|
|
82
104
|
|
|
83
105
|
|
|
84
106
|
def get_shell_name() -> str:
|
|
@@ -89,7 +111,7 @@ def get_shell_name() -> str:
|
|
|
89
111
|
str: Shell名称(例如bash, zsh, fish),默认为bash
|
|
90
112
|
|
|
91
113
|
获取顺序:
|
|
92
|
-
1. 先从GLOBAL_CONFIG_DATA中获取
|
|
114
|
+
1. 先从GLOBAL_CONFIG_DATA中获取shell配置
|
|
93
115
|
2. 再从GLOBAL_CONFIG_DATA中获取SHELL配置
|
|
94
116
|
3. 最后从环境变量SHELL获取
|
|
95
117
|
4. 如果都未配置,则默认返回bash
|
|
@@ -106,52 +128,221 @@ def _apply_llm_group_env_override(group_config: Dict[str, Any]) -> None:
|
|
|
106
128
|
)
|
|
107
129
|
|
|
108
130
|
|
|
131
|
+
def _apply_llm_config_to_env(resolved_config: Dict[str, Any]) -> None:
|
|
132
|
+
"""
|
|
133
|
+
将 resolved_config 中的 llm_config 应用到环境变量。
|
|
134
|
+
|
|
135
|
+
参数:
|
|
136
|
+
resolved_config: 解析后的模型配置字典
|
|
137
|
+
"""
|
|
138
|
+
# 处理 normal_llm 的 llm_config
|
|
139
|
+
if "llm_config" in resolved_config and isinstance(
|
|
140
|
+
resolved_config["llm_config"], dict
|
|
141
|
+
):
|
|
142
|
+
for key, value in resolved_config["llm_config"].items():
|
|
143
|
+
if value is not None:
|
|
144
|
+
# 将配置键转换为环境变量格式(大写,下划线分隔)
|
|
145
|
+
env_key = str(key).upper()
|
|
146
|
+
os.environ[env_key] = str(value)
|
|
147
|
+
|
|
148
|
+
# 处理 cheap_llm 的 llm_config
|
|
149
|
+
if "cheap_llm_config" in resolved_config and isinstance(
|
|
150
|
+
resolved_config["cheap_llm_config"], dict
|
|
151
|
+
):
|
|
152
|
+
for key, value in resolved_config["cheap_llm_config"].items():
|
|
153
|
+
if value is not None:
|
|
154
|
+
env_key = str(key).upper()
|
|
155
|
+
os.environ[env_key] = str(value)
|
|
156
|
+
|
|
157
|
+
# 处理 smart_llm 的 llm_config
|
|
158
|
+
if "smart_llm_config" in resolved_config and isinstance(
|
|
159
|
+
resolved_config["smart_llm_config"], dict
|
|
160
|
+
):
|
|
161
|
+
for key, value in resolved_config["smart_llm_config"].items():
|
|
162
|
+
if value is not None:
|
|
163
|
+
env_key = str(key).upper()
|
|
164
|
+
os.environ[env_key] = str(value)
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def _resolve_llm_reference(llm_name: str) -> Dict[str, Any]:
|
|
168
|
+
"""
|
|
169
|
+
从 llms 配置中解析引用的LLM配置。
|
|
170
|
+
|
|
171
|
+
参数:
|
|
172
|
+
llm_name: llms 中定义的LLM配置名称
|
|
173
|
+
|
|
174
|
+
返回:
|
|
175
|
+
Dict[str, Any]: 解析后的LLM配置字典,包含 platform, model, max_input_token_count, llm_config
|
|
176
|
+
"""
|
|
177
|
+
from jarvis.jarvis_utils.output import PrettyOutput
|
|
178
|
+
|
|
179
|
+
llms = GLOBAL_CONFIG_DATA.get("llms", {})
|
|
180
|
+
if not isinstance(llms, dict):
|
|
181
|
+
return {}
|
|
182
|
+
|
|
183
|
+
llm_config = llms.get(llm_name)
|
|
184
|
+
if not isinstance(llm_config, dict):
|
|
185
|
+
PrettyOutput.auto_print(f"⚠️ 警告:llms 中未找到名为 '{llm_name}' 的配置")
|
|
186
|
+
return {}
|
|
187
|
+
|
|
188
|
+
return llm_config.copy()
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
def _expand_llm_references(group_config: Dict[str, Any]) -> Dict[str, Any]:
|
|
192
|
+
"""
|
|
193
|
+
展开 llm_groups 中的 llm 引用(normal_llm, cheap_llm, smart_llm)到对应的配置字段。
|
|
194
|
+
|
|
195
|
+
注意:llm_groups 中不再支持直接定义 platform、model 等参数,只能通过引用 llms 中的配置。
|
|
196
|
+
|
|
197
|
+
参数:
|
|
198
|
+
group_config: 模型组配置字典
|
|
199
|
+
|
|
200
|
+
返回:
|
|
201
|
+
Dict[str, Any]: 展开后的配置字典
|
|
202
|
+
|
|
203
|
+
异常:
|
|
204
|
+
如果组配置中直接定义了 platform、model 等参数,会抛出 ValueError
|
|
205
|
+
"""
|
|
206
|
+
expanded_config = group_config.copy()
|
|
207
|
+
|
|
208
|
+
# 检查是否直接定义了不允许的参数
|
|
209
|
+
forbidden_keys = [
|
|
210
|
+
"platform",
|
|
211
|
+
"model",
|
|
212
|
+
"max_input_token_count",
|
|
213
|
+
"cheap_platform",
|
|
214
|
+
"cheap_model",
|
|
215
|
+
"cheap_max_input_token_count",
|
|
216
|
+
"smart_platform",
|
|
217
|
+
"smart_model",
|
|
218
|
+
"smart_max_input_token_count",
|
|
219
|
+
]
|
|
220
|
+
found_forbidden = [key for key in forbidden_keys if key in expanded_config]
|
|
221
|
+
if found_forbidden:
|
|
222
|
+
raise ValueError(
|
|
223
|
+
f"❌ 错误:llm_groups 中不再支持直接定义以下参数: {', '.join(found_forbidden)}。"
|
|
224
|
+
f"请使用 normal_llm、cheap_llm、smart_llm 引用 llms 中定义的配置。"
|
|
225
|
+
)
|
|
226
|
+
|
|
227
|
+
# 验证至少需要 normal_llm 引用
|
|
228
|
+
if "normal_llm" not in expanded_config:
|
|
229
|
+
raise ValueError(
|
|
230
|
+
"❌ 错误:llm_groups 中必须至少定义 normal_llm 引用。"
|
|
231
|
+
"请使用 normal_llm 引用 llms 中定义的配置。"
|
|
232
|
+
)
|
|
233
|
+
|
|
234
|
+
# 处理 normal_llm 引用
|
|
235
|
+
llm_ref = _resolve_llm_reference(expanded_config["normal_llm"])
|
|
236
|
+
if not llm_ref:
|
|
237
|
+
raise ValueError(
|
|
238
|
+
f"❌ 错误:normal_llm 引用的 '{expanded_config['normal_llm']}' 在 llms 中不存在。"
|
|
239
|
+
)
|
|
240
|
+
# 直接使用引用的值,不再检查是否已存在
|
|
241
|
+
expanded_config["platform"] = llm_ref.get("platform", "openai")
|
|
242
|
+
expanded_config["model"] = llm_ref.get("model", "gpt-5")
|
|
243
|
+
expanded_config["max_input_token_count"] = llm_ref.get(
|
|
244
|
+
"max_input_token_count", 32000
|
|
245
|
+
)
|
|
246
|
+
# 合并 llm_config
|
|
247
|
+
if "llm_config" in llm_ref:
|
|
248
|
+
expanded_config["llm_config"] = llm_ref["llm_config"].copy()
|
|
249
|
+
# 移除引用键
|
|
250
|
+
expanded_config.pop("normal_llm", None)
|
|
251
|
+
|
|
252
|
+
# 处理 cheap_llm 引用
|
|
253
|
+
if "cheap_llm" in expanded_config:
|
|
254
|
+
llm_ref = _resolve_llm_reference(expanded_config["cheap_llm"])
|
|
255
|
+
if not llm_ref:
|
|
256
|
+
raise ValueError(
|
|
257
|
+
f"❌ 错误:cheap_llm 引用的 '{expanded_config['cheap_llm']}' 在 llms 中不存在。"
|
|
258
|
+
)
|
|
259
|
+
# 直接使用引用的值
|
|
260
|
+
expanded_config["cheap_platform"] = llm_ref.get("platform", "openai")
|
|
261
|
+
expanded_config["cheap_model"] = llm_ref.get("model", "gpt-5")
|
|
262
|
+
expanded_config["cheap_max_input_token_count"] = llm_ref.get(
|
|
263
|
+
"max_input_token_count", 32000
|
|
264
|
+
)
|
|
265
|
+
# 合并 llm_config
|
|
266
|
+
if "llm_config" in llm_ref:
|
|
267
|
+
expanded_config["cheap_llm_config"] = llm_ref["llm_config"].copy()
|
|
268
|
+
expanded_config.pop("cheap_llm", None)
|
|
269
|
+
|
|
270
|
+
# 处理 smart_llm 引用
|
|
271
|
+
if "smart_llm" in expanded_config:
|
|
272
|
+
llm_ref = _resolve_llm_reference(expanded_config["smart_llm"])
|
|
273
|
+
if not llm_ref:
|
|
274
|
+
raise ValueError(
|
|
275
|
+
f"❌ 错误:smart_llm 引用的 '{expanded_config['smart_llm']}' 在 llms 中不存在。"
|
|
276
|
+
)
|
|
277
|
+
# 直接使用引用的值
|
|
278
|
+
expanded_config["smart_platform"] = llm_ref.get("platform", "openai")
|
|
279
|
+
expanded_config["smart_model"] = llm_ref.get("model", "gpt-5")
|
|
280
|
+
expanded_config["smart_max_input_token_count"] = llm_ref.get(
|
|
281
|
+
"max_input_token_count", 32000
|
|
282
|
+
)
|
|
283
|
+
# 合并 llm_config
|
|
284
|
+
if "llm_config" in llm_ref:
|
|
285
|
+
expanded_config["smart_llm_config"] = llm_ref["llm_config"].copy()
|
|
286
|
+
expanded_config.pop("smart_llm", None)
|
|
287
|
+
|
|
288
|
+
return expanded_config
|
|
289
|
+
|
|
290
|
+
|
|
109
291
|
def _get_resolved_model_config(
|
|
110
292
|
model_group_override: Optional[str] = None,
|
|
111
293
|
) -> Dict[str, Any]:
|
|
112
294
|
"""
|
|
113
295
|
解析并合并模型配置,处理模型组。
|
|
114
296
|
|
|
297
|
+
注意:
|
|
298
|
+
- llm_groups 格式为对象:{'group_name': {...}, ...},使用组名作为 key
|
|
299
|
+
- llm_groups 中不再支持直接定义 platform、model 等参数,只能通过 normal_llm、cheap_llm、smart_llm 引用 llms 中定义的配置
|
|
300
|
+
|
|
115
301
|
优先级顺序:
|
|
116
302
|
- 当通过 model_group_override(例如命令行 -g/--llm-group)指定组时:
|
|
117
|
-
1.
|
|
118
|
-
2. 仅当组未提供对应键时,回退到顶层环境变量 (
|
|
303
|
+
1. llm_group 中通过引用展开的配置
|
|
304
|
+
2. 仅当组未提供对应键时,回退到顶层环境变量 (platform, model, max_input_token_count)
|
|
119
305
|
3. 代码中的默认值
|
|
120
306
|
- 当未显式指定组时(使用默认组或未设置):
|
|
121
|
-
1. 顶层环境变量 (
|
|
122
|
-
2.
|
|
307
|
+
1. 顶层环境变量 (platform, model, max_input_token_count)
|
|
308
|
+
2. llm_group 中通过引用展开的配置
|
|
123
309
|
3. 代码中的默认值
|
|
124
310
|
|
|
125
311
|
返回:
|
|
126
312
|
Dict[str, Any]: 解析后的模型配置字典
|
|
313
|
+
|
|
314
|
+
异常:
|
|
315
|
+
如果 llm_groups 中直接定义了 platform、model 等参数,或缺少必需的引用,会抛出 ValueError
|
|
127
316
|
"""
|
|
317
|
+
from jarvis.jarvis_utils.output import PrettyOutput
|
|
318
|
+
|
|
128
319
|
group_config = {}
|
|
129
|
-
model_group_name = model_group_override or GLOBAL_CONFIG_DATA.get(
|
|
130
|
-
|
|
131
|
-
)
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
print("ℹ️ 可用的模型组: " +
|
|
147
|
-
", ".join(
|
|
148
|
-
list(group.keys())[0]
|
|
149
|
-
for group in model_groups
|
|
150
|
-
if isinstance(group, dict)
|
|
151
|
-
) if model_groups else "无可用模型组")
|
|
320
|
+
model_group_name = model_group_override or GLOBAL_CONFIG_DATA.get("llm_group")
|
|
321
|
+
# The format is an object: {'group_name': {...}, ...}
|
|
322
|
+
model_groups = GLOBAL_CONFIG_DATA.get("llm_groups", {})
|
|
323
|
+
|
|
324
|
+
if model_group_name and isinstance(model_groups, dict):
|
|
325
|
+
if model_group_name in model_groups:
|
|
326
|
+
group_config = model_groups[model_group_name]
|
|
327
|
+
elif model_group_override:
|
|
328
|
+
# 当显式指定了模型组但未找到时,报错并退出
|
|
329
|
+
PrettyOutput.auto_print(
|
|
330
|
+
f"❌ 错误:指定的模型组 '{model_group_name}' 不存在于配置中。"
|
|
331
|
+
)
|
|
332
|
+
PrettyOutput.auto_print(
|
|
333
|
+
"ℹ️ 可用的模型组: " + ", ".join(model_groups.keys())
|
|
334
|
+
if model_groups
|
|
335
|
+
else "无可用模型组"
|
|
336
|
+
)
|
|
152
337
|
import sys
|
|
338
|
+
|
|
153
339
|
sys.exit(1)
|
|
154
|
-
|
|
340
|
+
|
|
341
|
+
# 展开 llm 引用(normal_llm, cheap_llm, smart_llm)
|
|
342
|
+
# 只有当 group_config 不为空时才展开引用(说明使用了 llm_groups)
|
|
343
|
+
if group_config:
|
|
344
|
+
group_config = _expand_llm_references(group_config)
|
|
345
|
+
|
|
155
346
|
_apply_llm_group_env_override(group_config)
|
|
156
347
|
|
|
157
348
|
# Start with group config
|
|
@@ -162,13 +353,15 @@ def _get_resolved_model_config(
|
|
|
162
353
|
# 仅当组未提供对应键时,才回落到顶层 GLOBAL_CONFIG_DATA。
|
|
163
354
|
# - 若未传入 override(即使用默认组),保持原有行为:由顶层键覆盖组配置。
|
|
164
355
|
override_keys = [
|
|
165
|
-
"
|
|
166
|
-
"
|
|
167
|
-
"
|
|
168
|
-
"
|
|
169
|
-
"
|
|
170
|
-
"
|
|
171
|
-
"
|
|
356
|
+
"platform",
|
|
357
|
+
"model",
|
|
358
|
+
"max_input_token_count",
|
|
359
|
+
"cheap_platform",
|
|
360
|
+
"cheap_model",
|
|
361
|
+
"cheap_max_input_token_count",
|
|
362
|
+
"smart_platform",
|
|
363
|
+
"smart_model",
|
|
364
|
+
"smart_max_input_token_count",
|
|
172
365
|
]
|
|
173
366
|
for key in override_keys:
|
|
174
367
|
if key in GLOBAL_CONFIG_DATA:
|
|
@@ -180,9 +373,35 @@ def _get_resolved_model_config(
|
|
|
180
373
|
if key not in resolved_config:
|
|
181
374
|
resolved_config[key] = GLOBAL_CONFIG_DATA[key]
|
|
182
375
|
|
|
376
|
+
# 应用 llm_config 到环境变量
|
|
377
|
+
_apply_llm_config_to_env(resolved_config)
|
|
378
|
+
|
|
183
379
|
return resolved_config
|
|
184
380
|
|
|
185
381
|
|
|
382
|
+
def get_llm_config(
|
|
383
|
+
platform_type: str = "normal", model_group_override: Optional[str] = None
|
|
384
|
+
) -> Dict[str, Any]:
|
|
385
|
+
"""
|
|
386
|
+
获取指定平台类型的 llm_config 配置。
|
|
387
|
+
|
|
388
|
+
参数:
|
|
389
|
+
platform_type: 平台类型,可选值为 'normal'、'cheap' 或 'smart'
|
|
390
|
+
model_group_override: 模型组覆盖
|
|
391
|
+
|
|
392
|
+
返回:
|
|
393
|
+
Dict[str, Any]: llm_config 配置字典
|
|
394
|
+
"""
|
|
395
|
+
config = _get_resolved_model_config(model_group_override)
|
|
396
|
+
|
|
397
|
+
if platform_type == "cheap":
|
|
398
|
+
return dict(config.get("cheap_llm_config", {}))
|
|
399
|
+
elif platform_type == "smart":
|
|
400
|
+
return dict(config.get("smart_llm_config", {}))
|
|
401
|
+
else:
|
|
402
|
+
return dict(config.get("llm_config", {}))
|
|
403
|
+
|
|
404
|
+
|
|
186
405
|
def get_normal_platform_name(model_group_override: Optional[str] = None) -> str:
|
|
187
406
|
"""
|
|
188
407
|
获取正常操作的平台名称。
|
|
@@ -191,7 +410,7 @@ def get_normal_platform_name(model_group_override: Optional[str] = None) -> str:
|
|
|
191
410
|
str: 平台名称,默认为'openai'
|
|
192
411
|
"""
|
|
193
412
|
config = _get_resolved_model_config(model_group_override)
|
|
194
|
-
return cast(str, config.get("
|
|
413
|
+
return cast(str, config.get("platform", "openai"))
|
|
195
414
|
|
|
196
415
|
|
|
197
416
|
def get_normal_model_name(model_group_override: Optional[str] = None) -> str:
|
|
@@ -202,31 +421,7 @@ def get_normal_model_name(model_group_override: Optional[str] = None) -> str:
|
|
|
202
421
|
str: 模型名称,默认为'gpt-5'
|
|
203
422
|
"""
|
|
204
423
|
config = _get_resolved_model_config(model_group_override)
|
|
205
|
-
return cast(str, config.get("
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
def _deprecated_platform_name_v1(model_group_override: Optional[str] = None) -> str:
|
|
209
|
-
"""
|
|
210
|
-
获取思考操作的平台名称。
|
|
211
|
-
|
|
212
|
-
返回:
|
|
213
|
-
str: 平台名称,默认为正常操作平台
|
|
214
|
-
"""
|
|
215
|
-
_get_resolved_model_config(model_group_override)
|
|
216
|
-
# Fallback to normal platform if thinking platform is not specified
|
|
217
|
-
return get_normal_platform_name(model_group_override)
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
def _deprecated_model_name_v1(model_group_override: Optional[str] = None) -> str:
|
|
221
|
-
"""
|
|
222
|
-
获取思考操作的模型名称。
|
|
223
|
-
|
|
224
|
-
返回:
|
|
225
|
-
str: 模型名称,默认为正常操作模型
|
|
226
|
-
"""
|
|
227
|
-
_get_resolved_model_config(model_group_override)
|
|
228
|
-
# Fallback to normal model if thinking model is not specified
|
|
229
|
-
return get_normal_model_name(model_group_override)
|
|
424
|
+
return cast(str, config.get("model", "gpt-5"))
|
|
230
425
|
|
|
231
426
|
|
|
232
427
|
def get_cheap_platform_name(model_group_override: Optional[str] = None) -> str:
|
|
@@ -237,7 +432,7 @@ def get_cheap_platform_name(model_group_override: Optional[str] = None) -> str:
|
|
|
237
432
|
str: 平台名称,如果未配置则回退到正常操作平台
|
|
238
433
|
"""
|
|
239
434
|
config = _get_resolved_model_config(model_group_override)
|
|
240
|
-
cheap_platform = config.get("
|
|
435
|
+
cheap_platform = config.get("cheap_platform")
|
|
241
436
|
if cheap_platform:
|
|
242
437
|
return cast(str, cheap_platform)
|
|
243
438
|
return get_normal_platform_name(model_group_override)
|
|
@@ -251,7 +446,7 @@ def get_cheap_model_name(model_group_override: Optional[str] = None) -> str:
|
|
|
251
446
|
str: 模型名称,如果未配置则回退到正常操作模型
|
|
252
447
|
"""
|
|
253
448
|
config = _get_resolved_model_config(model_group_override)
|
|
254
|
-
cheap_model = config.get("
|
|
449
|
+
cheap_model = config.get("cheap_model")
|
|
255
450
|
if cheap_model:
|
|
256
451
|
return cast(str, cheap_model)
|
|
257
452
|
return get_normal_model_name(model_group_override)
|
|
@@ -265,7 +460,7 @@ def get_smart_platform_name(model_group_override: Optional[str] = None) -> str:
|
|
|
265
460
|
str: 平台名称,如果未配置则回退到正常操作平台
|
|
266
461
|
"""
|
|
267
462
|
config = _get_resolved_model_config(model_group_override)
|
|
268
|
-
smart_platform = config.get("
|
|
463
|
+
smart_platform = config.get("smart_platform")
|
|
269
464
|
if smart_platform:
|
|
270
465
|
return cast(str, smart_platform)
|
|
271
466
|
return get_normal_platform_name(model_group_override)
|
|
@@ -279,7 +474,7 @@ def get_smart_model_name(model_group_override: Optional[str] = None) -> str:
|
|
|
279
474
|
str: 模型名称,如果未配置则回退到正常操作模型
|
|
280
475
|
"""
|
|
281
476
|
config = _get_resolved_model_config(model_group_override)
|
|
282
|
-
smart_model = config.get("
|
|
477
|
+
smart_model = config.get("smart_model")
|
|
283
478
|
if smart_model:
|
|
284
479
|
return cast(str, smart_model)
|
|
285
480
|
return get_normal_model_name(model_group_override)
|
|
@@ -292,7 +487,7 @@ def is_execute_tool_confirm() -> bool:
|
|
|
292
487
|
返回:
|
|
293
488
|
bool: 如果需要确认则返回True,默认为False
|
|
294
489
|
"""
|
|
295
|
-
return cast(bool, GLOBAL_CONFIG_DATA.get("
|
|
490
|
+
return cast(bool, GLOBAL_CONFIG_DATA.get("execute_tool_confirm", False))
|
|
296
491
|
|
|
297
492
|
|
|
298
493
|
def is_confirm_before_apply_patch() -> bool:
|
|
@@ -302,19 +497,19 @@ def is_confirm_before_apply_patch() -> bool:
|
|
|
302
497
|
返回:
|
|
303
498
|
bool: 如果需要确认则返回True,默认为False
|
|
304
499
|
"""
|
|
305
|
-
return cast(bool, GLOBAL_CONFIG_DATA.get("
|
|
500
|
+
return cast(bool, GLOBAL_CONFIG_DATA.get("confirm_before_apply_patch", False))
|
|
306
501
|
|
|
307
502
|
|
|
308
503
|
def get_data_dir() -> str:
|
|
309
504
|
"""
|
|
310
505
|
获取Jarvis数据存储目录路径。
|
|
311
506
|
|
|
312
|
-
返回:
|
|
313
|
-
str: 数据目录路径,优先从
|
|
507
|
+
返回:
|
|
508
|
+
str: 数据目录路径,优先从data_path环境变量获取,
|
|
314
509
|
如果未设置或为空,则使用~/.jarvis作为默认值
|
|
315
510
|
"""
|
|
316
511
|
return os.path.expanduser(
|
|
317
|
-
cast(str, GLOBAL_CONFIG_DATA.get("
|
|
512
|
+
cast(str, GLOBAL_CONFIG_DATA.get("data_path", "~/.jarvis")).strip()
|
|
318
513
|
)
|
|
319
514
|
|
|
320
515
|
|
|
@@ -342,7 +537,7 @@ def get_pretty_output() -> bool:
|
|
|
342
537
|
if platform.system() == "Windows":
|
|
343
538
|
return False
|
|
344
539
|
|
|
345
|
-
return cast(bool, GLOBAL_CONFIG_DATA.get("
|
|
540
|
+
return cast(bool, GLOBAL_CONFIG_DATA.get("pretty_output", True))
|
|
346
541
|
|
|
347
542
|
|
|
348
543
|
def is_use_methodology() -> bool:
|
|
@@ -352,7 +547,7 @@ def is_use_methodology() -> bool:
|
|
|
352
547
|
返回:
|
|
353
548
|
bool: 如果启用方法论则返回True,默认为True
|
|
354
549
|
"""
|
|
355
|
-
return cast(bool, GLOBAL_CONFIG_DATA.get("
|
|
550
|
+
return cast(bool, GLOBAL_CONFIG_DATA.get("use_methodology", True))
|
|
356
551
|
|
|
357
552
|
|
|
358
553
|
def is_use_analysis() -> bool:
|
|
@@ -362,7 +557,7 @@ def is_use_analysis() -> bool:
|
|
|
362
557
|
返回:
|
|
363
558
|
bool: 如果启用任务分析则返回True,默认为True
|
|
364
559
|
"""
|
|
365
|
-
return cast(bool, GLOBAL_CONFIG_DATA.get("
|
|
560
|
+
return cast(bool, GLOBAL_CONFIG_DATA.get("use_analysis", True))
|
|
366
561
|
|
|
367
562
|
|
|
368
563
|
def get_tool_load_dirs() -> List[str]:
|
|
@@ -374,7 +569,7 @@ def get_tool_load_dirs() -> List[str]:
|
|
|
374
569
|
"""
|
|
375
570
|
return [
|
|
376
571
|
os.path.expanduser(os.path.expandvars(str(p)))
|
|
377
|
-
for p in GLOBAL_CONFIG_DATA.get("
|
|
572
|
+
for p in GLOBAL_CONFIG_DATA.get("tool_load_dirs", [])
|
|
378
573
|
if p
|
|
379
574
|
]
|
|
380
575
|
|
|
@@ -388,7 +583,7 @@ def get_methodology_dirs() -> List[str]:
|
|
|
388
583
|
"""
|
|
389
584
|
return [
|
|
390
585
|
os.path.expanduser(os.path.expandvars(str(p)))
|
|
391
|
-
for p in GLOBAL_CONFIG_DATA.get("
|
|
586
|
+
for p in GLOBAL_CONFIG_DATA.get("methodology_dirs", [])
|
|
392
587
|
if p
|
|
393
588
|
]
|
|
394
589
|
|
|
@@ -402,7 +597,7 @@ def get_agent_definition_dirs() -> List[str]:
|
|
|
402
597
|
"""
|
|
403
598
|
return [
|
|
404
599
|
os.path.expanduser(os.path.expandvars(str(p)))
|
|
405
|
-
for p in GLOBAL_CONFIG_DATA.get("
|
|
600
|
+
for p in GLOBAL_CONFIG_DATA.get("agent_definition_dirs", [])
|
|
406
601
|
if p
|
|
407
602
|
]
|
|
408
603
|
|
|
@@ -416,7 +611,7 @@ def get_multi_agent_dirs() -> List[str]:
|
|
|
416
611
|
"""
|
|
417
612
|
return [
|
|
418
613
|
os.path.expanduser(os.path.expandvars(str(p)))
|
|
419
|
-
for p in GLOBAL_CONFIG_DATA.get("
|
|
614
|
+
for p in GLOBAL_CONFIG_DATA.get("multi_agent_dirs", [])
|
|
420
615
|
if p
|
|
421
616
|
]
|
|
422
617
|
|
|
@@ -430,7 +625,7 @@ def get_roles_dirs() -> List[str]:
|
|
|
430
625
|
"""
|
|
431
626
|
return [
|
|
432
627
|
os.path.expanduser(os.path.expandvars(str(p)))
|
|
433
|
-
for p in GLOBAL_CONFIG_DATA.get("
|
|
628
|
+
for p in GLOBAL_CONFIG_DATA.get("roles_dirs", [])
|
|
434
629
|
if p
|
|
435
630
|
]
|
|
436
631
|
|
|
@@ -444,7 +639,7 @@ def get_after_tool_call_cb_dirs() -> List[str]:
|
|
|
444
639
|
"""
|
|
445
640
|
return [
|
|
446
641
|
os.path.expanduser(os.path.expandvars(str(p)))
|
|
447
|
-
for p in GLOBAL_CONFIG_DATA.get("
|
|
642
|
+
for p in GLOBAL_CONFIG_DATA.get("after_tool_call_cb_dirs", [])
|
|
448
643
|
if p
|
|
449
644
|
]
|
|
450
645
|
|
|
@@ -456,7 +651,7 @@ def get_central_methodology_repo() -> str:
|
|
|
456
651
|
返回:
|
|
457
652
|
str: 中心方法论Git仓库地址,如果未配置则返回空字符串
|
|
458
653
|
"""
|
|
459
|
-
return cast(str, GLOBAL_CONFIG_DATA.get("
|
|
654
|
+
return cast(str, GLOBAL_CONFIG_DATA.get("central_methodology_repo", ""))
|
|
460
655
|
|
|
461
656
|
|
|
462
657
|
def get_central_tool_repo() -> str:
|
|
@@ -466,7 +661,31 @@ def get_central_tool_repo() -> str:
|
|
|
466
661
|
返回:
|
|
467
662
|
str: 中心工具Git仓库地址,如果未配置则返回空字符串
|
|
468
663
|
"""
|
|
469
|
-
return cast(str, GLOBAL_CONFIG_DATA.get("
|
|
664
|
+
return cast(str, GLOBAL_CONFIG_DATA.get("central_tool_repo", ""))
|
|
665
|
+
|
|
666
|
+
|
|
667
|
+
def get_rules_load_dirs() -> List[str]:
|
|
668
|
+
"""
|
|
669
|
+
获取规则加载目录。
|
|
670
|
+
|
|
671
|
+
返回:
|
|
672
|
+
List[str]: 规则加载目录列表
|
|
673
|
+
"""
|
|
674
|
+
return [
|
|
675
|
+
os.path.expanduser(os.path.expandvars(str(p)))
|
|
676
|
+
for p in GLOBAL_CONFIG_DATA.get("rules_load_dirs", [])
|
|
677
|
+
if p
|
|
678
|
+
]
|
|
679
|
+
|
|
680
|
+
|
|
681
|
+
def get_central_rules_repo() -> str:
|
|
682
|
+
"""
|
|
683
|
+
获取中心规则Git仓库地址。
|
|
684
|
+
|
|
685
|
+
返回:
|
|
686
|
+
str: 中心规则Git仓库地址,如果未配置则返回空字符串
|
|
687
|
+
"""
|
|
688
|
+
return cast(str, GLOBAL_CONFIG_DATA.get("central_rules_repo", ""))
|
|
470
689
|
|
|
471
690
|
|
|
472
691
|
def is_print_prompt() -> bool:
|
|
@@ -476,7 +695,7 @@ def is_print_prompt() -> bool:
|
|
|
476
695
|
返回:
|
|
477
696
|
bool: 如果打印提示则返回True,默认为True
|
|
478
697
|
"""
|
|
479
|
-
return cast(bool, GLOBAL_CONFIG_DATA.get("
|
|
698
|
+
return cast(bool, GLOBAL_CONFIG_DATA.get("print_prompt", False))
|
|
480
699
|
|
|
481
700
|
|
|
482
701
|
def is_print_error_traceback() -> bool:
|
|
@@ -486,7 +705,7 @@ def is_print_error_traceback() -> bool:
|
|
|
486
705
|
返回:
|
|
487
706
|
bool: 如果打印回溯则返回True,默认为False(不打印)
|
|
488
707
|
"""
|
|
489
|
-
return GLOBAL_CONFIG_DATA.get("
|
|
708
|
+
return GLOBAL_CONFIG_DATA.get("print_error_traceback", False) is True
|
|
490
709
|
|
|
491
710
|
|
|
492
711
|
def is_force_save_memory() -> bool:
|
|
@@ -496,7 +715,7 @@ def is_force_save_memory() -> bool:
|
|
|
496
715
|
返回:
|
|
497
716
|
bool: 如果强制保存记忆则返回True,默认为False
|
|
498
717
|
"""
|
|
499
|
-
return GLOBAL_CONFIG_DATA.get("
|
|
718
|
+
return GLOBAL_CONFIG_DATA.get("force_save_memory", False) is True
|
|
500
719
|
|
|
501
720
|
|
|
502
721
|
def is_enable_static_analysis() -> bool:
|
|
@@ -506,7 +725,7 @@ def is_enable_static_analysis() -> bool:
|
|
|
506
725
|
返回:
|
|
507
726
|
bool: 如果启用静态代码分析则返回True,默认为True
|
|
508
727
|
"""
|
|
509
|
-
return GLOBAL_CONFIG_DATA.get("
|
|
728
|
+
return GLOBAL_CONFIG_DATA.get("enable_static_analysis", True) is True
|
|
510
729
|
|
|
511
730
|
|
|
512
731
|
def is_enable_build_validation() -> bool:
|
|
@@ -516,7 +735,7 @@ def is_enable_build_validation() -> bool:
|
|
|
516
735
|
返回:
|
|
517
736
|
bool: 如果启用构建验证则返回True,默认为True
|
|
518
737
|
"""
|
|
519
|
-
return GLOBAL_CONFIG_DATA.get("
|
|
738
|
+
return GLOBAL_CONFIG_DATA.get("enable_build_validation", True) is True
|
|
520
739
|
|
|
521
740
|
|
|
522
741
|
def is_enable_impact_analysis() -> bool:
|
|
@@ -526,7 +745,7 @@ def is_enable_impact_analysis() -> bool:
|
|
|
526
745
|
返回:
|
|
527
746
|
bool: 如果启用影响范围分析则返回True,默认为True
|
|
528
747
|
"""
|
|
529
|
-
return GLOBAL_CONFIG_DATA.get("
|
|
748
|
+
return GLOBAL_CONFIG_DATA.get("enable_impact_analysis", True) is True
|
|
530
749
|
|
|
531
750
|
|
|
532
751
|
def get_build_validation_timeout() -> int:
|
|
@@ -536,21 +755,7 @@ def get_build_validation_timeout() -> int:
|
|
|
536
755
|
返回:
|
|
537
756
|
int: 超时时间,默认为30秒
|
|
538
757
|
"""
|
|
539
|
-
return int(GLOBAL_CONFIG_DATA.get("
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
def get_git_check_mode() -> str:
|
|
543
|
-
"""
|
|
544
|
-
获取Git校验模式。
|
|
545
|
-
|
|
546
|
-
返回:
|
|
547
|
-
str: "strict" 或 "warn",默认为 "strict"
|
|
548
|
-
"""
|
|
549
|
-
mode = GLOBAL_CONFIG_DATA.get("JARVIS_GIT_CHECK_MODE", "strict")
|
|
550
|
-
try:
|
|
551
|
-
return str(mode)
|
|
552
|
-
except Exception:
|
|
553
|
-
return "strict"
|
|
758
|
+
return int(GLOBAL_CONFIG_DATA.get("build_validation_timeout", 30))
|
|
554
759
|
|
|
555
760
|
|
|
556
761
|
def get_mcp_config() -> List[Dict[str, Any]]:
|
|
@@ -560,7 +765,7 @@ def get_mcp_config() -> List[Dict[str, Any]]:
|
|
|
560
765
|
返回:
|
|
561
766
|
List[Dict[str, Any]]: MCP配置项列表,如果未配置则返回空列表
|
|
562
767
|
"""
|
|
563
|
-
return cast(List[Dict[str, Any]], GLOBAL_CONFIG_DATA.get("
|
|
768
|
+
return cast(List[Dict[str, Any]], GLOBAL_CONFIG_DATA.get("mcp", []))
|
|
564
769
|
|
|
565
770
|
|
|
566
771
|
# ==============================================================================
|
|
@@ -568,23 +773,191 @@ def get_mcp_config() -> List[Dict[str, Any]]:
|
|
|
568
773
|
# ==============================================================================
|
|
569
774
|
|
|
570
775
|
|
|
571
|
-
DEFAULT_RAG_GROUPS =
|
|
572
|
-
{
|
|
573
|
-
"
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
"use_rerank": True,
|
|
578
|
-
}
|
|
776
|
+
DEFAULT_RAG_GROUPS = {
|
|
777
|
+
"text": {
|
|
778
|
+
"embedding": "default-text-embedding",
|
|
779
|
+
"reranker": "default-text-reranker",
|
|
780
|
+
"use_bm25": True,
|
|
781
|
+
"use_rerank": True,
|
|
579
782
|
},
|
|
580
|
-
{
|
|
581
|
-
"
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
"use_rerank": False,
|
|
585
|
-
}
|
|
783
|
+
"code": {
|
|
784
|
+
"embedding": "default-code-embedding",
|
|
785
|
+
"use_bm25": False,
|
|
786
|
+
"use_rerank": False,
|
|
586
787
|
},
|
|
587
|
-
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
# 默认的 embeddings 配置(如果用户未定义)
|
|
791
|
+
DEFAULT_EMBEDDINGS = {
|
|
792
|
+
"default-text-embedding": {
|
|
793
|
+
"embedding_model": "BAAI/bge-m3",
|
|
794
|
+
"embedding_type": "LocalEmbeddingModel",
|
|
795
|
+
"embedding_max_length": 512,
|
|
796
|
+
},
|
|
797
|
+
"default-code-embedding": {
|
|
798
|
+
"embedding_model": "Qodo/Qodo-Embed-1-1.5B",
|
|
799
|
+
"embedding_type": "LocalEmbeddingModel",
|
|
800
|
+
"embedding_max_length": 512,
|
|
801
|
+
},
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
# 默认的 rerankers 配置(如果用户未定义)
|
|
805
|
+
DEFAULT_RERANKERS = {
|
|
806
|
+
"default-text-reranker": {
|
|
807
|
+
"rerank_model": "BAAI/bge-reranker-v2-m3",
|
|
808
|
+
"reranker_type": "LocalReranker",
|
|
809
|
+
"reranker_max_length": 512,
|
|
810
|
+
},
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
|
|
814
|
+
def _resolve_embedding_reference(embedding_name: str) -> Dict[str, Any]:
|
|
815
|
+
"""
|
|
816
|
+
从 embeddings 配置中解析引用的嵌入模型配置。
|
|
817
|
+
|
|
818
|
+
参数:
|
|
819
|
+
embedding_name: embeddings 中定义的嵌入模型配置名称
|
|
820
|
+
|
|
821
|
+
返回:
|
|
822
|
+
Dict[str, Any]: 解析后的嵌入模型配置字典,包含 embedding_model, embedding_type, embedding_max_length, embedding_config
|
|
823
|
+
"""
|
|
824
|
+
from jarvis.jarvis_utils.output import PrettyOutput
|
|
825
|
+
|
|
826
|
+
embeddings = GLOBAL_CONFIG_DATA.get("embeddings", {})
|
|
827
|
+
if not isinstance(embeddings, dict):
|
|
828
|
+
embeddings = {}
|
|
829
|
+
|
|
830
|
+
# 如果用户配置中没有,尝试使用默认配置
|
|
831
|
+
if embedding_name not in embeddings:
|
|
832
|
+
embeddings = {**DEFAULT_EMBEDDINGS, **embeddings}
|
|
833
|
+
|
|
834
|
+
embedding_config = embeddings.get(embedding_name)
|
|
835
|
+
if not isinstance(embedding_config, dict):
|
|
836
|
+
PrettyOutput.auto_print(
|
|
837
|
+
f"⚠️ 警告:embeddings 中未找到名为 '{embedding_name}' 的配置"
|
|
838
|
+
)
|
|
839
|
+
return {}
|
|
840
|
+
|
|
841
|
+
return embedding_config.copy()
|
|
842
|
+
|
|
843
|
+
|
|
844
|
+
def _resolve_reranker_reference(reranker_name: str) -> Dict[str, Any]:
|
|
845
|
+
"""
|
|
846
|
+
从 rerankers 配置中解析引用的重排模型配置。
|
|
847
|
+
|
|
848
|
+
参数:
|
|
849
|
+
reranker_name: rerankers 中定义的重排模型配置名称
|
|
850
|
+
|
|
851
|
+
返回:
|
|
852
|
+
Dict[str, Any]: 解析后的重排模型配置字典,包含 rerank_model, reranker_type, reranker_max_length, reranker_config
|
|
853
|
+
"""
|
|
854
|
+
from jarvis.jarvis_utils.output import PrettyOutput
|
|
855
|
+
|
|
856
|
+
rerankers = GLOBAL_CONFIG_DATA.get("rerankers", {})
|
|
857
|
+
if not isinstance(rerankers, dict):
|
|
858
|
+
rerankers = {}
|
|
859
|
+
|
|
860
|
+
# 如果用户配置中没有,尝试使用默认配置
|
|
861
|
+
if reranker_name not in rerankers:
|
|
862
|
+
rerankers = {**DEFAULT_RERANKERS, **rerankers}
|
|
863
|
+
|
|
864
|
+
reranker_config = rerankers.get(reranker_name)
|
|
865
|
+
if not isinstance(reranker_config, dict):
|
|
866
|
+
PrettyOutput.auto_print(
|
|
867
|
+
f"⚠️ 警告:rerankers 中未找到名为 '{reranker_name}' 的配置"
|
|
868
|
+
)
|
|
869
|
+
return {}
|
|
870
|
+
|
|
871
|
+
return reranker_config.copy()
|
|
872
|
+
|
|
873
|
+
|
|
874
|
+
def _expand_rag_references(group_config: Dict[str, Any]) -> Dict[str, Any]:
|
|
875
|
+
"""
|
|
876
|
+
展开 rag_groups 中的 embedding 和 reranker 引用到对应的配置字段。
|
|
877
|
+
|
|
878
|
+
注意:rag_groups 中不再支持直接定义 embedding_model、embedding_type 等参数,只能通过引用 embeddings 和 rerankers 中的配置。
|
|
879
|
+
|
|
880
|
+
参数:
|
|
881
|
+
group_config: RAG组配置字典
|
|
882
|
+
|
|
883
|
+
返回:
|
|
884
|
+
Dict[str, Any]: 展开后的配置字典
|
|
885
|
+
|
|
886
|
+
异常:
|
|
887
|
+
如果组配置中直接定义了 embedding_model、embedding_type 等参数,会抛出 ValueError
|
|
888
|
+
"""
|
|
889
|
+
expanded_config = group_config.copy()
|
|
890
|
+
|
|
891
|
+
# 检查是否直接定义了不允许的参数
|
|
892
|
+
forbidden_keys = [
|
|
893
|
+
"embedding_model",
|
|
894
|
+
"embedding_type",
|
|
895
|
+
"embedding_max_length",
|
|
896
|
+
"embedding_config",
|
|
897
|
+
"rerank_model",
|
|
898
|
+
"reranker_type",
|
|
899
|
+
"reranker_max_length",
|
|
900
|
+
"reranker_config",
|
|
901
|
+
]
|
|
902
|
+
found_forbidden = [key for key in forbidden_keys if key in expanded_config]
|
|
903
|
+
if found_forbidden:
|
|
904
|
+
raise ValueError(
|
|
905
|
+
f"❌ 错误:rag_groups 中不再支持直接定义以下参数: {', '.join(found_forbidden)}。"
|
|
906
|
+
f"请使用 embedding 和 reranker 引用 embeddings 和 rerankers 中定义的配置。"
|
|
907
|
+
)
|
|
908
|
+
|
|
909
|
+
# 处理 embedding 引用(必需)
|
|
910
|
+
if "embedding" not in expanded_config:
|
|
911
|
+
raise ValueError(
|
|
912
|
+
"❌ 错误:rag_groups 中必须定义 embedding 引用。"
|
|
913
|
+
"请使用 embedding 引用 embeddings 中定义的配置。"
|
|
914
|
+
)
|
|
915
|
+
|
|
916
|
+
embedding_ref = _resolve_embedding_reference(expanded_config["embedding"])
|
|
917
|
+
if not embedding_ref:
|
|
918
|
+
raise ValueError(
|
|
919
|
+
f"❌ 错误:embedding 引用的 '{expanded_config['embedding']}' 在 embeddings 中不存在。"
|
|
920
|
+
)
|
|
921
|
+
# 直接使用引用的值
|
|
922
|
+
expanded_config["embedding_model"] = embedding_ref.get(
|
|
923
|
+
"embedding_model", "BAAI/bge-m3"
|
|
924
|
+
)
|
|
925
|
+
expanded_config["embedding_type"] = embedding_ref.get(
|
|
926
|
+
"embedding_type", "LocalEmbeddingModel"
|
|
927
|
+
)
|
|
928
|
+
expanded_config["embedding_max_length"] = embedding_ref.get(
|
|
929
|
+
"embedding_max_length", 512
|
|
930
|
+
)
|
|
931
|
+
# 合并 embedding_config
|
|
932
|
+
if "embedding_config" in embedding_ref:
|
|
933
|
+
expanded_config["embedding_config"] = embedding_ref["embedding_config"].copy()
|
|
934
|
+
# 移除引用键
|
|
935
|
+
expanded_config.pop("embedding", None)
|
|
936
|
+
|
|
937
|
+
# 处理 reranker 引用(可选)
|
|
938
|
+
if "reranker" in expanded_config:
|
|
939
|
+
reranker_ref = _resolve_reranker_reference(expanded_config["reranker"])
|
|
940
|
+
if not reranker_ref:
|
|
941
|
+
raise ValueError(
|
|
942
|
+
f"❌ 错误:reranker 引用的 '{expanded_config['reranker']}' 在 rerankers 中不存在。"
|
|
943
|
+
)
|
|
944
|
+
# 直接使用引用的值
|
|
945
|
+
expanded_config["rerank_model"] = reranker_ref.get(
|
|
946
|
+
"rerank_model", "BAAI/bge-reranker-v2-m3"
|
|
947
|
+
)
|
|
948
|
+
expanded_config["reranker_type"] = reranker_ref.get(
|
|
949
|
+
"reranker_type", "LocalReranker"
|
|
950
|
+
)
|
|
951
|
+
expanded_config["reranker_max_length"] = reranker_ref.get(
|
|
952
|
+
"reranker_max_length", 512
|
|
953
|
+
)
|
|
954
|
+
# 合并 reranker_config
|
|
955
|
+
if "reranker_config" in reranker_ref:
|
|
956
|
+
expanded_config["reranker_config"] = reranker_ref["reranker_config"].copy()
|
|
957
|
+
# 移除引用键
|
|
958
|
+
expanded_config.pop("reranker", None)
|
|
959
|
+
|
|
960
|
+
return expanded_config
|
|
588
961
|
|
|
589
962
|
|
|
590
963
|
def _get_resolved_rag_config(
|
|
@@ -593,33 +966,61 @@ def _get_resolved_rag_config(
|
|
|
593
966
|
"""
|
|
594
967
|
解析并合并RAG配置,处理RAG组。
|
|
595
968
|
|
|
969
|
+
注意:
|
|
970
|
+
- rag_groups 格式为对象:{'group_name': {...}, ...},使用组名作为 key
|
|
971
|
+
- rag_groups 中不再支持直接定义 embedding_model、embedding_type 等参数,只能通过 embedding 和 reranker 引用 embeddings 和 rerankers 中定义的配置
|
|
972
|
+
|
|
596
973
|
优先级顺序:
|
|
597
|
-
1.
|
|
598
|
-
2.
|
|
974
|
+
1. rag 中的顶级设置 (embedding_model, etc.)
|
|
975
|
+
2. rag_group 中通过引用展开的组配置
|
|
599
976
|
3. 代码中的默认值
|
|
600
977
|
|
|
601
978
|
返回:
|
|
602
979
|
Dict[str, Any]: 解析后的RAG配置字典
|
|
980
|
+
|
|
981
|
+
异常:
|
|
982
|
+
如果 rag_groups 中直接定义了 embedding_model、embedding_type 等参数,或缺少必需的引用,会抛出 ValueError
|
|
603
983
|
"""
|
|
604
984
|
group_config = {}
|
|
605
|
-
rag_group_name = rag_group_override or GLOBAL_CONFIG_DATA.get("
|
|
606
|
-
|
|
985
|
+
rag_group_name = rag_group_override or GLOBAL_CONFIG_DATA.get("rag_group")
|
|
986
|
+
# The format is an object: {'group_name': {...}, ...}
|
|
987
|
+
rag_groups = GLOBAL_CONFIG_DATA.get("rag_groups", DEFAULT_RAG_GROUPS)
|
|
607
988
|
|
|
608
|
-
|
|
989
|
+
# 兼容旧格式:如果是列表,转换为对象格式
|
|
990
|
+
if isinstance(rag_groups, list):
|
|
991
|
+
converted_groups = {}
|
|
609
992
|
for group_item in rag_groups:
|
|
610
|
-
if isinstance(group_item, dict)
|
|
611
|
-
|
|
612
|
-
|
|
993
|
+
if isinstance(group_item, dict):
|
|
994
|
+
for group_name, group_config_item in group_item.items():
|
|
995
|
+
converted_groups[group_name] = group_config_item
|
|
996
|
+
rag_groups = converted_groups
|
|
997
|
+
# 更新全局配置(仅用于兼容,不持久化)
|
|
998
|
+
GLOBAL_CONFIG_DATA["rag_groups"] = converted_groups
|
|
999
|
+
|
|
1000
|
+
if rag_group_name and isinstance(rag_groups, dict):
|
|
1001
|
+
if rag_group_name in rag_groups:
|
|
1002
|
+
group_config = rag_groups[rag_group_name]
|
|
1003
|
+
|
|
1004
|
+
# 展开 embedding 和 reranker 引用
|
|
1005
|
+
# 只有当 group_config 不为空时才展开引用(说明使用了 rag_groups)
|
|
1006
|
+
if group_config:
|
|
1007
|
+
group_config = _expand_rag_references(group_config)
|
|
613
1008
|
|
|
614
1009
|
# Start with group config
|
|
615
1010
|
resolved_config = group_config.copy()
|
|
616
1011
|
|
|
617
|
-
# Override with specific settings from the top-level
|
|
618
|
-
top_level_rag_config = GLOBAL_CONFIG_DATA.get("
|
|
1012
|
+
# Override with specific settings from the top-level rag dict
|
|
1013
|
+
top_level_rag_config = GLOBAL_CONFIG_DATA.get("rag", {})
|
|
619
1014
|
if isinstance(top_level_rag_config, dict):
|
|
620
1015
|
for key in [
|
|
621
1016
|
"embedding_model",
|
|
1017
|
+
"embedding_type",
|
|
1018
|
+
"embedding_max_length", # 嵌入模型最大输入长度
|
|
1019
|
+
"embedding_config", # 额外的嵌入模型配置参数
|
|
622
1020
|
"rerank_model",
|
|
1021
|
+
"reranker_type",
|
|
1022
|
+
"reranker_max_length", # 重排模型最大输入长度
|
|
1023
|
+
"reranker_config", # 额外的重排模型配置参数
|
|
623
1024
|
"use_bm25",
|
|
624
1025
|
"use_rerank",
|
|
625
1026
|
]:
|
|
@@ -693,6 +1094,72 @@ def get_rag_use_rerank() -> bool:
|
|
|
693
1094
|
return config.get("use_rerank", True) is True
|
|
694
1095
|
|
|
695
1096
|
|
|
1097
|
+
def get_rag_embedding_type() -> str:
|
|
1098
|
+
"""
|
|
1099
|
+
获取RAG嵌入模型的实现类型。
|
|
1100
|
+
|
|
1101
|
+
返回:
|
|
1102
|
+
str: 嵌入模型类型(如 'LocalEmbeddingModel', 'OpenAIEmbeddingModel' 等),默认为 'LocalEmbeddingModel'
|
|
1103
|
+
"""
|
|
1104
|
+
config = _get_resolved_rag_config()
|
|
1105
|
+
return cast(str, config.get("embedding_type", "LocalEmbeddingModel"))
|
|
1106
|
+
|
|
1107
|
+
|
|
1108
|
+
def get_rag_reranker_type() -> str:
|
|
1109
|
+
"""
|
|
1110
|
+
获取RAG重排模型的实现类型。
|
|
1111
|
+
|
|
1112
|
+
返回:
|
|
1113
|
+
str: 重排模型类型(如 'LocalReranker', 'CohereReranker' 等),默认为 'LocalReranker'
|
|
1114
|
+
"""
|
|
1115
|
+
config = _get_resolved_rag_config()
|
|
1116
|
+
return cast(str, config.get("reranker_type", "LocalReranker"))
|
|
1117
|
+
|
|
1118
|
+
|
|
1119
|
+
def get_rag_embedding_config() -> Dict[str, Any]:
|
|
1120
|
+
"""
|
|
1121
|
+
获取RAG嵌入模型的额外配置参数。
|
|
1122
|
+
|
|
1123
|
+
返回:
|
|
1124
|
+
Dict[str, Any]: 嵌入模型的配置参数字典,如果未配置则返回空字典
|
|
1125
|
+
"""
|
|
1126
|
+
config = _get_resolved_rag_config()
|
|
1127
|
+
return dict(config.get("embedding_config", {}))
|
|
1128
|
+
|
|
1129
|
+
|
|
1130
|
+
def get_rag_reranker_config() -> Dict[str, Any]:
|
|
1131
|
+
"""
|
|
1132
|
+
获取RAG重排模型的额外配置参数。
|
|
1133
|
+
|
|
1134
|
+
返回:
|
|
1135
|
+
Dict[str, Any]: 重排模型的配置参数字典,如果未配置则返回空字典
|
|
1136
|
+
"""
|
|
1137
|
+
config = _get_resolved_rag_config()
|
|
1138
|
+
return dict(config.get("reranker_config", {}))
|
|
1139
|
+
|
|
1140
|
+
|
|
1141
|
+
def get_rag_embedding_max_length() -> int:
|
|
1142
|
+
"""
|
|
1143
|
+
获取RAG嵌入模型的最大输入长度(token数)。
|
|
1144
|
+
|
|
1145
|
+
返回:
|
|
1146
|
+
int: 嵌入模型的最大输入token数,默认为512
|
|
1147
|
+
"""
|
|
1148
|
+
config = _get_resolved_rag_config()
|
|
1149
|
+
return int(config.get("embedding_max_length", 512))
|
|
1150
|
+
|
|
1151
|
+
|
|
1152
|
+
def get_rag_reranker_max_length() -> int:
|
|
1153
|
+
"""
|
|
1154
|
+
获取RAG重排模型的最大输入长度(token数)。
|
|
1155
|
+
|
|
1156
|
+
返回:
|
|
1157
|
+
int: 重排模型的最大输入token数,默认为512
|
|
1158
|
+
"""
|
|
1159
|
+
config = _get_resolved_rag_config()
|
|
1160
|
+
return int(config.get("reranker_max_length", 512))
|
|
1161
|
+
|
|
1162
|
+
|
|
696
1163
|
# ==============================================================================
|
|
697
1164
|
# Web Search Configuration
|
|
698
1165
|
# ==============================================================================
|
|
@@ -705,7 +1172,11 @@ def get_web_search_platform_name() -> Optional[str]:
|
|
|
705
1172
|
返回:
|
|
706
1173
|
Optional[str]: 平台名称,如果未配置则返回None
|
|
707
1174
|
"""
|
|
708
|
-
return
|
|
1175
|
+
return (
|
|
1176
|
+
str(GLOBAL_CONFIG_DATA.get("web_search_platform"))
|
|
1177
|
+
if GLOBAL_CONFIG_DATA.get("web_search_platform") is not None
|
|
1178
|
+
else None
|
|
1179
|
+
)
|
|
709
1180
|
|
|
710
1181
|
|
|
711
1182
|
def get_web_search_model_name() -> Optional[str]:
|
|
@@ -715,7 +1186,11 @@ def get_web_search_model_name() -> Optional[str]:
|
|
|
715
1186
|
返回:
|
|
716
1187
|
Optional[str]: 模型名称,如果未配置则返回None
|
|
717
1188
|
"""
|
|
718
|
-
return
|
|
1189
|
+
return (
|
|
1190
|
+
str(GLOBAL_CONFIG_DATA.get("web_search_model"))
|
|
1191
|
+
if GLOBAL_CONFIG_DATA.get("web_search_model") is not None
|
|
1192
|
+
else None
|
|
1193
|
+
)
|
|
719
1194
|
|
|
720
1195
|
|
|
721
1196
|
# ==============================================================================
|
|
@@ -730,15 +1205,15 @@ def _get_resolved_tool_config(
|
|
|
730
1205
|
解析并合并工具配置,处理工具组。
|
|
731
1206
|
|
|
732
1207
|
优先级顺序:
|
|
733
|
-
1.
|
|
1208
|
+
1. tool_group 中定义的组配置
|
|
734
1209
|
2. 默认配置(所有工具都启用)
|
|
735
1210
|
|
|
736
1211
|
返回:
|
|
737
1212
|
Dict[str, Any]: 解析后的工具配置字典,包含 'use' 和 'dont_use' 列表
|
|
738
1213
|
"""
|
|
739
1214
|
group_config = {}
|
|
740
|
-
tool_group_name = tool_group_override or GLOBAL_CONFIG_DATA.get("
|
|
741
|
-
tool_groups = GLOBAL_CONFIG_DATA.get("
|
|
1215
|
+
tool_group_name = tool_group_override or GLOBAL_CONFIG_DATA.get("tool_group")
|
|
1216
|
+
tool_groups = GLOBAL_CONFIG_DATA.get("tool_groups", [])
|
|
742
1217
|
|
|
743
1218
|
if tool_group_name and isinstance(tool_groups, list):
|
|
744
1219
|
for group_item in tool_groups:
|
|
@@ -779,11 +1254,7 @@ def get_tool_filter_threshold() -> int:
|
|
|
779
1254
|
返回:
|
|
780
1255
|
int: 当工具数量超过此阈值时,触发AI筛选。默认为30
|
|
781
1256
|
"""
|
|
782
|
-
return int(GLOBAL_CONFIG_DATA.get("
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
1257
|
+
return int(GLOBAL_CONFIG_DATA.get("tool_filter_threshold", 30))
|
|
787
1258
|
|
|
788
1259
|
|
|
789
1260
|
def get_script_execution_timeout() -> int:
|
|
@@ -793,7 +1264,7 @@ def get_script_execution_timeout() -> int:
|
|
|
793
1264
|
返回:
|
|
794
1265
|
int: 超时时间,默认为300秒(5分钟)
|
|
795
1266
|
"""
|
|
796
|
-
return int(GLOBAL_CONFIG_DATA.get("
|
|
1267
|
+
return int(GLOBAL_CONFIG_DATA.get("script_execution_timeout", 300))
|
|
797
1268
|
|
|
798
1269
|
|
|
799
1270
|
def is_enable_git_repo_jca_switch() -> bool:
|
|
@@ -801,7 +1272,7 @@ def is_enable_git_repo_jca_switch() -> bool:
|
|
|
801
1272
|
是否启用:在初始化环境前检测Git仓库并提示可切换到代码开发模式(jca)
|
|
802
1273
|
默认开启
|
|
803
1274
|
"""
|
|
804
|
-
return GLOBAL_CONFIG_DATA.get("
|
|
1275
|
+
return GLOBAL_CONFIG_DATA.get("enable_git_jca_switch", True) is True
|
|
805
1276
|
|
|
806
1277
|
|
|
807
1278
|
def is_enable_builtin_config_selector() -> bool:
|
|
@@ -809,9 +1280,7 @@ def is_enable_builtin_config_selector() -> bool:
|
|
|
809
1280
|
是否启用:在进入默认通用代理前,列出可用配置(agent/multi_agent/roles)供选择
|
|
810
1281
|
默认开启
|
|
811
1282
|
"""
|
|
812
|
-
return (
|
|
813
|
-
GLOBAL_CONFIG_DATA.get("JARVIS_ENABLE_STARTUP_CONFIG_SELECTOR", True) is True
|
|
814
|
-
)
|
|
1283
|
+
return GLOBAL_CONFIG_DATA.get("enable_startup_config_selector", True) is True
|
|
815
1284
|
|
|
816
1285
|
|
|
817
1286
|
def is_save_session_history() -> bool:
|
|
@@ -821,7 +1290,7 @@ def is_save_session_history() -> bool:
|
|
|
821
1290
|
返回:
|
|
822
1291
|
bool: 如果要保存会话记录则返回True, 默认为False
|
|
823
1292
|
"""
|
|
824
|
-
return GLOBAL_CONFIG_DATA.get("
|
|
1293
|
+
return GLOBAL_CONFIG_DATA.get("save_session_history", False) is True
|
|
825
1294
|
|
|
826
1295
|
|
|
827
1296
|
def is_immediate_abort() -> bool:
|
|
@@ -829,53 +1298,56 @@ def is_immediate_abort() -> bool:
|
|
|
829
1298
|
是否启用立即中断:当在对话过程中检测到用户中断信号时,立即停止输出并返回。
|
|
830
1299
|
默认关闭
|
|
831
1300
|
"""
|
|
832
|
-
return GLOBAL_CONFIG_DATA.get("
|
|
1301
|
+
return GLOBAL_CONFIG_DATA.get("immediate_abort", False) is True
|
|
833
1302
|
|
|
834
1303
|
|
|
835
1304
|
def is_non_interactive() -> bool:
|
|
836
1305
|
"""
|
|
837
1306
|
获取是否启用非交互模式。
|
|
838
|
-
|
|
1307
|
+
|
|
839
1308
|
返回:
|
|
840
1309
|
bool: 如果启用非交互模式则返回True,默认为False
|
|
841
1310
|
"""
|
|
842
|
-
# 优先读取环境变量,确保 CLI 标志生效且不被配置覆盖
|
|
843
1311
|
try:
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
if
|
|
851
|
-
|
|
1312
|
+
# 优先基于当前激活的 Agent 状态判断,避免跨 Agent 互相污染
|
|
1313
|
+
from jarvis.jarvis_utils import globals as _g
|
|
1314
|
+
|
|
1315
|
+
current_agent_name = _g.get_current_agent_name()
|
|
1316
|
+
if current_agent_name:
|
|
1317
|
+
agent = _g.get_agent(current_agent_name)
|
|
1318
|
+
if agent is not None and hasattr(agent, "non_interactive"):
|
|
1319
|
+
try:
|
|
1320
|
+
return bool(getattr(agent, "non_interactive"))
|
|
1321
|
+
except Exception:
|
|
1322
|
+
return False
|
|
852
1323
|
except Exception:
|
|
853
|
-
#
|
|
854
|
-
|
|
855
|
-
|
|
1324
|
+
# 防御式兜底,保持返回 False 不影响主流程
|
|
1325
|
+
return False
|
|
1326
|
+
# 无当前 Agent 时默认返回 False,避免依赖全局配置或环境变量
|
|
1327
|
+
return False
|
|
856
1328
|
|
|
857
1329
|
|
|
858
1330
|
def is_skip_predefined_tasks() -> bool:
|
|
859
1331
|
"""
|
|
860
1332
|
是否跳过预定义任务加载。
|
|
861
|
-
|
|
1333
|
+
|
|
862
1334
|
返回:
|
|
863
1335
|
bool: 如果跳过预定义任务加载则返回True,默认为False
|
|
864
1336
|
"""
|
|
865
|
-
return GLOBAL_CONFIG_DATA.get("
|
|
1337
|
+
return GLOBAL_CONFIG_DATA.get("skip_predefined_tasks", False) is True
|
|
866
1338
|
|
|
867
1339
|
|
|
868
1340
|
def get_addon_prompt_threshold() -> int:
|
|
869
1341
|
"""
|
|
870
1342
|
获取附加提示的触发阈值(字符数)。
|
|
871
|
-
|
|
1343
|
+
|
|
872
1344
|
当消息长度超过此阈值时,会自动添加默认的附加提示。
|
|
873
|
-
|
|
1345
|
+
|
|
874
1346
|
返回:
|
|
875
1347
|
int: 触发阈值,默认为1024
|
|
876
1348
|
"""
|
|
877
1349
|
try:
|
|
878
|
-
return int(GLOBAL_CONFIG_DATA.get("
|
|
1350
|
+
return int(GLOBAL_CONFIG_DATA.get("addon_prompt_threshold", 1024))
|
|
879
1351
|
except Exception:
|
|
880
1352
|
return 1024
|
|
881
1353
|
|
|
@@ -883,26 +1355,59 @@ def get_addon_prompt_threshold() -> int:
|
|
|
883
1355
|
def is_enable_intent_recognition() -> bool:
|
|
884
1356
|
"""
|
|
885
1357
|
获取是否启用意图识别功能。
|
|
886
|
-
|
|
1358
|
+
|
|
887
1359
|
返回:
|
|
888
|
-
bool: 是否启用意图识别,默认为True(可通过 GLOBAL_CONFIG_DATA['
|
|
1360
|
+
bool: 是否启用意图识别,默认为True(可通过 GLOBAL_CONFIG_DATA['enable_intent_recognition'] 配置)
|
|
889
1361
|
"""
|
|
890
|
-
return GLOBAL_CONFIG_DATA.get("
|
|
1362
|
+
return GLOBAL_CONFIG_DATA.get("enable_intent_recognition", True) is True
|
|
891
1363
|
|
|
892
1364
|
|
|
893
1365
|
def is_enable_memory_organizer() -> bool:
|
|
894
1366
|
"""
|
|
895
1367
|
获取是否启用自动记忆整理功能。
|
|
896
|
-
|
|
1368
|
+
|
|
897
1369
|
返回:
|
|
898
|
-
bool: 是否启用自动记忆整理,默认为False(可通过 GLOBAL_CONFIG_DATA['
|
|
1370
|
+
bool: 是否启用自动记忆整理,默认为False(可通过 GLOBAL_CONFIG_DATA['enable_memory_organizer'] 配置)
|
|
899
1371
|
"""
|
|
900
|
-
return GLOBAL_CONFIG_DATA.get("
|
|
1372
|
+
return GLOBAL_CONFIG_DATA.get("enable_memory_organizer", False) is True
|
|
1373
|
+
|
|
1374
|
+
|
|
901
1375
|
def get_conversation_turn_threshold() -> int:
|
|
902
1376
|
"""
|
|
903
1377
|
获取对话轮次阈值,用于触发总结。
|
|
904
|
-
|
|
1378
|
+
|
|
905
1379
|
返回:
|
|
906
1380
|
int: 对话轮次阈值,默认为50
|
|
907
1381
|
"""
|
|
908
|
-
return int(GLOBAL_CONFIG_DATA.get("
|
|
1382
|
+
return int(GLOBAL_CONFIG_DATA.get("conversation_turn_threshold", 50))
|
|
1383
|
+
|
|
1384
|
+
|
|
1385
|
+
def get_diff_visualization_mode() -> str:
|
|
1386
|
+
"""
|
|
1387
|
+
获取 diff 可视化模式
|
|
1388
|
+
|
|
1389
|
+
返回:
|
|
1390
|
+
str: diff 可视化模式,可选值: "unified", "syntax", "compact", "side_by_side", "default"
|
|
1391
|
+
默认为 "unified"
|
|
1392
|
+
"""
|
|
1393
|
+
return cast(str, GLOBAL_CONFIG_DATA.get("diff_visualization_mode", "side_by_side"))
|
|
1394
|
+
|
|
1395
|
+
|
|
1396
|
+
def get_diff_show_line_numbers() -> bool:
|
|
1397
|
+
"""
|
|
1398
|
+
获取是否在 diff 中显示行号
|
|
1399
|
+
|
|
1400
|
+
返回:
|
|
1401
|
+
bool: 是否显示行号,默认为 True
|
|
1402
|
+
"""
|
|
1403
|
+
return cast(bool, GLOBAL_CONFIG_DATA.get("diff_show_line_numbers", True))
|
|
1404
|
+
|
|
1405
|
+
|
|
1406
|
+
def get_diff_large_file_threshold() -> int:
|
|
1407
|
+
"""
|
|
1408
|
+
获取大文件阈值(超过此行数只显示统计)
|
|
1409
|
+
|
|
1410
|
+
返回:
|
|
1411
|
+
int: 大文件阈值,默认为 300
|
|
1412
|
+
"""
|
|
1413
|
+
return int(GLOBAL_CONFIG_DATA.get("diff_large_file_threshold", 300))
|