jarvis-ai-assistant 0.1.222__py3-none-any.whl → 0.7.0__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 (162) hide show
  1. jarvis/__init__.py +1 -1
  2. jarvis/jarvis_agent/__init__.py +1143 -245
  3. jarvis/jarvis_agent/agent_manager.py +97 -0
  4. jarvis/jarvis_agent/builtin_input_handler.py +12 -10
  5. jarvis/jarvis_agent/config_editor.py +57 -0
  6. jarvis/jarvis_agent/edit_file_handler.py +392 -99
  7. jarvis/jarvis_agent/event_bus.py +48 -0
  8. jarvis/jarvis_agent/events.py +157 -0
  9. jarvis/jarvis_agent/file_context_handler.py +79 -0
  10. jarvis/jarvis_agent/file_methodology_manager.py +117 -0
  11. jarvis/jarvis_agent/jarvis.py +1117 -147
  12. jarvis/jarvis_agent/main.py +78 -34
  13. jarvis/jarvis_agent/memory_manager.py +195 -0
  14. jarvis/jarvis_agent/methodology_share_manager.py +174 -0
  15. jarvis/jarvis_agent/prompt_manager.py +82 -0
  16. jarvis/jarvis_agent/prompts.py +46 -9
  17. jarvis/jarvis_agent/protocols.py +4 -1
  18. jarvis/jarvis_agent/rewrite_file_handler.py +141 -0
  19. jarvis/jarvis_agent/run_loop.py +146 -0
  20. jarvis/jarvis_agent/session_manager.py +9 -9
  21. jarvis/jarvis_agent/share_manager.py +228 -0
  22. jarvis/jarvis_agent/shell_input_handler.py +23 -3
  23. jarvis/jarvis_agent/stdio_redirect.py +295 -0
  24. jarvis/jarvis_agent/task_analyzer.py +212 -0
  25. jarvis/jarvis_agent/task_manager.py +154 -0
  26. jarvis/jarvis_agent/task_planner.py +496 -0
  27. jarvis/jarvis_agent/tool_executor.py +8 -4
  28. jarvis/jarvis_agent/tool_share_manager.py +139 -0
  29. jarvis/jarvis_agent/user_interaction.py +42 -0
  30. jarvis/jarvis_agent/utils.py +54 -0
  31. jarvis/jarvis_agent/web_bridge.py +189 -0
  32. jarvis/jarvis_agent/web_output_sink.py +53 -0
  33. jarvis/jarvis_agent/web_server.py +751 -0
  34. jarvis/jarvis_c2rust/__init__.py +26 -0
  35. jarvis/jarvis_c2rust/cli.py +613 -0
  36. jarvis/jarvis_c2rust/collector.py +258 -0
  37. jarvis/jarvis_c2rust/library_replacer.py +1122 -0
  38. jarvis/jarvis_c2rust/llm_module_agent.py +1300 -0
  39. jarvis/jarvis_c2rust/optimizer.py +960 -0
  40. jarvis/jarvis_c2rust/scanner.py +1681 -0
  41. jarvis/jarvis_c2rust/transpiler.py +2325 -0
  42. jarvis/jarvis_code_agent/build_validation_config.py +133 -0
  43. jarvis/jarvis_code_agent/code_agent.py +1605 -178
  44. jarvis/jarvis_code_agent/code_analyzer/__init__.py +62 -0
  45. jarvis/jarvis_code_agent/code_analyzer/base_language.py +74 -0
  46. jarvis/jarvis_code_agent/code_analyzer/build_validator/__init__.py +44 -0
  47. jarvis/jarvis_code_agent/code_analyzer/build_validator/base.py +102 -0
  48. jarvis/jarvis_code_agent/code_analyzer/build_validator/cmake.py +59 -0
  49. jarvis/jarvis_code_agent/code_analyzer/build_validator/detector.py +125 -0
  50. jarvis/jarvis_code_agent/code_analyzer/build_validator/fallback.py +69 -0
  51. jarvis/jarvis_code_agent/code_analyzer/build_validator/go.py +38 -0
  52. jarvis/jarvis_code_agent/code_analyzer/build_validator/java_gradle.py +44 -0
  53. jarvis/jarvis_code_agent/code_analyzer/build_validator/java_maven.py +38 -0
  54. jarvis/jarvis_code_agent/code_analyzer/build_validator/makefile.py +50 -0
  55. jarvis/jarvis_code_agent/code_analyzer/build_validator/nodejs.py +93 -0
  56. jarvis/jarvis_code_agent/code_analyzer/build_validator/python.py +129 -0
  57. jarvis/jarvis_code_agent/code_analyzer/build_validator/rust.py +54 -0
  58. jarvis/jarvis_code_agent/code_analyzer/build_validator/validator.py +154 -0
  59. jarvis/jarvis_code_agent/code_analyzer/build_validator.py +43 -0
  60. jarvis/jarvis_code_agent/code_analyzer/context_manager.py +363 -0
  61. jarvis/jarvis_code_agent/code_analyzer/context_recommender.py +18 -0
  62. jarvis/jarvis_code_agent/code_analyzer/dependency_analyzer.py +132 -0
  63. jarvis/jarvis_code_agent/code_analyzer/file_ignore.py +330 -0
  64. jarvis/jarvis_code_agent/code_analyzer/impact_analyzer.py +781 -0
  65. jarvis/jarvis_code_agent/code_analyzer/language_registry.py +185 -0
  66. jarvis/jarvis_code_agent/code_analyzer/language_support.py +89 -0
  67. jarvis/jarvis_code_agent/code_analyzer/languages/__init__.py +31 -0
  68. jarvis/jarvis_code_agent/code_analyzer/languages/c_cpp_language.py +231 -0
  69. jarvis/jarvis_code_agent/code_analyzer/languages/go_language.py +183 -0
  70. jarvis/jarvis_code_agent/code_analyzer/languages/python_language.py +219 -0
  71. jarvis/jarvis_code_agent/code_analyzer/languages/rust_language.py +209 -0
  72. jarvis/jarvis_code_agent/code_analyzer/llm_context_recommender.py +451 -0
  73. jarvis/jarvis_code_agent/code_analyzer/symbol_extractor.py +77 -0
  74. jarvis/jarvis_code_agent/code_analyzer/tree_sitter_extractor.py +48 -0
  75. jarvis/jarvis_code_agent/lint.py +275 -13
  76. jarvis/jarvis_code_agent/utils.py +142 -0
  77. jarvis/jarvis_code_analysis/checklists/loader.py +20 -6
  78. jarvis/jarvis_code_analysis/code_review.py +583 -548
  79. jarvis/jarvis_data/config_schema.json +339 -28
  80. jarvis/jarvis_git_squash/main.py +22 -13
  81. jarvis/jarvis_git_utils/git_commiter.py +171 -55
  82. jarvis/jarvis_mcp/sse_mcp_client.py +22 -15
  83. jarvis/jarvis_mcp/stdio_mcp_client.py +4 -4
  84. jarvis/jarvis_mcp/streamable_mcp_client.py +36 -16
  85. jarvis/jarvis_memory_organizer/memory_organizer.py +753 -0
  86. jarvis/jarvis_methodology/main.py +48 -63
  87. jarvis/jarvis_multi_agent/__init__.py +302 -43
  88. jarvis/jarvis_multi_agent/main.py +70 -24
  89. jarvis/jarvis_platform/ai8.py +40 -23
  90. jarvis/jarvis_platform/base.py +210 -49
  91. jarvis/jarvis_platform/human.py +11 -1
  92. jarvis/jarvis_platform/kimi.py +82 -76
  93. jarvis/jarvis_platform/openai.py +73 -1
  94. jarvis/jarvis_platform/registry.py +8 -15
  95. jarvis/jarvis_platform/tongyi.py +115 -101
  96. jarvis/jarvis_platform/yuanbao.py +89 -63
  97. jarvis/jarvis_platform_manager/main.py +194 -132
  98. jarvis/jarvis_platform_manager/service.py +122 -86
  99. jarvis/jarvis_rag/cli.py +156 -53
  100. jarvis/jarvis_rag/embedding_manager.py +155 -12
  101. jarvis/jarvis_rag/llm_interface.py +10 -13
  102. jarvis/jarvis_rag/query_rewriter.py +63 -12
  103. jarvis/jarvis_rag/rag_pipeline.py +222 -40
  104. jarvis/jarvis_rag/reranker.py +26 -3
  105. jarvis/jarvis_rag/retriever.py +270 -14
  106. jarvis/jarvis_sec/__init__.py +3605 -0
  107. jarvis/jarvis_sec/checkers/__init__.py +32 -0
  108. jarvis/jarvis_sec/checkers/c_checker.py +2680 -0
  109. jarvis/jarvis_sec/checkers/rust_checker.py +1108 -0
  110. jarvis/jarvis_sec/cli.py +116 -0
  111. jarvis/jarvis_sec/report.py +257 -0
  112. jarvis/jarvis_sec/status.py +264 -0
  113. jarvis/jarvis_sec/types.py +20 -0
  114. jarvis/jarvis_sec/workflow.py +219 -0
  115. jarvis/jarvis_smart_shell/main.py +405 -137
  116. jarvis/jarvis_stats/__init__.py +13 -0
  117. jarvis/jarvis_stats/cli.py +387 -0
  118. jarvis/jarvis_stats/stats.py +711 -0
  119. jarvis/jarvis_stats/storage.py +612 -0
  120. jarvis/jarvis_stats/visualizer.py +282 -0
  121. jarvis/jarvis_tools/ask_user.py +1 -0
  122. jarvis/jarvis_tools/base.py +18 -2
  123. jarvis/jarvis_tools/clear_memory.py +239 -0
  124. jarvis/jarvis_tools/cli/main.py +220 -144
  125. jarvis/jarvis_tools/execute_script.py +52 -12
  126. jarvis/jarvis_tools/file_analyzer.py +17 -12
  127. jarvis/jarvis_tools/generate_new_tool.py +46 -24
  128. jarvis/jarvis_tools/read_code.py +277 -18
  129. jarvis/jarvis_tools/read_symbols.py +141 -0
  130. jarvis/jarvis_tools/read_webpage.py +86 -13
  131. jarvis/jarvis_tools/registry.py +294 -90
  132. jarvis/jarvis_tools/retrieve_memory.py +227 -0
  133. jarvis/jarvis_tools/save_memory.py +194 -0
  134. jarvis/jarvis_tools/search_web.py +62 -28
  135. jarvis/jarvis_tools/sub_agent.py +205 -0
  136. jarvis/jarvis_tools/sub_code_agent.py +217 -0
  137. jarvis/jarvis_tools/virtual_tty.py +330 -62
  138. jarvis/jarvis_utils/builtin_replace_map.py +4 -5
  139. jarvis/jarvis_utils/clipboard.py +90 -0
  140. jarvis/jarvis_utils/config.py +607 -50
  141. jarvis/jarvis_utils/embedding.py +3 -0
  142. jarvis/jarvis_utils/fzf.py +57 -0
  143. jarvis/jarvis_utils/git_utils.py +251 -29
  144. jarvis/jarvis_utils/globals.py +174 -17
  145. jarvis/jarvis_utils/http.py +58 -79
  146. jarvis/jarvis_utils/input.py +899 -153
  147. jarvis/jarvis_utils/methodology.py +210 -83
  148. jarvis/jarvis_utils/output.py +220 -137
  149. jarvis/jarvis_utils/utils.py +1906 -135
  150. jarvis_ai_assistant-0.7.0.dist-info/METADATA +465 -0
  151. jarvis_ai_assistant-0.7.0.dist-info/RECORD +192 -0
  152. {jarvis_ai_assistant-0.1.222.dist-info → jarvis_ai_assistant-0.7.0.dist-info}/entry_points.txt +8 -2
  153. jarvis/jarvis_git_details/main.py +0 -265
  154. jarvis/jarvis_platform/oyi.py +0 -357
  155. jarvis/jarvis_tools/edit_file.py +0 -255
  156. jarvis/jarvis_tools/rewrite_file.py +0 -195
  157. jarvis_ai_assistant-0.1.222.dist-info/METADATA +0 -767
  158. jarvis_ai_assistant-0.1.222.dist-info/RECORD +0 -110
  159. /jarvis/{jarvis_git_details → jarvis_memory_organizer}/__init__.py +0 -0
  160. {jarvis_ai_assistant-0.1.222.dist-info → jarvis_ai_assistant-0.7.0.dist-info}/WHEEL +0 -0
  161. {jarvis_ai_assistant-0.1.222.dist-info → jarvis_ai_assistant-0.7.0.dist-info}/licenses/LICENSE +0 -0
  162. {jarvis_ai_assistant-0.1.222.dist-info → jarvis_ai_assistant-0.7.0.dist-info}/top_level.txt +0 -0
@@ -1,10 +1,9 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  import os
3
3
  from functools import lru_cache
4
- from typing import Any, Dict, List
4
+ from typing import Any, Dict, List, Optional, cast
5
5
 
6
- import torch
7
- import yaml # type: ignore
6
+ import yaml
8
7
 
9
8
  from jarvis.jarvis_utils.builtin_replace_map import BUILTIN_REPLACE_MAP
10
9
 
@@ -38,7 +37,7 @@ def get_git_commit_prompt() -> str:
38
37
  返回:
39
38
  str: Git提交信息生成提示模板,如果未配置则返回空字符串
40
39
  """
41
- return GLOBAL_CONFIG_DATA.get("JARVIS_GIT_COMMIT_PROMPT", "")
40
+ return cast(str, GLOBAL_CONFIG_DATA.get("JARVIS_GIT_COMMIT_PROMPT", ""))
42
41
 
43
42
 
44
43
  # 输出窗口预留大小
@@ -77,24 +76,15 @@ def get_replace_map() -> dict:
77
76
  return {**BUILTIN_REPLACE_MAP, **file_map}
78
77
 
79
78
 
80
- def get_max_token_count() -> int:
81
- """
82
- 获取模型允许的最大token数量。
83
-
84
- 返回:
85
- int: 模型能处理的最大token数量。
86
- """
87
- return int(GLOBAL_CONFIG_DATA.get("JARVIS_MAX_TOKEN_COUNT", "960000"))
88
-
89
-
90
- def get_max_input_token_count() -> int:
79
+ def get_max_input_token_count(model_group_override: Optional[str] = None) -> int:
91
80
  """
92
81
  获取模型允许的最大输入token数量。
93
82
 
94
83
  返回:
95
84
  int: 模型能处理的最大输入token数量。
96
85
  """
97
- return int(GLOBAL_CONFIG_DATA.get("JARVIS_MAX_INPUT_TOKEN_COUNT", "32000"))
86
+ config = _get_resolved_model_config(model_group_override)
87
+ return int(config.get("JARVIS_MAX_INPUT_TOKEN_COUNT", "32000"))
98
88
 
99
89
 
100
90
  def get_shell_name() -> str:
@@ -111,51 +101,120 @@ def get_shell_name() -> str:
111
101
  4. 如果都未配置,则默认返回bash
112
102
  """
113
103
  shell_path = GLOBAL_CONFIG_DATA.get("SHELL", os.getenv("SHELL", "/bin/bash"))
114
- return os.path.basename(shell_path).lower()
104
+ return cast(str, os.path.basename(shell_path).lower())
105
+
106
+
107
+ def _apply_llm_group_env_override(group_config: Dict[str, Any]) -> None:
108
+ """如果模型组配置中包含ENV,则应用环境变量覆盖"""
109
+ if "ENV" in group_config and isinstance(group_config["ENV"], dict):
110
+ os.environ.update(
111
+ {str(k): str(v) for k, v in group_config["ENV"].items() if v is not None}
112
+ )
115
113
 
116
114
 
117
- def get_normal_platform_name() -> str:
115
+ def _get_resolved_model_config(
116
+ model_group_override: Optional[str] = None,
117
+ ) -> Dict[str, Any]:
118
+ """
119
+ 解析并合并模型配置,处理模型组。
120
+
121
+ 优先级顺序:
122
+ - 当通过 model_group_override(例如命令行 -g/--llm-group)指定组时:
123
+ 1. JARVIS_LLM_GROUP 中定义的组配置
124
+ 2. 仅当组未提供对应键时,回退到顶层环境变量 (JARVIS_PLATFORM, JARVIS_MODEL, JARVIS_MAX_INPUT_TOKEN_COUNT)
125
+ 3. 代码中的默认值
126
+ - 当未显式指定组时(使用默认组或未设置):
127
+ 1. 顶层环境变量 (JARVIS_PLATFORM, JARVIS_MODEL, JARVIS_MAX_INPUT_TOKEN_COUNT)
128
+ 2. JARVIS_LLM_GROUP 中定义的组配置
129
+ 3. 代码中的默认值
130
+
131
+ 返回:
132
+ Dict[str, Any]: 解析后的模型配置字典
133
+ """
134
+ group_config = {}
135
+ model_group_name = model_group_override or GLOBAL_CONFIG_DATA.get(
136
+ "JARVIS_LLM_GROUP"
137
+ )
138
+ # The format is a list of single-key dicts: [{'group_name': {...}}, ...]
139
+ model_groups = GLOBAL_CONFIG_DATA.get("JARVIS_LLM_GROUPS", [])
140
+
141
+ if model_group_name and isinstance(model_groups, list):
142
+ for group_item in model_groups:
143
+ if isinstance(group_item, dict) and model_group_name in group_item:
144
+ group_config = group_item[model_group_name]
145
+ break
146
+
147
+ _apply_llm_group_env_override(group_config)
148
+
149
+ # Start with group config
150
+ resolved_config = group_config.copy()
151
+
152
+ # 覆盖策略:
153
+ # - 若通过 CLI 传入了 model_group_override,则优先使用组内配置;
154
+ # 仅当组未提供对应键时,才回落到顶层 GLOBAL_CONFIG_DATA。
155
+ # - 若未传入 override(即使用默认组),保持原有行为:由顶层键覆盖组配置。
156
+ override_keys = [
157
+ "JARVIS_PLATFORM",
158
+ "JARVIS_MODEL",
159
+ "JARVIS_MAX_INPUT_TOKEN_COUNT",
160
+ ]
161
+ for key in override_keys:
162
+ if key in GLOBAL_CONFIG_DATA:
163
+ if model_group_override is None:
164
+ # 未显式指定组:顶层覆盖组
165
+ resolved_config[key] = GLOBAL_CONFIG_DATA[key]
166
+ else:
167
+ # 显式指定组:仅在组未定义该键时回退到顶层
168
+ if key not in resolved_config:
169
+ resolved_config[key] = GLOBAL_CONFIG_DATA[key]
170
+
171
+ return resolved_config
172
+
173
+
174
+ def get_normal_platform_name(model_group_override: Optional[str] = None) -> str:
118
175
  """
119
176
  获取正常操作的平台名称。
120
177
 
121
178
  返回:
122
179
  str: 平台名称,默认为'yuanbao'
123
180
  """
124
- return GLOBAL_CONFIG_DATA.get("JARVIS_PLATFORM", "yuanbao")
181
+ config = _get_resolved_model_config(model_group_override)
182
+ return cast(str, config.get("JARVIS_PLATFORM", "yuanbao"))
125
183
 
126
184
 
127
- def get_normal_model_name() -> str:
185
+ def get_normal_model_name(model_group_override: Optional[str] = None) -> str:
128
186
  """
129
187
  获取正常操作的模型名称。
130
188
 
131
189
  返回:
132
- str: 模型名称,默认为'deep_seek'
190
+ str: 模型名称,默认为'deep_seek_v3'
133
191
  """
134
- return GLOBAL_CONFIG_DATA.get("JARVIS_MODEL", "deep_seek_v3")
192
+ config = _get_resolved_model_config(model_group_override)
193
+ return cast(str, config.get("JARVIS_MODEL", "deep_seek_v3"))
135
194
 
136
195
 
137
- def get_thinking_platform_name() -> str:
196
+ def _deprecated_platform_name_v1(model_group_override: Optional[str] = None) -> str:
138
197
  """
139
198
  获取思考操作的平台名称。
140
199
 
141
200
  返回:
142
- str: 平台名称,默认为'yuanbao'
201
+ str: 平台名称,默认为正常操作平台
143
202
  """
144
- return GLOBAL_CONFIG_DATA.get(
145
- "JARVIS_THINKING_PLATFORM", GLOBAL_CONFIG_DATA.get("JARVIS_PLATFORM", "yuanbao")
146
- )
203
+ _get_resolved_model_config(model_group_override)
204
+ # Fallback to normal platform if thinking platform is not specified
205
+ return get_normal_platform_name(model_group_override)
147
206
 
148
207
 
149
- def get_thinking_model_name() -> str:
208
+ def _deprecated_model_name_v1(model_group_override: Optional[str] = None) -> str:
150
209
  """
151
210
  获取思考操作的模型名称。
152
211
 
153
212
  返回:
154
- str: 模型名称,默认为'deep_seek'
213
+ str: 模型名称,默认为正常操作模型
155
214
  """
156
- return GLOBAL_CONFIG_DATA.get(
157
- "JARVIS_THINKING_MODEL", GLOBAL_CONFIG_DATA.get("JARVIS_MODEL", "deep_seek")
158
- )
215
+ _get_resolved_model_config(model_group_override)
216
+ # Fallback to normal model if thinking model is not specified
217
+ return get_normal_model_name(model_group_override)
159
218
 
160
219
 
161
220
  def is_execute_tool_confirm() -> bool:
@@ -165,7 +224,7 @@ def is_execute_tool_confirm() -> bool:
165
224
  返回:
166
225
  bool: 如果需要确认则返回True,默认为False
167
226
  """
168
- return GLOBAL_CONFIG_DATA.get("JARVIS_EXECUTE_TOOL_CONFIRM", False) == True
227
+ return cast(bool, GLOBAL_CONFIG_DATA.get("JARVIS_EXECUTE_TOOL_CONFIRM", False))
169
228
 
170
229
 
171
230
  def is_confirm_before_apply_patch() -> bool:
@@ -175,7 +234,24 @@ def is_confirm_before_apply_patch() -> bool:
175
234
  返回:
176
235
  bool: 如果需要确认则返回True,默认为False
177
236
  """
178
- return GLOBAL_CONFIG_DATA.get("JARVIS_CONFIRM_BEFORE_APPLY_PATCH", False) == True
237
+ return cast(bool, GLOBAL_CONFIG_DATA.get("JARVIS_CONFIRM_BEFORE_APPLY_PATCH", False))
238
+
239
+
240
+ def get_patch_format() -> str:
241
+ """
242
+ 获取补丁格式。
243
+
244
+ - "search": 仅使用精确匹配的 `SEARCH` 模式。此模式对能力较弱的模型更稳定,因为它要求代码片段完全匹配。
245
+ - "search_range": 仅使用 `SEARCH_START` 和 `SEARCH_END` 的范围匹配模式。此模式对能力较强的模型更灵活,因为它允许在代码块内部进行修改,而不要求整个块完全匹配。
246
+ - "all": 同时支持以上两种模式(默认)。
247
+
248
+ 返回:
249
+ str: "all", "search", or "search_range"
250
+ """
251
+ mode = GLOBAL_CONFIG_DATA.get("JARVIS_PATCH_FORMAT", "all")
252
+ if mode in ["all", "search", "search_range"]:
253
+ return cast(str, mode)
254
+ return "all"
179
255
 
180
256
 
181
257
  def get_data_dir() -> str:
@@ -187,18 +263,19 @@ def get_data_dir() -> str:
187
263
  如果未设置或为空,则使用~/.jarvis作为默认值
188
264
  """
189
265
  return os.path.expanduser(
190
- GLOBAL_CONFIG_DATA.get("JARVIS_DATA_PATH", "~/.jarvis").strip()
266
+ cast(str, GLOBAL_CONFIG_DATA.get("JARVIS_DATA_PATH", "~/.jarvis")).strip()
191
267
  )
192
268
 
193
269
 
194
- def get_max_big_content_size() -> int:
270
+ def get_max_big_content_size(model_group_override: Optional[str] = None) -> int:
195
271
  """
196
272
  获取最大大内容大小。
197
273
 
198
274
  返回:
199
- int: 最大大内容大小
275
+ int: 最大大内容大小,为最大输入token数量的5倍
200
276
  """
201
- return int(GLOBAL_CONFIG_DATA.get("JARVIS_MAX_BIG_CONTENT_SIZE", "160000"))
277
+ max_input_tokens = get_max_input_token_count(model_group_override)
278
+ return max_input_tokens * 5
202
279
 
203
280
 
204
281
  def get_pretty_output() -> bool:
@@ -208,7 +285,13 @@ def get_pretty_output() -> bool:
208
285
  返回:
209
286
  bool: 如果启用PrettyOutput则返回True,默认为True
210
287
  """
211
- return GLOBAL_CONFIG_DATA.get("JARVIS_PRETTY_OUTPUT", False) == True
288
+ import platform
289
+
290
+ # Windows系统强制设置为False
291
+ if platform.system() == "Windows":
292
+ return False
293
+
294
+ return cast(bool, GLOBAL_CONFIG_DATA.get("JARVIS_PRETTY_OUTPUT", True))
212
295
 
213
296
 
214
297
  def is_use_methodology() -> bool:
@@ -218,7 +301,7 @@ def is_use_methodology() -> bool:
218
301
  返回:
219
302
  bool: 如果启用方法论则返回True,默认为True
220
303
  """
221
- return GLOBAL_CONFIG_DATA.get("JARVIS_USE_METHODOLOGY", True) == True
304
+ return cast(bool, GLOBAL_CONFIG_DATA.get("JARVIS_USE_METHODOLOGY", True))
222
305
 
223
306
 
224
307
  def is_use_analysis() -> bool:
@@ -228,7 +311,111 @@ def is_use_analysis() -> bool:
228
311
  返回:
229
312
  bool: 如果启用任务分析则返回True,默认为True
230
313
  """
231
- return GLOBAL_CONFIG_DATA.get("JARVIS_USE_ANALYSIS", True) == True
314
+ return cast(bool, GLOBAL_CONFIG_DATA.get("JARVIS_USE_ANALYSIS", True))
315
+
316
+
317
+ def get_tool_load_dirs() -> List[str]:
318
+ """
319
+ 获取工具加载目录。
320
+
321
+ 返回:
322
+ List[str]: 工具加载目录列表
323
+ """
324
+ return [
325
+ os.path.expanduser(os.path.expandvars(str(p)))
326
+ for p in GLOBAL_CONFIG_DATA.get("JARVIS_TOOL_LOAD_DIRS", [])
327
+ if p
328
+ ]
329
+
330
+
331
+ def get_methodology_dirs() -> List[str]:
332
+ """
333
+ 获取方法论加载目录。
334
+
335
+ 返回:
336
+ List[str]: 方法论加载目录列表
337
+ """
338
+ return [
339
+ os.path.expanduser(os.path.expandvars(str(p)))
340
+ for p in GLOBAL_CONFIG_DATA.get("JARVIS_METHODOLOGY_DIRS", [])
341
+ if p
342
+ ]
343
+
344
+
345
+ def get_agent_definition_dirs() -> List[str]:
346
+ """
347
+ 获取 agent 定义的加载目录。
348
+
349
+ 返回:
350
+ List[str]: agent 定义加载目录列表
351
+ """
352
+ return [
353
+ os.path.expanduser(os.path.expandvars(str(p)))
354
+ for p in GLOBAL_CONFIG_DATA.get("JARVIS_AGENT_DEFINITION_DIRS", [])
355
+ if p
356
+ ]
357
+
358
+
359
+ def get_multi_agent_dirs() -> List[str]:
360
+ """
361
+ 获取 multi_agent 的加载目录。
362
+
363
+ 返回:
364
+ List[str]: multi_agent 加载目录列表
365
+ """
366
+ return [
367
+ os.path.expanduser(os.path.expandvars(str(p)))
368
+ for p in GLOBAL_CONFIG_DATA.get("JARVIS_MULTI_AGENT_DIRS", [])
369
+ if p
370
+ ]
371
+
372
+
373
+ def get_roles_dirs() -> List[str]:
374
+ """
375
+ 获取 roles 的加载目录。
376
+
377
+ 返回:
378
+ List[str]: roles 加载目录列表
379
+ """
380
+ return [
381
+ os.path.expanduser(os.path.expandvars(str(p)))
382
+ for p in GLOBAL_CONFIG_DATA.get("JARVIS_ROLES_DIRS", [])
383
+ if p
384
+ ]
385
+
386
+
387
+ def get_after_tool_call_cb_dirs() -> List[str]:
388
+ """
389
+ 获取工具调用后回调函数实现目录。
390
+
391
+ 返回:
392
+ List[str]: 工具调用后回调函数实现目录列表
393
+ """
394
+ return [
395
+ os.path.expanduser(os.path.expandvars(str(p)))
396
+ for p in GLOBAL_CONFIG_DATA.get("JARVIS_AFTER_TOOL_CALL_CB_DIRS", [])
397
+ if p
398
+ ]
399
+
400
+
401
+ def get_central_methodology_repo() -> str:
402
+ """
403
+ 获取中心方法论Git仓库地址。
404
+
405
+ 返回:
406
+ str: 中心方法论Git仓库地址,如果未配置则返回空字符串
407
+ """
408
+ return cast(str, GLOBAL_CONFIG_DATA.get("JARVIS_CENTRAL_METHODOLOGY_REPO", ""))
409
+
410
+
411
+ def get_central_tool_repo() -> str:
412
+ """
413
+ 获取中心工具Git仓库地址。
414
+
415
+ 返回:
416
+ str: 中心工具Git仓库地址,如果未配置则返回空字符串
417
+ """
418
+ return cast(str, GLOBAL_CONFIG_DATA.get("JARVIS_CENTRAL_TOOL_REPO", ""))
232
419
 
233
420
 
234
421
  def is_print_prompt() -> bool:
@@ -238,7 +425,27 @@ def is_print_prompt() -> bool:
238
425
  返回:
239
426
  bool: 如果打印提示则返回True,默认为True
240
427
  """
241
- return GLOBAL_CONFIG_DATA.get("JARVIS_PRINT_PROMPT", False) == True
428
+ return cast(bool, GLOBAL_CONFIG_DATA.get("JARVIS_PRINT_PROMPT", False))
429
+
430
+
431
+ def is_print_error_traceback() -> bool:
432
+ """
433
+ 获取是否在错误输出时打印回溯调用链。
434
+
435
+ 返回:
436
+ bool: 如果打印回溯则返回True,默认为False(不打印)
437
+ """
438
+ return GLOBAL_CONFIG_DATA.get("JARVIS_PRINT_ERROR_TRACEBACK", False) is True
439
+
440
+
441
+ def is_force_save_memory() -> bool:
442
+ """
443
+ 获取是否强制保存记忆。
444
+
445
+ 返回:
446
+ bool: 如果强制保存记忆则返回True,默认为False
447
+ """
448
+ return GLOBAL_CONFIG_DATA.get("JARVIS_FORCE_SAVE_MEMORY", False) is True
242
449
 
243
450
 
244
451
  def is_enable_static_analysis() -> bool:
@@ -251,6 +458,50 @@ def is_enable_static_analysis() -> bool:
251
458
  return GLOBAL_CONFIG_DATA.get("JARVIS_ENABLE_STATIC_ANALYSIS", True) is True
252
459
 
253
460
 
461
+ def is_enable_build_validation() -> bool:
462
+ """
463
+ 获取是否启用构建验证。
464
+
465
+ 返回:
466
+ bool: 如果启用构建验证则返回True,默认为True
467
+ """
468
+ return GLOBAL_CONFIG_DATA.get("JARVIS_ENABLE_BUILD_VALIDATION", True) is True
469
+
470
+
471
+ def is_enable_impact_analysis() -> bool:
472
+ """
473
+ 获取是否启用编辑影响范围分析。
474
+
475
+ 返回:
476
+ bool: 如果启用影响范围分析则返回True,默认为True
477
+ """
478
+ return GLOBAL_CONFIG_DATA.get("JARVIS_ENABLE_IMPACT_ANALYSIS", True) is True
479
+
480
+
481
+ def get_build_validation_timeout() -> int:
482
+ """
483
+ 获取构建验证的超时时间(秒)。
484
+
485
+ 返回:
486
+ int: 超时时间,默认为30秒
487
+ """
488
+ return int(GLOBAL_CONFIG_DATA.get("JARVIS_BUILD_VALIDATION_TIMEOUT", 30))
489
+
490
+
491
+ def get_git_check_mode() -> str:
492
+ """
493
+ 获取Git校验模式。
494
+
495
+ 返回:
496
+ str: "strict" 或 "warn",默认为 "strict"
497
+ """
498
+ mode = GLOBAL_CONFIG_DATA.get("JARVIS_GIT_CHECK_MODE", "strict")
499
+ try:
500
+ return str(mode)
501
+ except Exception:
502
+ return "strict"
503
+
504
+
254
505
  def get_mcp_config() -> List[Dict[str, Any]]:
255
506
  """
256
507
  获取MCP配置列表。
@@ -258,7 +509,7 @@ def get_mcp_config() -> List[Dict[str, Any]]:
258
509
  返回:
259
510
  List[Dict[str, Any]]: MCP配置项列表,如果未配置则返回空列表
260
511
  """
261
- return GLOBAL_CONFIG_DATA.get("JARVIS_MCP", [])
512
+ return cast(List[Dict[str, Any]], GLOBAL_CONFIG_DATA.get("JARVIS_MCP", []))
262
513
 
263
514
 
264
515
  # ==============================================================================
@@ -266,14 +517,65 @@ def get_mcp_config() -> List[Dict[str, Any]]:
266
517
  # ==============================================================================
267
518
 
268
519
 
269
- def get_rag_config() -> Dict[str, Any]:
270
- """
271
- 获取RAG框架的配置。
520
+ DEFAULT_RAG_GROUPS = [
521
+ {
522
+ "text": {
523
+ "embedding_model": "BAAI/bge-m3",
524
+ "rerank_model": "BAAI/bge-reranker-v2-m3",
525
+ "use_bm25": True,
526
+ "use_rerank": True,
527
+ }
528
+ },
529
+ {
530
+ "code": {
531
+ "embedding_model": "Qodo/Qodo-Embed-1-1.5B",
532
+ "use_bm25": False,
533
+ "use_rerank": False,
534
+ }
535
+ },
536
+ ]
537
+
538
+
539
+ def _get_resolved_rag_config(
540
+ rag_group_override: Optional[str] = None,
541
+ ) -> Dict[str, Any]:
542
+ """
543
+ 解析并合并RAG配置,处理RAG组。
544
+
545
+ 优先级顺序:
546
+ 1. JARVIS_RAG 中的顶级设置 (embedding_model, etc.)
547
+ 2. JARVIS_RAG_GROUP 中定义的组配置
548
+ 3. 代码中的默认值
272
549
 
273
550
  返回:
274
- Dict[str, Any]: RAG配置字典
551
+ Dict[str, Any]: 解析后的RAG配置字典
275
552
  """
276
- return GLOBAL_CONFIG_DATA.get("JARVIS_RAG", {})
553
+ group_config = {}
554
+ rag_group_name = rag_group_override or GLOBAL_CONFIG_DATA.get("JARVIS_RAG_GROUP")
555
+ rag_groups = GLOBAL_CONFIG_DATA.get("JARVIS_RAG_GROUPS", DEFAULT_RAG_GROUPS)
556
+
557
+ if rag_group_name and isinstance(rag_groups, list):
558
+ for group_item in rag_groups:
559
+ if isinstance(group_item, dict) and rag_group_name in group_item:
560
+ group_config = group_item[rag_group_name]
561
+ break
562
+
563
+ # Start with group config
564
+ resolved_config = group_config.copy()
565
+
566
+ # Override with specific settings from the top-level JARVIS_RAG dict
567
+ top_level_rag_config = GLOBAL_CONFIG_DATA.get("JARVIS_RAG", {})
568
+ if isinstance(top_level_rag_config, dict):
569
+ for key in [
570
+ "embedding_model",
571
+ "rerank_model",
572
+ "use_bm25",
573
+ "use_rerank",
574
+ ]:
575
+ if key in top_level_rag_config:
576
+ resolved_config[key] = top_level_rag_config[key]
577
+
578
+ return resolved_config
277
579
 
278
580
 
279
581
  def get_rag_embedding_model() -> str:
@@ -283,7 +585,8 @@ def get_rag_embedding_model() -> str:
283
585
  返回:
284
586
  str: 嵌入模型的名称
285
587
  """
286
- return get_rag_config().get("embedding_model", "BAAI/bge-base-zh-v1.5")
588
+ config = _get_resolved_rag_config()
589
+ return cast(str, config.get("embedding_model", "BAAI/bge-m3"))
287
590
 
288
591
 
289
592
  def get_rag_rerank_model() -> str:
@@ -293,7 +596,8 @@ def get_rag_rerank_model() -> str:
293
596
  返回:
294
597
  str: rerank模型的名称
295
598
  """
296
- return get_rag_config().get("rerank_model", "BAAI/bge-reranker-base")
599
+ config = _get_resolved_rag_config()
600
+ return cast(str, config.get("rerank_model", "BAAI/bge-reranker-v2-m3"))
297
601
 
298
602
 
299
603
  def get_rag_embedding_cache_path() -> str:
@@ -314,3 +618,256 @@ def get_rag_vector_db_path() -> str:
314
618
  str: 数据库路径
315
619
  """
316
620
  return ".jarvis/rag/vectordb"
621
+
622
+
623
+ def get_rag_use_bm25() -> bool:
624
+ """
625
+ 获取RAG是否使用BM25。
626
+
627
+ 返回:
628
+ bool: 如果使用BM25则返回True,默认为True
629
+ """
630
+ config = _get_resolved_rag_config()
631
+ return config.get("use_bm25", True) is True
632
+
633
+
634
+ def get_rag_use_rerank() -> bool:
635
+ """
636
+ 获取RAG是否使用rerank。
637
+
638
+ 返回:
639
+ bool: 如果使用rerank则返回True,默认为True
640
+ """
641
+ config = _get_resolved_rag_config()
642
+ return config.get("use_rerank", True) is True
643
+
644
+
645
+ # ==============================================================================
646
+ # Web Search Configuration
647
+ # ==============================================================================
648
+
649
+
650
+ def get_web_search_platform_name() -> Optional[str]:
651
+ """
652
+ 获取Web搜索使用的平台名称。
653
+
654
+ 返回:
655
+ Optional[str]: 平台名称,如果未配置则返回None
656
+ """
657
+ return GLOBAL_CONFIG_DATA.get("JARVIS_WEB_SEARCH_PLATFORM")
658
+
659
+
660
+ def get_web_search_model_name() -> Optional[str]:
661
+ """
662
+ 获取Web搜索使用的模型名称。
663
+
664
+ 返回:
665
+ Optional[str]: 模型名称,如果未配置则返回None
666
+ """
667
+ return GLOBAL_CONFIG_DATA.get("JARVIS_WEB_SEARCH_MODEL")
668
+
669
+
670
+ # ==============================================================================
671
+ # Tool Configuration
672
+ # ==============================================================================
673
+
674
+
675
+ def _get_resolved_tool_config(
676
+ tool_group_override: Optional[str] = None,
677
+ ) -> Dict[str, Any]:
678
+ """
679
+ 解析并合并工具配置,处理工具组。
680
+
681
+ 优先级顺序:
682
+ 1. JARVIS_TOOL_GROUP 中定义的组配置
683
+ 2. 默认配置(所有工具都启用)
684
+
685
+ 返回:
686
+ Dict[str, Any]: 解析后的工具配置字典,包含 'use' 和 'dont_use' 列表
687
+ """
688
+ group_config = {}
689
+ tool_group_name = tool_group_override or GLOBAL_CONFIG_DATA.get("JARVIS_TOOL_GROUP")
690
+ tool_groups = GLOBAL_CONFIG_DATA.get("JARVIS_TOOL_GROUPS", [])
691
+
692
+ if tool_group_name and isinstance(tool_groups, list):
693
+ for group_item in tool_groups:
694
+ if isinstance(group_item, dict) and tool_group_name in group_item:
695
+ group_config = group_item[tool_group_name]
696
+ break
697
+
698
+ # 如果没有找到配置组,返回默认配置(空列表表示使用所有工具)
699
+ return group_config.copy() if group_config else {"use": [], "dont_use": []}
700
+
701
+
702
+ def get_tool_use_list() -> List[str]:
703
+ """
704
+ 获取要使用的工具列表。
705
+
706
+ 返回:
707
+ List[str]: 要使用的工具名称列表,空列表表示使用所有工具
708
+ """
709
+ config = _get_resolved_tool_config()
710
+ return cast(List[str], config.get("use", []))
711
+
712
+
713
+ def get_tool_dont_use_list() -> List[str]:
714
+ """
715
+ 获取不使用的工具列表。
716
+
717
+ 返回:
718
+ List[str]: 不使用的工具名称列表
719
+ """
720
+ config = _get_resolved_tool_config()
721
+ return cast(List[str], config.get("dont_use", []))
722
+
723
+
724
+ def get_tool_filter_threshold() -> int:
725
+ """
726
+ 获取AI工具筛选的阈值。
727
+
728
+ 返回:
729
+ int: 当工具数量超过此阈值时,触发AI筛选。默认为30
730
+ """
731
+ return int(GLOBAL_CONFIG_DATA.get("JARVIS_TOOL_FILTER_THRESHOLD", 30))
732
+
733
+ def get_plan_max_depth() -> int:
734
+ """
735
+ 获取任务规划的最大层数。
736
+
737
+ 返回:
738
+ int: 最大规划层数,默认为2(可通过 GLOBAL_CONFIG_DATA['JARVIS_PLAN_MAX_DEPTH'] 配置)
739
+ """
740
+ try:
741
+ return int(GLOBAL_CONFIG_DATA.get("JARVIS_PLAN_MAX_DEPTH", 2))
742
+ except Exception:
743
+ return 2
744
+
745
+
746
+ def is_plan_enabled() -> bool:
747
+ """
748
+ 获取是否默认启用任务规划。
749
+
750
+ 返回:
751
+ bool: 如果启用任务规划则返回True,默认为True
752
+ """
753
+ return GLOBAL_CONFIG_DATA.get("JARVIS_PLAN_ENABLED", True) is True
754
+
755
+
756
+ def get_auto_summary_rounds() -> int:
757
+ """
758
+ 获取基于对话轮次的自动总结阈值。
759
+
760
+ 返回:
761
+ int: 轮次阈值,默认20
762
+ """
763
+ try:
764
+ return int(GLOBAL_CONFIG_DATA.get("JARVIS_AUTO_SUMMARY_ROUNDS", 50))
765
+ except Exception:
766
+ return 50
767
+
768
+
769
+
770
+
771
+
772
+ def get_script_execution_timeout() -> int:
773
+ """
774
+ 获取脚本执行的超时时间(秒)。
775
+
776
+ 返回:
777
+ int: 超时时间,默认为300秒(5分钟)
778
+ """
779
+ return int(GLOBAL_CONFIG_DATA.get("JARVIS_SCRIPT_EXECUTION_TIMEOUT", 300))
780
+
781
+
782
+ def is_enable_git_repo_jca_switch() -> bool:
783
+ """
784
+ 是否启用:在初始化环境前检测Git仓库并提示可切换到代码开发模式(jca)
785
+ 默认开启
786
+ """
787
+ return GLOBAL_CONFIG_DATA.get("JARVIS_ENABLE_GIT_JCA_SWITCH", True) is True
788
+
789
+
790
+ def is_enable_builtin_config_selector() -> bool:
791
+ """
792
+ 是否启用:在进入默认通用代理前,列出可用配置(agent/multi_agent/roles)供选择
793
+ 默认开启
794
+ """
795
+ return (
796
+ GLOBAL_CONFIG_DATA.get("JARVIS_ENABLE_STARTUP_CONFIG_SELECTOR", True) is True
797
+ )
798
+
799
+
800
+ def is_save_session_history() -> bool:
801
+ """
802
+ 是否保存会话记录。
803
+
804
+ 返回:
805
+ bool: 如果要保存会话记录则返回True, 默认为False
806
+ """
807
+ return GLOBAL_CONFIG_DATA.get("JARVIS_SAVE_SESSION_HISTORY", False) is True
808
+
809
+
810
+ def is_immediate_abort() -> bool:
811
+ """
812
+ 是否启用立即中断:当在对话过程中检测到用户中断信号时,立即停止输出并返回。
813
+ 默认关闭
814
+ """
815
+ return GLOBAL_CONFIG_DATA.get("JARVIS_IMMEDIATE_ABORT", False) is True
816
+
817
+
818
+ def is_non_interactive() -> bool:
819
+ """
820
+ 获取是否启用非交互模式。
821
+
822
+ 返回:
823
+ bool: 如果启用非交互模式则返回True,默认为False
824
+ """
825
+ # 优先读取环境变量,确保 CLI 标志生效且不被配置覆盖
826
+ try:
827
+ import os
828
+ v = os.getenv("JARVIS_NON_INTERACTIVE")
829
+ if v is not None:
830
+ val = str(v).strip().lower()
831
+ if val in ("1", "true", "yes", "on"):
832
+ return True
833
+ if val in ("0", "false", "no", "off"):
834
+ return False
835
+ except Exception:
836
+ # 忽略环境变量解析异常,回退到配置
837
+ pass
838
+ return GLOBAL_CONFIG_DATA.get("JARVIS_NON_INTERACTIVE", False) is True
839
+
840
+
841
+ def is_skip_predefined_tasks() -> bool:
842
+ """
843
+ 是否跳过预定义任务加载。
844
+
845
+ 返回:
846
+ bool: 如果跳过预定义任务加载则返回True,默认为False
847
+ """
848
+ return GLOBAL_CONFIG_DATA.get("JARVIS_SKIP_PREDEFINED_TASKS", False) is True
849
+
850
+
851
+ def get_addon_prompt_threshold() -> int:
852
+ """
853
+ 获取附加提示的触发阈值(字符数)。
854
+
855
+ 当消息长度超过此阈值时,会自动添加默认的附加提示。
856
+
857
+ 返回:
858
+ int: 触发阈值,默认为1024
859
+ """
860
+ try:
861
+ return int(GLOBAL_CONFIG_DATA.get("JARVIS_ADDON_PROMPT_THRESHOLD", 1024))
862
+ except Exception:
863
+ return 1024
864
+
865
+
866
+ def is_enable_intent_recognition() -> bool:
867
+ """
868
+ 获取是否启用意图识别功能。
869
+
870
+ 返回:
871
+ bool: 是否启用意图识别,默认为True(可通过 GLOBAL_CONFIG_DATA['JARVIS_ENABLE_INTENT_RECOGNITION'] 配置)
872
+ """
873
+ return GLOBAL_CONFIG_DATA.get("JARVIS_ENABLE_INTENT_RECOGNITION", True) is True