jarvis-ai-assistant 0.3.2__py3-none-any.whl → 0.3.4__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 (27) hide show
  1. jarvis/__init__.py +1 -1
  2. jarvis/jarvis_agent/__init__.py +170 -9
  3. jarvis/jarvis_agent/file_methodology_manager.py +6 -1
  4. jarvis/jarvis_agent/share_manager.py +21 -0
  5. jarvis/jarvis_agent/tool_executor.py +8 -4
  6. jarvis/jarvis_code_agent/code_agent.py +7 -12
  7. jarvis/jarvis_code_analysis/code_review.py +117 -12
  8. jarvis/jarvis_git_utils/git_commiter.py +63 -9
  9. jarvis/jarvis_memory_organizer/__init__.py +0 -0
  10. jarvis/jarvis_memory_organizer/memory_organizer.py +729 -0
  11. jarvis/jarvis_platform/base.py +9 -0
  12. jarvis/jarvis_platform/kimi.py +20 -0
  13. jarvis/jarvis_platform/openai.py +27 -0
  14. jarvis/jarvis_platform/tongyi.py +19 -0
  15. jarvis/jarvis_platform/yuanbao.py +18 -0
  16. jarvis/jarvis_platform_manager/main.py +22 -16
  17. jarvis/jarvis_tools/base.py +8 -1
  18. jarvis/jarvis_utils/git_utils.py +20 -3
  19. jarvis/jarvis_utils/globals.py +16 -10
  20. jarvis/jarvis_utils/methodology.py +19 -2
  21. jarvis/jarvis_utils/utils.py +159 -78
  22. {jarvis_ai_assistant-0.3.2.dist-info → jarvis_ai_assistant-0.3.4.dist-info}/METADATA +40 -1
  23. {jarvis_ai_assistant-0.3.2.dist-info → jarvis_ai_assistant-0.3.4.dist-info}/RECORD +27 -25
  24. {jarvis_ai_assistant-0.3.2.dist-info → jarvis_ai_assistant-0.3.4.dist-info}/entry_points.txt +2 -0
  25. {jarvis_ai_assistant-0.3.2.dist-info → jarvis_ai_assistant-0.3.4.dist-info}/WHEEL +0 -0
  26. {jarvis_ai_assistant-0.3.2.dist-info → jarvis_ai_assistant-0.3.4.dist-info}/licenses/LICENSE +0 -0
  27. {jarvis_ai_assistant-0.3.2.dist-info → jarvis_ai_assistant-0.3.4.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.2"
4
+ __version__ = "0.3.4"
@@ -3,6 +3,7 @@
3
3
  import datetime
4
4
  import os
5
5
  import platform
6
+ from pathlib import Path
6
7
  from typing import Any, Callable, Dict, List, Optional, Protocol, Tuple, Union
7
8
 
8
9
  # 第三方库导入
@@ -14,6 +15,7 @@ from jarvis.jarvis_agent.protocols import OutputHandlerProtocol
14
15
  from jarvis.jarvis_agent.session_manager import SessionManager
15
16
  from jarvis.jarvis_agent.tool_executor import execute_tool_call
16
17
  from jarvis.jarvis_agent.memory_manager import MemoryManager
18
+ from jarvis.jarvis_memory_organizer.memory_organizer import MemoryOrganizer
17
19
  from jarvis.jarvis_agent.task_analyzer import TaskAnalyzer
18
20
  from jarvis.jarvis_agent.file_methodology_manager import FileMethodologyManager
19
21
  from jarvis.jarvis_agent.prompts import (
@@ -28,6 +30,7 @@ from jarvis.jarvis_platform.registry import PlatformRegistry
28
30
 
29
31
  # jarvis_utils 相关
30
32
  from jarvis.jarvis_utils.config import (
33
+ get_data_dir,
31
34
  get_max_token_count,
32
35
  get_normal_model_name,
33
36
  get_normal_platform_name,
@@ -50,6 +53,98 @@ from jarvis.jarvis_utils.input import get_multiline_input, user_confirm
50
53
  from jarvis.jarvis_utils.output import OutputType, PrettyOutput
51
54
  from jarvis.jarvis_utils.tag import ct, ot
52
55
 
56
+
57
+ def show_agent_startup_stats(agent_name: str, model_name: str) -> None:
58
+ """输出启动时的统计信息
59
+
60
+ 参数:
61
+ agent_name: Agent的名称
62
+ model_name: 使用的模型名称
63
+ """
64
+ try:
65
+ from jarvis.jarvis_utils.methodology import _load_all_methodologies
66
+ from jarvis.jarvis_tools.registry import ToolRegistry
67
+ from jarvis.jarvis_utils.config import get_data_dir
68
+ from pathlib import Path
69
+ from rich.console import Console
70
+ from rich.panel import Panel
71
+ from rich.text import Text
72
+ from rich.align import Align
73
+ import os
74
+
75
+ methodologies = _load_all_methodologies()
76
+ methodology_count = len(methodologies)
77
+
78
+ # 获取工具数量
79
+ # 创建一个临时的工具注册表类来获取所有工具(不应用过滤)
80
+ class TempToolRegistry(ToolRegistry):
81
+ def _apply_tool_config_filter(self) -> None:
82
+ """重写过滤方法,不执行任何过滤"""
83
+ pass
84
+
85
+ # 获取所有工具的数量
86
+ tool_registry_all = TempToolRegistry()
87
+ total_tool_count = len(tool_registry_all.tools)
88
+
89
+ # 获取可用工具的数量(应用过滤)
90
+ tool_registry = ToolRegistry()
91
+ available_tool_count = len(tool_registry.get_all_tools())
92
+
93
+ global_memory_dir = Path(get_data_dir()) / "memory" / "global_long_term"
94
+ global_memory_count = 0
95
+ if global_memory_dir.exists():
96
+ global_memory_count = len(list(global_memory_dir.glob("*.json")))
97
+
98
+ # 检查项目记忆
99
+ project_memory_dir = Path(".jarvis/memory")
100
+ project_memory_count = 0
101
+ if project_memory_dir.exists():
102
+ project_memory_count = len(list(project_memory_dir.glob("*.json")))
103
+
104
+ # 获取当前工作目录
105
+ current_dir = os.getcwd()
106
+
107
+ # 构建欢迎信息
108
+ welcome_message = f"{agent_name} 初始化完成 - 使用 {model_name} 模型"
109
+
110
+ stats_parts = [
111
+ f"📚 本地方法论: [bold cyan]{methodology_count}[/bold cyan]",
112
+ f"🛠️ 工具: [bold green]{available_tool_count}/{total_tool_count}[/bold green] (可用/全部)",
113
+ f"🧠 全局记忆: [bold yellow]{global_memory_count}[/bold yellow]",
114
+ ]
115
+
116
+ # 如果有项目记忆,添加到统计信息中
117
+ if project_memory_count > 0:
118
+ stats_parts.append(
119
+ f"📝 项目记忆: [bold magenta]{project_memory_count}[/bold magenta]"
120
+ )
121
+
122
+ stats_text = Text.from_markup(" | ".join(stats_parts), justify="center")
123
+
124
+ # 创建包含欢迎信息和统计信息的面板内容
125
+ panel_content = Text()
126
+ panel_content.append(welcome_message, style="bold white")
127
+ panel_content.append("\n")
128
+ panel_content.append(f"📁 工作目录: {current_dir}", style="dim white")
129
+ panel_content.append("\n\n")
130
+ panel_content.append(stats_text)
131
+ panel_content.justify = "center"
132
+
133
+ panel = Panel(
134
+ panel_content,
135
+ title="✨ Jarvis 资源概览 ✨",
136
+ title_align="center",
137
+ border_style="blue",
138
+ expand=False,
139
+ )
140
+
141
+ console = Console()
142
+ console.print(Align.center(panel))
143
+
144
+ except Exception as e:
145
+ PrettyOutput.print(f"加载统计信息失败: {e}", OutputType.WARNING)
146
+
147
+
53
148
  origin_agent_system_prompt = f"""
54
149
  <role>
55
150
  # 🤖 角色
@@ -175,9 +270,8 @@ class Agent:
175
270
  # 设置系统提示词
176
271
  self._setup_system_prompt()
177
272
 
178
- # 打印欢迎信息
179
- welcome_message = f"{name} 初始化完成 - 使用 {self.model.name()} 模型" # type: ignore
180
- PrettyOutput.print(welcome_message, OutputType.SYSTEM)
273
+ # 输出统计信息(包含欢迎信息)
274
+ show_agent_startup_stats(name, self.model.name()) # type: ignore
181
275
 
182
276
  def _init_model(self, llm_type: str, model_group: Optional[str]):
183
277
  """初始化模型平台"""
@@ -190,7 +284,9 @@ class Agent:
190
284
 
191
285
  self.model = PlatformRegistry().create_platform(platform_name)
192
286
  if self.model is None:
193
- PrettyOutput.print(f"平台 {platform_name} 不存在,将使用普通模型", OutputType.WARNING)
287
+ PrettyOutput.print(
288
+ f"平台 {platform_name} 不存在,将使用普通模型", OutputType.WARNING
289
+ )
194
290
  self.model = PlatformRegistry().get_normal_platform()
195
291
 
196
292
  if model_name:
@@ -512,10 +608,8 @@ class Agent:
512
608
 
513
609
  if self.use_analysis:
514
610
  self.task_analyzer.analysis_task(satisfaction_feedback)
515
- else:
516
- # 如果没有开启分析,也提示用户是否有值得记忆的信息
517
- if self.force_save_memory:
518
- self.memory_manager.prompt_memory_save()
611
+
612
+ self._check_and_organize_memory()
519
613
 
520
614
  if self.need_summary:
521
615
  print("📄 正在生成总结...")
@@ -689,7 +783,9 @@ class Agent:
689
783
  返回:
690
784
  str: "continue" 或 "complete"
691
785
  """
692
- user_input = self.multiline_inputer(f"{self.name}: 请输入,或输入空行来结束当前任务:")
786
+ user_input = self.multiline_inputer(
787
+ f"{self.name}: 请输入,或输入空行来结束当前任务:"
788
+ )
693
789
 
694
790
  if user_input:
695
791
  self.session.prompt = user_input
@@ -711,6 +807,71 @@ class Agent:
711
807
 
712
808
  self.first = False
713
809
 
810
+ def _check_and_organize_memory(self):
811
+ """
812
+ 检查记忆库状态,如果满足条件则提示用户整理。
813
+ 每天只检测一次。
814
+ """
815
+ try:
816
+ # 检查项目记忆
817
+ self._perform_memory_check("project_long_term", Path(".jarvis"), "project")
818
+ # 检查全局记忆
819
+ self._perform_memory_check(
820
+ "global_long_term",
821
+ Path(get_data_dir()),
822
+ "global",
823
+ )
824
+ except Exception as e:
825
+ PrettyOutput.print(f"检查记忆库时发生意外错误: {e}", OutputType.WARNING)
826
+
827
+ def _perform_memory_check(self, memory_type: str, base_path: Path, scope_name: str):
828
+ """执行特定范围的记忆检查和整理"""
829
+ check_file = base_path / ".last_memory_organizer_check"
830
+ now = datetime.datetime.now()
831
+
832
+ if check_file.exists():
833
+ try:
834
+ last_check_time = datetime.datetime.fromisoformat(
835
+ check_file.read_text()
836
+ )
837
+ if (now - last_check_time).total_seconds() < 24 * 3600:
838
+ return # 24小时内已检查
839
+ except (ValueError, FileNotFoundError):
840
+ # 文件内容无效或文件在读取时被删除,继续执行检查
841
+ pass
842
+
843
+ # 立即更新检查时间,防止并发或重复检查
844
+ base_path.mkdir(parents=True, exist_ok=True)
845
+ check_file.write_text(now.isoformat())
846
+
847
+ organizer = MemoryOrganizer()
848
+ # NOTE: 使用受保护方法以避免重复实现逻辑
849
+ memories = organizer._load_memories(memory_type)
850
+
851
+ if len(memories) < 200:
852
+ return
853
+
854
+ # NOTE: 使用受保护方法以避免重复实现逻辑
855
+ overlap_groups = organizer._find_overlapping_memories(memories, min_overlap=3)
856
+ has_significant_overlap = any(groups for groups in overlap_groups.values())
857
+
858
+ if not has_significant_overlap:
859
+ return
860
+
861
+ prompt = (
862
+ f"检测到您的 '{scope_name}' 记忆库中包含 {len(memories)} 条记忆,"
863
+ f"并且存在3个以上标签重叠的记忆。\n"
864
+ f"是否立即整理记忆库以优化性能和相关性?"
865
+ )
866
+ if user_confirm(prompt, default=True):
867
+ PrettyOutput.print(
868
+ f"正在开始整理 '{scope_name}' ({memory_type}) 记忆库...",
869
+ OutputType.INFO,
870
+ )
871
+ organizer.organize_memories(memory_type, min_overlap=3)
872
+ else:
873
+ PrettyOutput.print(f"已取消 '{scope_name}' 记忆库整理。", OutputType.INFO)
874
+
714
875
  def clear_history(self):
715
876
  """
716
877
  Clears conversation history by delegating to the session manager.
@@ -80,7 +80,12 @@ class FileMethodologyManager:
80
80
 
81
81
  memory_manager = MemoryManager(self.agent)
82
82
  memory_tags_prompt = memory_manager.prepare_memory_tags_prompt()
83
- methodology = load_methodology(msg, self.agent.get_tool_registry())
83
+ methodology = load_methodology(
84
+ msg,
85
+ self.agent.get_tool_registry(),
86
+ platform_name=self.agent.model.platform_name(),
87
+ model_name=self.agent.model.name(),
88
+ )
84
89
  self.agent.session.prompt = f"{self.agent.session.prompt}\n\n以下是历史类似问题的执行经验,可参考:\n{methodology}{memory_tags_prompt}"
85
90
 
86
91
  def handle_history_with_file_upload(self) -> str:
@@ -98,6 +98,27 @@ class ShareManager(ABC):
98
98
  )
99
99
  # 如果有远程分支,执行pull
100
100
  if result.stdout.strip():
101
+ # 检查是否有未提交的更改
102
+ status_result = subprocess.run(
103
+ ["git", "status", "--porcelain"],
104
+ cwd=self.repo_path,
105
+ capture_output=True,
106
+ text=True,
107
+ check=True,
108
+ )
109
+ if status_result.stdout:
110
+ if user_confirm(
111
+ f"检测到中心{self.get_resource_type()}仓库 '{self.repo_name}' 存在未提交的更改,是否放弃这些更改并更新?"
112
+ ):
113
+ subprocess.run(
114
+ ["git", "checkout", "."], cwd=self.repo_path, check=True
115
+ )
116
+ else:
117
+ PrettyOutput.print(
118
+ f"跳过更新 '{self.repo_name}' 以保留未提交的更改。",
119
+ OutputType.INFO,
120
+ )
121
+ return
101
122
  subprocess.run(["git", "pull"], cwd=self.repo_path, check=True)
102
123
  else:
103
124
  PrettyOutput.print(
@@ -41,9 +41,13 @@ def execute_tool_call(response: str, agent: "Agent") -> Tuple[bool, Any]:
41
41
  if not agent.execute_tool_confirm or user_confirm(
42
42
  f"需要执行{tool_to_execute.name()}确认执行?", True
43
43
  ):
44
- print(f"🔧 正在执行{tool_to_execute.name()}...")
45
- result = tool_to_execute.handle(response, agent)
46
- print(f"✅ {tool_to_execute.name()}执行完成")
47
- return result
44
+ try:
45
+ print(f"🔧 正在执行{tool_to_execute.name()}...")
46
+ result = tool_to_execute.handle(response, agent)
47
+ print(f"✅ {tool_to_execute.name()}执行完成")
48
+ return result
49
+ except Exception as e:
50
+ PrettyOutput.print(f"工具执行失败: {str(e)}", OutputType.ERROR)
51
+ return False, str(e)
48
52
 
49
53
  return False, ""
@@ -398,11 +398,6 @@ class CodeAgent:
398
398
  if not user_confirm("是否要提交?", True):
399
399
  return
400
400
 
401
- # 用户确认修改,统计修改次数
402
- from jarvis.jarvis_stats.stats import StatsManager
403
-
404
- StatsManager.increment("code_modification_confirmed", group="code_agent")
405
-
406
401
  try:
407
402
  confirm_add_new_files()
408
403
 
@@ -431,9 +426,6 @@ class CodeAgent:
431
426
  ["git", "commit", "-m", f"CheckPoint #{commit_count + 1}"],
432
427
  check=True,
433
428
  )
434
-
435
- # 统计提交次数
436
- StatsManager.increment("code_commits_accepted", group="code_agent")
437
429
  except subprocess.CalledProcessError as e:
438
430
  PrettyOutput.print(f"提交失败: {str(e)}", OutputType.ERROR)
439
431
 
@@ -484,6 +476,10 @@ class CodeAgent:
484
476
  )
485
477
  git_commiter = GitCommitTool()
486
478
  git_commiter.execute({})
479
+
480
+ # 在用户接受commit后,根据配置决定是否保存记忆
481
+ if self.agent.force_save_memory:
482
+ self.agent.memory_manager.prompt_memory_save()
487
483
  elif start_commit:
488
484
  os.system(f"git reset --hard {str(start_commit)}") # 确保转换为字符串
489
485
  PrettyOutput.print("已重置到初始提交", OutputType.INFO)
@@ -642,7 +638,8 @@ class CodeAgent:
642
638
  def cli(
643
639
  llm_type: str = typer.Option(
644
640
  "normal",
645
- "-t", "--llm_type",
641
+ "-t",
642
+ "--llm_type",
646
643
  help="使用的LLM类型,可选值:'normal'(普通)或 'thinking'(思考模式)",
647
644
  ),
648
645
  model_group: Optional[str] = typer.Option(
@@ -695,9 +692,7 @@ def cli(
695
692
  sys.exit(0)
696
693
 
697
694
  curr_dir = os.getcwd()
698
- git_dir = find_git_root_and_cd(curr_dir)
699
- PrettyOutput.print(f"当前目录: {git_dir}", OutputType.INFO)
700
-
695
+ find_git_root_and_cd(curr_dir)
701
696
  try:
702
697
  agent = CodeAgent(
703
698
  llm_type=llm_type,
@@ -300,7 +300,11 @@ class CodeReviewTool:
300
300
 
301
301
  # Execute git command and get diff output
302
302
  diff_output = subprocess.check_output(
303
- diff_cmd, shell=True, text=True, encoding="utf-8", errors="replace"
303
+ diff_cmd,
304
+ shell=True,
305
+ text=True,
306
+ encoding="utf-8",
307
+ errors="replace",
304
308
  )
305
309
  if not diff_output:
306
310
  return {
@@ -339,7 +343,11 @@ class CodeReviewTool:
339
343
 
340
344
  # Execute git command and get diff output
341
345
  diff_output = subprocess.check_output(
342
- diff_cmd, shell=True, text=True, encoding="utf-8", errors="replace"
346
+ diff_cmd,
347
+ shell=True,
348
+ text=True,
349
+ encoding="utf-8",
350
+ errors="replace",
343
351
  )
344
352
  if not diff_output:
345
353
  return {
@@ -381,7 +389,11 @@ class CodeReviewTool:
381
389
 
382
390
  # Execute git command and get diff output
383
391
  diff_output = subprocess.check_output(
384
- diff_cmd, shell=True, text=True, encoding="utf-8", errors="replace"
392
+ diff_cmd,
393
+ shell=True,
394
+ text=True,
395
+ encoding="utf-8",
396
+ errors="replace",
385
397
  )
386
398
  if not diff_output:
387
399
  return {
@@ -581,16 +593,48 @@ class CodeReviewTool:
581
593
  tool_registry = ToolRegistry()
582
594
  tool_registry.dont_use_tools(["code_review"])
583
595
 
584
- # Use the provided agent's model_group or get it from globals
596
+ # Get llm_type and model_group from args
597
+ llm_type = args.get("llm_type", "normal")
598
+ model_group = args.get("model_group")
599
+
600
+ # Get platform and model based on llm_type and model_group
601
+ from jarvis.jarvis_utils.config import (
602
+ get_normal_platform_name,
603
+ get_normal_model_name,
604
+ get_thinking_platform_name,
605
+ get_thinking_model_name,
606
+ )
607
+
608
+ if llm_type == "thinking":
609
+ platform_name = get_thinking_platform_name(model_group)
610
+ model_name = get_thinking_model_name(model_group)
611
+ else:
612
+ platform_name = get_normal_platform_name(model_group)
613
+ model_name = get_normal_model_name(model_group)
614
+
615
+ # If no explicit parameters, try to get from existing agent
585
616
  calling_agent = agent or get_agent(current_agent_name)
586
- model_group = None
587
- if calling_agent and hasattr(calling_agent, "model") and calling_agent.model:
588
- model_group = calling_agent.model.model_group
617
+ if (
618
+ not platform_name
619
+ and calling_agent
620
+ and hasattr(calling_agent, "model")
621
+ and calling_agent.model
622
+ ):
623
+ platform_name = calling_agent.model.platform_name()
624
+ model_name = calling_agent.model.name()
625
+
626
+ # Create a new platform instance
627
+ review_model = None
628
+ if platform_name:
629
+ review_model = PlatformRegistry().create_platform(platform_name)
630
+ if review_model and model_name:
631
+ review_model.set_model_name(model_name)
632
+ if model_group:
633
+ review_model.model_group = model_group
589
634
 
590
635
  agent = Agent(
591
636
  system_prompt=system_prompt,
592
637
  name="Code Review Agent",
593
- model_group=model_group,
594
638
  summary_prompt=f"""<code_review_report>
595
639
  <overview>
596
640
  # 整体评估
@@ -660,6 +704,10 @@ class CodeReviewTool:
660
704
  auto_complete=False,
661
705
  )
662
706
 
707
+ # Replace the agent's model with our custom platform instance
708
+ if review_model:
709
+ agent.model = review_model
710
+
663
711
  # Determine if we need to split the diff due to size
664
712
  max_diff_size = 100 * 1024 * 1024 # Limit to 100MB
665
713
 
@@ -693,7 +741,9 @@ class CodeReviewTool:
693
741
 
694
742
  try:
695
743
  # Check if content is too large
696
- is_large_content = is_context_overflow(diff_output, model_group)
744
+ is_large_content = is_context_overflow(
745
+ diff_output, review_model.model_group if review_model else None
746
+ )
697
747
 
698
748
  # Upload the file to the agent's model
699
749
  if is_large_content:
@@ -773,10 +823,25 @@ def extract_code_report(result: str) -> str:
773
823
  def review_commit(
774
824
  commit: str = typer.Argument(..., help="要审查的提交SHA"),
775
825
  root_dir: str = typer.Option(".", "--root-dir", help="代码库根目录路径"),
826
+ llm_type: str = typer.Option(
827
+ "normal",
828
+ "-t",
829
+ "--llm_type",
830
+ help="使用的LLM类型,可选值:'normal'(普通)或 'thinking'(思考模式)",
831
+ ),
832
+ model_group: Optional[str] = typer.Option(
833
+ None, "-g", "--llm_group", help="使用的模型组,覆盖配置文件中的设置"
834
+ ),
776
835
  ):
777
836
  """审查指定的提交"""
778
837
  tool = CodeReviewTool()
779
- tool_args = {"review_type": "commit", "commit_sha": commit, "root_dir": root_dir}
838
+ tool_args = {
839
+ "review_type": "commit",
840
+ "commit_sha": commit,
841
+ "root_dir": root_dir,
842
+ "llm_type": llm_type,
843
+ "model_group": model_group,
844
+ }
780
845
  result = tool.execute(tool_args)
781
846
  if result["success"]:
782
847
  PrettyOutput.section("自动代码审查结果:", OutputType.SUCCESS)
@@ -789,10 +854,24 @@ def review_commit(
789
854
  @app.command("current")
790
855
  def review_current(
791
856
  root_dir: str = typer.Option(".", "--root-dir", help="代码库根目录路径"),
857
+ llm_type: str = typer.Option(
858
+ "normal",
859
+ "-t",
860
+ "--llm_type",
861
+ help="使用的LLM类型,可选值:'normal'(普通)或 'thinking'(思考模式)",
862
+ ),
863
+ model_group: Optional[str] = typer.Option(
864
+ None, "-g", "--llm_group", help="使用的模型组,覆盖配置文件中的设置"
865
+ ),
792
866
  ):
793
867
  """审查当前的变更"""
794
868
  tool = CodeReviewTool()
795
- tool_args = {"review_type": "current", "root_dir": root_dir}
869
+ tool_args = {
870
+ "review_type": "current",
871
+ "root_dir": root_dir,
872
+ "llm_type": llm_type,
873
+ "model_group": model_group,
874
+ }
796
875
  result = tool.execute(tool_args)
797
876
  if result["success"]:
798
877
  PrettyOutput.section("自动代码审查结果:", OutputType.SUCCESS)
@@ -807,6 +886,15 @@ def review_range(
807
886
  start_commit: str = typer.Argument(..., help="起始提交SHA"),
808
887
  end_commit: str = typer.Argument(..., help="结束提交SHA"),
809
888
  root_dir: str = typer.Option(".", "--root-dir", help="代码库根目录路径"),
889
+ llm_type: str = typer.Option(
890
+ "normal",
891
+ "-t",
892
+ "--llm_type",
893
+ help="使用的LLM类型,可选值:'normal'(普通)或 'thinking'(思考模式)",
894
+ ),
895
+ model_group: Optional[str] = typer.Option(
896
+ None, "-g", "--llm_group", help="使用的模型组,覆盖配置文件中的设置"
897
+ ),
810
898
  ):
811
899
  """审查提交范围"""
812
900
  tool = CodeReviewTool()
@@ -815,6 +903,8 @@ def review_range(
815
903
  "start_commit": start_commit,
816
904
  "end_commit": end_commit,
817
905
  "root_dir": root_dir,
906
+ "llm_type": llm_type,
907
+ "model_group": model_group,
818
908
  }
819
909
  result = tool.execute(tool_args)
820
910
  if result["success"]:
@@ -829,10 +919,25 @@ def review_range(
829
919
  def review_file(
830
920
  file: str = typer.Argument(..., help="要审查的文件路径"),
831
921
  root_dir: str = typer.Option(".", "--root-dir", help="代码库根目录路径"),
922
+ llm_type: str = typer.Option(
923
+ "normal",
924
+ "-t",
925
+ "--llm_type",
926
+ help="使用的LLM类型,可选值:'normal'(普通)或 'thinking'(思考模式)",
927
+ ),
928
+ model_group: Optional[str] = typer.Option(
929
+ None, "-g", "--llm_group", help="使用的模型组,覆盖配置文件中的设置"
930
+ ),
832
931
  ):
833
932
  """审查指定的文件"""
834
933
  tool = CodeReviewTool()
835
- tool_args = {"review_type": "file", "file_path": file, "root_dir": root_dir}
934
+ tool_args = {
935
+ "review_type": "file",
936
+ "file_path": file,
937
+ "root_dir": root_dir,
938
+ "llm_type": llm_type,
939
+ "model_group": model_group,
940
+ }
836
941
  result = tool.execute(tool_args)
837
942
  if result["success"]:
838
943
  PrettyOutput.section("自动代码审查结果:", OutputType.SUCCESS)
@@ -164,14 +164,59 @@ commit信息
164
164
  {ct("COMMIT_MESSAGE")}
165
165
  """
166
166
 
167
- # 获取模型并尝试上传文件
167
+ # Get llm_type and model_group from args
168
+ llm_type = args.get("llm_type", "normal")
169
+ model_group = args.get("model_group")
170
+
171
+ # Get platform and model based on llm_type and model_group
172
+ from jarvis.jarvis_utils.config import (
173
+ get_normal_platform_name,
174
+ get_normal_model_name,
175
+ get_thinking_platform_name,
176
+ get_thinking_model_name,
177
+ )
178
+
179
+ if llm_type == "thinking":
180
+ platform_name = get_thinking_platform_name(model_group)
181
+ model_name = get_thinking_model_name(model_group)
182
+ else:
183
+ platform_name = get_normal_platform_name(model_group)
184
+ model_name = get_normal_model_name(model_group)
185
+
186
+ # If no explicit parameters, try to get from existing agent
168
187
  agent = get_agent(current_agent_name)
169
- if agent:
170
- platform = agent.model
171
- model_group = agent.model.model_group
188
+ if (
189
+ not platform_name
190
+ and agent
191
+ and hasattr(agent, "model")
192
+ and agent.model
193
+ ):
194
+ platform_name = agent.model.platform_name()
195
+ model_name = agent.model.name()
196
+ if not model_group:
197
+ model_group = agent.model.model_group
198
+
199
+ # Create a new platform instance
200
+ if platform_name:
201
+ platform = PlatformRegistry().create_platform(platform_name)
202
+ if platform and model_name:
203
+ platform.set_model_name(model_name)
204
+ if model_group:
205
+ platform.model_group = model_group
172
206
  else:
173
- platform = PlatformRegistry().get_normal_platform()
174
- model_group = None
207
+ if llm_type == "thinking":
208
+ platform = PlatformRegistry().get_thinking_platform()
209
+ else:
210
+ platform = PlatformRegistry().get_normal_platform()
211
+
212
+ # Ensure platform is not None
213
+ if not platform:
214
+ return {
215
+ "success": False,
216
+ "stdout": "",
217
+ "stderr": "错误:无法创建平台实例",
218
+ }
219
+
175
220
  upload_success = False
176
221
 
177
222
  # Check if content is too large
@@ -330,9 +375,7 @@ commit信息
330
375
 
331
376
  @app.command()
332
377
  def cli(
333
- root_dir: str = typer.Option(
334
- ".", "--root-dir", help="Git仓库的根目录路径"
335
- ),
378
+ root_dir: str = typer.Option(".", "--root-dir", help="Git仓库的根目录路径"),
336
379
  prefix: str = typer.Option(
337
380
  "",
338
381
  "--prefix",
@@ -343,6 +386,15 @@ def cli(
343
386
  "--suffix",
344
387
  help="提交信息后缀(用换行分隔)",
345
388
  ),
389
+ llm_type: str = typer.Option(
390
+ "normal",
391
+ "-t",
392
+ "--llm_type",
393
+ help="使用的LLM类型,可选值:'normal'(普通)或 'thinking'(思考模式)",
394
+ ),
395
+ model_group: Optional[str] = typer.Option(
396
+ None, "-g", "--llm_group", help="使用的模型组,覆盖配置文件中的设置"
397
+ ),
346
398
  ):
347
399
  init_env("欢迎使用 Jarvis-GitCommitTool,您的Git提交助手已准备就绪!")
348
400
  tool = GitCommitTool()
@@ -351,6 +403,8 @@ def cli(
351
403
  "root_dir": root_dir,
352
404
  "prefix": prefix,
353
405
  "suffix": suffix,
406
+ "llm_type": llm_type,
407
+ "model_group": model_group,
354
408
  }
355
409
  )
356
410
 
File without changes