jarvis-ai-assistant 0.1.177__py3-none-any.whl → 0.1.179__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.
Potentially problematic release.
This version of jarvis-ai-assistant might be problematic. Click here for more details.
- jarvis/__init__.py +1 -1
- jarvis/jarvis_agent/__init__.py +145 -125
- jarvis/jarvis_agent/builtin_input_handler.py +1 -1
- jarvis/jarvis_agent/jarvis.py +9 -13
- jarvis/jarvis_agent/main.py +4 -2
- jarvis/jarvis_code_agent/code_agent.py +34 -23
- jarvis/jarvis_code_agent/lint.py +164 -0
- jarvis/jarvis_code_analysis/checklists/loader.py +6 -20
- jarvis/jarvis_code_analysis/code_review.py +8 -6
- jarvis/jarvis_dev/main.py +1 -8
- jarvis/jarvis_event/__init__.py +0 -0
- jarvis/jarvis_git_details/main.py +1 -1
- jarvis/jarvis_git_squash/main.py +5 -3
- jarvis/jarvis_git_utils/git_commiter.py +24 -23
- jarvis/jarvis_mcp/sse_mcp_client.py +6 -4
- jarvis/jarvis_mcp/stdio_mcp_client.py +5 -4
- jarvis/jarvis_mcp/streamable_mcp_client.py +404 -0
- jarvis/jarvis_methodology/main.py +10 -9
- jarvis/jarvis_multi_agent/main.py +3 -1
- jarvis/jarvis_platform/base.py +14 -8
- jarvis/jarvis_platform/human.py +3 -1
- jarvis/jarvis_platform/kimi.py +10 -7
- jarvis/jarvis_platform/openai.py +70 -11
- jarvis/jarvis_platform/registry.py +6 -2
- jarvis/jarvis_platform/yuanbao.py +13 -10
- jarvis/jarvis_platform_manager/main.py +11 -9
- jarvis/jarvis_smart_shell/main.py +1 -0
- jarvis/jarvis_tools/ask_codebase.py +6 -4
- jarvis/jarvis_tools/ask_user.py +2 -1
- jarvis/jarvis_tools/base.py +3 -1
- jarvis/jarvis_tools/chdir.py +2 -1
- jarvis/jarvis_tools/cli/main.py +1 -0
- jarvis/jarvis_tools/code_plan.py +5 -3
- jarvis/jarvis_tools/create_code_agent.py +5 -2
- jarvis/jarvis_tools/create_sub_agent.py +1 -3
- jarvis/jarvis_tools/edit_file.py +37 -29
- jarvis/jarvis_tools/execute_script.py +1 -1
- jarvis/jarvis_tools/file_analyzer.py +5 -3
- jarvis/jarvis_tools/file_operation.py +4 -7
- jarvis/jarvis_tools/find_methodology.py +4 -2
- jarvis/jarvis_tools/generate_new_tool.py +2 -1
- jarvis/jarvis_tools/methodology.py +3 -4
- jarvis/jarvis_tools/read_code.py +2 -1
- jarvis/jarvis_tools/read_webpage.py +3 -1
- jarvis/jarvis_tools/registry.py +23 -14
- jarvis/jarvis_tools/rewrite_file.py +2 -1
- jarvis/jarvis_tools/search_web.py +1 -0
- jarvis/jarvis_tools/virtual_tty.py +5 -4
- jarvis/jarvis_utils/__init__.py +2 -0
- jarvis/jarvis_utils/builtin_replace_map.py +1 -1
- jarvis/jarvis_utils/config.py +40 -1
- jarvis/jarvis_utils/embedding.py +4 -3
- jarvis/jarvis_utils/file_processors.py +1 -0
- jarvis/jarvis_utils/git_utils.py +55 -25
- jarvis/jarvis_utils/globals.py +4 -2
- jarvis/jarvis_utils/input.py +14 -7
- jarvis/jarvis_utils/methodology.py +6 -4
- jarvis/jarvis_utils/output.py +10 -6
- jarvis/jarvis_utils/utils.py +89 -13
- {jarvis_ai_assistant-0.1.177.dist-info → jarvis_ai_assistant-0.1.179.dist-info}/METADATA +45 -33
- jarvis_ai_assistant-0.1.179.dist-info/RECORD +98 -0
- jarvis/jarvis_lsp/base.py +0 -66
- jarvis/jarvis_lsp/cpp.py +0 -99
- jarvis/jarvis_lsp/go.py +0 -104
- jarvis/jarvis_lsp/python.py +0 -58
- jarvis/jarvis_lsp/registry.py +0 -169
- jarvis/jarvis_lsp/rust.py +0 -107
- jarvis/jarvis_tools/lsp_get_diagnostics.py +0 -147
- jarvis_ai_assistant-0.1.177.dist-info/RECORD +0 -102
- {jarvis_ai_assistant-0.1.177.dist-info → jarvis_ai_assistant-0.1.179.dist-info}/WHEEL +0 -0
- {jarvis_ai_assistant-0.1.177.dist-info → jarvis_ai_assistant-0.1.179.dist-info}/entry_points.txt +0 -0
- {jarvis_ai_assistant-0.1.177.dist-info → jarvis_ai_assistant-0.1.179.dist-info}/licenses/LICENSE +0 -0
- {jarvis_ai_assistant-0.1.177.dist-info → jarvis_ai_assistant-0.1.179.dist-info}/top_level.txt +0 -0
jarvis/__init__.py
CHANGED
jarvis/jarvis_agent/__init__.py
CHANGED
|
@@ -1,26 +1,33 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
|
+
# 标准库导入
|
|
2
3
|
import datetime
|
|
3
4
|
import platform
|
|
4
|
-
from typing import Any, Callable, List, Optional, Tuple, Union
|
|
5
|
+
from typing import Any, Callable, List, Optional, Protocol, Tuple, Union
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
# 第三方库导入
|
|
8
|
+
from yaspin import yaspin # type: ignore
|
|
7
9
|
|
|
8
|
-
|
|
10
|
+
# 本地库导入
|
|
11
|
+
# jarvis_agent 相关
|
|
12
|
+
# jarvis_platform 相关
|
|
9
13
|
from jarvis.jarvis_platform.base import BasePlatform
|
|
10
14
|
from jarvis.jarvis_platform.registry import PlatformRegistry
|
|
11
|
-
|
|
15
|
+
# jarvis_utils 相关
|
|
16
|
+
from jarvis.jarvis_utils.config import (get_max_token_count,
|
|
17
|
+
get_max_tool_call_count,
|
|
18
|
+
is_auto_complete,
|
|
19
|
+
is_execute_tool_confirm,
|
|
20
|
+
is_use_analysis, is_use_methodology)
|
|
12
21
|
from jarvis.jarvis_utils.embedding import get_context_token_count
|
|
13
|
-
from jarvis.jarvis_utils.
|
|
14
|
-
|
|
15
|
-
from jarvis.jarvis_utils.globals import make_agent_name, set_agent, delete_agent
|
|
22
|
+
from jarvis.jarvis_utils.globals import (delete_agent, make_agent_name,
|
|
23
|
+
set_agent)
|
|
16
24
|
from jarvis.jarvis_utils.input import get_multiline_input
|
|
17
|
-
from jarvis.jarvis_utils.
|
|
25
|
+
from jarvis.jarvis_utils.methodology import (load_methodology,
|
|
26
|
+
upload_methodology)
|
|
27
|
+
from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
|
18
28
|
from jarvis.jarvis_utils.tag import ct, ot
|
|
19
29
|
from jarvis.jarvis_utils.utils import user_confirm
|
|
20
30
|
|
|
21
|
-
from jarvis.jarvis_platform.registry import PlatformRegistry
|
|
22
|
-
|
|
23
|
-
|
|
24
31
|
origin_agent_system_prompt = f"""
|
|
25
32
|
<role>
|
|
26
33
|
# 🤖 角色
|
|
@@ -105,14 +112,20 @@ origin_agent_system_prompt = f"""
|
|
|
105
112
|
|
|
106
113
|
|
|
107
114
|
class OutputHandlerProtocol(Protocol):
|
|
108
|
-
def name(self) -> str:
|
|
109
|
-
|
|
110
|
-
def prompt(self) -> str: ...
|
|
111
|
-
def handle(self, response: str, agent: Any) -> Tuple[bool, Any]: ...
|
|
115
|
+
def name(self) -> str:
|
|
116
|
+
...
|
|
112
117
|
|
|
118
|
+
def can_handle(self, response: str) -> bool:
|
|
119
|
+
...
|
|
113
120
|
|
|
114
|
-
|
|
121
|
+
def prompt(self) -> str:
|
|
122
|
+
...
|
|
115
123
|
|
|
124
|
+
def handle(self, response: str, agent: Any) -> Tuple[bool, Any]:
|
|
125
|
+
...
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
class Agent:
|
|
116
129
|
def set_summary_prompt(self, summary_prompt: str):
|
|
117
130
|
"""设置任务完成时的总结提示模板。
|
|
118
131
|
|
|
@@ -129,28 +142,31 @@ class Agent:
|
|
|
129
142
|
2. 重置对话长度计数器
|
|
130
143
|
3. 清空当前提示
|
|
131
144
|
"""
|
|
132
|
-
self.model.reset()
|
|
145
|
+
self.model.reset() # type: ignore
|
|
133
146
|
self.conversation_length = 0
|
|
134
147
|
self.prompt = ""
|
|
135
148
|
|
|
136
149
|
def __del__(self):
|
|
137
150
|
delete_agent(self.name)
|
|
138
151
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
152
|
+
def __init__(
|
|
153
|
+
self,
|
|
154
|
+
system_prompt: str,
|
|
155
|
+
name: str = "Jarvis",
|
|
156
|
+
description: str = "",
|
|
157
|
+
platform: Union[Optional[BasePlatform], Optional[str]] = None,
|
|
158
|
+
model_name: Optional[str] = None,
|
|
159
|
+
summary_prompt: Optional[str] = None,
|
|
160
|
+
auto_complete: Optional[bool] = None,
|
|
161
|
+
output_handler: List[OutputHandlerProtocol] = [],
|
|
162
|
+
use_tools: List[str] = [],
|
|
163
|
+
input_handler: Optional[List[Callable[[str, Any], Tuple[str, bool]]]] = None,
|
|
164
|
+
execute_tool_confirm: Optional[bool] = None,
|
|
165
|
+
need_summary: bool = True,
|
|
166
|
+
multiline_inputer: Optional[Callable[[str], str]] = None,
|
|
167
|
+
use_methodology: Optional[bool] = None,
|
|
168
|
+
use_analysis: Optional[bool] = None,
|
|
169
|
+
):
|
|
154
170
|
"""初始化Jarvis Agent实例
|
|
155
171
|
|
|
156
172
|
参数:
|
|
@@ -167,6 +183,8 @@ class Agent:
|
|
|
167
183
|
execute_tool_confirm: 执行工具前是否需要确认
|
|
168
184
|
need_summary: 是否需要生成总结
|
|
169
185
|
multiline_inputer: 多行输入处理器
|
|
186
|
+
use_methodology: 是否使用方法论
|
|
187
|
+
use_analysis: 是否使用任务分析
|
|
170
188
|
"""
|
|
171
189
|
self.name = make_agent_name(name)
|
|
172
190
|
self.description = description
|
|
@@ -180,7 +198,9 @@ class Agent:
|
|
|
180
198
|
else:
|
|
181
199
|
self.model = platform
|
|
182
200
|
else:
|
|
183
|
-
self.model =
|
|
201
|
+
self.model = (
|
|
202
|
+
PlatformRegistry.get_global_platform_registry().get_normal_platform()
|
|
203
|
+
)
|
|
184
204
|
|
|
185
205
|
if model_name is not None:
|
|
186
206
|
self.model.set_model_name(model_name)
|
|
@@ -188,11 +208,20 @@ class Agent:
|
|
|
188
208
|
self.model.set_suppress_output(False)
|
|
189
209
|
|
|
190
210
|
from jarvis.jarvis_tools.registry import ToolRegistry
|
|
211
|
+
|
|
191
212
|
self.output_handler = output_handler if output_handler else [ToolRegistry()]
|
|
192
213
|
self.set_use_tools(use_tools)
|
|
193
214
|
|
|
194
|
-
self.multiline_inputer =
|
|
215
|
+
self.multiline_inputer = (
|
|
216
|
+
multiline_inputer if multiline_inputer else get_multiline_input
|
|
217
|
+
)
|
|
195
218
|
|
|
219
|
+
self.use_methodology = (
|
|
220
|
+
use_methodology if use_methodology is not None else is_use_methodology()
|
|
221
|
+
)
|
|
222
|
+
self.use_analysis = (
|
|
223
|
+
use_analysis if use_analysis is not None else is_use_analysis()
|
|
224
|
+
)
|
|
196
225
|
self.prompt = ""
|
|
197
226
|
self.conversation_length = 0 # Use length counter instead
|
|
198
227
|
self.system_prompt = system_prompt
|
|
@@ -205,10 +234,16 @@ class Agent:
|
|
|
205
234
|
self.max_tool_call_count = get_max_tool_call_count()
|
|
206
235
|
self.after_tool_call_cb: Optional[Callable[[Agent], None]] = None
|
|
207
236
|
|
|
237
|
+
self.execute_tool_confirm = (
|
|
238
|
+
execute_tool_confirm
|
|
239
|
+
if execute_tool_confirm is not None
|
|
240
|
+
else is_execute_tool_confirm()
|
|
241
|
+
)
|
|
208
242
|
|
|
209
|
-
self.
|
|
210
|
-
|
|
211
|
-
|
|
243
|
+
self.summary_prompt = (
|
|
244
|
+
summary_prompt
|
|
245
|
+
if summary_prompt
|
|
246
|
+
else f"""<report>
|
|
212
247
|
请生成任务执行的简明总结报告,包括:
|
|
213
248
|
|
|
214
249
|
<content>
|
|
@@ -224,9 +259,12 @@ class Agent:
|
|
|
224
259
|
</format>
|
|
225
260
|
</report>
|
|
226
261
|
"""
|
|
262
|
+
)
|
|
227
263
|
|
|
228
|
-
self.max_token_count =
|
|
229
|
-
self.auto_complete =
|
|
264
|
+
self.max_token_count = get_max_token_count()
|
|
265
|
+
self.auto_complete = (
|
|
266
|
+
auto_complete if auto_complete is not None else is_auto_complete()
|
|
267
|
+
)
|
|
230
268
|
welcome_message = f"{name} 初始化完成 - 使用 {self.model.name()} 模型"
|
|
231
269
|
|
|
232
270
|
PrettyOutput.print(welcome_message, OutputType.SYSTEM)
|
|
@@ -239,7 +277,9 @@ class Agent:
|
|
|
239
277
|
|
|
240
278
|
# 添加工具列表概览
|
|
241
279
|
action_prompt += "\n<overview>\n## Action List\n"
|
|
242
|
-
action_prompt +=
|
|
280
|
+
action_prompt += (
|
|
281
|
+
"[" + ", ".join([handler.name() for handler in self.output_handler]) + "]"
|
|
282
|
+
)
|
|
243
283
|
action_prompt += "\n</overview>"
|
|
244
284
|
|
|
245
285
|
# 添加每个工具的详细说明
|
|
@@ -249,8 +289,10 @@ class Agent:
|
|
|
249
289
|
# 获取工具的提示词并确保格式正确
|
|
250
290
|
handler_prompt = handler.prompt().strip()
|
|
251
291
|
# 调整缩进以保持层级结构
|
|
252
|
-
handler_prompt = "\n".join(
|
|
253
|
-
|
|
292
|
+
handler_prompt = "\n".join(
|
|
293
|
+
" " + line if line.strip() else line
|
|
294
|
+
for line in handler_prompt.split("\n")
|
|
295
|
+
)
|
|
254
296
|
action_prompt += handler_prompt + "\n</tool>\n"
|
|
255
297
|
|
|
256
298
|
# 添加工具使用总结
|
|
@@ -268,40 +310,25 @@ class Agent:
|
|
|
268
310
|
</actions>
|
|
269
311
|
"""
|
|
270
312
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
complete_prompt = f"""
|
|
274
|
-
<completion>
|
|
275
|
-
<instruction>
|
|
276
|
-
## 任务完成
|
|
277
|
-
当任务完成时,你应该打印以下信息:
|
|
278
|
-
</instruction>
|
|
279
|
-
|
|
280
|
-
<marker>
|
|
281
|
-
{ot("!!!COMPLETE!!!")}
|
|
282
|
-
</marker>
|
|
283
|
-
</completion>
|
|
284
|
-
"""
|
|
285
|
-
|
|
286
|
-
self.model.set_system_message(f"""
|
|
313
|
+
self.model.set_system_message(
|
|
314
|
+
f"""
|
|
287
315
|
{self.system_prompt}
|
|
288
316
|
|
|
289
317
|
{action_prompt}
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
""")
|
|
318
|
+
"""
|
|
319
|
+
)
|
|
293
320
|
self.first = True
|
|
294
321
|
|
|
295
322
|
def set_use_tools(self, use_tools):
|
|
296
323
|
"""设置要使用的工具列表"""
|
|
297
324
|
from jarvis.jarvis_tools.registry import ToolRegistry
|
|
325
|
+
|
|
298
326
|
for handler in self.output_handler:
|
|
299
327
|
if isinstance(handler, ToolRegistry):
|
|
300
328
|
if use_tools:
|
|
301
329
|
handler.use_tools(use_tools)
|
|
302
330
|
break
|
|
303
331
|
|
|
304
|
-
|
|
305
332
|
def set_addon_prompt(self, addon_prompt: str):
|
|
306
333
|
"""设置附加提示。
|
|
307
334
|
|
|
@@ -310,7 +337,7 @@ class Agent:
|
|
|
310
337
|
"""
|
|
311
338
|
self.addon_prompt = addon_prompt
|
|
312
339
|
|
|
313
|
-
def set_after_tool_call_cb(self, cb: Callable[[Any], None]):
|
|
340
|
+
def set_after_tool_call_cb(self, cb: Callable[[Any], None]): # type: ignore
|
|
314
341
|
"""设置工具调用后回调函数。
|
|
315
342
|
|
|
316
343
|
参数:
|
|
@@ -321,6 +348,7 @@ class Agent:
|
|
|
321
348
|
def get_tool_registry(self) -> Optional[Any]:
|
|
322
349
|
"""获取工具注册表实例"""
|
|
323
350
|
from jarvis.jarvis_tools.registry import ToolRegistry
|
|
351
|
+
|
|
324
352
|
for handler in self.output_handler:
|
|
325
353
|
if isinstance(handler, ToolRegistry):
|
|
326
354
|
return handler
|
|
@@ -334,22 +362,25 @@ class Agent:
|
|
|
334
362
|
|
|
335
363
|
"""
|
|
336
364
|
# 结构化系统指令
|
|
337
|
-
action_handlers =
|
|
365
|
+
action_handlers = ", ".join([handler.name() for handler in self.output_handler])
|
|
338
366
|
|
|
339
367
|
# 任务完成提示
|
|
340
|
-
complete_prompt =
|
|
368
|
+
complete_prompt = (
|
|
369
|
+
f"- 输出{ot('!!!COMPLETE!!!')}"
|
|
370
|
+
if need_complete and self.auto_complete
|
|
371
|
+
else ""
|
|
372
|
+
)
|
|
341
373
|
|
|
342
374
|
addon_prompt = f"""
|
|
343
375
|
[系统提示开始]
|
|
344
376
|
请判断是否已经完成任务,如果已经完成:
|
|
345
|
-
-
|
|
377
|
+
- 直接输出完成原因,不需要再有新的操作,不要输出{ot("TOOL_CALL")}标签
|
|
346
378
|
{complete_prompt}
|
|
347
379
|
如果没有完成,请进行下一步操作:
|
|
348
380
|
- 仅包含一个操作
|
|
349
381
|
- 如果信息不明确,请请求用户补充
|
|
350
382
|
- 如果执行过程中连续失败5次,请使用ask_user询问用户操作
|
|
351
|
-
- 操作列表:
|
|
352
|
-
{action_handlers}
|
|
383
|
+
- 操作列表:{action_handlers}
|
|
353
384
|
[系统提示结束]
|
|
354
385
|
|
|
355
386
|
请继续。
|
|
@@ -390,8 +421,7 @@ class Agent:
|
|
|
390
421
|
if self.conversation_length > self.max_token_count:
|
|
391
422
|
message = self._summarize_and_clear_history() + "\n\n" + message
|
|
392
423
|
self.conversation_length += get_context_token_count(message)
|
|
393
|
-
return self.model.chat_until_success(message)
|
|
394
|
-
|
|
424
|
+
return self.model.chat_until_success(message) # type: ignore
|
|
395
425
|
|
|
396
426
|
def _summarize_and_clear_history(self) -> str:
|
|
397
427
|
"""总结当前对话并清理历史记录
|
|
@@ -412,7 +442,6 @@ class Agent:
|
|
|
412
442
|
# Create a new model instance to summarize, avoid affecting the main conversation
|
|
413
443
|
|
|
414
444
|
with yaspin(text="正在总结对话历史...", color="cyan") as spinner:
|
|
415
|
-
|
|
416
445
|
summary_prompt = """
|
|
417
446
|
<summary_request>
|
|
418
447
|
<objective>
|
|
@@ -438,9 +467,9 @@ class Agent:
|
|
|
438
467
|
|
|
439
468
|
try:
|
|
440
469
|
with spinner.hidden():
|
|
441
|
-
summary = self.model.chat_until_success(self.prompt + "\n" + summary_prompt)
|
|
470
|
+
summary = self.model.chat_until_success(self.prompt + "\n" + summary_prompt) # type: ignore
|
|
442
471
|
|
|
443
|
-
self.model.reset()
|
|
472
|
+
self.model.reset() # type: ignore
|
|
444
473
|
|
|
445
474
|
# 清空当前对话历史,但保留系统消息
|
|
446
475
|
self.conversation_length = 0 # Reset conversation length
|
|
@@ -448,7 +477,7 @@ class Agent:
|
|
|
448
477
|
# 添加总结作为新的上下文
|
|
449
478
|
spinner.text = "总结对话历史完成"
|
|
450
479
|
spinner.ok("✅")
|
|
451
|
-
return
|
|
480
|
+
return f"""<summary>
|
|
452
481
|
<header>
|
|
453
482
|
以下是之前对话的关键信息总结:
|
|
454
483
|
</header>
|
|
@@ -488,18 +517,29 @@ class Agent:
|
|
|
488
517
|
if handler.can_handle(response):
|
|
489
518
|
tool_list.append(handler)
|
|
490
519
|
if len(tool_list) > 1:
|
|
491
|
-
PrettyOutput.print(
|
|
492
|
-
|
|
520
|
+
PrettyOutput.print(
|
|
521
|
+
f"操作失败:检测到多个操作。一次只能执行一个操作。尝试执行的操作:{', '.join([handler.name() for handler in tool_list])}",
|
|
522
|
+
OutputType.WARNING,
|
|
523
|
+
)
|
|
524
|
+
return (
|
|
525
|
+
False,
|
|
526
|
+
f"操作失败:检测到多个操作。一次只能执行一个操作。尝试执行的操作:{', '.join([handler.name() for handler in tool_list])}",
|
|
527
|
+
)
|
|
493
528
|
if len(tool_list) == 0:
|
|
494
529
|
return False, ""
|
|
495
|
-
if
|
|
530
|
+
if (
|
|
531
|
+
self.max_tool_call_count > 0
|
|
532
|
+
and self.tool_call_count >= self.max_tool_call_count
|
|
533
|
+
):
|
|
496
534
|
if user_confirm(f"工具调用次数超过限制,是否继续执行?", True):
|
|
497
535
|
self.reset_tool_call_count()
|
|
498
536
|
else:
|
|
499
537
|
return False, ""
|
|
500
538
|
if self.execute_tool_confirm:
|
|
501
539
|
self.reset_tool_call_count()
|
|
502
|
-
if not self.execute_tool_confirm or user_confirm(
|
|
540
|
+
if not self.execute_tool_confirm or user_confirm(
|
|
541
|
+
f"需要执行{tool_list[0].name()}确认执行?", True
|
|
542
|
+
):
|
|
503
543
|
with yaspin(text=f"正在执行{tool_list[0].name()}...", color="cyan") as spinner:
|
|
504
544
|
with spinner.hidden():
|
|
505
545
|
result = tool_list[0].handle(response, self)
|
|
@@ -508,11 +548,10 @@ class Agent:
|
|
|
508
548
|
self.tool_call_count += 1
|
|
509
549
|
return result
|
|
510
550
|
return False, ""
|
|
511
|
-
|
|
551
|
+
|
|
512
552
|
def reset_tool_call_count(self):
|
|
513
553
|
self.tool_call_count = 0
|
|
514
554
|
|
|
515
|
-
|
|
516
555
|
def _complete_task(self) -> str:
|
|
517
556
|
"""完成任务并生成总结(如果需要)
|
|
518
557
|
|
|
@@ -524,34 +563,43 @@ class Agent:
|
|
|
524
563
|
2. 对于子Agent: 可能会生成总结(如果启用)
|
|
525
564
|
3. 使用spinner显示生成状态
|
|
526
565
|
"""
|
|
566
|
+
if self.use_analysis:
|
|
567
|
+
self._analysis_task()
|
|
568
|
+
if self.need_summary:
|
|
569
|
+
with yaspin(text="正在生成总结...", color="cyan") as spinner:
|
|
570
|
+
self.prompt = self.summary_prompt
|
|
571
|
+
with spinner.hidden():
|
|
572
|
+
ret = self.model.chat_until_success(self.prompt) # type: ignore
|
|
573
|
+
spinner.text = "总结生成完成"
|
|
574
|
+
spinner.ok("✅")
|
|
575
|
+
return ret
|
|
576
|
+
|
|
577
|
+
return "任务完成"
|
|
578
|
+
|
|
579
|
+
def _analysis_task(self):
|
|
527
580
|
with yaspin(text="正在分析任务...", color="cyan") as spinner:
|
|
528
581
|
try:
|
|
529
582
|
# 让模型判断是否需要生成方法论
|
|
530
583
|
analysis_prompt = f"""<task_analysis>
|
|
531
584
|
<request>
|
|
532
585
|
当前任务已结束,请分析该任务的解决方案:
|
|
533
|
-
|
|
534
586
|
1. 首先检查现有工具或方法论是否已经可以完成该任务,如果可以,直接说明即可,无需生成新内容
|
|
535
587
|
2. 如果现有工具/方法论不足,评估当前任务是否可以通过编写新工具来自动化解决
|
|
536
588
|
3. 如果可以通过工具解决,请设计并提供工具代码
|
|
537
589
|
4. 如果无法通过编写通用工具完成,评估当前的执行流程是否可以总结为通用方法论
|
|
538
590
|
5. 如果以上都不可行,给出详细理由
|
|
539
|
-
|
|
540
591
|
请根据分析结果采取相应行动:说明现有工具/方法论、创建新工具、生成新方法论或说明原因。
|
|
541
592
|
</request>
|
|
542
|
-
|
|
543
593
|
<evaluation_criteria>
|
|
544
594
|
现有资源评估:
|
|
545
595
|
1. 现有工具 - 检查系统中是否已有可以完成该任务的工具
|
|
546
596
|
2. 现有方法论 - 检查是否已有适用于该任务的方法论
|
|
547
597
|
3. 组合使用 - 评估现有工具和方法论组合使用是否可以解决问题
|
|
548
|
-
|
|
549
598
|
工具评估标准:
|
|
550
599
|
1. 通用性 - 该工具是否可以解决一类问题,而不仅仅是当前特定问题
|
|
551
600
|
2. 自动化 - 该工具是否可以减少人工干预,提高效率
|
|
552
601
|
3. 可靠性 - 该工具是否可以在不同场景下稳定工作
|
|
553
602
|
4. 简单性 - 该工具是否易于使用,参数设计是否合理
|
|
554
|
-
|
|
555
603
|
方法论评估标准:
|
|
556
604
|
1. 方法论应聚焦于通用且可重复的解决方案流程
|
|
557
605
|
2. 方法论应该具备足够的通用性,可应用于同类问题
|
|
@@ -559,7 +607,6 @@ class Agent:
|
|
|
559
607
|
4. 如果用户明确指出了某个解决步骤的优化方向,这应该被纳入方法论
|
|
560
608
|
5. 方法论要严格按照实际的执行流程来总结,不要遗漏或增加任何步骤
|
|
561
609
|
</evaluation_criteria>
|
|
562
|
-
|
|
563
610
|
<tool_requirements>
|
|
564
611
|
工具代码要求:
|
|
565
612
|
1. 工具类名应与工具名称保持一致
|
|
@@ -569,13 +616,11 @@ class Agent:
|
|
|
569
616
|
5. 工具描述应详细说明用途、适用场景和使用示例
|
|
570
617
|
6. 参数定义应遵循JSON Schema格式
|
|
571
618
|
7. 不要包含特定任务的细节,保持通用性
|
|
572
|
-
|
|
573
619
|
工具设计关键点:
|
|
574
620
|
1. **使用PrettyOutput打印执行过程**:强烈建议在工具中使用PrettyOutput显示执行过程,
|
|
575
621
|
这样用户可以了解工具在做什么,提升用户体验。示例:
|
|
576
622
|
```python
|
|
577
623
|
from jarvis.jarvis_utils.output import PrettyOutput, OutputType
|
|
578
|
-
|
|
579
624
|
# 执行中打印信息
|
|
580
625
|
PrettyOutput.print("正在处理数据...", OutputType.INFO)
|
|
581
626
|
# 成功信息
|
|
@@ -585,12 +630,10 @@ class Agent:
|
|
|
585
630
|
# 错误信息
|
|
586
631
|
PrettyOutput.print("操作失败", OutputType.ERROR)
|
|
587
632
|
```
|
|
588
|
-
|
|
589
633
|
2. **结构化返回结果**:工具应该始终返回结构化的结果字典,包含以下字段:
|
|
590
634
|
- success: 布尔值,表示操作是否成功
|
|
591
635
|
- stdout: 字符串,包含工具的主要输出内容
|
|
592
636
|
- stderr: 字符串,包含错误信息(如果有)
|
|
593
|
-
|
|
594
637
|
3. **异常处理**:工具应该妥善处理可能发生的异常,并在失败时清理已创建的资源
|
|
595
638
|
```python
|
|
596
639
|
try:
|
|
@@ -610,7 +653,6 @@ class Agent:
|
|
|
610
653
|
}}
|
|
611
654
|
```
|
|
612
655
|
</tool_requirements>
|
|
613
|
-
|
|
614
656
|
<methodology_requirements>
|
|
615
657
|
方法论格式要求:
|
|
616
658
|
1. 问题重述: 简明扼要的问题归纳,不含特定细节
|
|
@@ -618,15 +660,12 @@ class Agent:
|
|
|
618
660
|
3. 注意事项: 执行中可能遇到的常见问题和注意点,尤其是用户指出的问题
|
|
619
661
|
4. 可选步骤: 对于有多种解决路径的问题,标注出可选步骤和适用场景
|
|
620
662
|
</methodology_requirements>
|
|
621
|
-
|
|
622
663
|
<output_requirements>
|
|
623
664
|
根据分析结果,输出以下三种情况之一:
|
|
624
|
-
|
|
625
665
|
1. 如果现有工具/方法论可以解决,直接输出说明:
|
|
626
666
|
已有工具/方法论可以解决该问题,无需创建新内容。
|
|
627
667
|
可用的工具/方法论:[列出工具名称或方法论名称]
|
|
628
668
|
使用方法:[简要说明如何使用]
|
|
629
|
-
|
|
630
669
|
2. 工具创建(如果需要创建新工具):
|
|
631
670
|
{ot("TOOL_CALL")}
|
|
632
671
|
want: 创建新工具来解决XXX问题
|
|
@@ -637,14 +676,12 @@ arguments:
|
|
|
637
676
|
# -*- coding: utf-8 -*-
|
|
638
677
|
from typing import Dict, Any
|
|
639
678
|
from jarvis.jarvis_utils.output import PrettyOutput, OutputType
|
|
640
|
-
|
|
641
679
|
class 工具名称:
|
|
642
680
|
name = "工具名称"
|
|
643
681
|
description = "Tool for text transformation"
|
|
644
682
|
Tool description
|
|
645
683
|
适用场景:1. 格式化文本; 2. 处理标题; 3. 标准化输出
|
|
646
684
|
\"\"\"
|
|
647
|
-
|
|
648
685
|
parameters = {{
|
|
649
686
|
"type": "object",
|
|
650
687
|
"properties": {{
|
|
@@ -652,19 +689,15 @@ arguments:
|
|
|
652
689
|
}},
|
|
653
690
|
"required": []
|
|
654
691
|
}}
|
|
655
|
-
|
|
656
692
|
@staticmethod
|
|
657
693
|
def check() -> bool:
|
|
658
694
|
return True
|
|
659
|
-
|
|
660
695
|
def execute(self, args: Dict[str, Any]) -> Dict[str, Any]:
|
|
661
696
|
try:
|
|
662
697
|
# 使用PrettyOutput显示执行过程
|
|
663
698
|
PrettyOutput.print("开始执行操作...", OutputType.INFO)
|
|
664
|
-
|
|
665
699
|
# 实现逻辑
|
|
666
700
|
# ...
|
|
667
|
-
|
|
668
701
|
PrettyOutput.print("操作已完成", OutputType.SUCCESS)
|
|
669
702
|
return {{
|
|
670
703
|
"success": True,
|
|
@@ -679,7 +712,6 @@ arguments:
|
|
|
679
712
|
"stderr": f"操作失败: {{str(e)}}"
|
|
680
713
|
}}
|
|
681
714
|
{ct("TOOL_CALL")}
|
|
682
|
-
|
|
683
715
|
3. 方法论创建(如果需要创建新方法论):
|
|
684
716
|
{ot("TOOL_CALL")}
|
|
685
717
|
want: 添加/更新xxxx的方法论
|
|
@@ -690,14 +722,13 @@ arguments:
|
|
|
690
722
|
content: |2
|
|
691
723
|
方法论内容
|
|
692
724
|
{ct("TOOL_CALL")}
|
|
693
|
-
|
|
694
725
|
如果以上三种情况都不适用,则直接输出原因分析,不要使用工具调用格式。
|
|
695
726
|
</output_requirements>
|
|
696
727
|
</task_analysis>"""
|
|
697
728
|
|
|
698
729
|
self.prompt = analysis_prompt
|
|
699
730
|
with spinner.hidden():
|
|
700
|
-
response = self.model.chat_until_success(self.prompt)
|
|
731
|
+
response = self.model.chat_until_success(self.prompt) # type: ignore
|
|
701
732
|
|
|
702
733
|
with spinner.hidden():
|
|
703
734
|
self._call_tools(response)
|
|
@@ -706,17 +737,6 @@ arguments:
|
|
|
706
737
|
except Exception as e:
|
|
707
738
|
spinner.text = "分析失败"
|
|
708
739
|
spinner.fail("❌")
|
|
709
|
-
if self.need_summary:
|
|
710
|
-
with yaspin(text="正在生成总结...", color="cyan") as spinner:
|
|
711
|
-
self.prompt = self.summary_prompt
|
|
712
|
-
with spinner.hidden():
|
|
713
|
-
ret = self.model.chat_until_success(self.prompt) # type: ignore
|
|
714
|
-
spinner.text = "总结生成完成"
|
|
715
|
-
spinner.ok("✅")
|
|
716
|
-
return ret
|
|
717
|
-
|
|
718
|
-
return "任务完成"
|
|
719
|
-
|
|
720
740
|
|
|
721
741
|
def run(self, user_input: str) -> Any:
|
|
722
742
|
"""处理用户输入并执行任务
|
|
@@ -738,10 +758,9 @@ arguments:
|
|
|
738
758
|
|
|
739
759
|
self.prompt = f"{user_input}"
|
|
740
760
|
|
|
741
|
-
if self.first:
|
|
742
|
-
|
|
761
|
+
if self.first and self.use_methodology:
|
|
743
762
|
# 先尝试上传方法轮
|
|
744
|
-
platform = self.model if hasattr(self.model,
|
|
763
|
+
platform = self.model if hasattr(self.model, "upload_files") else None
|
|
745
764
|
if platform and upload_methodology(platform):
|
|
746
765
|
self.prompt = f"{user_input}\n\n方法论已上传到平台,请参考平台上的方法论内容"
|
|
747
766
|
else:
|
|
@@ -750,7 +769,7 @@ arguments:
|
|
|
750
769
|
msg, _ = handler(msg, self)
|
|
751
770
|
# 上传失败则回退到本地加载
|
|
752
771
|
self.prompt = f"{user_input}\n\n以下是历史类似问题的执行经验,可参考:\n{load_methodology(msg, self.get_tool_registry())}"
|
|
753
|
-
|
|
772
|
+
|
|
754
773
|
self.first = False
|
|
755
774
|
|
|
756
775
|
self.conversation_length = get_context_token_count(self.prompt)
|
|
@@ -760,7 +779,9 @@ arguments:
|
|
|
760
779
|
|
|
761
780
|
current_response = self._call_model(self.prompt, True)
|
|
762
781
|
self.prompt = ""
|
|
763
|
-
self.conversation_length += get_context_token_count(
|
|
782
|
+
self.conversation_length += get_context_token_count(
|
|
783
|
+
current_response
|
|
784
|
+
)
|
|
764
785
|
|
|
765
786
|
need_return, self.prompt = self._call_tools(current_response)
|
|
766
787
|
|
|
@@ -775,11 +796,13 @@ arguments:
|
|
|
775
796
|
|
|
776
797
|
if self.auto_complete and ot("!!!COMPLETE!!!") in current_response:
|
|
777
798
|
return self._complete_task()
|
|
778
|
-
|
|
799
|
+
|
|
779
800
|
self.reset_tool_call_count()
|
|
780
801
|
|
|
781
802
|
# 获取用户输入
|
|
782
|
-
user_input = self.multiline_inputer(
|
|
803
|
+
user_input = self.multiline_inputer(
|
|
804
|
+
f"{self.name}: 请输入,或输入空行来结束当前任务:"
|
|
805
|
+
)
|
|
783
806
|
|
|
784
807
|
if user_input:
|
|
785
808
|
self.prompt = user_input
|
|
@@ -808,8 +831,5 @@ arguments:
|
|
|
808
831
|
用于重置Agent状态而不影响系统消息
|
|
809
832
|
"""
|
|
810
833
|
self.prompt = ""
|
|
811
|
-
self.model.reset()
|
|
834
|
+
self.model.reset() # type: ignore
|
|
812
835
|
self.conversation_length = 0 # 重置对话长度
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
2
|
import re
|
|
3
3
|
from typing import Any, Tuple
|
|
4
|
-
from jarvis.jarvis_utils.config import get_replace_map
|
|
5
4
|
|
|
5
|
+
from jarvis.jarvis_utils.config import get_replace_map
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
def builtin_input_handler(user_input: str, agent: Any) -> Tuple[str, bool]:
|
jarvis/jarvis_agent/jarvis.py
CHANGED
|
@@ -2,24 +2,20 @@
|
|
|
2
2
|
import argparse
|
|
3
3
|
import os
|
|
4
4
|
import sys
|
|
5
|
+
from typing import Dict
|
|
5
6
|
|
|
6
|
-
from typing import Dict, List, Tuple # 增加必要的类型导入
|
|
7
|
-
|
|
8
|
-
from jarvis.jarvis_utils.config import get_data_dir
|
|
9
|
-
from prompt_toolkit import prompt
|
|
10
7
|
import yaml
|
|
8
|
+
from prompt_toolkit import prompt
|
|
11
9
|
from yaspin import yaspin
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
)
|
|
10
|
+
|
|
11
|
+
from jarvis.jarvis_agent import (Agent, OutputType, PrettyOutput,
|
|
12
|
+
get_multiline_input,
|
|
13
|
+
origin_agent_system_prompt, user_confirm)
|
|
14
|
+
from jarvis.jarvis_agent.builtin_input_handler import builtin_input_handler
|
|
15
|
+
from jarvis.jarvis_agent.shell_input_handler import shell_input_handler
|
|
19
16
|
from jarvis.jarvis_tools.registry import ToolRegistry
|
|
17
|
+
from jarvis.jarvis_utils.config import get_data_dir
|
|
20
18
|
from jarvis.jarvis_utils.utils import init_env
|
|
21
|
-
from jarvis.jarvis_agent.shell_input_handler import shell_input_handler
|
|
22
|
-
from jarvis.jarvis_agent.builtin_input_handler import builtin_input_handler
|
|
23
19
|
|
|
24
20
|
|
|
25
21
|
def _load_tasks() -> Dict[str, str]:
|