jarvis-ai-assistant 0.1.78__py3-none-any.whl → 0.1.80__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/agent.py +22 -31
- jarvis/{rag → jarvis_rag}/main.py +3 -2
- jarvis/jarvis_smart_shell/__init__.py +0 -0
- jarvis/jarvis_smart_shell/main.py +123 -0
- jarvis/models/registry.py +3 -1
- jarvis/tools/ask_user.py +67 -0
- jarvis/tools/chdir.py +89 -0
- jarvis/tools/registry.py +41 -1
- {jarvis_ai_assistant-0.1.78.dist-info → jarvis_ai_assistant-0.1.80.dist-info}/METADATA +1 -1
- {jarvis_ai_assistant-0.1.78.dist-info → jarvis_ai_assistant-0.1.80.dist-info}/RECORD +16 -12
- {jarvis_ai_assistant-0.1.78.dist-info → jarvis_ai_assistant-0.1.80.dist-info}/entry_points.txt +3 -1
- /jarvis/{rag → jarvis_rag}/__init__.py +0 -0
- {jarvis_ai_assistant-0.1.78.dist-info → jarvis_ai_assistant-0.1.80.dist-info}/LICENSE +0 -0
- {jarvis_ai_assistant-0.1.78.dist-info → jarvis_ai_assistant-0.1.80.dist-info}/WHEEL +0 -0
- {jarvis_ai_assistant-0.1.78.dist-info → jarvis_ai_assistant-0.1.80.dist-info}/top_level.txt +0 -0
jarvis/__init__.py
CHANGED
jarvis/agent.py
CHANGED
|
@@ -29,10 +29,11 @@ class Agent:
|
|
|
29
29
|
self.name = name
|
|
30
30
|
self.is_sub_agent = is_sub_agent
|
|
31
31
|
self.prompt = ""
|
|
32
|
-
self.
|
|
32
|
+
self.conversation_length = 0 # 改用长度计数器
|
|
33
33
|
|
|
34
|
-
#
|
|
34
|
+
# 从环境变量加载配置
|
|
35
35
|
self.embedding_dimension = 1536 # Default for many embedding models
|
|
36
|
+
self.max_context_length = int(os.getenv('JARVIS_MAX_CONTEXT_LENGTH', '30720')) # 默认30k
|
|
36
37
|
|
|
37
38
|
# 初始化嵌入模型
|
|
38
39
|
try:
|
|
@@ -194,7 +195,9 @@ class Agent:
|
|
|
194
195
|
return {}
|
|
195
196
|
|
|
196
197
|
def _summarize_and_clear_history(self) -> None:
|
|
197
|
-
"""
|
|
198
|
+
"""
|
|
199
|
+
[系统消息]
|
|
200
|
+
总结当前对话历史并清空历史记录,只保留系统消息和总结
|
|
198
201
|
|
|
199
202
|
这个方法会:
|
|
200
203
|
1. 请求模型总结当前对话的关键信息
|
|
@@ -218,10 +221,11 @@ class Agent:
|
|
|
218
221
|
"""
|
|
219
222
|
|
|
220
223
|
try:
|
|
221
|
-
summary = self.model.chat(prompt)
|
|
224
|
+
summary = self.model.chat(self.prompt + "\n" + prompt)
|
|
222
225
|
|
|
223
226
|
# 清空当前对话历史,但保留系统消息
|
|
224
227
|
self.model.delete_chat()
|
|
228
|
+
self.conversation_length = 0 # 重置对话长度
|
|
225
229
|
|
|
226
230
|
# 添加总结作为新的上下文
|
|
227
231
|
self.prompt = f"""以下是之前对话的关键信息总结:
|
|
@@ -230,9 +234,7 @@ class Agent:
|
|
|
230
234
|
|
|
231
235
|
请基于以上信息继续完成任务。
|
|
232
236
|
"""
|
|
233
|
-
|
|
234
|
-
# 重置对话轮数
|
|
235
|
-
self.conversation_turns = 0
|
|
237
|
+
self.conversation_length = len(self.prompt) # 设置新的起始长度
|
|
236
238
|
|
|
237
239
|
except Exception as e:
|
|
238
240
|
PrettyOutput.print(f"总结对话历史失败: {str(e)}", OutputType.ERROR)
|
|
@@ -318,6 +320,7 @@ class Agent:
|
|
|
318
320
|
tools_prompt = ""
|
|
319
321
|
|
|
320
322
|
# 选择工具
|
|
323
|
+
PrettyOutput.section("选择工具", OutputType.PLANNING)
|
|
321
324
|
tools = self.tool_registry.get_all_tools()
|
|
322
325
|
if tools:
|
|
323
326
|
tools_prompt += "可用工具:\n"
|
|
@@ -330,8 +333,7 @@ class Agent:
|
|
|
330
333
|
# 显示任务开始
|
|
331
334
|
PrettyOutput.section(f"开始新任务: {self.name}", OutputType.PLANNING)
|
|
332
335
|
|
|
333
|
-
self.clear_history()
|
|
334
|
-
self.conversation_turns = 0
|
|
336
|
+
self.clear_history()
|
|
335
337
|
|
|
336
338
|
self.model.set_system_message(f"""你是 {self.name},一个问题处理能力强大的 AI 助手。
|
|
337
339
|
|
|
@@ -341,12 +343,11 @@ class Agent:
|
|
|
341
343
|
3. 设定目标:需要可达成,可检验的一个或多个目标
|
|
342
344
|
4. 生成解决方案:生成一个或者多个具备可操作性的解决方案
|
|
343
345
|
5. 评估解决方案:从众多解决方案中选择一种最优的方案
|
|
344
|
-
6.
|
|
346
|
+
6. 制定行动计划:根据目前可以使用的工具制定行动计划,使用 PlantUML 格式输出明确的执行流程
|
|
345
347
|
7. 执行行动计划:每步执行一个步骤,最多使用一个工具(工具执行完成后,等待工具结果再执行下一步)
|
|
346
348
|
8. 监控与调整:如果执行结果与预期不符,则反思并调整行动计划,迭代之前的步骤
|
|
347
349
|
9. 方法论:如果当前任务具有通用性且执行过程中遇到了值得记录的经验,使用方法论工具记录方法论,以提升后期处理类似问题的能力
|
|
348
350
|
10. 任务结束:如果任务已经完成,使用任务结束指令结束任务
|
|
349
|
-
-------------------------------------------------------------
|
|
350
351
|
|
|
351
352
|
方法论模板:
|
|
352
353
|
1. 问题重述
|
|
@@ -381,13 +382,6 @@ arguments:
|
|
|
381
382
|
8. 在多次迭代却没有任何进展时,可请求用户指导
|
|
382
383
|
9. 如果返回的yaml字符串中包含冒号,请将整个字符串用引号包裹,避免yaml解析错误
|
|
383
384
|
|
|
384
|
-
-------------------------------------------------------------
|
|
385
|
-
|
|
386
|
-
特殊指令:
|
|
387
|
-
1. !<<SUMMARIZE>>! - 当你发现对话历史过长可能导致token超限时,可以使用此指令总结当前对话要点并清空历史。使用方法:直接回复"!<<SUMMARIZE>>!"即可。
|
|
388
|
-
|
|
389
|
-
-------------------------------------------------------------
|
|
390
|
-
|
|
391
385
|
{methodology_prompt}
|
|
392
386
|
|
|
393
387
|
-------------------------------------------------------------
|
|
@@ -400,20 +394,16 @@ arguments:
|
|
|
400
394
|
# 显示思考状态
|
|
401
395
|
PrettyOutput.print("分析任务...", OutputType.PROGRESS)
|
|
402
396
|
|
|
403
|
-
#
|
|
404
|
-
self.
|
|
405
|
-
|
|
406
|
-
# 如果对话超过10轮,在提示中添加提醒
|
|
407
|
-
if self.conversation_turns > 10:
|
|
408
|
-
self.prompt = f"{self.prompt}\n(提示:当前对话已超过10轮,建议使用 !<<SUMMARIZE>>! 指令总结对话历史,避免token超限)"
|
|
409
|
-
|
|
410
|
-
current_response = self._call_model(self.prompt)
|
|
397
|
+
# 累加对话长度
|
|
398
|
+
self.conversation_length += len(self.prompt)
|
|
411
399
|
|
|
412
|
-
#
|
|
413
|
-
if
|
|
414
|
-
self._summarize_and_clear_history()
|
|
400
|
+
# 如果对话历史长度超过限制,在提示中添加提醒
|
|
401
|
+
if self.conversation_length > self.max_context_length:
|
|
402
|
+
current_response = self._summarize_and_clear_history()
|
|
415
403
|
continue
|
|
416
|
-
|
|
404
|
+
else:
|
|
405
|
+
current_response = self._call_model(self.prompt)
|
|
406
|
+
self.conversation_length += len(current_response) # 添加响应长度
|
|
417
407
|
try:
|
|
418
408
|
result = Agent.extract_tool_calls(current_response)
|
|
419
409
|
except Exception as e:
|
|
@@ -462,6 +452,7 @@ arguments:
|
|
|
462
452
|
"""清除对话历史,只保留系统提示"""
|
|
463
453
|
self.prompt = ""
|
|
464
454
|
self.model.reset()
|
|
465
|
-
self.
|
|
455
|
+
self.conversation_length = 0 # 重置对话长度
|
|
456
|
+
|
|
466
457
|
|
|
467
458
|
|
|
@@ -373,7 +373,7 @@ class RAGTool:
|
|
|
373
373
|
for file in files:
|
|
374
374
|
file_path = os.path.join(root, file)
|
|
375
375
|
# 跳过大文件
|
|
376
|
-
if os.path.getsize(file_path) >
|
|
376
|
+
if os.path.getsize(file_path) > 100 * 1024 * 1024: # 100MB
|
|
377
377
|
PrettyOutput.print(f"跳过大文件: {file_path}",
|
|
378
378
|
output_type=OutputType.WARNING)
|
|
379
379
|
continue
|
|
@@ -412,7 +412,8 @@ class RAGTool:
|
|
|
412
412
|
文档和相似度得分的列表
|
|
413
413
|
"""
|
|
414
414
|
if not self.index:
|
|
415
|
-
|
|
415
|
+
PrettyOutput.print("索引未构建,正在构建...", output_type=OutputType.INFO)
|
|
416
|
+
self.build_index(self.root_dir)
|
|
416
417
|
|
|
417
418
|
# 获取查询的向量表示
|
|
418
419
|
query_vector = self._get_embedding(query)
|
|
File without changes
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
import argparse
|
|
3
|
+
import os
|
|
4
|
+
import sys
|
|
5
|
+
import readline
|
|
6
|
+
from typing import Optional
|
|
7
|
+
|
|
8
|
+
from jarvis.models.registry import PlatformRegistry
|
|
9
|
+
from jarvis.utils import PrettyOutput, OutputType, load_env_from_file
|
|
10
|
+
|
|
11
|
+
def execute_command(command: str) -> None:
|
|
12
|
+
"""显示命令并允许用户编辑,回车执行,Ctrl+C取消"""
|
|
13
|
+
try:
|
|
14
|
+
print("生成的命令 (可以编辑,回车执行,Ctrl+C取消):")
|
|
15
|
+
# 预填充输入行
|
|
16
|
+
readline.set_startup_hook(lambda: readline.insert_text(command))
|
|
17
|
+
try:
|
|
18
|
+
edited_command = input("> ")
|
|
19
|
+
if edited_command.strip(): # 确保命令不为空
|
|
20
|
+
os.system(edited_command)
|
|
21
|
+
except KeyboardInterrupt:
|
|
22
|
+
print("\n已取消执行")
|
|
23
|
+
finally:
|
|
24
|
+
readline.set_startup_hook() # 清除预填充
|
|
25
|
+
except Exception as e:
|
|
26
|
+
PrettyOutput.print(f"执行命令时发生错误: {str(e)}", OutputType.ERROR)
|
|
27
|
+
|
|
28
|
+
def process_request(request: str) -> Optional[str]:
|
|
29
|
+
"""处理用户请求并返回对应的shell命令
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
request: 用户的自然语言请求
|
|
33
|
+
|
|
34
|
+
Returns:
|
|
35
|
+
Optional[str]: 对应的shell命令,如果处理失败则返回None
|
|
36
|
+
"""
|
|
37
|
+
try:
|
|
38
|
+
# 获取语言模型实例
|
|
39
|
+
PlatformRegistry.suppress_output = True
|
|
40
|
+
model = PlatformRegistry.get_global_platform_registry().get_normal_platform()
|
|
41
|
+
model.set_suppress_output(True)
|
|
42
|
+
|
|
43
|
+
shell = os.environ.get("SHELL") or "bash"
|
|
44
|
+
current_path = os.getcwd()
|
|
45
|
+
|
|
46
|
+
# 设置系统提示
|
|
47
|
+
system_message = f"""你是一个 shell 命令生成助手。
|
|
48
|
+
|
|
49
|
+
你的唯一任务是将用户的自然语言需求转换为对应的shell命令。
|
|
50
|
+
|
|
51
|
+
严格要求:
|
|
52
|
+
1. 只返回shell命令本身
|
|
53
|
+
2. 不要添加任何标记(如```、/**/、//等)
|
|
54
|
+
3. 不要添加任何解释或说明
|
|
55
|
+
4. 不要添加任何换行或额外空格
|
|
56
|
+
5. 如果需要多个命令,使用 && 连接
|
|
57
|
+
|
|
58
|
+
安全要求:
|
|
59
|
+
- 生成的命令必须是安全的,不能包含危险操作
|
|
60
|
+
- 如果需要sudo权限,要明确提示用户
|
|
61
|
+
- 对于复杂操作,优先使用管道而不是临时文件
|
|
62
|
+
- 确保命令的可移植性,优先使用通用的POSIX命令
|
|
63
|
+
|
|
64
|
+
示例输入:
|
|
65
|
+
"查找当前目录下的所有Python文件"
|
|
66
|
+
|
|
67
|
+
示例输出:
|
|
68
|
+
find . -name "*.py"
|
|
69
|
+
|
|
70
|
+
记住:只返回命令本身,不要有任何额外的内容。
|
|
71
|
+
"""
|
|
72
|
+
model.set_system_message(system_message)
|
|
73
|
+
|
|
74
|
+
prefix = f"当前路径: {current_path}\n"
|
|
75
|
+
prefix += f"当前shell: {shell}\n"
|
|
76
|
+
|
|
77
|
+
# 处理请求
|
|
78
|
+
result = model.chat(prefix + request)
|
|
79
|
+
|
|
80
|
+
# 提取命令 - 简化处理逻辑,因为现在应该只返回纯命令
|
|
81
|
+
if result and isinstance(result, str):
|
|
82
|
+
return result.strip()
|
|
83
|
+
|
|
84
|
+
return None
|
|
85
|
+
|
|
86
|
+
except Exception as e:
|
|
87
|
+
PrettyOutput.print(f"处理请求时发生错误: {str(e)}", OutputType.ERROR)
|
|
88
|
+
return None
|
|
89
|
+
|
|
90
|
+
def main():
|
|
91
|
+
# 创建参数解析器
|
|
92
|
+
load_env_from_file()
|
|
93
|
+
parser = argparse.ArgumentParser(
|
|
94
|
+
description="将自然语言需求转换为shell命令",
|
|
95
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
96
|
+
epilog="""
|
|
97
|
+
示例:
|
|
98
|
+
%(prog)s "查找当前目录下所有的Python文件"
|
|
99
|
+
%(prog)s "压缩所有jpg图片"
|
|
100
|
+
%(prog)s "查找最近一周修改过的文档"
|
|
101
|
+
""")
|
|
102
|
+
|
|
103
|
+
# 添加参数
|
|
104
|
+
parser.add_argument(
|
|
105
|
+
"request",
|
|
106
|
+
help="用自然语言描述你需要执行的操作"
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
# 解析参数
|
|
110
|
+
args = parser.parse_args()
|
|
111
|
+
|
|
112
|
+
# 处理请求
|
|
113
|
+
command = process_request(args.request)
|
|
114
|
+
|
|
115
|
+
# 输出结果
|
|
116
|
+
if command:
|
|
117
|
+
execute_command(command) # 显示并执行命令
|
|
118
|
+
return 0
|
|
119
|
+
else:
|
|
120
|
+
return 1
|
|
121
|
+
|
|
122
|
+
if __name__ == "__main__":
|
|
123
|
+
sys.exit(main())
|
jarvis/models/registry.py
CHANGED
|
@@ -19,6 +19,7 @@ class PlatformRegistry:
|
|
|
19
19
|
|
|
20
20
|
global_platform_name = "kimi"
|
|
21
21
|
global_platform_registry = None
|
|
22
|
+
suppress_output = False
|
|
22
23
|
|
|
23
24
|
@staticmethod
|
|
24
25
|
def get_platform_dir() -> str:
|
|
@@ -121,7 +122,8 @@ class PlatformRegistry:
|
|
|
121
122
|
# 检查平台实现
|
|
122
123
|
if not PlatformRegistry.check_platform_implementation(obj):
|
|
123
124
|
continue
|
|
124
|
-
|
|
125
|
+
if not PlatformRegistry.suppress_output:
|
|
126
|
+
PrettyOutput.print(f"从 {os.path.join(directory, filename)} 加载平台:{obj.platform_name}", OutputType.SUCCESS)
|
|
125
127
|
platforms[obj.platform_name] = obj
|
|
126
128
|
break
|
|
127
129
|
except Exception as e:
|
jarvis/tools/ask_user.py
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
from typing import Dict, Any
|
|
2
|
+
from jarvis.tools.base import Tool
|
|
3
|
+
from jarvis.utils import get_multiline_input, PrettyOutput, OutputType
|
|
4
|
+
|
|
5
|
+
class AskUserTool(Tool):
|
|
6
|
+
def __init__(self):
|
|
7
|
+
super().__init__(
|
|
8
|
+
name="ask_user",
|
|
9
|
+
description="""当缺少完成任务的信息或有关键决策信息缺失时,询问用户。
|
|
10
|
+
用户可以输入多行文本,空行结束输入。
|
|
11
|
+
|
|
12
|
+
使用场景:
|
|
13
|
+
1. 需要用户提供更多信息来完成任务
|
|
14
|
+
2. 需要用户做出关键决策
|
|
15
|
+
3. 需要用户确认某些重要操作
|
|
16
|
+
4. 需要用户提供额外信息
|
|
17
|
+
|
|
18
|
+
参数说明:
|
|
19
|
+
- question: 要询问用户的问题,应该清晰明确""",
|
|
20
|
+
parameters={
|
|
21
|
+
"type": "object",
|
|
22
|
+
"properties": {
|
|
23
|
+
"question": {
|
|
24
|
+
"type": "string",
|
|
25
|
+
"description": "要询问用户的问题"
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"required": ["question"]
|
|
29
|
+
}
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
def execute(self, args: Dict[str, Any]) -> Dict[str, Any]:
|
|
33
|
+
"""执行询问用户操作
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
args: 包含问题的字典
|
|
37
|
+
|
|
38
|
+
Returns:
|
|
39
|
+
Dict: 包含用户响应的字典
|
|
40
|
+
"""
|
|
41
|
+
try:
|
|
42
|
+
question = args["question"]
|
|
43
|
+
|
|
44
|
+
# 显示问题
|
|
45
|
+
PrettyOutput.print("\n问题:", OutputType.QUESTION)
|
|
46
|
+
PrettyOutput.print(question, OutputType.QUESTION)
|
|
47
|
+
|
|
48
|
+
# 获取用户输入
|
|
49
|
+
PrettyOutput.print("\n请输入您的回答(输入空行结束):", OutputType.INPUT)
|
|
50
|
+
user_response = get_multiline_input()
|
|
51
|
+
|
|
52
|
+
if user_response == "__interrupt__":
|
|
53
|
+
return {
|
|
54
|
+
"success": False,
|
|
55
|
+
"error": "用户取消了输入"
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return {
|
|
59
|
+
"success": True,
|
|
60
|
+
"stdout": user_response
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
except Exception as e:
|
|
64
|
+
return {
|
|
65
|
+
"success": False,
|
|
66
|
+
"error": f"询问用户失败: {str(e)}"
|
|
67
|
+
}
|
jarvis/tools/chdir.py
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
from typing import Dict, Any
|
|
2
|
+
import os
|
|
3
|
+
from jarvis.utils import PrettyOutput, OutputType
|
|
4
|
+
|
|
5
|
+
class ChdirTool:
|
|
6
|
+
"""修改当前工作目录的工具"""
|
|
7
|
+
|
|
8
|
+
name = "chdir"
|
|
9
|
+
description = "修改当前工作目录"
|
|
10
|
+
parameters = {
|
|
11
|
+
"type": "object",
|
|
12
|
+
"properties": {
|
|
13
|
+
"path": {
|
|
14
|
+
"type": "string",
|
|
15
|
+
"description": "要切换到的目录路径,支持相对路径和绝对路径"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"required": ["path"]
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
def execute(self, args: Dict[str, Any]) -> Dict[str, Any]:
|
|
22
|
+
"""执行目录切换
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
args: 包含 path 参数的字典
|
|
26
|
+
|
|
27
|
+
Returns:
|
|
28
|
+
执行结果字典,包含:
|
|
29
|
+
- success: 是否成功
|
|
30
|
+
- stdout: 成功时的输出信息
|
|
31
|
+
- error: 失败时的错误信息
|
|
32
|
+
"""
|
|
33
|
+
try:
|
|
34
|
+
path = os.path.expanduser(args["path"]) # 展开 ~ 等路径
|
|
35
|
+
path = os.path.abspath(path) # 转换为绝对路径
|
|
36
|
+
|
|
37
|
+
# 检查目录是否存在
|
|
38
|
+
if not os.path.exists(path):
|
|
39
|
+
return {
|
|
40
|
+
"success": False,
|
|
41
|
+
"error": f"目录不存在: {path}"
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
# 检查是否是目录
|
|
45
|
+
if not os.path.isdir(path):
|
|
46
|
+
return {
|
|
47
|
+
"success": False,
|
|
48
|
+
"error": f"路径不是目录: {path}"
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
# 尝试切换目录
|
|
52
|
+
old_path = os.getcwd()
|
|
53
|
+
os.chdir(path)
|
|
54
|
+
|
|
55
|
+
return {
|
|
56
|
+
"success": True,
|
|
57
|
+
"stdout": f"已切换工作目录:\n从: {old_path}\n到: {path}",
|
|
58
|
+
"stderr": ""
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
except PermissionError:
|
|
62
|
+
return {
|
|
63
|
+
"success": False,
|
|
64
|
+
"error": f"没有权限访问目录: {path}"
|
|
65
|
+
}
|
|
66
|
+
except Exception as e:
|
|
67
|
+
return {
|
|
68
|
+
"success": False,
|
|
69
|
+
"error": f"切换目录失败: {str(e)}"
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
def main():
|
|
73
|
+
"""命令行直接运行工具"""
|
|
74
|
+
import argparse
|
|
75
|
+
|
|
76
|
+
parser = argparse.ArgumentParser(description='修改当前工作目录')
|
|
77
|
+
parser.add_argument('path', help='要切换到的目录路径')
|
|
78
|
+
args = parser.parse_args()
|
|
79
|
+
|
|
80
|
+
tool = ChdirTool()
|
|
81
|
+
result = tool.execute({"path": args.path})
|
|
82
|
+
|
|
83
|
+
if result["success"]:
|
|
84
|
+
PrettyOutput.print(result["stdout"], OutputType.SUCCESS)
|
|
85
|
+
else:
|
|
86
|
+
PrettyOutput.print(result["error"], OutputType.ERROR)
|
|
87
|
+
|
|
88
|
+
if __name__ == "__main__":
|
|
89
|
+
main()
|
jarvis/tools/registry.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
|
|
2
1
|
import importlib
|
|
3
2
|
import json
|
|
3
|
+
import os
|
|
4
4
|
from pathlib import Path
|
|
5
5
|
import sys
|
|
6
6
|
from typing import Any, Callable, Dict, List, Optional
|
|
@@ -19,6 +19,7 @@ class ToolRegistry:
|
|
|
19
19
|
# 加载内置工具和外部工具
|
|
20
20
|
self._load_builtin_tools()
|
|
21
21
|
self._load_external_tools()
|
|
22
|
+
self.max_context_length = int(os.getenv('JARVIS_MAX_CONTEXT_LENGTH', '30720')) # 默认30k
|
|
22
23
|
|
|
23
24
|
@staticmethod
|
|
24
25
|
def get_global_tool_registry():
|
|
@@ -173,12 +174,51 @@ class ToolRegistry:
|
|
|
173
174
|
output = "\n\n".join(output_parts)
|
|
174
175
|
output = "没有输出和错误" if not output else output
|
|
175
176
|
PrettyOutput.section("执行成功", OutputType.SUCCESS)
|
|
177
|
+
|
|
178
|
+
# 如果输出超过4k字符,使用大模型总结
|
|
179
|
+
if len(output) > 4096:
|
|
180
|
+
try:
|
|
181
|
+
PrettyOutput.print("输出较长,正在总结...", OutputType.PROGRESS)
|
|
182
|
+
model = PlatformRegistry.get_global_platform_registry().get_normal_platform()
|
|
183
|
+
|
|
184
|
+
# 如果输出超过30k,只取最后30k字符
|
|
185
|
+
if len(output) > self.max_context_length:
|
|
186
|
+
output_to_summarize = output[-self.max_context_length:]
|
|
187
|
+
truncation_notice = "\n(注意: 由于输出过长,仅总结最后30720字符)"
|
|
188
|
+
else:
|
|
189
|
+
output_to_summarize = output
|
|
190
|
+
truncation_notice = ""
|
|
191
|
+
|
|
192
|
+
prompt = f"""请总结以下工具执行结果,提取关键信息和重要结果。注意:
|
|
193
|
+
1. 保留所有重要的数值、路径、错误信息等关键数据
|
|
194
|
+
2. 保持结果的准确性
|
|
195
|
+
3. 用简洁的语言描述主要内容
|
|
196
|
+
4. 如果有错误信息,确保包含在总结中
|
|
197
|
+
|
|
198
|
+
工具名称: {name}
|
|
199
|
+
执行结果:
|
|
200
|
+
{output_to_summarize}
|
|
201
|
+
|
|
202
|
+
请提供总结:"""
|
|
203
|
+
|
|
204
|
+
summary = model.chat(prompt)
|
|
205
|
+
output = f"""--- 原始输出较长,以下是总结 ---{truncation_notice}
|
|
206
|
+
|
|
207
|
+
{summary}
|
|
208
|
+
|
|
209
|
+
--- 总结结束 ---"""
|
|
210
|
+
|
|
211
|
+
except Exception as e:
|
|
212
|
+
PrettyOutput.print(f"总结失败: {str(e)}", OutputType.WARNING)
|
|
213
|
+
output = f"输出较长 ({len(output)} 字符),建议查看原始输出。\n前300字符预览:\n{output[:300]}..."
|
|
214
|
+
|
|
176
215
|
else:
|
|
177
216
|
error_msg = result["error"]
|
|
178
217
|
output = f"执行失败: {error_msg}"
|
|
179
218
|
PrettyOutput.section("执行失败", OutputType.ERROR)
|
|
180
219
|
|
|
181
220
|
return output
|
|
221
|
+
|
|
182
222
|
except Exception as e:
|
|
183
223
|
PrettyOutput.print(f"执行工具失败: {str(e)}", OutputType.ERROR)
|
|
184
224
|
return f"Tool call failed: {str(e)}"
|
|
@@ -1,35 +1,39 @@
|
|
|
1
|
-
jarvis/__init__.py,sha256=
|
|
2
|
-
jarvis/agent.py,sha256=
|
|
1
|
+
jarvis/__init__.py,sha256=Z6ETkmEWC686kbdrf_q6ASeGGE04U-Rr-b2LXZPRVzE,50
|
|
2
|
+
jarvis/agent.py,sha256=BDBFtvSbKfcUxd-pDvNv3ivfm0X1yCrjZDAkxmE1gwo,19373
|
|
3
3
|
jarvis/main.py,sha256=OJc7e5i988eQLByT7SzX7eoa0HKm4LMg814gZv9hBX8,5487
|
|
4
4
|
jarvis/utils.py,sha256=jvo6ylvrTaSmXWcYY0qTTf14TwCkAhPsCUuIl5WHEuw,8640
|
|
5
5
|
jarvis/jarvis_codebase/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
6
|
jarvis/jarvis_codebase/main.py,sha256=DPMPw8qoKHooydELKwf_bXPa0a3459kdFcZOXdrM-N8,24785
|
|
7
7
|
jarvis/jarvis_coder/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
8
|
jarvis/jarvis_coder/main.py,sha256=Hr6T5LHC5n08s9tnOt-2_h8TmzothBUhqcd2-fzwuVI,23790
|
|
9
|
+
jarvis/jarvis_rag/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
|
+
jarvis/jarvis_rag/main.py,sha256=drCH9KmwQozxtPICIfTFXmkIhwN8WDreMOCTxtj9SPc,20842
|
|
11
|
+
jarvis/jarvis_smart_shell/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
12
|
+
jarvis/jarvis_smart_shell/main.py,sha256=QgR1CZRcTVfC8a5hMso3onH3pFdDoniRjr0YQvY2jXQ,3809
|
|
9
13
|
jarvis/models/__init__.py,sha256=mrOt67nselz_H1gX9wdAO4y2DY5WPXzABqJbr5Des8k,63
|
|
10
14
|
jarvis/models/ai8.py,sha256=vgy-r_3HHxGMAalZrA65VWHC1PuwBTYgtprSgHkCbrk,12557
|
|
11
15
|
jarvis/models/base.py,sha256=ShV1H8Unee4RMaiFO4idROQA0Hc6wu4dyeRPX5fcszk,1433
|
|
12
16
|
jarvis/models/kimi.py,sha256=1iTB0Z_WOmCML3Ufsge6jmeKOYvccr7I5lS3JUXymU4,17611
|
|
13
17
|
jarvis/models/openai.py,sha256=ayaBWAN5VexMcKVrjEPDNB-Q9wx0sCV9Z4BCrvwYJ9w,4315
|
|
14
18
|
jarvis/models/oyi.py,sha256=X2c5SWDIuQDCCFBcEKbzIWEz3I34eOAi0d1XAFgxlpw,15001
|
|
15
|
-
jarvis/models/registry.py,sha256=
|
|
16
|
-
jarvis/rag/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
17
|
-
jarvis/rag/main.py,sha256=D3JrRQd4dTyf4ZB0gN131a3D4R933BhlNypimo1ZX7w,20775
|
|
19
|
+
jarvis/models/registry.py,sha256=Lt8IdVBAEx_CCFtfZJPgw3nxSEjfFcqI47I-U64kIbg,8257
|
|
18
20
|
jarvis/tools/__init__.py,sha256=7Rqyj5hBAv5cWDVr5T9ZTZASO7ssBHeQNm2_4ZARdkA,72
|
|
21
|
+
jarvis/tools/ask_user.py,sha256=xLXkYK3_f8EJ7kudA8MumOOCxyFl6z3DBS_zcscMH6Y,2151
|
|
19
22
|
jarvis/tools/base.py,sha256=EGRGbdfbLXDLwtyoWdvp9rlxNX7bzc20t0Vc2VkwIEY,652
|
|
23
|
+
jarvis/tools/chdir.py,sha256=TjfPbX8yvNKgUNJEMXh3ZlVDEIse_Fo8xMoVsiK7_dA,2688
|
|
20
24
|
jarvis/tools/codebase_qa.py,sha256=LsowsgL7HBmdBwa7zXcYi_OkwOok4qbnzYWYsuZxHtU,2413
|
|
21
25
|
jarvis/tools/coder.py,sha256=kmotT2Klsug44S51QoSW9DzkxLzcF-XonyYAEoWZV6c,2295
|
|
22
26
|
jarvis/tools/file_ops.py,sha256=h8g0eT9UvlJf4kt0DLXvdSsjcPj7x19lxWdDApeDfpg,3842
|
|
23
27
|
jarvis/tools/generator.py,sha256=S1DhHBfhNvF6SrORnlk8Mz210yDiJPuxbfswbX_UACs,5791
|
|
24
28
|
jarvis/tools/methodology.py,sha256=UG6s5VYRcd9wrKX4cg6f7zJhet5AIcthFGMOAdevBiw,5175
|
|
25
|
-
jarvis/tools/registry.py,sha256=
|
|
29
|
+
jarvis/tools/registry.py,sha256=XhFufp57hJZkRj6MUC5m-q4WEHFp8hzGmW2zFIzk12w,9074
|
|
26
30
|
jarvis/tools/search.py,sha256=c9dXtyICdl8Lm8shNPNyIx9k67uY0rMF8xnIKu2RsnE,8787
|
|
27
31
|
jarvis/tools/shell.py,sha256=UPKshPyOaUwTngresUw-ot1jHjQIb4wCY5nkJqa38lU,2520
|
|
28
32
|
jarvis/tools/sub_agent.py,sha256=rEtAmSVY2ZjFOZEKr5m5wpACOQIiM9Zr_3dT92FhXYU,2621
|
|
29
33
|
jarvis/tools/webpage.py,sha256=d3w3Jcjcu1ESciezTkz3n3Zf-rp_l91PrVoDEZnckOo,2391
|
|
30
|
-
jarvis_ai_assistant-0.1.
|
|
31
|
-
jarvis_ai_assistant-0.1.
|
|
32
|
-
jarvis_ai_assistant-0.1.
|
|
33
|
-
jarvis_ai_assistant-0.1.
|
|
34
|
-
jarvis_ai_assistant-0.1.
|
|
35
|
-
jarvis_ai_assistant-0.1.
|
|
34
|
+
jarvis_ai_assistant-0.1.80.dist-info/LICENSE,sha256=AGgVgQmTqFvaztRtCAXsAMryUymB18gZif7_l2e1XOg,1063
|
|
35
|
+
jarvis_ai_assistant-0.1.80.dist-info/METADATA,sha256=mfPbf9OcczggJFffilTxhlHqwDNYDsF9SOKDqstbQ-c,12736
|
|
36
|
+
jarvis_ai_assistant-0.1.80.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
|
37
|
+
jarvis_ai_assistant-0.1.80.dist-info/entry_points.txt,sha256=sdmIO86MrIUepJTGyHs0i_Ho9VGf1q9YRP4RgQvGWcI,280
|
|
38
|
+
jarvis_ai_assistant-0.1.80.dist-info/top_level.txt,sha256=1BOxyWfzOP_ZXj8rVTDnNCJ92bBGB0rwq8N1PCpoMIs,7
|
|
39
|
+
jarvis_ai_assistant-0.1.80.dist-info/RECORD,,
|
{jarvis_ai_assistant-0.1.78.dist-info → jarvis_ai_assistant-0.1.80.dist-info}/entry_points.txt
RENAMED
|
@@ -2,4 +2,6 @@
|
|
|
2
2
|
jarvis = jarvis.main:main
|
|
3
3
|
jarvis-codebase = jarvis.jarvis_codebase.main:main
|
|
4
4
|
jarvis-coder = jarvis.jarvis_coder.main:main
|
|
5
|
-
jarvis-rag = jarvis.
|
|
5
|
+
jarvis-rag = jarvis.jarvis_rag.main:main
|
|
6
|
+
jarvis-smart-shell = jarvis.jarvis_smart_shell.main:main
|
|
7
|
+
jss = jarvis.jarvis_smart_shell.main:main
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|