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.
- jarvis/__init__.py +1 -1
- jarvis/jarvis_agent/__init__.py +170 -9
- jarvis/jarvis_agent/file_methodology_manager.py +6 -1
- jarvis/jarvis_agent/share_manager.py +21 -0
- jarvis/jarvis_agent/tool_executor.py +8 -4
- jarvis/jarvis_code_agent/code_agent.py +7 -12
- jarvis/jarvis_code_analysis/code_review.py +117 -12
- jarvis/jarvis_git_utils/git_commiter.py +63 -9
- jarvis/jarvis_memory_organizer/__init__.py +0 -0
- jarvis/jarvis_memory_organizer/memory_organizer.py +729 -0
- jarvis/jarvis_platform/base.py +9 -0
- jarvis/jarvis_platform/kimi.py +20 -0
- jarvis/jarvis_platform/openai.py +27 -0
- jarvis/jarvis_platform/tongyi.py +19 -0
- jarvis/jarvis_platform/yuanbao.py +18 -0
- jarvis/jarvis_platform_manager/main.py +22 -16
- jarvis/jarvis_tools/base.py +8 -1
- jarvis/jarvis_utils/git_utils.py +20 -3
- jarvis/jarvis_utils/globals.py +16 -10
- jarvis/jarvis_utils/methodology.py +19 -2
- jarvis/jarvis_utils/utils.py +159 -78
- {jarvis_ai_assistant-0.3.2.dist-info → jarvis_ai_assistant-0.3.4.dist-info}/METADATA +40 -1
- {jarvis_ai_assistant-0.3.2.dist-info → jarvis_ai_assistant-0.3.4.dist-info}/RECORD +27 -25
- {jarvis_ai_assistant-0.3.2.dist-info → jarvis_ai_assistant-0.3.4.dist-info}/entry_points.txt +2 -0
- {jarvis_ai_assistant-0.3.2.dist-info → jarvis_ai_assistant-0.3.4.dist-info}/WHEEL +0 -0
- {jarvis_ai_assistant-0.3.2.dist-info → jarvis_ai_assistant-0.3.4.dist-info}/licenses/LICENSE +0 -0
- {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
jarvis/jarvis_agent/__init__.py
CHANGED
@@ -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
|
-
|
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(
|
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
|
-
|
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(
|
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(
|
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
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
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",
|
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
|
-
|
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,
|
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,
|
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,
|
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
|
-
#
|
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
|
-
|
587
|
-
|
588
|
-
|
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(
|
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 = {
|
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 = {
|
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 = {
|
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
|
170
|
-
|
171
|
-
|
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
|
-
|
174
|
-
|
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
|