jarvis-ai-assistant 0.3.23__py3-none-any.whl → 0.3.25__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 (43) hide show
  1. jarvis/__init__.py +1 -1
  2. jarvis/jarvis_agent/__init__.py +96 -13
  3. jarvis/jarvis_agent/agent_manager.py +0 -3
  4. jarvis/jarvis_agent/jarvis.py +19 -34
  5. jarvis/jarvis_agent/main.py +2 -8
  6. jarvis/jarvis_code_agent/code_agent.py +5 -11
  7. jarvis/jarvis_code_analysis/code_review.py +12 -40
  8. jarvis/jarvis_data/config_schema.json +11 -18
  9. jarvis/jarvis_git_utils/git_commiter.py +11 -25
  10. jarvis/jarvis_mcp/sse_mcp_client.py +4 -3
  11. jarvis/jarvis_mcp/streamable_mcp_client.py +9 -8
  12. jarvis/jarvis_memory_organizer/memory_organizer.py +46 -53
  13. jarvis/jarvis_methodology/main.py +4 -2
  14. jarvis/jarvis_platform/base.py +90 -21
  15. jarvis/jarvis_platform/kimi.py +16 -22
  16. jarvis/jarvis_platform/registry.py +7 -14
  17. jarvis/jarvis_platform/tongyi.py +21 -32
  18. jarvis/jarvis_platform/yuanbao.py +15 -17
  19. jarvis/jarvis_platform_manager/main.py +14 -51
  20. jarvis/jarvis_rag/cli.py +21 -13
  21. jarvis/jarvis_rag/embedding_manager.py +138 -6
  22. jarvis/jarvis_rag/llm_interface.py +0 -2
  23. jarvis/jarvis_rag/rag_pipeline.py +41 -17
  24. jarvis/jarvis_rag/reranker.py +24 -2
  25. jarvis/jarvis_rag/retriever.py +21 -23
  26. jarvis/jarvis_smart_shell/main.py +1 -10
  27. jarvis/jarvis_tools/cli/main.py +22 -15
  28. jarvis/jarvis_tools/edit_file.py +6 -6
  29. jarvis/jarvis_tools/execute_script.py +1 -2
  30. jarvis/jarvis_tools/file_analyzer.py +12 -6
  31. jarvis/jarvis_tools/registry.py +13 -10
  32. jarvis/jarvis_tools/sub_agent.py +5 -8
  33. jarvis/jarvis_tools/sub_code_agent.py +5 -5
  34. jarvis/jarvis_utils/config.py +24 -10
  35. jarvis/jarvis_utils/input.py +8 -5
  36. jarvis/jarvis_utils/methodology.py +11 -6
  37. jarvis/jarvis_utils/utils.py +29 -12
  38. {jarvis_ai_assistant-0.3.23.dist-info → jarvis_ai_assistant-0.3.25.dist-info}/METADATA +10 -3
  39. {jarvis_ai_assistant-0.3.23.dist-info → jarvis_ai_assistant-0.3.25.dist-info}/RECORD +43 -43
  40. {jarvis_ai_assistant-0.3.23.dist-info → jarvis_ai_assistant-0.3.25.dist-info}/WHEEL +0 -0
  41. {jarvis_ai_assistant-0.3.23.dist-info → jarvis_ai_assistant-0.3.25.dist-info}/entry_points.txt +0 -0
  42. {jarvis_ai_assistant-0.3.23.dist-info → jarvis_ai_assistant-0.3.25.dist-info}/licenses/LICENSE +0 -0
  43. {jarvis_ai_assistant-0.3.23.dist-info → jarvis_ai_assistant-0.3.25.dist-info}/top_level.txt +0 -0
jarvis/__init__.py CHANGED
@@ -1,4 +1,4 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  """Jarvis AI Assistant"""
3
3
 
4
- __version__ = "0.3.23"
4
+ __version__ = "0.3.25"
@@ -34,12 +34,11 @@ from jarvis.jarvis_utils.config import (
34
34
  get_max_token_count,
35
35
  get_normal_model_name,
36
36
  get_normal_platform_name,
37
- get_thinking_model_name,
38
- get_thinking_platform_name,
39
37
  is_execute_tool_confirm,
40
38
  is_force_save_memory,
41
39
  is_use_analysis,
42
40
  is_use_methodology,
41
+ get_tool_filter_threshold,
43
42
  )
44
43
  from jarvis.jarvis_utils.embedding import get_context_token_count
45
44
  from jarvis.jarvis_utils.globals import (
@@ -224,7 +223,6 @@ class Agent:
224
223
  system_prompt: str,
225
224
  name: str = "Jarvis",
226
225
  description: str = "",
227
- llm_type: str = "normal",
228
226
  model_group: Optional[str] = None,
229
227
  summary_prompt: Optional[str] = None,
230
228
  auto_complete: bool = False,
@@ -246,7 +244,7 @@ class Agent:
246
244
  system_prompt: 系统提示词,定义Agent的行为准则
247
245
  name: Agent名称,默认为"Jarvis"
248
246
  description: Agent描述信息
249
- llm_type: LLM类型,可以是 'normal' 或 'thinking'
247
+
250
248
  summary_prompt: 任务总结提示模板
251
249
  auto_complete: 是否自动完成任务
252
250
  output_handler: 输出处理器列表
@@ -277,7 +275,7 @@ class Agent:
277
275
  )
278
276
 
279
277
  # 初始化模型和会话
280
- self._init_model(llm_type, model_group)
278
+ self._init_model(model_group)
281
279
  self._init_session()
282
280
 
283
281
  # 初始化处理器
@@ -312,14 +310,10 @@ class Agent:
312
310
  # 输出统计信息(包含欢迎信息)
313
311
  show_agent_startup_stats(name, self.model.name(), self.get_tool_registry()) # type: ignore
314
312
 
315
- def _init_model(self, llm_type: str, model_group: Optional[str]):
316
- """初始化模型平台"""
317
- if llm_type == "thinking":
318
- platform_name = get_thinking_platform_name(model_group)
319
- model_name = get_thinking_model_name(model_group)
320
- else: # 默认为 normal
321
- platform_name = get_normal_platform_name(model_group)
322
- model_name = get_normal_model_name(model_group)
313
+ def _init_model(self, model_group: Optional[str]):
314
+ """初始化模型平台(统一使用 normal 平台/模型)"""
315
+ platform_name = get_normal_platform_name(model_group)
316
+ model_name = get_normal_model_name(model_group)
323
317
 
324
318
  self.model = PlatformRegistry().create_platform(platform_name)
325
319
  if self.model is None:
@@ -865,6 +859,10 @@ class Agent:
865
859
 
866
860
  def _first_run(self):
867
861
  """首次运行初始化"""
862
+ # 如果工具过多,使用AI进行筛选
863
+ if self.session.prompt:
864
+ self._filter_tools_if_needed(self.session.prompt)
865
+
868
866
  # 准备记忆标签提示
869
867
  memory_tags_prompt = self.memory_manager.prepare_memory_tags_prompt()
870
868
 
@@ -877,6 +875,91 @@ class Agent:
877
875
 
878
876
  self.first = False
879
877
 
878
+ def _filter_tools_if_needed(self, task: str):
879
+ """如果工具数量超过阈值,使用大模型筛选相关工具"""
880
+ import re
881
+ from jarvis.jarvis_tools.registry import ToolRegistry
882
+
883
+ tool_registry = self.get_tool_registry()
884
+ if not isinstance(tool_registry, ToolRegistry):
885
+ return
886
+
887
+ all_tools = tool_registry.get_all_tools()
888
+ threshold = get_tool_filter_threshold()
889
+ if len(all_tools) <= threshold:
890
+ return
891
+
892
+ # 为工具选择构建提示
893
+ tools_prompt_part = ""
894
+ tool_names = []
895
+ for i, tool in enumerate(all_tools, 1):
896
+ tool_names.append(tool["name"])
897
+ tools_prompt_part += f"{i}. {tool['name']}: {tool['description']}\n"
898
+
899
+ selection_prompt = f"""
900
+ 用户任务是:
901
+ <task>
902
+ {task}
903
+ </task>
904
+
905
+ 这是一个可用工具的列表:
906
+ <tools>
907
+ {tools_prompt_part}
908
+ </tools>
909
+
910
+ 请根据用户任务,从列表中选择最相关的工具。
911
+ 请仅返回所选工具的编号,以逗号分隔。例如:1, 5, 12
912
+ """
913
+ PrettyOutput.print(
914
+ f"工具数量超过{threshold}个,正在使用AI筛选相关工具...", OutputType.INFO
915
+ )
916
+
917
+ # 使用临时模型实例调用模型,以避免污染历史记录
918
+ try:
919
+ from jarvis.jarvis_platform.registry import PlatformRegistry
920
+
921
+ temp_model = PlatformRegistry().create_platform(
922
+ self.model.platform_name() # type: ignore
923
+ )
924
+ if not temp_model:
925
+ raise RuntimeError("为工具选择创建临时模型失败。")
926
+
927
+ temp_model.set_model_name(self.model.name()) # type: ignore
928
+ temp_model.set_system_prompt("你是一个帮助筛选工具的助手。")
929
+ selected_tools_str = temp_model.chat_until_success(
930
+ selection_prompt
931
+ ) # type: ignore
932
+
933
+ # 解析响应并筛选工具
934
+ selected_indices = [
935
+ int(i.strip()) for i in re.findall(r"\d+", selected_tools_str)
936
+ ]
937
+ selected_tool_names = [
938
+ tool_names[i - 1]
939
+ for i in selected_indices
940
+ if 0 < i <= len(tool_names)
941
+ ]
942
+
943
+ if selected_tool_names:
944
+ # 移除重复项
945
+ selected_tool_names = sorted(list(set(selected_tool_names)))
946
+ tool_registry.use_tools(selected_tool_names)
947
+ # 使用筛选后的工具列表重新设置系统提示
948
+ self._setup_system_prompt()
949
+ PrettyOutput.print(
950
+ f"已筛选出 {len(selected_tool_names)} 个相关工具: {', '.join(selected_tool_names)}",
951
+ OutputType.SUCCESS,
952
+ )
953
+ else:
954
+ PrettyOutput.print(
955
+ "AI 未能筛选出任何相关工具,将使用所有工具。", OutputType.WARNING
956
+ )
957
+
958
+ except Exception as e:
959
+ PrettyOutput.print(
960
+ f"工具筛选失败: {e},将使用所有工具。", OutputType.ERROR
961
+ )
962
+
880
963
  def _check_and_organize_memory(self):
881
964
  """
882
965
  检查记忆库状态,如果满足条件则提示用户整理。
@@ -22,12 +22,10 @@ class AgentManager:
22
22
 
23
23
  def __init__(
24
24
  self,
25
- llm_type: str,
26
25
  model_group: Optional[str] = None,
27
26
  tool_group: Optional[str] = None,
28
27
  restore_session: bool = False,
29
28
  ):
30
- self.llm_type = llm_type
31
29
  self.model_group = model_group
32
30
  self.tool_group = tool_group
33
31
  self.restore_session = restore_session
@@ -43,7 +41,6 @@ class AgentManager:
43
41
 
44
42
  self.agent = Agent(
45
43
  system_prompt=origin_agent_system_prompt,
46
- llm_type=self.llm_type,
47
44
  model_group=self.model_group,
48
45
  input_handler=[shell_input_handler, builtin_input_handler],
49
46
  output_handler=[ToolRegistry()], # type: ignore
@@ -195,7 +195,6 @@ def preload_config_for_flags(config_file: Optional[str]) -> None:
195
195
 
196
196
 
197
197
  def try_switch_to_jca_if_git_repo(
198
- llm_type: str,
199
198
  model_group: Optional[str],
200
199
  tool_group: Optional[str],
201
200
  config_file: Optional[str],
@@ -221,8 +220,6 @@ def try_switch_to_jca_if_git_repo(
221
220
  ):
222
221
  # 构建并切换到 jarvis-code-agent 命令,传递兼容参数
223
222
  args = ["jarvis-code-agent"]
224
- if llm_type:
225
- args += ["-t", llm_type]
226
223
  if model_group:
227
224
  args += ["-g", model_group]
228
225
  if tool_group:
@@ -244,7 +241,6 @@ def try_switch_to_jca_if_git_repo(
244
241
 
245
242
 
246
243
  def handle_builtin_config_selector(
247
- llm_type: str,
248
244
  model_group: Optional[str],
249
245
  tool_group: Optional[str],
250
246
  config_file: Optional[str],
@@ -388,21 +384,21 @@ def handle_builtin_config_selector(
388
384
  table.add_column("描述", style="white")
389
385
 
390
386
  for idx, opt in enumerate(options, 1):
391
- category = opt.get("category", "")
392
- name = opt.get("name", "")
393
- file_path = opt.get("file", "")
387
+ category = str(opt.get("category", ""))
388
+ name = str(opt.get("name", ""))
389
+ file_path = str(opt.get("file", ""))
394
390
  # 描述列显示配置描述;若为 roles 同时显示角色数量与列表
395
391
  if category == "roles":
396
392
  count = opt.get("roles_count")
397
- details = opt.get("details", "")
398
- parts = []
393
+ details_val = opt.get("details", "")
394
+ parts: list[str] = []
399
395
  if isinstance(count, int) and count > 0:
400
396
  parts.append(f"{count} 个角色")
401
- if details:
402
- parts.append(details)
397
+ if isinstance(details_val, str) and details_val:
398
+ parts.append(details_val)
403
399
  desc_display = "\n".join(parts) if parts else ""
404
400
  else:
405
- desc_display = opt.get("desc", "")
401
+ desc_display = str(opt.get("desc", ""))
406
402
  table.add_row(str(idx), category, name, file_path, desc_display)
407
403
 
408
404
  Console().print(table)
@@ -416,33 +412,29 @@ def handle_builtin_config_selector(
416
412
  index = int(choice.strip())
417
413
  if 1 <= index <= len(options):
418
414
  sel = options[index - 1]
419
- args = []
415
+ args: list[str] = []
420
416
 
421
417
  if sel["category"] == "agent":
422
418
  # jarvis-agent 支持 -f/--config(全局配置)与 -c/--agent-definition
423
- args = [sel["cmd"], "-c", sel["file"]]
424
- if llm_type:
425
- args += ["--llm-type", llm_type]
419
+ args = [str(sel["cmd"]), "-c", str(sel["file"])]
426
420
  if model_group:
427
- args += ["-g", model_group]
421
+ args += ["-g", str(model_group)]
428
422
  if config_file:
429
- args += ["-f", config_file]
423
+ args += ["-f", str(config_file)]
430
424
  if task:
431
- args += ["--task", task]
425
+ args += ["--task", str(task)]
432
426
 
433
427
  elif sel["category"] == "multi_agent":
434
428
  # jarvis-multi-agent 需要 -c/--config,用户输入通过 -i/--input 传递
435
- args = [sel["cmd"], "-c", sel["file"]]
429
+ args = [str(sel["cmd"]), "-c", str(sel["file"])]
436
430
  if task:
437
- args += ["-i", task]
431
+ args += ["-i", str(task)]
438
432
 
439
433
  elif sel["category"] == "roles":
440
434
  # jarvis-platform-manager role 子命令,支持 -c/-t/-g
441
- args = [sel["cmd"], "role", "-c", sel["file"]]
442
- if llm_type:
443
- args += ["-t", llm_type]
435
+ args = [str(sel["cmd"]), "role", "-c", str(sel["file"])]
444
436
  if model_group:
445
- args += ["-g", model_group]
437
+ args += ["-g", str(model_group)]
446
438
 
447
439
  if args:
448
440
  PrettyOutput.print(
@@ -460,12 +452,6 @@ def handle_builtin_config_selector(
460
452
  @app.callback(invoke_without_command=True)
461
453
  def run_cli(
462
454
  ctx: typer.Context,
463
- llm_type: str = typer.Option(
464
- "normal",
465
- "-t",
466
- "--llm-type",
467
- help="使用的LLM类型,可选值:'normal'(普通)或 'thinking'(思考模式)",
468
- ),
469
455
  task: Optional[str] = typer.Option(
470
456
  None, "-T", "--task", help="从命令行直接输入任务内容"
471
457
  ),
@@ -525,11 +511,11 @@ def run_cli(
525
511
 
526
512
  # 在初始化环境前检测Git仓库,并可选择自动切换到代码开发模式(jca)
527
513
  try_switch_to_jca_if_git_repo(
528
- llm_type, model_group, tool_group, config_file, restore_session, task
514
+ model_group, tool_group, config_file, restore_session, task
529
515
  )
530
516
 
531
517
  # 在进入默认通用代理前,列出内置配置供选择(agent/multi_agent/roles)
532
- handle_builtin_config_selector(llm_type, model_group, tool_group, config_file, task)
518
+ handle_builtin_config_selector(model_group, tool_group, config_file, task)
533
519
 
534
520
  # 初始化环境
535
521
  init_env(
@@ -539,7 +525,6 @@ def run_cli(
539
525
  # 运行主流程
540
526
  try:
541
527
  agent_manager = AgentManager(
542
- llm_type=llm_type,
543
528
  model_group=model_group,
544
529
  tool_group=tool_group,
545
530
  restore_session=restore_session,
@@ -46,12 +46,7 @@ def cli(
46
46
  None, "-c", "--agent-definition", help="代理定义文件路径"
47
47
  ),
48
48
  task: Optional[str] = typer.Option(None, "-T", "--task", help="初始任务内容"),
49
- llm_type: str = typer.Option(
50
- "normal",
51
- "-t",
52
- "--llm-type",
53
- help="使用的LLM类型,覆盖配置文件中的设置",
54
- ),
49
+
55
50
  model_group: Optional[str] = typer.Option(
56
51
  None, "-g", "--llm-group", help="使用的模型组,覆盖配置文件中的设置"
57
52
  ),
@@ -66,8 +61,7 @@ def cli(
66
61
  config = load_config(agent_definition) if agent_definition else {}
67
62
 
68
63
  # Override config with command-line arguments if provided
69
- if llm_type:
70
- config["llm_type"] = llm_type
64
+
71
65
  if model_group:
72
66
  config["model_group"] = model_group
73
67
 
@@ -48,7 +48,6 @@ class CodeAgent:
48
48
 
49
49
  def __init__(
50
50
  self,
51
- llm_type: str = "normal",
52
51
  model_group: Optional[str] = None,
53
52
  need_summary: bool = True,
54
53
  append_tools: Optional[str] = None,
@@ -87,7 +86,6 @@ class CodeAgent:
87
86
  name="CodeAgent",
88
87
  auto_complete=False,
89
88
  output_handler=[tool_registry, EditFileHandler()], # type: ignore
90
- llm_type=llm_type,
91
89
  model_group=model_group,
92
90
  input_handler=[shell_input_handler, builtin_input_handler],
93
91
  need_summary=need_summary,
@@ -299,10 +297,12 @@ class CodeAgent:
299
297
  "⚠️ 正在修改git换行符敏感设置,这会影响所有文件的换行符处理方式",
300
298
  OutputType.WARNING,
301
299
  )
302
- PrettyOutput.print("将进行以下设置:", OutputType.INFO)
300
+ # 避免在循环中逐条打印,先拼接后统一打印
301
+ lines = ["将进行以下设置:"]
303
302
  for key, value in target_settings.items():
304
303
  current = current_settings.get(key, "未设置")
305
- PrettyOutput.print(f"{key}: {current} -> {value}", OutputType.INFO)
304
+ lines.append(f"{key}: {current} -> {value}")
305
+ PrettyOutput.print("\n".join(lines), OutputType.INFO)
306
306
 
307
307
  # 直接执行设置,不需要用户确认
308
308
  for key, value in target_settings.items():
@@ -672,12 +672,7 @@ class CodeAgent:
672
672
 
673
673
  @app.command()
674
674
  def cli(
675
- llm_type: str = typer.Option(
676
- "normal",
677
- "-t",
678
- "--llm-type",
679
- help="使用的LLM类型,可选值:'normal'(普通)或 'thinking'(思考模式)",
680
- ),
675
+
681
676
  model_group: Optional[str] = typer.Option(
682
677
  None, "-g", "--llm-group", help="使用的模型组,覆盖配置文件中的设置"
683
678
  ),
@@ -753,7 +748,6 @@ def cli(
753
748
  find_git_root_and_cd(curr_dir)
754
749
  try:
755
750
  agent = CodeAgent(
756
- llm_type=llm_type,
757
751
  model_group=model_group,
758
752
  need_summary=False,
759
753
  append_tools=append_tools,
@@ -591,24 +591,17 @@ class CodeReviewTool:
591
591
  tool_registry = ToolRegistry()
592
592
  tool_registry.dont_use_tools(["code_review"])
593
593
 
594
- # Get llm_type and model_group from args
595
- llm_type = args.get("llm_type", "normal")
594
+ # Get model_group from args (thinking mode removed)
596
595
  model_group = args.get("model_group")
597
596
 
598
- # Get platform and model based on llm_type and model_group
597
+ # Get platform and model from model_group
599
598
  from jarvis.jarvis_utils.config import (
600
599
  get_normal_platform_name,
601
600
  get_normal_model_name,
602
- get_thinking_platform_name,
603
- get_thinking_model_name,
604
601
  )
605
602
 
606
- if llm_type == "thinking":
607
- platform_name = get_thinking_platform_name(model_group)
608
- model_name = get_thinking_model_name(model_group)
609
- else:
610
- platform_name = get_normal_platform_name(model_group)
611
- model_name = get_normal_model_name(model_group)
603
+ platform_name = get_normal_platform_name(model_group)
604
+ model_name = get_normal_model_name(model_group)
612
605
 
613
606
  # If no explicit parameters, try to get from existing agent
614
607
  calling_agent = agent or get_agent(current_agent_name)
@@ -698,7 +691,6 @@ class CodeReviewTool:
698
691
  [在此处插入完整MARKDOWN格式的审查报告]
699
692
  {ct("REPORT")}""",
700
693
  output_handler=[tool_registry], # type: ignore
701
- llm_type="thinking",
702
694
  auto_complete=False,
703
695
  )
704
696
 
@@ -821,12 +813,7 @@ def extract_code_report(result: str) -> str:
821
813
  def review_commit(
822
814
  commit: str = typer.Argument(..., help="要审查的提交SHA"),
823
815
  root_dir: str = typer.Option(".", "--root-dir", help="代码库根目录路径"),
824
- llm_type: str = typer.Option(
825
- "normal",
826
- "-t",
827
- "--llm-type",
828
- help="使用的LLM类型,可选值:'normal'(普通)或 'thinking'(思考模式)",
829
- ),
816
+
830
817
  model_group: Optional[str] = typer.Option(
831
818
  None, "-g", "--llm-group", help="使用的模型组,覆盖配置文件中的设置"
832
819
  ),
@@ -837,7 +824,7 @@ def review_commit(
837
824
  "review_type": "commit",
838
825
  "commit_sha": commit,
839
826
  "root_dir": root_dir,
840
- "llm_type": llm_type,
827
+
841
828
  "model_group": model_group,
842
829
  }
843
830
  result = tool.execute(tool_args)
@@ -852,12 +839,7 @@ def review_commit(
852
839
  @app.command("current")
853
840
  def review_current(
854
841
  root_dir: str = typer.Option(".", "--root-dir", help="代码库根目录路径"),
855
- llm_type: str = typer.Option(
856
- "normal",
857
- "-t",
858
- "--llm-type",
859
- help="使用的LLM类型,可选值:'normal'(普通)或 'thinking'(思考模式)",
860
- ),
842
+
861
843
  model_group: Optional[str] = typer.Option(
862
844
  None, "-g", "--llm-group", help="使用的模型组,覆盖配置文件中的设置"
863
845
  ),
@@ -867,7 +849,7 @@ def review_current(
867
849
  tool_args = {
868
850
  "review_type": "current",
869
851
  "root_dir": root_dir,
870
- "llm_type": llm_type,
852
+
871
853
  "model_group": model_group,
872
854
  }
873
855
  result = tool.execute(tool_args)
@@ -884,12 +866,7 @@ def review_range(
884
866
  start_commit: str = typer.Argument(..., help="起始提交SHA"),
885
867
  end_commit: str = typer.Argument(..., help="结束提交SHA"),
886
868
  root_dir: str = typer.Option(".", "--root-dir", help="代码库根目录路径"),
887
- llm_type: str = typer.Option(
888
- "normal",
889
- "-t",
890
- "--llm-type",
891
- help="使用的LLM类型,可选值:'normal'(普通)或 'thinking'(思考模式)",
892
- ),
869
+
893
870
  model_group: Optional[str] = typer.Option(
894
871
  None, "-g", "--llm-group", help="使用的模型组,覆盖配置文件中的设置"
895
872
  ),
@@ -901,7 +878,7 @@ def review_range(
901
878
  "start_commit": start_commit,
902
879
  "end_commit": end_commit,
903
880
  "root_dir": root_dir,
904
- "llm_type": llm_type,
881
+
905
882
  "model_group": model_group,
906
883
  }
907
884
  result = tool.execute(tool_args)
@@ -917,12 +894,7 @@ def review_range(
917
894
  def review_file(
918
895
  file: str = typer.Argument(..., help="要审查的文件路径"),
919
896
  root_dir: str = typer.Option(".", "--root-dir", help="代码库根目录路径"),
920
- llm_type: str = typer.Option(
921
- "normal",
922
- "-t",
923
- "--llm-type",
924
- help="使用的LLM类型,可选值:'normal'(普通)或 'thinking'(思考模式)",
925
- ),
897
+
926
898
  model_group: Optional[str] = typer.Option(
927
899
  None, "-g", "--llm-group", help="使用的模型组,覆盖配置文件中的设置"
928
900
  ),
@@ -933,7 +905,7 @@ def review_file(
933
905
  "review_type": "file",
934
906
  "file_path": file,
935
907
  "root_dir": root_dir,
936
- "llm_type": llm_type,
908
+
937
909
  "model_group": model_group,
938
910
  }
939
911
  result = tool.execute(tool_args)
@@ -126,16 +126,8 @@
126
126
  "description": "常规操作模型名称",
127
127
  "default": "deep_seek_v3"
128
128
  },
129
- "JARVIS_THINKING_PLATFORM": {
130
- "type": "string",
131
- "description": "思考操作平台名称",
132
- "default": "yuanbao"
133
- },
134
- "JARVIS_THINKING_MODEL": {
135
- "type": "string",
136
- "description": "思考操作模型名称",
137
- "default": "deep_seek_v3"
138
- },
129
+
130
+
139
131
  "JARVIS_WEB_SEARCH_PLATFORM": {
140
132
  "type": "string",
141
133
  "description": "Web搜索使用的平台名称",
@@ -168,17 +160,18 @@
168
160
  "type": "string",
169
161
  "default": "deep_seek_v3"
170
162
  },
171
- "JARVIS_THINKING_PLATFORM": {
172
- "type": "string",
173
- "default": "yuanbao"
174
- },
175
- "JARVIS_THINKING_MODEL": {
176
- "type": "string",
177
- "default": "deep_seek_v3"
178
- },
163
+
164
+
179
165
  "JARVIS_MAX_INPUT_TOKEN_COUNT": {
180
166
  "type": "number",
181
167
  "default": 32000
168
+ },
169
+ "ENV": {
170
+ "type": "object",
171
+ "description": "该模型组特定的环境变量,会覆盖全局 ENV 配置",
172
+ "additionalProperties": {
173
+ "type": "string"
174
+ }
182
175
  }
183
176
  },
184
177
  "required": [
@@ -113,9 +113,9 @@ class GitCommitTool:
113
113
  # 获取文件列表
114
114
  files_cmd = ["git", "diff", "--cached", "--name-only"]
115
115
  process = subprocess.Popen(
116
- files_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE
116
+ files_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True
117
117
  )
118
- files_output = process.communicate()[0].decode()
118
+ files_output = process.communicate()[0]
119
119
  files = [f.strip() for f in files_output.split("\n") if f.strip()]
120
120
  file_count = len(files)
121
121
 
@@ -124,8 +124,9 @@ class GitCommitTool:
124
124
  ["git", "diff", "--cached", "--exit-code"],
125
125
  stdout=subprocess.PIPE,
126
126
  stderr=subprocess.PIPE,
127
+ text=True,
127
128
  )
128
- diff = process.communicate()[0].decode(errors="ignore")
129
+ diff = process.communicate()[0]
129
130
 
130
131
  try:
131
132
  temp_diff_file_path = None
@@ -162,24 +163,17 @@ commit信息
162
163
  {ct("COMMIT_MESSAGE")}
163
164
  """
164
165
 
165
- # Get llm_type and model_group from args
166
- llm_type = args.get("llm_type", "normal")
166
+ # Get model_group from args
167
167
  model_group = args.get("model_group")
168
168
 
169
- # Get platform and model based on llm_type and model_group
169
+ # Get platform and model based on model_group (thinking mode removed)
170
170
  from jarvis.jarvis_utils.config import (
171
171
  get_normal_platform_name,
172
172
  get_normal_model_name,
173
- get_thinking_platform_name,
174
- get_thinking_model_name,
175
173
  )
176
174
 
177
- if llm_type == "thinking":
178
- platform_name = get_thinking_platform_name(model_group)
179
- model_name = get_thinking_model_name(model_group)
180
- else:
181
- platform_name = get_normal_platform_name(model_group)
182
- model_name = get_normal_model_name(model_group)
175
+ platform_name = get_normal_platform_name(model_group)
176
+ model_name = get_normal_model_name(model_group)
183
177
 
184
178
  # If no explicit parameters, try to get from existing agent
185
179
  agent = get_agent(current_agent_name)
@@ -202,10 +196,7 @@ commit信息
202
196
  if model_group:
203
197
  platform.model_group = model_group
204
198
  else:
205
- if llm_type == "thinking":
206
- platform = PlatformRegistry().get_thinking_platform()
207
- else:
208
- platform = PlatformRegistry().get_normal_platform()
199
+ platform = PlatformRegistry().get_normal_platform()
209
200
 
210
201
  # Ensure platform is not None
211
202
  if not platform:
@@ -382,12 +373,7 @@ def cli(
382
373
  "--suffix",
383
374
  help="提交信息后缀(用换行分隔)",
384
375
  ),
385
- llm_type: str = typer.Option(
386
- "normal",
387
- "-t",
388
- "--llm-type",
389
- help="使用的LLM类型,可选值:'normal'(普通)或 'thinking'(思考模式)",
390
- ),
376
+
391
377
  model_group: Optional[str] = typer.Option(
392
378
  None, "-g", "--llm-group", help="使用的模型组,覆盖配置文件中的设置"
393
379
  ),
@@ -399,7 +385,7 @@ def cli(
399
385
  "root_dir": root_dir,
400
386
  "prefix": prefix,
401
387
  "suffix": suffix,
402
- "llm_type": llm_type,
388
+
403
389
  "model_group": model_group,
404
390
  }
405
391
  )
@@ -210,13 +210,14 @@ class SSEMcpClient(McpClient):
210
210
 
211
211
  # 调用已注册的处理器
212
212
  if method in self.notification_handlers:
213
+ error_lines: list[str] = []
213
214
  for handler in self.notification_handlers[method]:
214
215
  try:
215
216
  handler(params)
216
217
  except Exception as e:
217
- PrettyOutput.print(
218
- f"处理通知时出错 ({method}): {e}", OutputType.ERROR
219
- )
218
+ error_lines.append(f"处理通知时出错 ({method}): {e}")
219
+ if error_lines:
220
+ PrettyOutput.print("\n".join(error_lines), OutputType.ERROR)
220
221
  except json.JSONDecodeError:
221
222
  PrettyOutput.print(f"无法解析SSE事件: {data}", OutputType.WARNING)
222
223
  except Exception as e: