jarvis-ai-assistant 0.3.26__py3-none-any.whl → 0.3.28__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 +303 -177
- jarvis/jarvis_agent/agent_manager.py +6 -0
- jarvis/jarvis_agent/config.py +92 -0
- jarvis/jarvis_agent/config_editor.py +1 -1
- jarvis/jarvis_agent/event_bus.py +48 -0
- jarvis/jarvis_agent/file_methodology_manager.py +1 -3
- jarvis/jarvis_agent/jarvis.py +77 -36
- jarvis/jarvis_agent/memory_manager.py +70 -3
- jarvis/jarvis_agent/prompt_manager.py +82 -0
- jarvis/jarvis_agent/run_loop.py +130 -0
- jarvis/jarvis_agent/shell_input_handler.py +1 -1
- jarvis/jarvis_agent/task_analyzer.py +89 -11
- jarvis/jarvis_agent/task_manager.py +26 -0
- jarvis/jarvis_agent/user_interaction.py +42 -0
- jarvis/jarvis_code_agent/code_agent.py +18 -3
- jarvis/jarvis_code_agent/lint.py +5 -5
- jarvis/jarvis_code_analysis/code_review.py +0 -1
- jarvis/jarvis_data/config_schema.json +7 -6
- jarvis/jarvis_git_squash/main.py +6 -1
- jarvis/jarvis_git_utils/git_commiter.py +51 -16
- jarvis/jarvis_mcp/stdio_mcp_client.py +1 -1
- jarvis/jarvis_memory_organizer/memory_organizer.py +2 -5
- jarvis/jarvis_methodology/main.py +0 -2
- jarvis/jarvis_multi_agent/__init__.py +3 -3
- jarvis/jarvis_platform/base.py +5 -6
- jarvis/jarvis_platform/registry.py +1 -1
- jarvis/jarvis_platform/yuanbao.py +0 -1
- jarvis/jarvis_platform_manager/main.py +28 -11
- jarvis/jarvis_platform_manager/service.py +1 -1
- jarvis/jarvis_rag/cli.py +1 -1
- jarvis/jarvis_rag/embedding_manager.py +0 -1
- jarvis/jarvis_rag/llm_interface.py +0 -3
- jarvis/jarvis_smart_shell/main.py +0 -1
- jarvis/jarvis_stats/cli.py +15 -35
- jarvis/jarvis_stats/stats.py +178 -51
- jarvis/jarvis_tools/clear_memory.py +1 -3
- jarvis/jarvis_tools/cli/main.py +0 -1
- jarvis/jarvis_tools/edit_file.py +0 -1
- jarvis/jarvis_tools/generate_new_tool.py +3 -5
- jarvis/jarvis_tools/registry.py +17 -3
- jarvis/jarvis_tools/retrieve_memory.py +2 -3
- jarvis/jarvis_tools/save_memory.py +3 -3
- jarvis/jarvis_tools/search_web.py +2 -2
- jarvis/jarvis_tools/sub_agent.py +114 -85
- jarvis/jarvis_tools/sub_code_agent.py +29 -7
- jarvis/jarvis_tools/virtual_tty.py +3 -14
- jarvis/jarvis_utils/builtin_replace_map.py +4 -4
- jarvis/jarvis_utils/config.py +44 -15
- jarvis/jarvis_utils/fzf.py +56 -0
- jarvis/jarvis_utils/git_utils.py +1 -1
- jarvis/jarvis_utils/globals.py +1 -2
- jarvis/jarvis_utils/input.py +0 -3
- jarvis/jarvis_utils/methodology.py +3 -5
- jarvis/jarvis_utils/output.py +1 -1
- jarvis/jarvis_utils/utils.py +117 -27
- {jarvis_ai_assistant-0.3.26.dist-info → jarvis_ai_assistant-0.3.28.dist-info}/METADATA +2 -3
- {jarvis_ai_assistant-0.3.26.dist-info → jarvis_ai_assistant-0.3.28.dist-info}/RECORD +62 -56
- {jarvis_ai_assistant-0.3.26.dist-info → jarvis_ai_assistant-0.3.28.dist-info}/WHEEL +0 -0
- {jarvis_ai_assistant-0.3.26.dist-info → jarvis_ai_assistant-0.3.28.dist-info}/entry_points.txt +0 -0
- {jarvis_ai_assistant-0.3.26.dist-info → jarvis_ai_assistant-0.3.28.dist-info}/licenses/LICENSE +0 -0
- {jarvis_ai_assistant-0.3.26.dist-info → jarvis_ai_assistant-0.3.28.dist-info}/top_level.txt +0 -0
@@ -3,10 +3,9 @@
|
|
3
3
|
任务分析器模块
|
4
4
|
负责处理任务分析和方法论生成功能
|
5
5
|
"""
|
6
|
-
from typing import Optional
|
7
6
|
|
8
7
|
from jarvis.jarvis_utils.globals import get_interrupt, set_interrupt
|
9
|
-
|
8
|
+
|
10
9
|
from jarvis.jarvis_agent.prompts import TASK_ANALYSIS_PROMPT
|
11
10
|
from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
12
11
|
|
@@ -22,6 +21,12 @@ class TaskAnalyzer:
|
|
22
21
|
agent: Agent实例
|
23
22
|
"""
|
24
23
|
self.agent = agent
|
24
|
+
self._analysis_done = False
|
25
|
+
# 旁路集成事件订阅,失败不影响主流程
|
26
|
+
try:
|
27
|
+
self._subscribe_events()
|
28
|
+
except Exception:
|
29
|
+
pass
|
25
30
|
|
26
31
|
def analysis_task(self, satisfaction_feedback: str = ""):
|
27
32
|
"""分析任务并生成方法论"""
|
@@ -38,8 +43,15 @@ class TaskAnalyzer:
|
|
38
43
|
# 循环处理工具调用,直到没有工具调用为止
|
39
44
|
self._process_analysis_loop()
|
40
45
|
|
41
|
-
except Exception
|
46
|
+
except Exception:
|
42
47
|
PrettyOutput.print("分析失败", OutputType.ERROR)
|
48
|
+
finally:
|
49
|
+
# 标记已完成一次分析,避免事件回调重复执行
|
50
|
+
self._analysis_done = True
|
51
|
+
try:
|
52
|
+
self.agent.set_user_data("__task_analysis_done__", True)
|
53
|
+
except Exception:
|
54
|
+
pass
|
43
55
|
|
44
56
|
def _prepare_analysis_prompt(self, satisfaction_feedback: str) -> str:
|
45
57
|
"""准备分析提示"""
|
@@ -59,8 +71,27 @@ class TaskAnalyzer:
|
|
59
71
|
if not self._handle_analysis_interrupt(response):
|
60
72
|
break
|
61
73
|
|
62
|
-
#
|
63
|
-
|
74
|
+
# 执行工具调用(补充事件:before_tool_call/after_tool_call)
|
75
|
+
try:
|
76
|
+
self.agent.event_bus.emit(
|
77
|
+
"before_tool_call",
|
78
|
+
agent=self.agent,
|
79
|
+
current_response=response,
|
80
|
+
)
|
81
|
+
except Exception:
|
82
|
+
pass
|
83
|
+
need_return, tool_prompt = self.agent._call_tools(response)
|
84
|
+
self.agent.session.prompt = tool_prompt
|
85
|
+
try:
|
86
|
+
self.agent.event_bus.emit(
|
87
|
+
"after_tool_call",
|
88
|
+
agent=self.agent,
|
89
|
+
current_response=response,
|
90
|
+
need_return=need_return,
|
91
|
+
tool_prompt=tool_prompt,
|
92
|
+
)
|
93
|
+
except Exception:
|
94
|
+
pass
|
64
95
|
|
65
96
|
# 如果没有工具调用或者没有新的提示,退出循环
|
66
97
|
if not self.agent.session.prompt:
|
@@ -73,8 +104,8 @@ class TaskAnalyzer:
|
|
73
104
|
bool: True 继续分析,False 退出分析
|
74
105
|
"""
|
75
106
|
set_interrupt(False)
|
76
|
-
user_input = self.agent.
|
77
|
-
|
107
|
+
user_input = self.agent._multiline_input(
|
108
|
+
"分析任务期间被中断,请输入用户干预信息:", False
|
78
109
|
)
|
79
110
|
|
80
111
|
if not user_input:
|
@@ -98,7 +129,7 @@ class TaskAnalyzer:
|
|
98
129
|
|
99
130
|
def _handle_interrupt_with_tool_calls(self, user_input: str) -> str:
|
100
131
|
"""处理有工具调用时的中断"""
|
101
|
-
if user_confirm("检测到有工具调用,是否继续处理工具调用?", True):
|
132
|
+
if self.agent.user_confirm("检测到有工具调用,是否继续处理工具调用?", True):
|
102
133
|
return f"被用户中断,用户补充信息为:{user_input}\n\n用户同意继续工具调用。"
|
103
134
|
else:
|
104
135
|
return f"被用户中断,用户补充信息为:{user_input}\n\n检测到有工具调用,但被用户拒绝执行。请根据用户的补充信息重新考虑下一步操作。"
|
@@ -108,11 +139,11 @@ class TaskAnalyzer:
|
|
108
139
|
satisfaction_feedback = ""
|
109
140
|
|
110
141
|
if not auto_completed and self.agent.use_analysis:
|
111
|
-
if user_confirm("您对本次任务的完成是否满意?", True):
|
142
|
+
if self.agent.user_confirm("您对本次任务的完成是否满意?", True):
|
112
143
|
satisfaction_feedback = "\n\n用户对本次任务的完成表示满意。"
|
113
144
|
else:
|
114
|
-
feedback = self.agent.
|
115
|
-
"请提供您的反馈意见(可留空直接回车):"
|
145
|
+
feedback = self.agent._multiline_input(
|
146
|
+
"请提供您的反馈意见(可留空直接回车):", False
|
116
147
|
)
|
117
148
|
if feedback:
|
118
149
|
satisfaction_feedback = (
|
@@ -124,3 +155,50 @@ class TaskAnalyzer:
|
|
124
155
|
)
|
125
156
|
|
126
157
|
return satisfaction_feedback
|
158
|
+
|
159
|
+
# -----------------------
|
160
|
+
# 事件订阅与处理(旁路)
|
161
|
+
# -----------------------
|
162
|
+
def _subscribe_events(self) -> None:
|
163
|
+
bus = self.agent.get_event_bus() # type: ignore[attr-defined]
|
164
|
+
# 在生成总结前触发(保持与原顺序一致)
|
165
|
+
bus.subscribe("before_summary", self._on_before_summary)
|
166
|
+
# 当无需总结时,作为兜底触发分析
|
167
|
+
bus.subscribe("task_completed", self._on_task_completed)
|
168
|
+
|
169
|
+
def _on_before_summary(self, **payload) -> None:
|
170
|
+
if self._analysis_done:
|
171
|
+
return
|
172
|
+
# 避免与直接调用重复
|
173
|
+
try:
|
174
|
+
if bool(self.agent.get_user_data("__task_analysis_done__")):
|
175
|
+
self._analysis_done = True
|
176
|
+
return
|
177
|
+
except Exception:
|
178
|
+
pass
|
179
|
+
auto_completed = bool(payload.get("auto_completed", False))
|
180
|
+
try:
|
181
|
+
feedback = self.collect_satisfaction_feedback(auto_completed)
|
182
|
+
if getattr(self.agent, "use_analysis", False):
|
183
|
+
self.analysis_task(feedback)
|
184
|
+
except Exception:
|
185
|
+
# 忽略事件处理异常,保证主流程
|
186
|
+
self._analysis_done = True
|
187
|
+
|
188
|
+
def _on_task_completed(self, **payload) -> None:
|
189
|
+
# 当未在 before_summary 阶段执行过时,作为兜底
|
190
|
+
if self._analysis_done:
|
191
|
+
return
|
192
|
+
try:
|
193
|
+
if bool(self.agent.get_user_data("__task_analysis_done__")):
|
194
|
+
self._analysis_done = True
|
195
|
+
return
|
196
|
+
except Exception:
|
197
|
+
pass
|
198
|
+
auto_completed = bool(payload.get("auto_completed", False))
|
199
|
+
try:
|
200
|
+
feedback = self.collect_satisfaction_feedback(auto_completed)
|
201
|
+
if getattr(self.agent, "use_analysis", False):
|
202
|
+
self.analysis_task(feedback)
|
203
|
+
except Exception:
|
204
|
+
self._analysis_done = True
|
@@ -15,6 +15,7 @@ from jarvis.jarvis_agent import (
|
|
15
15
|
user_confirm,
|
16
16
|
)
|
17
17
|
from jarvis.jarvis_utils.config import get_data_dir
|
18
|
+
from jarvis.jarvis_utils.fzf import fzf_select
|
18
19
|
|
19
20
|
|
20
21
|
class TaskManager:
|
@@ -89,6 +90,31 @@ class TaskManager:
|
|
89
90
|
Console().print(table)
|
90
91
|
PrettyOutput.print("[0] 跳过预定义任务", OutputType.INFO)
|
91
92
|
|
93
|
+
# Try fzf selection first (with numbered options and a skip option)
|
94
|
+
fzf_list = [f"{0:>3} | 跳过预定义任务"] + [
|
95
|
+
f"{i:>3} | {name}" for i, name in enumerate(task_names, 1)
|
96
|
+
]
|
97
|
+
selected_str = fzf_select(fzf_list, prompt="选择一个任务编号 (ESC跳过) > ")
|
98
|
+
if selected_str:
|
99
|
+
try:
|
100
|
+
num_part = selected_str.split("|", 1)[0].strip()
|
101
|
+
idx = int(num_part)
|
102
|
+
if idx == 0:
|
103
|
+
return ""
|
104
|
+
if 1 <= idx <= len(task_names):
|
105
|
+
selected_task = tasks[task_names[idx - 1]]
|
106
|
+
PrettyOutput.print(f"将要执行任务:\n {selected_task}", OutputType.INFO)
|
107
|
+
# 询问是否需要补充信息
|
108
|
+
need_additional = user_confirm("需要为此任务添加补充信息吗?", default=False)
|
109
|
+
if need_additional:
|
110
|
+
additional_input = get_multiline_input("请输入补充信息:")
|
111
|
+
if additional_input:
|
112
|
+
selected_task = f"{selected_task}\n\n补充信息:\n{additional_input}"
|
113
|
+
return selected_task
|
114
|
+
except Exception:
|
115
|
+
# 如果解析失败,则回退到手动输入
|
116
|
+
pass
|
117
|
+
|
92
118
|
while True:
|
93
119
|
try:
|
94
120
|
choice_str = prompt(
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
"""
|
3
|
+
UserInteractionHandler: 抽象用户交互(多行输入与确认)逻辑,便于将来替换为 TUI/WebUI。
|
4
|
+
|
5
|
+
阶段一(最小变更):
|
6
|
+
- 仅提供封装,不直接修改 Agent 的现有调用
|
7
|
+
- 后续步骤在 Agent 中以旁路方式接入,保持向后兼容
|
8
|
+
"""
|
9
|
+
from typing import Callable
|
10
|
+
|
11
|
+
|
12
|
+
|
13
|
+
class UserInteractionHandler:
|
14
|
+
def __init__(
|
15
|
+
self,
|
16
|
+
multiline_inputer: Callable[..., str],
|
17
|
+
confirm_func: Callable[[str, bool], bool],
|
18
|
+
) -> None:
|
19
|
+
"""
|
20
|
+
参数:
|
21
|
+
- multiline_inputer: 提供多行输入的函数,优先支持 (tip, print_on_empty=bool),兼容仅接受 (tip) 的实现
|
22
|
+
- confirm_func: 用户确认函数 (tip: str, default: bool) -> bool
|
23
|
+
"""
|
24
|
+
self._multiline_inputer = multiline_inputer
|
25
|
+
self._confirm = confirm_func
|
26
|
+
|
27
|
+
def multiline_input(self, tip: str, print_on_empty: bool) -> str:
|
28
|
+
"""
|
29
|
+
多行输入封装:兼容两类签名
|
30
|
+
1) func(tip, print_on_empty=True/False)
|
31
|
+
2) func(tip)
|
32
|
+
"""
|
33
|
+
try:
|
34
|
+
return self._multiline_inputer(tip, print_on_empty=print_on_empty) # type: ignore[call-arg]
|
35
|
+
except TypeError:
|
36
|
+
return self._multiline_inputer(tip) # type: ignore[misc]
|
37
|
+
|
38
|
+
def confirm(self, tip: str, default: bool = True) -> bool:
|
39
|
+
"""
|
40
|
+
用户确认封装,直接委派
|
41
|
+
"""
|
42
|
+
return self._confirm(tip, default)
|
@@ -21,6 +21,7 @@ from jarvis.jarvis_tools.registry import ToolRegistry
|
|
21
21
|
from jarvis.jarvis_utils.config import (
|
22
22
|
is_confirm_before_apply_patch,
|
23
23
|
is_enable_static_analysis,
|
24
|
+
get_git_check_mode,
|
24
25
|
)
|
25
26
|
from jarvis.jarvis_utils.git_utils import (
|
26
27
|
confirm_add_new_files,
|
@@ -197,6 +198,17 @@ class CodeAgent:
|
|
197
198
|
missing_configs
|
198
199
|
)
|
199
200
|
PrettyOutput.print(message, OutputType.WARNING)
|
201
|
+
# 通过配置控制严格校验模式(JARVIS_GIT_CHECK_MODE):
|
202
|
+
# - warn: 仅告警并继续,后续提交可能失败
|
203
|
+
# - strict: 严格模式(默认),直接退出
|
204
|
+
mode = get_git_check_mode().lower()
|
205
|
+
if mode == "warn":
|
206
|
+
PrettyOutput.print(
|
207
|
+
"已启用 Git 校验警告模式(JARVIS_GIT_CHECK_MODE=warn),将继续运行。"
|
208
|
+
"注意:后续提交可能失败,请尽快配置 git user.name 与 user.email。",
|
209
|
+
OutputType.INFO,
|
210
|
+
)
|
211
|
+
return
|
200
212
|
sys.exit(1)
|
201
213
|
|
202
214
|
except FileNotFoundError:
|
@@ -250,7 +262,7 @@ class CodeAgent:
|
|
250
262
|
if has_uncommitted_changes():
|
251
263
|
|
252
264
|
git_commiter = GitCommitTool()
|
253
|
-
git_commiter.execute({"prefix": prefix, "suffix": suffix})
|
265
|
+
git_commiter.execute({"prefix": prefix, "suffix": suffix, "agent": self.agent, "model_group": getattr(self.agent.model, "model_group", None)})
|
254
266
|
|
255
267
|
def _init_env(self, prefix: str, suffix: str) -> None:
|
256
268
|
"""初始化环境,组合以下功能:
|
@@ -510,7 +522,7 @@ class CodeAgent:
|
|
510
522
|
check=True,
|
511
523
|
)
|
512
524
|
git_commiter = GitCommitTool()
|
513
|
-
git_commiter.execute({"prefix": prefix, "suffix": suffix})
|
525
|
+
git_commiter.execute({"prefix": prefix, "suffix": suffix, "agent": self.agent, "model_group": getattr(self.agent.model, "model_group", None)})
|
514
526
|
|
515
527
|
# 在用户接受commit后,根据配置决定是否保存记忆
|
516
528
|
if self.agent.force_save_memory:
|
@@ -544,7 +556,7 @@ class CodeAgent:
|
|
544
556
|
f"提交 {i+1}: {commit['hash'][:7]} - {commit['message']} ({len(commit['files'])}个文件)\n"
|
545
557
|
+ "\n".join(f" - {file}" for file in commit["files"][:5])
|
546
558
|
+ ("\n ..." if len(commit["files"]) > 5 else "")
|
547
|
-
for i, commit in enumerate(commits_info)
|
559
|
+
for i, commit in enumerate(commits_info[:5])
|
548
560
|
)
|
549
561
|
project_info.append(f"最近提交:\n{commits_str}")
|
550
562
|
|
@@ -575,6 +587,8 @@ class CodeAgent:
|
|
575
587
|
PrettyOutput.print(f"执行失败: {str(e)}", OutputType.WARNING)
|
576
588
|
return str(e)
|
577
589
|
|
590
|
+
|
591
|
+
|
578
592
|
self._handle_uncommitted_changes()
|
579
593
|
end_commit = get_latest_commit_hash()
|
580
594
|
commits = self._show_commit_history(start_commit, end_commit)
|
@@ -615,6 +629,7 @@ class CodeAgent:
|
|
615
629
|
|
616
630
|
StatsManager.increment("code_modifications", group="code_agent")
|
617
631
|
|
632
|
+
|
618
633
|
# 获取提交信息
|
619
634
|
end_hash = get_latest_commit_hash()
|
620
635
|
commits = get_commits_between(start_hash, end_hash)
|
jarvis/jarvis_code_agent/lint.py
CHANGED
@@ -27,11 +27,11 @@ LINT_TOOLS = {
|
|
27
27
|
# Go
|
28
28
|
".go": ["go vet"],
|
29
29
|
# Python
|
30
|
-
".py": ["
|
31
|
-
".pyw": ["
|
32
|
-
".pyi": ["
|
33
|
-
".pyx": ["
|
34
|
-
".pxd": ["
|
30
|
+
".py": ["ruff", "mypy"],
|
31
|
+
".pyw": ["ruff", "mypy"],
|
32
|
+
".pyi": ["ruff", "mypy"],
|
33
|
+
".pyx": ["ruff", "mypy"],
|
34
|
+
".pxd": ["ruff", "mypy"],
|
35
35
|
# Rust
|
36
36
|
".rs": ["cargo clippy", "rustfmt"],
|
37
37
|
".rlib": ["cargo clippy", "rustfmt"],
|
@@ -126,8 +126,6 @@
|
|
126
126
|
"description": "常规操作模型名称",
|
127
127
|
"default": "deep_seek_v3"
|
128
128
|
},
|
129
|
-
|
130
|
-
|
131
129
|
"JARVIS_WEB_SEARCH_PLATFORM": {
|
132
130
|
"type": "string",
|
133
131
|
"description": "Web搜索使用的平台名称",
|
@@ -160,8 +158,6 @@
|
|
160
158
|
"type": "string",
|
161
159
|
"default": "deep_seek_v3"
|
162
160
|
},
|
163
|
-
|
164
|
-
|
165
161
|
"JARVIS_MAX_INPUT_TOKEN_COUNT": {
|
166
162
|
"type": "number",
|
167
163
|
"default": 32000
|
@@ -196,7 +192,6 @@
|
|
196
192
|
"description": "Jarvis数据存储目录路径",
|
197
193
|
"default": "~/.jarvis"
|
198
194
|
},
|
199
|
-
|
200
195
|
"JARVIS_PRETTY_OUTPUT": {
|
201
196
|
"type": "boolean",
|
202
197
|
"description": "是否启用美化输出",
|
@@ -292,6 +287,12 @@
|
|
292
287
|
"description": "是否启用立即中断:在对话迭代中检测到中断信号时立即返回",
|
293
288
|
"default": false
|
294
289
|
},
|
290
|
+
"JARVIS_GIT_CHECK_MODE": {
|
291
|
+
"type": "string",
|
292
|
+
"enum": ["strict", "warn"],
|
293
|
+
"description": "Git 配置校验模式:strict 表示严格模式(默认),缺失配置时直接退出;warn 表示警告模式,仅提示并继续运行",
|
294
|
+
"default": "strict"
|
295
|
+
},
|
295
296
|
"JARVIS_TOOL_GROUP": {
|
296
297
|
"type": "string",
|
297
298
|
"description": "选择一个预定义的工具配置组",
|
@@ -445,4 +446,4 @@
|
|
445
446
|
}
|
446
447
|
},
|
447
448
|
"additionalProperties": true
|
448
|
-
}
|
449
|
+
}
|
jarvis/jarvis_git_squash/main.py
CHANGED
@@ -8,6 +8,7 @@ from jarvis.jarvis_git_utils.git_commiter import GitCommitTool
|
|
8
8
|
from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
9
9
|
from jarvis.jarvis_utils.utils import init_env
|
10
10
|
from jarvis.jarvis_utils.input import user_confirm
|
11
|
+
from jarvis.jarvis_utils.globals import get_agent, current_agent_name
|
11
12
|
|
12
13
|
app = typer.Typer(help="Git压缩工具")
|
13
14
|
|
@@ -46,7 +47,11 @@ class GitSquashTool:
|
|
46
47
|
|
47
48
|
# Use existing GitCommitTool for new commit
|
48
49
|
commit_tool = GitCommitTool()
|
49
|
-
|
50
|
+
agent = get_agent(current_agent_name)
|
51
|
+
exec_args = {"lang": args.get("lang", "Chinese")}
|
52
|
+
if agent:
|
53
|
+
exec_args["agent"] = agent
|
54
|
+
commit_tool.execute(exec_args)
|
50
55
|
except Exception as e:
|
51
56
|
PrettyOutput.print(f"压缩提交失败: {str(e)}", OutputType.WARNING)
|
52
57
|
|
@@ -2,7 +2,6 @@
|
|
2
2
|
import os
|
3
3
|
import re
|
4
4
|
import subprocess
|
5
|
-
import sys
|
6
5
|
import tempfile
|
7
6
|
from typing import Any, Dict, Optional
|
8
7
|
|
@@ -138,7 +137,7 @@ class GitCommitTool:
|
|
138
137
|
base_prompt = (
|
139
138
|
custom_prompt
|
140
139
|
if custom_prompt
|
141
|
-
else
|
140
|
+
else """根据代码差异生成提交信息:
|
142
141
|
提交信息应使用中文书写
|
143
142
|
# 格式模板
|
144
143
|
必须使用以下格式:
|
@@ -163,6 +162,9 @@ commit信息
|
|
163
162
|
{ct("COMMIT_MESSAGE")}
|
164
163
|
"""
|
165
164
|
|
165
|
+
# 优先从调用方传入的 agent 获取平台与模型
|
166
|
+
agent_from_args = args.get("agent")
|
167
|
+
|
166
168
|
# Get model_group from args
|
167
169
|
model_group = args.get("model_group")
|
168
170
|
|
@@ -172,32 +174,65 @@ commit信息
|
|
172
174
|
get_normal_model_name,
|
173
175
|
)
|
174
176
|
|
175
|
-
platform_name =
|
176
|
-
model_name =
|
177
|
+
platform_name = None
|
178
|
+
model_name = None
|
177
179
|
|
178
|
-
# If no explicit parameters, try to get from existing agent
|
179
|
-
agent = get_agent(current_agent_name)
|
180
180
|
if (
|
181
|
-
|
182
|
-
and
|
183
|
-
and
|
184
|
-
and agent.model
|
181
|
+
agent_from_args
|
182
|
+
and hasattr(agent_from_args, "model")
|
183
|
+
and getattr(agent_from_args, "model", None)
|
185
184
|
):
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
model_group
|
185
|
+
try:
|
186
|
+
platform_name = agent_from_args.model.platform_name()
|
187
|
+
model_name = agent_from_args.model.name()
|
188
|
+
if not model_group and hasattr(
|
189
|
+
agent_from_args.model, "model_group"
|
190
|
+
):
|
191
|
+
model_group = agent_from_args.model.model_group
|
192
|
+
except Exception:
|
193
|
+
# 安全回退到后续逻辑
|
194
|
+
platform_name = None
|
195
|
+
model_name = None
|
196
|
+
|
197
|
+
# 如果未能从agent获取到,再根据 model_group 获取
|
198
|
+
if not platform_name:
|
199
|
+
platform_name = get_normal_platform_name(model_group)
|
200
|
+
if not model_name:
|
201
|
+
model_name = get_normal_model_name(model_group)
|
202
|
+
|
203
|
+
# If no explicit parameters, try to get from existing global agent
|
204
|
+
if not platform_name:
|
205
|
+
agent = get_agent(current_agent_name)
|
206
|
+
if (
|
207
|
+
agent
|
208
|
+
and hasattr(agent, "model")
|
209
|
+
and getattr(agent, "model", None)
|
210
|
+
):
|
211
|
+
platform_name = agent.model.platform_name()
|
212
|
+
model_name = agent.model.name()
|
213
|
+
if not model_group and hasattr(agent.model, "model_group"):
|
214
|
+
model_group = agent.model.model_group
|
190
215
|
|
191
216
|
# Create a new platform instance
|
192
217
|
if platform_name:
|
193
218
|
platform = PlatformRegistry().create_platform(platform_name)
|
194
219
|
if platform and model_name:
|
195
220
|
platform.set_model_name(model_name)
|
196
|
-
|
197
|
-
|
221
|
+
if platform and model_group:
|
222
|
+
try:
|
223
|
+
platform.set_model_group(model_group)
|
224
|
+
except Exception:
|
225
|
+
# 兼容早期实现
|
226
|
+
platform.model_group = model_group # type: ignore
|
198
227
|
else:
|
199
228
|
platform = PlatformRegistry().get_normal_platform()
|
200
229
|
|
230
|
+
# 跳过模型可用性校验:
|
231
|
+
# 为避免某些平台/代理不支持 get_model_list 接口导致的噪音日志(如 404),
|
232
|
+
# 这里默认不调用 platform.get_model_list() 进行模型可用性校验。
|
233
|
+
# 如果未来需要恢复校验,可参考被移除的逻辑。
|
234
|
+
# no-op
|
235
|
+
|
201
236
|
# Ensure platform is not None
|
202
237
|
if not platform:
|
203
238
|
return {
|
@@ -7,14 +7,11 @@
|
|
7
7
|
"""
|
8
8
|
|
9
9
|
import json
|
10
|
-
import sys
|
11
10
|
from collections import defaultdict
|
12
|
-
from itertools import combinations
|
13
11
|
from pathlib import Path
|
14
|
-
from typing import Dict, List, Set,
|
12
|
+
from typing import Dict, List, Set, Any, Optional
|
15
13
|
|
16
14
|
import typer
|
17
|
-
import yaml
|
18
15
|
|
19
16
|
from jarvis.jarvis_utils.config import (
|
20
17
|
get_data_dir,
|
@@ -311,7 +308,7 @@ tags:
|
|
311
308
|
group_memories = [memories[i] for i in original_indices]
|
312
309
|
|
313
310
|
# 显示将要合并的记忆(先拼接后统一打印,避免循环逐条输出)
|
314
|
-
lines = [
|
311
|
+
lines = ["", f"准备合并 {len(group_memories)} 个记忆:"]
|
315
312
|
for mem in group_memories:
|
316
313
|
lines.append(
|
317
314
|
f" - ID: {mem.get('id', '未知')}, "
|
@@ -73,7 +73,7 @@ content: |2
|
|
73
73
|
if len(send_messages) > 1:
|
74
74
|
return (
|
75
75
|
False,
|
76
|
-
|
76
|
+
"Send multiple messages, please only send one message at a time.",
|
77
77
|
)
|
78
78
|
if len(send_messages) == 0:
|
79
79
|
return False, ""
|
@@ -100,7 +100,7 @@ content: |2
|
|
100
100
|
msg = yaml.safe_load(item)
|
101
101
|
if "to" in msg and "content" in msg:
|
102
102
|
ret.append(msg)
|
103
|
-
except Exception
|
103
|
+
except Exception:
|
104
104
|
continue
|
105
105
|
return ret
|
106
106
|
|
@@ -161,7 +161,7 @@ content: {msg['content']}
|
|
161
161
|
"""
|
162
162
|
to_agent_name = msg.get("to")
|
163
163
|
if not to_agent_name:
|
164
|
-
return
|
164
|
+
return "消息中未指定 `to` 字段"
|
165
165
|
|
166
166
|
if to_agent_name not in self.agents_config_map:
|
167
167
|
PrettyOutput.print(
|
jarvis/jarvis_platform/base.py
CHANGED
@@ -88,7 +88,7 @@ class BasePlatform(ABC):
|
|
88
88
|
PrettyOutput.print(
|
89
89
|
f"长上下文,分批提交,共{len(inputs)}部分...", OutputType.INFO
|
90
90
|
)
|
91
|
-
prefix_prompt =
|
91
|
+
prefix_prompt = """
|
92
92
|
我将分多次提供大量内容,在我明确告诉你内容已经全部提供完毕之前,每次仅需要输出"已收到",明白请输出"开始接收输入"。
|
93
93
|
"""
|
94
94
|
while_true(lambda: while_success(lambda: self._chat(prefix_prompt), 5), 5)
|
@@ -188,12 +188,11 @@ class BasePlatform(ABC):
|
|
188
188
|
|
189
189
|
# If content overflows, truncate to show only the last few lines
|
190
190
|
if len(lines) > max_text_height:
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
]
|
191
|
+
# Rebuild the text from the wrapped lines to ensure visual consistency
|
192
|
+
# This correctly handles both wrapped long lines and explicit newlines
|
193
|
+
text_content.plain = "\n".join(
|
194
|
+
[line.plain for line in lines[-max_text_height:]]
|
195
195
|
)
|
196
|
-
text_content.plain = new_text
|
197
196
|
|
198
197
|
panel.subtitle = (
|
199
198
|
"[yellow]正在回答... (按 Ctrl+C 中断)[/yellow]"
|
@@ -69,7 +69,6 @@ class YuanbaoPlatform(BasePlatform):
|
|
69
69
|
"X-Requested-With": "XMLHttpRequest",
|
70
70
|
"chat_version": "v1",
|
71
71
|
"X-Instance-ID": "5",
|
72
|
-
"X-Requested-With": "XMLHttpRequest",
|
73
72
|
"Accept": "application/json, text/plain, */*",
|
74
73
|
"Content-Type": "application/json",
|
75
74
|
"sec-ch-ua-mobile": "?0",
|