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.
Files changed (279) hide show
  1. jarvis/__init__.py +1 -1
  2. jarvis/jarvis_agent/__init__.py +567 -222
  3. jarvis/jarvis_agent/agent_manager.py +19 -12
  4. jarvis/jarvis_agent/builtin_input_handler.py +79 -11
  5. jarvis/jarvis_agent/config_editor.py +7 -2
  6. jarvis/jarvis_agent/event_bus.py +24 -13
  7. jarvis/jarvis_agent/events.py +19 -1
  8. jarvis/jarvis_agent/file_context_handler.py +67 -64
  9. jarvis/jarvis_agent/file_methodology_manager.py +38 -24
  10. jarvis/jarvis_agent/jarvis.py +186 -114
  11. jarvis/jarvis_agent/language_extractors/__init__.py +8 -1
  12. jarvis/jarvis_agent/language_extractors/c_extractor.py +7 -4
  13. jarvis/jarvis_agent/language_extractors/cpp_extractor.py +9 -4
  14. jarvis/jarvis_agent/language_extractors/go_extractor.py +7 -4
  15. jarvis/jarvis_agent/language_extractors/java_extractor.py +27 -20
  16. jarvis/jarvis_agent/language_extractors/javascript_extractor.py +22 -17
  17. jarvis/jarvis_agent/language_extractors/python_extractor.py +7 -4
  18. jarvis/jarvis_agent/language_extractors/rust_extractor.py +7 -4
  19. jarvis/jarvis_agent/language_extractors/typescript_extractor.py +22 -17
  20. jarvis/jarvis_agent/language_support_info.py +250 -219
  21. jarvis/jarvis_agent/main.py +19 -23
  22. jarvis/jarvis_agent/memory_manager.py +9 -6
  23. jarvis/jarvis_agent/methodology_share_manager.py +21 -15
  24. jarvis/jarvis_agent/output_handler.py +4 -2
  25. jarvis/jarvis_agent/prompt_builder.py +7 -6
  26. jarvis/jarvis_agent/prompt_manager.py +113 -8
  27. jarvis/jarvis_agent/prompts.py +317 -85
  28. jarvis/jarvis_agent/protocols.py +5 -2
  29. jarvis/jarvis_agent/run_loop.py +192 -32
  30. jarvis/jarvis_agent/session_manager.py +7 -3
  31. jarvis/jarvis_agent/share_manager.py +23 -13
  32. jarvis/jarvis_agent/shell_input_handler.py +12 -8
  33. jarvis/jarvis_agent/stdio_redirect.py +25 -26
  34. jarvis/jarvis_agent/task_analyzer.py +29 -23
  35. jarvis/jarvis_agent/task_list.py +869 -0
  36. jarvis/jarvis_agent/task_manager.py +26 -23
  37. jarvis/jarvis_agent/tool_executor.py +6 -5
  38. jarvis/jarvis_agent/tool_share_manager.py +24 -14
  39. jarvis/jarvis_agent/user_interaction.py +3 -3
  40. jarvis/jarvis_agent/utils.py +9 -1
  41. jarvis/jarvis_agent/web_bridge.py +37 -17
  42. jarvis/jarvis_agent/web_output_sink.py +5 -2
  43. jarvis/jarvis_agent/web_server.py +165 -36
  44. jarvis/jarvis_c2rust/__init__.py +1 -1
  45. jarvis/jarvis_c2rust/cli.py +260 -141
  46. jarvis/jarvis_c2rust/collector.py +37 -18
  47. jarvis/jarvis_c2rust/constants.py +60 -0
  48. jarvis/jarvis_c2rust/library_replacer.py +242 -1010
  49. jarvis/jarvis_c2rust/library_replacer_checkpoint.py +133 -0
  50. jarvis/jarvis_c2rust/library_replacer_llm.py +287 -0
  51. jarvis/jarvis_c2rust/library_replacer_loader.py +191 -0
  52. jarvis/jarvis_c2rust/library_replacer_output.py +134 -0
  53. jarvis/jarvis_c2rust/library_replacer_prompts.py +124 -0
  54. jarvis/jarvis_c2rust/library_replacer_utils.py +188 -0
  55. jarvis/jarvis_c2rust/llm_module_agent.py +98 -1044
  56. jarvis/jarvis_c2rust/llm_module_agent_apply.py +170 -0
  57. jarvis/jarvis_c2rust/llm_module_agent_executor.py +288 -0
  58. jarvis/jarvis_c2rust/llm_module_agent_loader.py +170 -0
  59. jarvis/jarvis_c2rust/llm_module_agent_prompts.py +268 -0
  60. jarvis/jarvis_c2rust/llm_module_agent_types.py +57 -0
  61. jarvis/jarvis_c2rust/llm_module_agent_utils.py +150 -0
  62. jarvis/jarvis_c2rust/llm_module_agent_validator.py +119 -0
  63. jarvis/jarvis_c2rust/loaders.py +28 -10
  64. jarvis/jarvis_c2rust/models.py +5 -2
  65. jarvis/jarvis_c2rust/optimizer.py +192 -1974
  66. jarvis/jarvis_c2rust/optimizer_build_fix.py +286 -0
  67. jarvis/jarvis_c2rust/optimizer_clippy.py +766 -0
  68. jarvis/jarvis_c2rust/optimizer_config.py +49 -0
  69. jarvis/jarvis_c2rust/optimizer_docs.py +183 -0
  70. jarvis/jarvis_c2rust/optimizer_options.py +48 -0
  71. jarvis/jarvis_c2rust/optimizer_progress.py +469 -0
  72. jarvis/jarvis_c2rust/optimizer_report.py +52 -0
  73. jarvis/jarvis_c2rust/optimizer_unsafe.py +309 -0
  74. jarvis/jarvis_c2rust/optimizer_utils.py +469 -0
  75. jarvis/jarvis_c2rust/optimizer_visibility.py +185 -0
  76. jarvis/jarvis_c2rust/scanner.py +229 -166
  77. jarvis/jarvis_c2rust/transpiler.py +531 -2732
  78. jarvis/jarvis_c2rust/transpiler_agents.py +503 -0
  79. jarvis/jarvis_c2rust/transpiler_build.py +1294 -0
  80. jarvis/jarvis_c2rust/transpiler_codegen.py +204 -0
  81. jarvis/jarvis_c2rust/transpiler_compile.py +146 -0
  82. jarvis/jarvis_c2rust/transpiler_config.py +178 -0
  83. jarvis/jarvis_c2rust/transpiler_context.py +122 -0
  84. jarvis/jarvis_c2rust/transpiler_executor.py +516 -0
  85. jarvis/jarvis_c2rust/transpiler_generation.py +278 -0
  86. jarvis/jarvis_c2rust/transpiler_git.py +163 -0
  87. jarvis/jarvis_c2rust/transpiler_mod_utils.py +225 -0
  88. jarvis/jarvis_c2rust/transpiler_modules.py +336 -0
  89. jarvis/jarvis_c2rust/transpiler_planning.py +394 -0
  90. jarvis/jarvis_c2rust/transpiler_review.py +1196 -0
  91. jarvis/jarvis_c2rust/transpiler_symbols.py +176 -0
  92. jarvis/jarvis_c2rust/utils.py +269 -79
  93. jarvis/jarvis_code_agent/after_change.py +233 -0
  94. jarvis/jarvis_code_agent/build_validation_config.py +37 -30
  95. jarvis/jarvis_code_agent/builtin_rules.py +68 -0
  96. jarvis/jarvis_code_agent/code_agent.py +976 -1517
  97. jarvis/jarvis_code_agent/code_agent_build.py +227 -0
  98. jarvis/jarvis_code_agent/code_agent_diff.py +246 -0
  99. jarvis/jarvis_code_agent/code_agent_git.py +525 -0
  100. jarvis/jarvis_code_agent/code_agent_impact.py +177 -0
  101. jarvis/jarvis_code_agent/code_agent_lint.py +283 -0
  102. jarvis/jarvis_code_agent/code_agent_llm.py +159 -0
  103. jarvis/jarvis_code_agent/code_agent_postprocess.py +105 -0
  104. jarvis/jarvis_code_agent/code_agent_prompts.py +46 -0
  105. jarvis/jarvis_code_agent/code_agent_rules.py +305 -0
  106. jarvis/jarvis_code_agent/code_analyzer/__init__.py +52 -48
  107. jarvis/jarvis_code_agent/code_analyzer/base_language.py +12 -10
  108. jarvis/jarvis_code_agent/code_analyzer/build_validator/__init__.py +12 -11
  109. jarvis/jarvis_code_agent/code_analyzer/build_validator/base.py +16 -12
  110. jarvis/jarvis_code_agent/code_analyzer/build_validator/cmake.py +26 -17
  111. jarvis/jarvis_code_agent/code_analyzer/build_validator/detector.py +558 -104
  112. jarvis/jarvis_code_agent/code_analyzer/build_validator/fallback.py +27 -16
  113. jarvis/jarvis_code_agent/code_analyzer/build_validator/go.py +22 -18
  114. jarvis/jarvis_code_agent/code_analyzer/build_validator/java_gradle.py +21 -16
  115. jarvis/jarvis_code_agent/code_analyzer/build_validator/java_maven.py +20 -16
  116. jarvis/jarvis_code_agent/code_analyzer/build_validator/makefile.py +27 -16
  117. jarvis/jarvis_code_agent/code_analyzer/build_validator/nodejs.py +47 -23
  118. jarvis/jarvis_code_agent/code_analyzer/build_validator/python.py +71 -37
  119. jarvis/jarvis_code_agent/code_analyzer/build_validator/rust.py +162 -35
  120. jarvis/jarvis_code_agent/code_analyzer/build_validator/validator.py +111 -57
  121. jarvis/jarvis_code_agent/code_analyzer/build_validator.py +18 -12
  122. jarvis/jarvis_code_agent/code_analyzer/context_manager.py +185 -183
  123. jarvis/jarvis_code_agent/code_analyzer/context_recommender.py +2 -1
  124. jarvis/jarvis_code_agent/code_analyzer/dependency_analyzer.py +24 -15
  125. jarvis/jarvis_code_agent/code_analyzer/file_ignore.py +227 -141
  126. jarvis/jarvis_code_agent/code_analyzer/impact_analyzer.py +321 -247
  127. jarvis/jarvis_code_agent/code_analyzer/language_registry.py +37 -29
  128. jarvis/jarvis_code_agent/code_analyzer/language_support.py +21 -13
  129. jarvis/jarvis_code_agent/code_analyzer/languages/__init__.py +15 -9
  130. jarvis/jarvis_code_agent/code_analyzer/languages/c_cpp_language.py +75 -45
  131. jarvis/jarvis_code_agent/code_analyzer/languages/go_language.py +87 -52
  132. jarvis/jarvis_code_agent/code_analyzer/languages/java_language.py +84 -51
  133. jarvis/jarvis_code_agent/code_analyzer/languages/javascript_language.py +94 -64
  134. jarvis/jarvis_code_agent/code_analyzer/languages/python_language.py +109 -71
  135. jarvis/jarvis_code_agent/code_analyzer/languages/rust_language.py +97 -63
  136. jarvis/jarvis_code_agent/code_analyzer/languages/typescript_language.py +103 -69
  137. jarvis/jarvis_code_agent/code_analyzer/llm_context_recommender.py +271 -268
  138. jarvis/jarvis_code_agent/code_analyzer/symbol_extractor.py +76 -64
  139. jarvis/jarvis_code_agent/code_analyzer/tree_sitter_extractor.py +92 -19
  140. jarvis/jarvis_code_agent/diff_visualizer.py +998 -0
  141. jarvis/jarvis_code_agent/lint.py +223 -524
  142. jarvis/jarvis_code_agent/rule_share_manager.py +158 -0
  143. jarvis/jarvis_code_agent/rules/clean_code.md +144 -0
  144. jarvis/jarvis_code_agent/rules/code_review.md +115 -0
  145. jarvis/jarvis_code_agent/rules/documentation.md +165 -0
  146. jarvis/jarvis_code_agent/rules/generate_rules.md +52 -0
  147. jarvis/jarvis_code_agent/rules/performance.md +158 -0
  148. jarvis/jarvis_code_agent/rules/refactoring.md +139 -0
  149. jarvis/jarvis_code_agent/rules/security.md +160 -0
  150. jarvis/jarvis_code_agent/rules/tdd.md +78 -0
  151. jarvis/jarvis_code_agent/test_rules/cpp_test.md +118 -0
  152. jarvis/jarvis_code_agent/test_rules/go_test.md +98 -0
  153. jarvis/jarvis_code_agent/test_rules/java_test.md +99 -0
  154. jarvis/jarvis_code_agent/test_rules/javascript_test.md +113 -0
  155. jarvis/jarvis_code_agent/test_rules/php_test.md +117 -0
  156. jarvis/jarvis_code_agent/test_rules/python_test.md +91 -0
  157. jarvis/jarvis_code_agent/test_rules/ruby_test.md +102 -0
  158. jarvis/jarvis_code_agent/test_rules/rust_test.md +86 -0
  159. jarvis/jarvis_code_agent/utils.py +36 -26
  160. jarvis/jarvis_code_analysis/checklists/loader.py +21 -21
  161. jarvis/jarvis_code_analysis/code_review.py +64 -33
  162. jarvis/jarvis_data/config_schema.json +285 -192
  163. jarvis/jarvis_git_squash/main.py +8 -6
  164. jarvis/jarvis_git_utils/git_commiter.py +53 -76
  165. jarvis/jarvis_mcp/__init__.py +5 -2
  166. jarvis/jarvis_mcp/sse_mcp_client.py +40 -30
  167. jarvis/jarvis_mcp/stdio_mcp_client.py +27 -19
  168. jarvis/jarvis_mcp/streamable_mcp_client.py +35 -26
  169. jarvis/jarvis_memory_organizer/memory_organizer.py +78 -55
  170. jarvis/jarvis_methodology/main.py +48 -39
  171. jarvis/jarvis_multi_agent/__init__.py +56 -23
  172. jarvis/jarvis_multi_agent/main.py +15 -18
  173. jarvis/jarvis_platform/base.py +179 -111
  174. jarvis/jarvis_platform/human.py +27 -16
  175. jarvis/jarvis_platform/kimi.py +52 -45
  176. jarvis/jarvis_platform/openai.py +101 -40
  177. jarvis/jarvis_platform/registry.py +51 -33
  178. jarvis/jarvis_platform/tongyi.py +68 -38
  179. jarvis/jarvis_platform/yuanbao.py +59 -43
  180. jarvis/jarvis_platform_manager/main.py +68 -76
  181. jarvis/jarvis_platform_manager/service.py +24 -14
  182. jarvis/jarvis_rag/README_CONFIG.md +314 -0
  183. jarvis/jarvis_rag/README_DYNAMIC_LOADING.md +311 -0
  184. jarvis/jarvis_rag/README_ONLINE_MODELS.md +230 -0
  185. jarvis/jarvis_rag/__init__.py +57 -4
  186. jarvis/jarvis_rag/cache.py +3 -1
  187. jarvis/jarvis_rag/cli.py +48 -68
  188. jarvis/jarvis_rag/embedding_interface.py +39 -0
  189. jarvis/jarvis_rag/embedding_manager.py +7 -230
  190. jarvis/jarvis_rag/embeddings/__init__.py +41 -0
  191. jarvis/jarvis_rag/embeddings/base.py +114 -0
  192. jarvis/jarvis_rag/embeddings/cohere.py +66 -0
  193. jarvis/jarvis_rag/embeddings/edgefn.py +117 -0
  194. jarvis/jarvis_rag/embeddings/local.py +260 -0
  195. jarvis/jarvis_rag/embeddings/openai.py +62 -0
  196. jarvis/jarvis_rag/embeddings/registry.py +293 -0
  197. jarvis/jarvis_rag/llm_interface.py +8 -6
  198. jarvis/jarvis_rag/query_rewriter.py +8 -9
  199. jarvis/jarvis_rag/rag_pipeline.py +61 -52
  200. jarvis/jarvis_rag/reranker.py +7 -75
  201. jarvis/jarvis_rag/reranker_interface.py +32 -0
  202. jarvis/jarvis_rag/rerankers/__init__.py +41 -0
  203. jarvis/jarvis_rag/rerankers/base.py +109 -0
  204. jarvis/jarvis_rag/rerankers/cohere.py +67 -0
  205. jarvis/jarvis_rag/rerankers/edgefn.py +140 -0
  206. jarvis/jarvis_rag/rerankers/jina.py +79 -0
  207. jarvis/jarvis_rag/rerankers/local.py +89 -0
  208. jarvis/jarvis_rag/rerankers/registry.py +293 -0
  209. jarvis/jarvis_rag/retriever.py +58 -43
  210. jarvis/jarvis_sec/__init__.py +66 -141
  211. jarvis/jarvis_sec/agents.py +21 -17
  212. jarvis/jarvis_sec/analysis.py +80 -33
  213. jarvis/jarvis_sec/checkers/__init__.py +7 -13
  214. jarvis/jarvis_sec/checkers/c_checker.py +356 -164
  215. jarvis/jarvis_sec/checkers/rust_checker.py +47 -29
  216. jarvis/jarvis_sec/cli.py +43 -21
  217. jarvis/jarvis_sec/clustering.py +430 -272
  218. jarvis/jarvis_sec/file_manager.py +99 -55
  219. jarvis/jarvis_sec/parsers.py +9 -6
  220. jarvis/jarvis_sec/prompts.py +4 -3
  221. jarvis/jarvis_sec/report.py +44 -22
  222. jarvis/jarvis_sec/review.py +180 -107
  223. jarvis/jarvis_sec/status.py +50 -41
  224. jarvis/jarvis_sec/types.py +3 -0
  225. jarvis/jarvis_sec/utils.py +160 -83
  226. jarvis/jarvis_sec/verification.py +411 -181
  227. jarvis/jarvis_sec/workflow.py +132 -21
  228. jarvis/jarvis_smart_shell/main.py +28 -41
  229. jarvis/jarvis_stats/cli.py +14 -12
  230. jarvis/jarvis_stats/stats.py +28 -19
  231. jarvis/jarvis_stats/storage.py +14 -8
  232. jarvis/jarvis_stats/visualizer.py +12 -7
  233. jarvis/jarvis_tools/base.py +5 -2
  234. jarvis/jarvis_tools/clear_memory.py +13 -9
  235. jarvis/jarvis_tools/cli/main.py +23 -18
  236. jarvis/jarvis_tools/edit_file.py +572 -873
  237. jarvis/jarvis_tools/execute_script.py +10 -7
  238. jarvis/jarvis_tools/file_analyzer.py +7 -8
  239. jarvis/jarvis_tools/meta_agent.py +287 -0
  240. jarvis/jarvis_tools/methodology.py +5 -3
  241. jarvis/jarvis_tools/read_code.py +305 -1438
  242. jarvis/jarvis_tools/read_symbols.py +50 -17
  243. jarvis/jarvis_tools/read_webpage.py +19 -18
  244. jarvis/jarvis_tools/registry.py +435 -156
  245. jarvis/jarvis_tools/retrieve_memory.py +16 -11
  246. jarvis/jarvis_tools/save_memory.py +8 -6
  247. jarvis/jarvis_tools/search_web.py +31 -31
  248. jarvis/jarvis_tools/sub_agent.py +32 -28
  249. jarvis/jarvis_tools/sub_code_agent.py +44 -60
  250. jarvis/jarvis_tools/task_list_manager.py +1811 -0
  251. jarvis/jarvis_tools/virtual_tty.py +29 -19
  252. jarvis/jarvis_utils/__init__.py +4 -0
  253. jarvis/jarvis_utils/builtin_replace_map.py +2 -1
  254. jarvis/jarvis_utils/clipboard.py +9 -8
  255. jarvis/jarvis_utils/collections.py +331 -0
  256. jarvis/jarvis_utils/config.py +699 -194
  257. jarvis/jarvis_utils/dialogue_recorder.py +294 -0
  258. jarvis/jarvis_utils/embedding.py +6 -3
  259. jarvis/jarvis_utils/file_processors.py +7 -1
  260. jarvis/jarvis_utils/fzf.py +9 -3
  261. jarvis/jarvis_utils/git_utils.py +71 -42
  262. jarvis/jarvis_utils/globals.py +116 -32
  263. jarvis/jarvis_utils/http.py +6 -2
  264. jarvis/jarvis_utils/input.py +318 -83
  265. jarvis/jarvis_utils/jsonnet_compat.py +119 -104
  266. jarvis/jarvis_utils/methodology.py +37 -28
  267. jarvis/jarvis_utils/output.py +201 -44
  268. jarvis/jarvis_utils/utils.py +986 -628
  269. {jarvis_ai_assistant-0.7.16.dist-info → jarvis_ai_assistant-1.0.2.dist-info}/METADATA +49 -33
  270. jarvis_ai_assistant-1.0.2.dist-info/RECORD +304 -0
  271. jarvis/jarvis_code_agent/code_analyzer/structured_code.py +0 -556
  272. jarvis/jarvis_tools/generate_new_tool.py +0 -205
  273. jarvis/jarvis_tools/lsp_client.py +0 -1552
  274. jarvis/jarvis_tools/rewrite_file.py +0 -105
  275. jarvis_ai_assistant-0.7.16.dist-info/RECORD +0 -218
  276. {jarvis_ai_assistant-0.7.16.dist-info → jarvis_ai_assistant-1.0.2.dist-info}/WHEEL +0 -0
  277. {jarvis_ai_assistant-0.7.16.dist-info → jarvis_ai_assistant-1.0.2.dist-info}/entry_points.txt +0 -0
  278. {jarvis_ai_assistant-0.7.16.dist-info → jarvis_ai_assistant-1.0.2.dist-info}/licenses/LICENSE +0 -0
  279. {jarvis_ai_assistant-0.7.16.dist-info → jarvis_ai_assistant-1.0.2.dist-info}/top_level.txt +0 -0
@@ -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, Dict, List, Optional, cast
5
-
6
- import yaml
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: Dict[str, Any] = {}
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("JARVIS_GIT_COMMIT_PROMPT", ""))
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['JARVIS_REPLACE_MAP']的配置,
53
- 如果没有则从数据目录下的replace_map.yaml文件中读取替换映射表,
54
- 如果文件不存在则返回内置替换映射表。
55
+ 优先使用GLOBAL_CONFIG_DATA['replace_map']的配置,
56
+ 如果未配置则返回内置替换映射表。
55
57
 
56
58
  返回:
57
- dict: 合并后的替换映射表字典(内置+文件中的映射表)
59
+ dict: 合并后的替换映射表字典(内置+配置中的映射表)
58
60
  """
59
- if "JARVIS_REPLACE_MAP" in GLOBAL_CONFIG_DATA:
60
- return {**BUILTIN_REPLACE_MAP, **GLOBAL_CONFIG_DATA["JARVIS_REPLACE_MAP"]}
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
- print("⚠️ 警告:使用replace_map.yaml进行配置的方式已被弃用,将在未来版本中移除。请迁移到使用GLOBAL_CONFIG_DATA中的JARVIS_REPLACE_MAP配置。")
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("JARVIS_MAX_INPUT_TOKEN_COUNT", "32000"))
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中获取JARVIS_SHELL配置
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. JARVIS_LLM_GROUP 中定义的组配置
118
- 2. 仅当组未提供对应键时,回退到顶层环境变量 (JARVIS_PLATFORM, JARVIS_MODEL, JARVIS_MAX_INPUT_TOKEN_COUNT)
303
+ 1. llm_group 中通过引用展开的配置
304
+ 2. 仅当组未提供对应键时,回退到顶层环境变量 (platform, model, max_input_token_count)
119
305
  3. 代码中的默认值
120
306
  - 当未显式指定组时(使用默认组或未设置):
121
- 1. 顶层环境变量 (JARVIS_PLATFORM, JARVIS_MODEL, JARVIS_MAX_INPUT_TOKEN_COUNT)
122
- 2. JARVIS_LLM_GROUP 中定义的组配置
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
- "JARVIS_LLM_GROUP"
131
- )
132
- # The format is a list of single-key dicts: [{'group_name': {...}}, ...]
133
- model_groups = GLOBAL_CONFIG_DATA.get("JARVIS_LLM_GROUPS", [])
134
-
135
- if model_group_name and isinstance(model_groups, list):
136
- found = False
137
- for group_item in model_groups:
138
- if isinstance(group_item, dict) and model_group_name in group_item:
139
- group_config = group_item[model_group_name]
140
- found = True
141
- break
142
-
143
- # 当显式指定了模型组但未找到时,报错并退出
144
- if model_group_override and not found:
145
- print(f"❌ 错误:指定的模型组 '{model_group_name}' 不存在于配置中。")
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
- "JARVIS_PLATFORM",
166
- "JARVIS_MODEL",
167
- "JARVIS_MAX_INPUT_TOKEN_COUNT",
168
- "JARVIS_CHEAP_PLATFORM",
169
- "JARVIS_CHEAP_MODEL",
170
- "JARVIS_SMART_PLATFORM",
171
- "JARVIS_SMART_MODEL",
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("JARVIS_PLATFORM", "openai"))
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("JARVIS_MODEL", "gpt-5"))
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("JARVIS_CHEAP_PLATFORM")
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("JARVIS_CHEAP_MODEL")
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("JARVIS_SMART_PLATFORM")
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("JARVIS_SMART_MODEL")
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("JARVIS_EXECUTE_TOOL_CONFIRM", False))
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("JARVIS_CONFIRM_BEFORE_APPLY_PATCH", False))
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: 数据目录路径,优先从JARVIS_DATA_PATH环境变量获取,
507
+ 返回:
508
+ str: 数据目录路径,优先从data_path环境变量获取,
314
509
  如果未设置或为空,则使用~/.jarvis作为默认值
315
510
  """
316
511
  return os.path.expanduser(
317
- cast(str, GLOBAL_CONFIG_DATA.get("JARVIS_DATA_PATH", "~/.jarvis")).strip()
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("JARVIS_PRETTY_OUTPUT", True))
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("JARVIS_USE_METHODOLOGY", True))
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("JARVIS_USE_ANALYSIS", True))
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("JARVIS_TOOL_LOAD_DIRS", [])
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("JARVIS_METHODOLOGY_DIRS", [])
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("JARVIS_AGENT_DEFINITION_DIRS", [])
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("JARVIS_MULTI_AGENT_DIRS", [])
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("JARVIS_ROLES_DIRS", [])
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("JARVIS_AFTER_TOOL_CALL_CB_DIRS", [])
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("JARVIS_CENTRAL_METHODOLOGY_REPO", ""))
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("JARVIS_CENTRAL_TOOL_REPO", ""))
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("JARVIS_PRINT_PROMPT", False))
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("JARVIS_PRINT_ERROR_TRACEBACK", False) is True
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("JARVIS_FORCE_SAVE_MEMORY", False) is True
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("JARVIS_ENABLE_STATIC_ANALYSIS", True) is True
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("JARVIS_ENABLE_BUILD_VALIDATION", True) is True
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("JARVIS_ENABLE_IMPACT_ANALYSIS", True) is True
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("JARVIS_BUILD_VALIDATION_TIMEOUT", 30))
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("JARVIS_MCP", []))
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
- "text": {
574
- "embedding_model": "BAAI/bge-m3",
575
- "rerank_model": "BAAI/bge-reranker-v2-m3",
576
- "use_bm25": True,
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
- "code": {
582
- "embedding_model": "Qodo/Qodo-Embed-1-1.5B",
583
- "use_bm25": False,
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. JARVIS_RAG 中的顶级设置 (embedding_model, etc.)
598
- 2. JARVIS_RAG_GROUP 中定义的组配置
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("JARVIS_RAG_GROUP")
606
- rag_groups = GLOBAL_CONFIG_DATA.get("JARVIS_RAG_GROUPS", DEFAULT_RAG_GROUPS)
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
- if rag_group_name and isinstance(rag_groups, list):
989
+ # 兼容旧格式:如果是列表,转换为对象格式
990
+ if isinstance(rag_groups, list):
991
+ converted_groups = {}
609
992
  for group_item in rag_groups:
610
- if isinstance(group_item, dict) and rag_group_name in group_item:
611
- group_config = group_item[rag_group_name]
612
- break
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 JARVIS_RAG dict
618
- top_level_rag_config = GLOBAL_CONFIG_DATA.get("JARVIS_RAG", {})
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 GLOBAL_CONFIG_DATA.get("JARVIS_WEB_SEARCH_PLATFORM")
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 GLOBAL_CONFIG_DATA.get("JARVIS_WEB_SEARCH_MODEL")
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. JARVIS_TOOL_GROUP 中定义的组配置
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("JARVIS_TOOL_GROUP")
741
- tool_groups = GLOBAL_CONFIG_DATA.get("JARVIS_TOOL_GROUPS", [])
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("JARVIS_TOOL_FILTER_THRESHOLD", 30))
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("JARVIS_SCRIPT_EXECUTION_TIMEOUT", 300))
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("JARVIS_ENABLE_GIT_JCA_SWITCH", True) is True
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("JARVIS_SAVE_SESSION_HISTORY", False) is True
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("JARVIS_IMMEDIATE_ABORT", False) is True
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
- import os
845
- v = os.getenv("JARVIS_NON_INTERACTIVE")
846
- if v is not None:
847
- val = str(v).strip().lower()
848
- if val in ("1", "true", "yes", "on"):
849
- return True
850
- if val in ("0", "false", "no", "off"):
851
- return False
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
- pass
855
- return GLOBAL_CONFIG_DATA.get("JARVIS_NON_INTERACTIVE", False) is True
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("JARVIS_SKIP_PREDEFINED_TASKS", False) is True
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("JARVIS_ADDON_PROMPT_THRESHOLD", 1024))
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['JARVIS_ENABLE_INTENT_RECOGNITION'] 配置)
1360
+ bool: 是否启用意图识别,默认为True(可通过 GLOBAL_CONFIG_DATA['enable_intent_recognition'] 配置)
889
1361
  """
890
- return GLOBAL_CONFIG_DATA.get("JARVIS_ENABLE_INTENT_RECOGNITION", True) is True
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['JARVIS_ENABLE_MEMORY_ORGANIZER'] 配置)
1370
+ bool: 是否启用自动记忆整理,默认为False(可通过 GLOBAL_CONFIG_DATA['enable_memory_organizer'] 配置)
899
1371
  """
900
- return GLOBAL_CONFIG_DATA.get("JARVIS_ENABLE_MEMORY_ORGANIZER", False) is True
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("JARVIS_CONVERSATION_TURN_THRESHOLD", 50))
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))