jarvis-ai-assistant 0.3.19__py3-none-any.whl → 0.3.21__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 +33 -5
- jarvis/jarvis_agent/config_editor.py +5 -1
- jarvis/jarvis_agent/edit_file_handler.py +15 -9
- jarvis/jarvis_agent/jarvis.py +99 -3
- jarvis/jarvis_agent/memory_manager.py +3 -3
- jarvis/jarvis_agent/share_manager.py +3 -1
- jarvis/jarvis_agent/shell_input_handler.py +17 -2
- jarvis/jarvis_agent/task_analyzer.py +0 -1
- jarvis/jarvis_agent/task_manager.py +15 -5
- jarvis/jarvis_agent/tool_executor.py +2 -2
- jarvis/jarvis_code_agent/code_agent.py +39 -16
- jarvis/jarvis_git_utils/git_commiter.py +3 -6
- jarvis/jarvis_mcp/sse_mcp_client.py +9 -3
- jarvis/jarvis_mcp/streamable_mcp_client.py +15 -5
- jarvis/jarvis_memory_organizer/memory_organizer.py +1 -1
- jarvis/jarvis_methodology/main.py +4 -4
- jarvis/jarvis_multi_agent/__init__.py +3 -3
- jarvis/jarvis_platform/ai8.py +0 -4
- jarvis/jarvis_platform/base.py +12 -7
- jarvis/jarvis_platform/kimi.py +18 -6
- jarvis/jarvis_platform/tongyi.py +18 -5
- jarvis/jarvis_platform/yuanbao.py +10 -3
- jarvis/jarvis_platform_manager/main.py +21 -7
- jarvis/jarvis_platform_manager/service.py +4 -3
- jarvis/jarvis_rag/cli.py +61 -22
- jarvis/jarvis_rag/embedding_manager.py +10 -3
- jarvis/jarvis_rag/llm_interface.py +4 -1
- jarvis/jarvis_rag/query_rewriter.py +3 -1
- jarvis/jarvis_rag/rag_pipeline.py +11 -3
- jarvis/jarvis_rag/retriever.py +151 -2
- jarvis/jarvis_smart_shell/main.py +60 -19
- jarvis/jarvis_stats/cli.py +12 -9
- jarvis/jarvis_stats/stats.py +17 -11
- jarvis/jarvis_stats/storage.py +23 -6
- jarvis/jarvis_tools/cli/main.py +63 -29
- jarvis/jarvis_tools/edit_file.py +3 -4
- jarvis/jarvis_tools/file_analyzer.py +0 -1
- jarvis/jarvis_tools/generate_new_tool.py +3 -3
- jarvis/jarvis_tools/read_code.py +0 -1
- jarvis/jarvis_tools/read_webpage.py +14 -4
- jarvis/jarvis_tools/registry.py +0 -3
- jarvis/jarvis_tools/retrieve_memory.py +0 -1
- jarvis/jarvis_tools/save_memory.py +0 -1
- jarvis/jarvis_tools/search_web.py +0 -2
- jarvis/jarvis_tools/sub_agent.py +197 -0
- jarvis/jarvis_tools/sub_code_agent.py +194 -0
- jarvis/jarvis_tools/virtual_tty.py +21 -13
- jarvis/jarvis_utils/clipboard.py +1 -1
- jarvis/jarvis_utils/config.py +35 -5
- jarvis/jarvis_utils/input.py +528 -41
- jarvis/jarvis_utils/methodology.py +3 -1
- jarvis/jarvis_utils/output.py +218 -129
- jarvis/jarvis_utils/utils.py +480 -170
- {jarvis_ai_assistant-0.3.19.dist-info → jarvis_ai_assistant-0.3.21.dist-info}/METADATA +10 -2
- {jarvis_ai_assistant-0.3.19.dist-info → jarvis_ai_assistant-0.3.21.dist-info}/RECORD +60 -58
- {jarvis_ai_assistant-0.3.19.dist-info → jarvis_ai_assistant-0.3.21.dist-info}/WHEEL +0 -0
- {jarvis_ai_assistant-0.3.19.dist-info → jarvis_ai_assistant-0.3.21.dist-info}/entry_points.txt +0 -0
- {jarvis_ai_assistant-0.3.19.dist-info → jarvis_ai_assistant-0.3.21.dist-info}/licenses/LICENSE +0 -0
- {jarvis_ai_assistant-0.3.19.dist-info → jarvis_ai_assistant-0.3.21.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,194 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
"""
|
3
|
+
sub_code_agent 工具
|
4
|
+
将子任务交给 CodeAgent 执行,并返回执行结果。
|
5
|
+
|
6
|
+
约定:
|
7
|
+
- 仅接收一个参数:task
|
8
|
+
- 不依赖父 Agent,所有配置使用系统默认与全局变量
|
9
|
+
- 子Agent必须自动完成(auto_complete=True)且需要summary(need_summary=True)
|
10
|
+
"""
|
11
|
+
from typing import Any, Dict, Optional
|
12
|
+
import json
|
13
|
+
|
14
|
+
from jarvis.jarvis_code_agent.code_agent import CodeAgent
|
15
|
+
from jarvis.jarvis_utils.globals import delete_agent
|
16
|
+
from jarvis.jarvis_code_agent import code_agent as code_agent_module
|
17
|
+
|
18
|
+
|
19
|
+
class SubCodeAgentTool:
|
20
|
+
"""
|
21
|
+
使用 CodeAgent 托管执行子任务,执行完立即清理内部 Agent。
|
22
|
+
- 不注册至全局
|
23
|
+
- 使用系统默认/全局配置
|
24
|
+
- 启用自动完成与总结
|
25
|
+
"""
|
26
|
+
|
27
|
+
# 必须与文件名一致,供 ToolRegistry 自动注册
|
28
|
+
name = "sub_code_agent"
|
29
|
+
description = "将子任务交给 CodeAgent 执行,并返回执行结果(使用系统默认配置,自动完成并生成总结)。"
|
30
|
+
parameters = {
|
31
|
+
"type": "object",
|
32
|
+
"properties": {
|
33
|
+
"task": {
|
34
|
+
"type": "string",
|
35
|
+
"description": "要执行的子任务内容(必填)",
|
36
|
+
},
|
37
|
+
"background": {
|
38
|
+
"type": "string",
|
39
|
+
"description": "任务背景与已知信息(可选,将与任务一并提供给子Agent)",
|
40
|
+
},
|
41
|
+
},
|
42
|
+
"required": ["task"],
|
43
|
+
}
|
44
|
+
|
45
|
+
def execute(self, args: Dict[str, Any]) -> Dict[str, Any]:
|
46
|
+
"""
|
47
|
+
执行代码子任务并返回结果(由 CodeAgent 托管执行)。
|
48
|
+
返回:
|
49
|
+
- success: 是否成功
|
50
|
+
- stdout: CodeAgent 执行结果(字符串;若为 None 则返回“任务执行完成”)
|
51
|
+
- stderr: 错误信息(如有)
|
52
|
+
"""
|
53
|
+
try:
|
54
|
+
task: str = str(args.get("task", "")).strip()
|
55
|
+
if not task:
|
56
|
+
return {
|
57
|
+
"success": False,
|
58
|
+
"stdout": "",
|
59
|
+
"stderr": "task 不能为空",
|
60
|
+
}
|
61
|
+
|
62
|
+
# 在模块级别打补丁,仅自动确认交互(允许用户输入)
|
63
|
+
def _auto_confirm(tip: str, default: bool = True) -> bool:
|
64
|
+
return default
|
65
|
+
|
66
|
+
code_agent_module.user_confirm = _auto_confirm
|
67
|
+
|
68
|
+
# 读取背景信息并组合任务
|
69
|
+
background: str = str(args.get("background", "")).strip()
|
70
|
+
enhanced_task = (
|
71
|
+
f"背景信息:\n{background}\n\n任务:\n{task}" if background else task
|
72
|
+
)
|
73
|
+
|
74
|
+
# 继承父Agent的模型组与工具使用集(用于覆盖默认值)
|
75
|
+
parent_agent = args.get("agent")
|
76
|
+
# 如未注入父Agent,尝试从全局获取当前或任一已注册Agent
|
77
|
+
if parent_agent is None:
|
78
|
+
try:
|
79
|
+
from jarvis.jarvis_utils import globals as G # 延迟导入避免循环
|
80
|
+
|
81
|
+
curr = getattr(G, "current_agent_name", "")
|
82
|
+
if curr:
|
83
|
+
parent_agent = getattr(G, "global_agents", {}).get(curr)
|
84
|
+
if parent_agent is None and getattr(G, "global_agents", {}):
|
85
|
+
try:
|
86
|
+
parent_agent = next(iter(G.global_agents.values()))
|
87
|
+
except Exception:
|
88
|
+
parent_agent = None
|
89
|
+
except Exception:
|
90
|
+
parent_agent = None
|
91
|
+
model_group = None
|
92
|
+
use_tools: list[str] = []
|
93
|
+
try:
|
94
|
+
if parent_agent is not None:
|
95
|
+
if getattr(parent_agent, "model", None):
|
96
|
+
model_group = getattr(parent_agent.model, "model_group", None)
|
97
|
+
parent_registry = parent_agent.get_tool_registry()
|
98
|
+
if parent_registry:
|
99
|
+
for t in parent_registry.get_all_tools():
|
100
|
+
if isinstance(t, dict) and t.get("name"):
|
101
|
+
use_tools.append(str(t["name"]))
|
102
|
+
except Exception:
|
103
|
+
pass
|
104
|
+
|
105
|
+
# 创建 CodeAgent:参数优先使用父Agent的配置(若可获取),否则使用默认
|
106
|
+
# 推断/继承 llm_type、need_summary、tool_group
|
107
|
+
llm_type = "normal"
|
108
|
+
tool_group = None
|
109
|
+
try:
|
110
|
+
if parent_agent is not None:
|
111
|
+
llm_type = getattr(parent_agent, "llm_type", llm_type)
|
112
|
+
tool_group = getattr(parent_agent, "tool_group", tool_group)
|
113
|
+
except Exception:
|
114
|
+
pass
|
115
|
+
|
116
|
+
# 依据父Agent已启用工具集,推导 append_tools(作为在 CodeAgent 基础工具上的增量)
|
117
|
+
append_tools = None
|
118
|
+
try:
|
119
|
+
base_tools = [
|
120
|
+
"execute_script",
|
121
|
+
"search_web",
|
122
|
+
"ask_user",
|
123
|
+
"read_code",
|
124
|
+
"rewrite_file",
|
125
|
+
"save_memory",
|
126
|
+
"retrieve_memory",
|
127
|
+
"clear_memory",
|
128
|
+
"sub_code_agent",
|
129
|
+
]
|
130
|
+
if use_tools:
|
131
|
+
extras = [t for t in use_tools if t not in base_tools]
|
132
|
+
append_tools = ",".join(extras) if extras else None
|
133
|
+
except Exception:
|
134
|
+
append_tools = None
|
135
|
+
|
136
|
+
try:
|
137
|
+
code_agent = CodeAgent(
|
138
|
+
llm_type=llm_type,
|
139
|
+
model_group=model_group,
|
140
|
+
need_summary=True,
|
141
|
+
append_tools=append_tools,
|
142
|
+
tool_group=tool_group,
|
143
|
+
)
|
144
|
+
except SystemExit as se:
|
145
|
+
# 将底层 sys.exit 转换为工具错误,避免终止进程
|
146
|
+
return {
|
147
|
+
"success": False,
|
148
|
+
"stdout": "",
|
149
|
+
"stderr": f"初始化 CodeAgent 失败(可能未配置 git 或当前非 git 仓库): {se}",
|
150
|
+
}
|
151
|
+
|
152
|
+
# 子Agent需要自动完成
|
153
|
+
try:
|
154
|
+
code_agent.agent.auto_complete = True
|
155
|
+
# 同步父Agent工具使用集(如可用)
|
156
|
+
if use_tools:
|
157
|
+
code_agent.agent.set_use_tools(use_tools)
|
158
|
+
# 同步父Agent的模型名称(如可用),以尽量保持平台与模型一致
|
159
|
+
if (
|
160
|
+
parent_agent is not None
|
161
|
+
and getattr(parent_agent, "model", None)
|
162
|
+
and getattr(code_agent.agent, "model", None)
|
163
|
+
):
|
164
|
+
try:
|
165
|
+
parent_model_name = parent_agent.model.name() # type: ignore[attr-defined]
|
166
|
+
if parent_model_name:
|
167
|
+
code_agent.agent.model.set_model_name(parent_model_name) # type: ignore[attr-defined]
|
168
|
+
except Exception:
|
169
|
+
pass
|
170
|
+
except Exception:
|
171
|
+
pass
|
172
|
+
|
173
|
+
# 执行子任务(无提交信息前后缀)
|
174
|
+
ret = code_agent.run(enhanced_task, prefix="", suffix="")
|
175
|
+
stdout = ret if isinstance(ret, str) and ret else "任务执行完成"
|
176
|
+
|
177
|
+
# 主动清理内部 Agent,避免污染父Agent的全局状态
|
178
|
+
try:
|
179
|
+
inner_agent = code_agent.agent
|
180
|
+
delete_agent(inner_agent.name)
|
181
|
+
except Exception:
|
182
|
+
pass
|
183
|
+
|
184
|
+
return {
|
185
|
+
"success": True,
|
186
|
+
"stdout": json.dumps({"result": stdout}, ensure_ascii=False, indent=2),
|
187
|
+
"stderr": "",
|
188
|
+
}
|
189
|
+
except Exception as e:
|
190
|
+
return {
|
191
|
+
"success": False,
|
192
|
+
"stdout": "",
|
193
|
+
"stderr": f"执行子任务失败: {str(e)}",
|
194
|
+
}
|
@@ -127,7 +127,9 @@ class VirtualTTYTool:
|
|
127
127
|
try:
|
128
128
|
if action == "launch":
|
129
129
|
if args.get("keys", "") != "":
|
130
|
-
PrettyOutput.print(
|
130
|
+
PrettyOutput.print(
|
131
|
+
"启动虚拟终端时,不能同时指定 keys 参数", OutputType.ERROR
|
132
|
+
)
|
131
133
|
return {
|
132
134
|
"success": False,
|
133
135
|
"stdout": "",
|
@@ -136,7 +138,9 @@ class VirtualTTYTool:
|
|
136
138
|
|
137
139
|
result = self._launch_tty(agent, tty_id)
|
138
140
|
if not result["success"]:
|
139
|
-
PrettyOutput.print(
|
141
|
+
PrettyOutput.print(
|
142
|
+
f"启动虚拟终端 [{tty_id}] 失败", OutputType.ERROR
|
143
|
+
)
|
140
144
|
return result
|
141
145
|
elif action == "send_keys":
|
142
146
|
keys = args.get("keys", "").strip()
|
@@ -145,26 +149,34 @@ class VirtualTTYTool:
|
|
145
149
|
|
146
150
|
result = self._input_command(agent, tty_id, keys, timeout, add_enter)
|
147
151
|
if not result["success"]:
|
148
|
-
PrettyOutput.print(
|
152
|
+
PrettyOutput.print(
|
153
|
+
f"发送按键序列到终端 [{tty_id}] 失败", OutputType.ERROR
|
154
|
+
)
|
149
155
|
return result
|
150
156
|
elif action == "output":
|
151
157
|
timeout = args.get("timeout", 5.0) # 默认5秒超时
|
152
158
|
|
153
159
|
result = self._get_output(agent, tty_id, timeout)
|
154
160
|
if not result["success"]:
|
155
|
-
PrettyOutput.print(
|
161
|
+
PrettyOutput.print(
|
162
|
+
f"获取终端 [{tty_id}] 输出失败", OutputType.ERROR
|
163
|
+
)
|
156
164
|
return result
|
157
165
|
elif action == "close":
|
158
166
|
|
159
167
|
result = self._close_tty(agent, tty_id)
|
160
168
|
if not result["success"]:
|
161
|
-
PrettyOutput.print(
|
169
|
+
PrettyOutput.print(
|
170
|
+
f"关闭虚拟终端 [{tty_id}] 失败", OutputType.ERROR
|
171
|
+
)
|
162
172
|
return result
|
163
173
|
elif action == "get_screen":
|
164
174
|
|
165
175
|
result = self._get_screen(agent, tty_id)
|
166
176
|
if not result["success"]:
|
167
|
-
PrettyOutput.print(
|
177
|
+
PrettyOutput.print(
|
178
|
+
f"获取终端 [{tty_id}] 屏幕内容失败", OutputType.ERROR
|
179
|
+
)
|
168
180
|
return result
|
169
181
|
elif action == "list":
|
170
182
|
|
@@ -230,8 +242,6 @@ class VirtualTTYTool:
|
|
230
242
|
except BlockingIOError:
|
231
243
|
continue
|
232
244
|
|
233
|
-
|
234
|
-
|
235
245
|
return {"success": True, "stdout": output, "stderr": ""}
|
236
246
|
|
237
247
|
except Exception as e:
|
@@ -297,8 +307,6 @@ class VirtualTTYTool:
|
|
297
307
|
except _queue.Empty:
|
298
308
|
continue
|
299
309
|
|
300
|
-
|
301
|
-
|
302
310
|
return {"success": True, "stdout": output, "stderr": ""}
|
303
311
|
|
304
312
|
except Exception as e:
|
@@ -668,9 +676,9 @@ class VirtualTTYTool:
|
|
668
676
|
{
|
669
677
|
"id": tty_id,
|
670
678
|
"status": status,
|
671
|
-
"pid":
|
672
|
-
|
673
|
-
|
679
|
+
"pid": (
|
680
|
+
tty_data["process"].pid if tty_data["process"] else None
|
681
|
+
),
|
674
682
|
"shell": tty_data["shell"],
|
675
683
|
}
|
676
684
|
)
|
jarvis/jarvis_utils/clipboard.py
CHANGED
@@ -12,7 +12,7 @@ def copy_to_clipboard(text: str) -> None:
|
|
12
12
|
text: 要复制的文本
|
13
13
|
"""
|
14
14
|
PrettyOutput.print("--- 剪贴板内容开始 ---", OutputType.INFO)
|
15
|
-
|
15
|
+
print(text)
|
16
16
|
PrettyOutput.print("--- 剪贴板内容结束 ---", OutputType.INFO)
|
17
17
|
|
18
18
|
system = platform.system()
|
jarvis/jarvis_utils/config.py
CHANGED
@@ -296,7 +296,11 @@ def get_tool_load_dirs() -> List[str]:
|
|
296
296
|
返回:
|
297
297
|
List[str]: 工具加载目录列表
|
298
298
|
"""
|
299
|
-
return
|
299
|
+
return [
|
300
|
+
os.path.expanduser(os.path.expandvars(str(p)))
|
301
|
+
for p in GLOBAL_CONFIG_DATA.get("JARVIS_TOOL_LOAD_DIRS", [])
|
302
|
+
if p
|
303
|
+
]
|
300
304
|
|
301
305
|
|
302
306
|
def get_methodology_dirs() -> List[str]:
|
@@ -306,7 +310,11 @@ def get_methodology_dirs() -> List[str]:
|
|
306
310
|
返回:
|
307
311
|
List[str]: 方法论加载目录列表
|
308
312
|
"""
|
309
|
-
return
|
313
|
+
return [
|
314
|
+
os.path.expanduser(os.path.expandvars(str(p)))
|
315
|
+
for p in GLOBAL_CONFIG_DATA.get("JARVIS_METHODOLOGY_DIRS", [])
|
316
|
+
if p
|
317
|
+
]
|
310
318
|
|
311
319
|
|
312
320
|
def get_agent_definition_dirs() -> List[str]:
|
@@ -316,7 +324,11 @@ def get_agent_definition_dirs() -> List[str]:
|
|
316
324
|
返回:
|
317
325
|
List[str]: agent 定义加载目录列表
|
318
326
|
"""
|
319
|
-
return
|
327
|
+
return [
|
328
|
+
os.path.expanduser(os.path.expandvars(str(p)))
|
329
|
+
for p in GLOBAL_CONFIG_DATA.get("JARVIS_AGENT_DEFINITION_DIRS", [])
|
330
|
+
if p
|
331
|
+
]
|
320
332
|
|
321
333
|
|
322
334
|
def get_multi_agent_dirs() -> List[str]:
|
@@ -326,7 +338,11 @@ def get_multi_agent_dirs() -> List[str]:
|
|
326
338
|
返回:
|
327
339
|
List[str]: multi_agent 加载目录列表
|
328
340
|
"""
|
329
|
-
return
|
341
|
+
return [
|
342
|
+
os.path.expanduser(os.path.expandvars(str(p)))
|
343
|
+
for p in GLOBAL_CONFIG_DATA.get("JARVIS_MULTI_AGENT_DIRS", [])
|
344
|
+
if p
|
345
|
+
]
|
330
346
|
|
331
347
|
|
332
348
|
def get_roles_dirs() -> List[str]:
|
@@ -336,7 +352,11 @@ def get_roles_dirs() -> List[str]:
|
|
336
352
|
返回:
|
337
353
|
List[str]: roles 加载目录列表
|
338
354
|
"""
|
339
|
-
return
|
355
|
+
return [
|
356
|
+
os.path.expanduser(os.path.expandvars(str(p)))
|
357
|
+
for p in GLOBAL_CONFIG_DATA.get("JARVIS_ROLES_DIRS", [])
|
358
|
+
if p
|
359
|
+
]
|
340
360
|
|
341
361
|
|
342
362
|
def get_central_methodology_repo() -> str:
|
@@ -369,6 +389,16 @@ def is_print_prompt() -> bool:
|
|
369
389
|
return GLOBAL_CONFIG_DATA.get("JARVIS_PRINT_PROMPT", False) == True
|
370
390
|
|
371
391
|
|
392
|
+
def is_print_error_traceback() -> bool:
|
393
|
+
"""
|
394
|
+
获取是否在错误输出时打印回溯调用链。
|
395
|
+
|
396
|
+
返回:
|
397
|
+
bool: 如果打印回溯则返回True,默认为False(不打印)
|
398
|
+
"""
|
399
|
+
return GLOBAL_CONFIG_DATA.get("JARVIS_PRINT_ERROR_TRACEBACK", False) is True
|
400
|
+
|
401
|
+
|
372
402
|
def is_force_save_memory() -> bool:
|
373
403
|
"""
|
374
404
|
获取是否强制保存记忆。
|