jarvis-ai-assistant 0.3.30__py3-none-any.whl → 0.7.6__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 +458 -152
- jarvis/jarvis_agent/agent_manager.py +17 -13
- jarvis/jarvis_agent/builtin_input_handler.py +2 -6
- jarvis/jarvis_agent/config_editor.py +2 -7
- jarvis/jarvis_agent/event_bus.py +82 -12
- jarvis/jarvis_agent/file_context_handler.py +329 -0
- jarvis/jarvis_agent/file_methodology_manager.py +3 -4
- jarvis/jarvis_agent/jarvis.py +628 -55
- jarvis/jarvis_agent/language_extractors/__init__.py +57 -0
- jarvis/jarvis_agent/language_extractors/c_extractor.py +21 -0
- jarvis/jarvis_agent/language_extractors/cpp_extractor.py +21 -0
- jarvis/jarvis_agent/language_extractors/go_extractor.py +21 -0
- jarvis/jarvis_agent/language_extractors/java_extractor.py +84 -0
- jarvis/jarvis_agent/language_extractors/javascript_extractor.py +79 -0
- jarvis/jarvis_agent/language_extractors/python_extractor.py +21 -0
- jarvis/jarvis_agent/language_extractors/rust_extractor.py +21 -0
- jarvis/jarvis_agent/language_extractors/typescript_extractor.py +84 -0
- jarvis/jarvis_agent/language_support_info.py +486 -0
- jarvis/jarvis_agent/main.py +34 -10
- jarvis/jarvis_agent/memory_manager.py +7 -16
- jarvis/jarvis_agent/methodology_share_manager.py +10 -16
- jarvis/jarvis_agent/prompt_manager.py +1 -1
- jarvis/jarvis_agent/prompts.py +193 -171
- jarvis/jarvis_agent/protocols.py +8 -12
- jarvis/jarvis_agent/run_loop.py +105 -9
- jarvis/jarvis_agent/session_manager.py +2 -3
- jarvis/jarvis_agent/share_manager.py +20 -22
- jarvis/jarvis_agent/shell_input_handler.py +1 -2
- jarvis/jarvis_agent/stdio_redirect.py +295 -0
- jarvis/jarvis_agent/task_analyzer.py +31 -6
- jarvis/jarvis_agent/task_manager.py +11 -27
- jarvis/jarvis_agent/tool_executor.py +2 -3
- jarvis/jarvis_agent/tool_share_manager.py +12 -24
- jarvis/jarvis_agent/utils.py +5 -1
- jarvis/jarvis_agent/web_bridge.py +189 -0
- jarvis/jarvis_agent/web_output_sink.py +53 -0
- jarvis/jarvis_agent/web_server.py +786 -0
- jarvis/jarvis_c2rust/__init__.py +26 -0
- jarvis/jarvis_c2rust/cli.py +575 -0
- jarvis/jarvis_c2rust/collector.py +250 -0
- jarvis/jarvis_c2rust/constants.py +26 -0
- jarvis/jarvis_c2rust/library_replacer.py +1254 -0
- jarvis/jarvis_c2rust/llm_module_agent.py +1272 -0
- jarvis/jarvis_c2rust/loaders.py +207 -0
- jarvis/jarvis_c2rust/models.py +28 -0
- jarvis/jarvis_c2rust/optimizer.py +2157 -0
- jarvis/jarvis_c2rust/scanner.py +1681 -0
- jarvis/jarvis_c2rust/transpiler.py +2983 -0
- jarvis/jarvis_c2rust/utils.py +385 -0
- jarvis/jarvis_code_agent/build_validation_config.py +132 -0
- jarvis/jarvis_code_agent/code_agent.py +1371 -220
- jarvis/jarvis_code_agent/code_analyzer/__init__.py +65 -0
- jarvis/jarvis_code_agent/code_analyzer/base_language.py +74 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/__init__.py +44 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/base.py +106 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/cmake.py +74 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/detector.py +125 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/fallback.py +72 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/go.py +70 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/java_gradle.py +53 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/java_maven.py +47 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/makefile.py +61 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/nodejs.py +110 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/python.py +154 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/rust.py +110 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/validator.py +153 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator.py +43 -0
- jarvis/jarvis_code_agent/code_analyzer/context_manager.py +648 -0
- jarvis/jarvis_code_agent/code_analyzer/context_recommender.py +18 -0
- jarvis/jarvis_code_agent/code_analyzer/dependency_analyzer.py +132 -0
- jarvis/jarvis_code_agent/code_analyzer/file_ignore.py +330 -0
- jarvis/jarvis_code_agent/code_analyzer/impact_analyzer.py +781 -0
- jarvis/jarvis_code_agent/code_analyzer/language_registry.py +185 -0
- jarvis/jarvis_code_agent/code_analyzer/language_support.py +110 -0
- jarvis/jarvis_code_agent/code_analyzer/languages/__init__.py +49 -0
- jarvis/jarvis_code_agent/code_analyzer/languages/c_cpp_language.py +299 -0
- jarvis/jarvis_code_agent/code_analyzer/languages/go_language.py +215 -0
- jarvis/jarvis_code_agent/code_analyzer/languages/java_language.py +212 -0
- jarvis/jarvis_code_agent/code_analyzer/languages/javascript_language.py +254 -0
- jarvis/jarvis_code_agent/code_analyzer/languages/python_language.py +269 -0
- jarvis/jarvis_code_agent/code_analyzer/languages/rust_language.py +281 -0
- jarvis/jarvis_code_agent/code_analyzer/languages/typescript_language.py +280 -0
- jarvis/jarvis_code_agent/code_analyzer/llm_context_recommender.py +605 -0
- jarvis/jarvis_code_agent/code_analyzer/structured_code.py +556 -0
- jarvis/jarvis_code_agent/code_analyzer/symbol_extractor.py +252 -0
- jarvis/jarvis_code_agent/code_analyzer/tree_sitter_extractor.py +58 -0
- jarvis/jarvis_code_agent/lint.py +501 -8
- jarvis/jarvis_code_agent/utils.py +141 -0
- jarvis/jarvis_code_analysis/code_review.py +493 -584
- jarvis/jarvis_data/config_schema.json +128 -12
- jarvis/jarvis_git_squash/main.py +4 -5
- jarvis/jarvis_git_utils/git_commiter.py +82 -75
- jarvis/jarvis_mcp/sse_mcp_client.py +22 -29
- jarvis/jarvis_mcp/stdio_mcp_client.py +12 -13
- jarvis/jarvis_mcp/streamable_mcp_client.py +15 -14
- jarvis/jarvis_memory_organizer/memory_organizer.py +55 -74
- jarvis/jarvis_methodology/main.py +32 -48
- jarvis/jarvis_multi_agent/__init__.py +287 -55
- jarvis/jarvis_multi_agent/main.py +36 -4
- jarvis/jarvis_platform/base.py +524 -202
- jarvis/jarvis_platform/human.py +7 -8
- jarvis/jarvis_platform/kimi.py +30 -36
- jarvis/jarvis_platform/openai.py +88 -25
- jarvis/jarvis_platform/registry.py +26 -10
- jarvis/jarvis_platform/tongyi.py +24 -25
- jarvis/jarvis_platform/yuanbao.py +32 -43
- jarvis/jarvis_platform_manager/main.py +66 -77
- jarvis/jarvis_platform_manager/service.py +8 -13
- jarvis/jarvis_rag/cli.py +53 -55
- jarvis/jarvis_rag/embedding_manager.py +13 -18
- jarvis/jarvis_rag/llm_interface.py +8 -9
- jarvis/jarvis_rag/query_rewriter.py +10 -21
- jarvis/jarvis_rag/rag_pipeline.py +24 -27
- jarvis/jarvis_rag/reranker.py +4 -5
- jarvis/jarvis_rag/retriever.py +28 -30
- jarvis/jarvis_sec/__init__.py +305 -0
- jarvis/jarvis_sec/agents.py +143 -0
- jarvis/jarvis_sec/analysis.py +276 -0
- jarvis/jarvis_sec/checkers/__init__.py +32 -0
- jarvis/jarvis_sec/checkers/c_checker.py +2680 -0
- jarvis/jarvis_sec/checkers/rust_checker.py +1108 -0
- jarvis/jarvis_sec/cli.py +139 -0
- jarvis/jarvis_sec/clustering.py +1439 -0
- jarvis/jarvis_sec/file_manager.py +427 -0
- jarvis/jarvis_sec/parsers.py +73 -0
- jarvis/jarvis_sec/prompts.py +268 -0
- jarvis/jarvis_sec/report.py +336 -0
- jarvis/jarvis_sec/review.py +453 -0
- jarvis/jarvis_sec/status.py +264 -0
- jarvis/jarvis_sec/types.py +20 -0
- jarvis/jarvis_sec/utils.py +499 -0
- jarvis/jarvis_sec/verification.py +848 -0
- jarvis/jarvis_sec/workflow.py +226 -0
- jarvis/jarvis_smart_shell/main.py +38 -87
- jarvis/jarvis_stats/cli.py +2 -2
- jarvis/jarvis_stats/stats.py +8 -8
- jarvis/jarvis_stats/storage.py +15 -21
- jarvis/jarvis_stats/visualizer.py +1 -1
- jarvis/jarvis_tools/clear_memory.py +3 -20
- jarvis/jarvis_tools/cli/main.py +21 -23
- jarvis/jarvis_tools/edit_file.py +1019 -132
- jarvis/jarvis_tools/execute_script.py +83 -25
- jarvis/jarvis_tools/file_analyzer.py +6 -9
- jarvis/jarvis_tools/generate_new_tool.py +14 -21
- jarvis/jarvis_tools/lsp_client.py +1552 -0
- jarvis/jarvis_tools/methodology.py +2 -3
- jarvis/jarvis_tools/read_code.py +1736 -35
- jarvis/jarvis_tools/read_symbols.py +140 -0
- jarvis/jarvis_tools/read_webpage.py +12 -13
- jarvis/jarvis_tools/registry.py +427 -200
- jarvis/jarvis_tools/retrieve_memory.py +20 -19
- jarvis/jarvis_tools/rewrite_file.py +72 -158
- jarvis/jarvis_tools/save_memory.py +3 -15
- jarvis/jarvis_tools/search_web.py +18 -18
- jarvis/jarvis_tools/sub_agent.py +36 -43
- jarvis/jarvis_tools/sub_code_agent.py +25 -26
- jarvis/jarvis_tools/virtual_tty.py +55 -33
- jarvis/jarvis_utils/clipboard.py +7 -10
- jarvis/jarvis_utils/config.py +232 -45
- jarvis/jarvis_utils/embedding.py +8 -5
- jarvis/jarvis_utils/fzf.py +8 -8
- jarvis/jarvis_utils/git_utils.py +225 -36
- jarvis/jarvis_utils/globals.py +3 -3
- jarvis/jarvis_utils/http.py +1 -1
- jarvis/jarvis_utils/input.py +99 -48
- jarvis/jarvis_utils/jsonnet_compat.py +465 -0
- jarvis/jarvis_utils/methodology.py +52 -48
- jarvis/jarvis_utils/utils.py +819 -491
- jarvis_ai_assistant-0.7.6.dist-info/METADATA +600 -0
- jarvis_ai_assistant-0.7.6.dist-info/RECORD +218 -0
- {jarvis_ai_assistant-0.3.30.dist-info → jarvis_ai_assistant-0.7.6.dist-info}/entry_points.txt +4 -0
- jarvis/jarvis_agent/config.py +0 -92
- jarvis/jarvis_agent/edit_file_handler.py +0 -296
- jarvis/jarvis_platform/ai8.py +0 -332
- jarvis/jarvis_tools/ask_user.py +0 -54
- jarvis_ai_assistant-0.3.30.dist-info/METADATA +0 -381
- jarvis_ai_assistant-0.3.30.dist-info/RECORD +0 -137
- {jarvis_ai_assistant-0.3.30.dist-info → jarvis_ai_assistant-0.7.6.dist-info}/WHEEL +0 -0
- {jarvis_ai_assistant-0.3.30.dist-info → jarvis_ai_assistant-0.7.6.dist-info}/licenses/LICENSE +0 -0
- {jarvis_ai_assistant-0.3.30.dist-info → jarvis_ai_assistant-0.7.6.dist-info}/top_level.txt +0 -0
|
@@ -4,22 +4,21 @@ sub_code_agent 工具
|
|
|
4
4
|
将子任务交给 CodeAgent 执行,并返回执行结果。
|
|
5
5
|
|
|
6
6
|
约定:
|
|
7
|
-
-
|
|
7
|
+
- 必填参数:task
|
|
8
|
+
- 可选参数:background
|
|
8
9
|
- 不依赖父 Agent,所有配置使用系统默认与全局变量
|
|
9
10
|
- 子Agent必须自动完成(auto_complete=True)且需要summary(need_summary=True)
|
|
10
11
|
"""
|
|
11
12
|
from typing import Any, Dict, List
|
|
12
|
-
import json
|
|
13
13
|
|
|
14
14
|
from jarvis.jarvis_code_agent.code_agent import CodeAgent
|
|
15
15
|
from jarvis.jarvis_utils.globals import delete_agent
|
|
16
16
|
from jarvis.jarvis_utils.config import set_config, get_git_check_mode
|
|
17
|
-
from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
|
18
17
|
|
|
19
18
|
|
|
20
19
|
class SubCodeAgentTool:
|
|
21
20
|
"""
|
|
22
|
-
使用 CodeAgent
|
|
21
|
+
使用 CodeAgent 托管执行子任务,执行完立即清理 CodeAgent 实例。
|
|
23
22
|
- 不注册至全局
|
|
24
23
|
- 使用系统默认/全局配置
|
|
25
24
|
- 启用自动完成与总结
|
|
@@ -27,7 +26,7 @@ class SubCodeAgentTool:
|
|
|
27
26
|
|
|
28
27
|
# 必须与文件名一致,供 ToolRegistry 自动注册
|
|
29
28
|
name = "sub_code_agent"
|
|
30
|
-
description = "将子任务交给 CodeAgent
|
|
29
|
+
description = "将子任务交给 CodeAgent 执行并返回结果(自动完成并生成总结)。"
|
|
31
30
|
parameters = {
|
|
32
31
|
"type": "object",
|
|
33
32
|
"properties": {
|
|
@@ -84,6 +83,7 @@ class SubCodeAgentTool:
|
|
|
84
83
|
parent_agent = None
|
|
85
84
|
except Exception:
|
|
86
85
|
parent_agent = None
|
|
86
|
+
parent_non_interactive = getattr(parent_agent, "non_interactive", None) if parent_agent is not None else None
|
|
87
87
|
model_group = None
|
|
88
88
|
use_tools: List[str] = []
|
|
89
89
|
try:
|
|
@@ -108,21 +108,20 @@ class SubCodeAgentTool:
|
|
|
108
108
|
pass
|
|
109
109
|
|
|
110
110
|
# 依据父Agent已启用工具集,推导 append_tools(作为在 CodeAgent 基础工具上的增量)
|
|
111
|
+
# 禁用 sub_agent 和 sub_code_agent,避免无限递归
|
|
112
|
+
forbidden_tools = {"sub_agent", "sub_code_agent"}
|
|
111
113
|
append_tools = None
|
|
112
114
|
try:
|
|
113
115
|
base_tools = [
|
|
114
116
|
"execute_script",
|
|
115
|
-
"search_web",
|
|
116
|
-
"ask_user",
|
|
117
117
|
"read_code",
|
|
118
|
+
"edit_file",
|
|
118
119
|
"rewrite_file",
|
|
119
|
-
"
|
|
120
|
-
"retrieve_memory",
|
|
121
|
-
"clear_memory",
|
|
122
|
-
"sub_code_agent",
|
|
120
|
+
"lsp_client",
|
|
123
121
|
]
|
|
124
122
|
if use_tools:
|
|
125
|
-
|
|
123
|
+
# 过滤掉基础工具和禁止的工具
|
|
124
|
+
extras = [t for t in use_tools if t not in base_tools and t not in forbidden_tools]
|
|
126
125
|
append_tools = ",".join(extras) if extras else None
|
|
127
126
|
except Exception:
|
|
128
127
|
append_tools = None
|
|
@@ -138,6 +137,7 @@ class SubCodeAgentTool:
|
|
|
138
137
|
need_summary=True,
|
|
139
138
|
append_tools=append_tools,
|
|
140
139
|
tool_group=tool_group,
|
|
140
|
+
non_interactive=parent_non_interactive,
|
|
141
141
|
)
|
|
142
142
|
except SystemExit as se:
|
|
143
143
|
# 将底层 sys.exit 转换为工具错误,避免终止进程
|
|
@@ -155,21 +155,24 @@ class SubCodeAgentTool:
|
|
|
155
155
|
|
|
156
156
|
# 子Agent需要自动完成
|
|
157
157
|
try:
|
|
158
|
-
code_agent.
|
|
159
|
-
# 同步父Agent
|
|
158
|
+
code_agent.auto_complete = True
|
|
159
|
+
# 同步父Agent工具使用集(如可用),但禁用 sub_agent 和 sub_code_agent 避免无限递归
|
|
160
160
|
if use_tools:
|
|
161
|
-
|
|
161
|
+
forbidden_tools = {"sub_agent", "sub_code_agent"}
|
|
162
|
+
filtered_tools = [t for t in use_tools if t not in forbidden_tools]
|
|
163
|
+
if filtered_tools:
|
|
164
|
+
code_agent.set_use_tools(filtered_tools)
|
|
162
165
|
# 同步父Agent的模型名称(如可用),以尽量保持平台与模型一致
|
|
163
166
|
if (
|
|
164
167
|
parent_agent is not None
|
|
165
168
|
and getattr(parent_agent, "model", None)
|
|
166
|
-
and getattr(code_agent
|
|
169
|
+
and getattr(code_agent, "model", None)
|
|
167
170
|
):
|
|
168
171
|
try:
|
|
169
172
|
parent_model_name = parent_agent.model.name() # type: ignore[attr-defined]
|
|
170
173
|
if parent_model_name:
|
|
171
174
|
from typing import Any
|
|
172
|
-
model_obj: Any = getattr(code_agent
|
|
175
|
+
model_obj: Any = getattr(code_agent, "model", None)
|
|
173
176
|
if model_obj is not None:
|
|
174
177
|
model_obj.set_model_name(parent_model_name)
|
|
175
178
|
# 模型有效性校验与回退,确保父Agent模型在子Agent平台上可用
|
|
@@ -179,10 +182,7 @@ class SubCodeAgentTool:
|
|
|
179
182
|
available_names = [m for m, _ in available_models]
|
|
180
183
|
current_model_name = model_obj.name()
|
|
181
184
|
if current_model_name not in available_names:
|
|
182
|
-
|
|
183
|
-
f"检测到子CodeAgent模型 {current_model_name} 不存在于平台 {model_obj.platform_name()} 的可用模型列表,将回退到 {available_names[0]}",
|
|
184
|
-
OutputType.WARNING,
|
|
185
|
-
)
|
|
185
|
+
print(f"⚠️ 检测到子CodeAgent模型 {current_model_name} 不存在于平台 {model_obj.platform_name()} 的可用模型列表,将回退到 {available_names[0]}")
|
|
186
186
|
model_obj.set_model_name(available_names[0])
|
|
187
187
|
except Exception:
|
|
188
188
|
# 获取模型列表或设置模型失败时,保持原设置并继续,交由底层报错处理
|
|
@@ -194,18 +194,17 @@ class SubCodeAgentTool:
|
|
|
194
194
|
|
|
195
195
|
# 执行子任务(无提交信息前后缀)
|
|
196
196
|
ret = code_agent.run(enhanced_task, prefix="", suffix="")
|
|
197
|
-
stdout = ret if isinstance(ret, str) and ret else "任务执行完成"
|
|
198
197
|
|
|
199
|
-
#
|
|
198
|
+
# 主动清理 CodeAgent 实例,避免污染父Agent的全局状态
|
|
200
199
|
try:
|
|
201
|
-
|
|
202
|
-
delete_agent(
|
|
200
|
+
# CodeAgent 现在直接继承 Agent,所以直接使用 code_agent
|
|
201
|
+
delete_agent(code_agent.name)
|
|
203
202
|
except Exception:
|
|
204
203
|
pass
|
|
205
204
|
|
|
206
205
|
return {
|
|
207
206
|
"success": True,
|
|
208
|
-
"stdout":
|
|
207
|
+
"stdout": ret,
|
|
209
208
|
"stderr": "",
|
|
210
209
|
}
|
|
211
210
|
except Exception as e:
|
|
@@ -3,7 +3,6 @@ import os
|
|
|
3
3
|
import sys
|
|
4
4
|
import time
|
|
5
5
|
from typing import Any, Dict, TYPE_CHECKING
|
|
6
|
-
from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
|
7
6
|
|
|
8
7
|
# 为了类型检查,总是导入这些模块
|
|
9
8
|
if TYPE_CHECKING:
|
|
@@ -19,12 +18,7 @@ else:
|
|
|
19
18
|
|
|
20
19
|
class VirtualTTYTool:
|
|
21
20
|
name = "virtual_tty"
|
|
22
|
-
description =
|
|
23
|
-
"控制虚拟终端执行各种操作,如启动终端、输入命令、获取输出等。"
|
|
24
|
-
+ "与execute_script不同,此工具会创建一个持久的虚拟终端会话,可以连续执行多个命令,并保持终端状态。"
|
|
25
|
-
+ "适用于需要交互式操作的场景,如运行需要用户输入的交互式程序(如:ssh连接、sftp传输、gdb/dlv调试等)。"
|
|
26
|
-
+ "注意:Windows平台功能有限,某些Unix特有功能可能不可用。"
|
|
27
|
-
)
|
|
21
|
+
description = "控制虚拟终端执行交互式操作(如ssh、sftp、gdb等)。与execute_script不同,此工具创建持久会话,保持终端状态。Windows平台功能有限。"
|
|
28
22
|
parameters = {
|
|
29
23
|
"type": "object",
|
|
30
24
|
"properties": {
|
|
@@ -42,19 +36,19 @@ class VirtualTTYTool:
|
|
|
42
36
|
},
|
|
43
37
|
"keys": {
|
|
44
38
|
"type": "string",
|
|
45
|
-
"description": "
|
|
39
|
+
"description": "要发送的按键序列(仅当action为send_keys时有效)",
|
|
46
40
|
},
|
|
47
41
|
"add_enter": {
|
|
48
42
|
"type": "boolean",
|
|
49
|
-
"description": "
|
|
43
|
+
"description": "是否在命令末尾自动添加回车符(仅当action为send_keys时有效,默认true)",
|
|
50
44
|
},
|
|
51
45
|
"timeout": {
|
|
52
46
|
"type": "number",
|
|
53
|
-
"description": "等待输出的超时时间(秒,仅当action为send_keys或output
|
|
47
|
+
"description": "等待输出的超时时间(秒,仅当action为send_keys或output时有效,默认5.0)",
|
|
54
48
|
},
|
|
55
49
|
"tty_id": {
|
|
56
50
|
"type": "string",
|
|
57
|
-
"description": "
|
|
51
|
+
"description": "虚拟终端的唯一标识符(默认'default')",
|
|
58
52
|
},
|
|
59
53
|
},
|
|
60
54
|
"required": ["action"],
|
|
@@ -83,6 +77,8 @@ class VirtualTTYTool:
|
|
|
83
77
|
# 确保agent有tty_sessions字典
|
|
84
78
|
if not hasattr(agent, "tty_sessions"):
|
|
85
79
|
agent.tty_sessions = {}
|
|
80
|
+
elif agent.tty_sessions is None:
|
|
81
|
+
agent.tty_sessions = {}
|
|
86
82
|
|
|
87
83
|
# 如果指定的tty_id不存在,为其创建一个新的tty_data
|
|
88
84
|
if tty_id not in agent.tty_sessions:
|
|
@@ -116,9 +112,7 @@ class VirtualTTYTool:
|
|
|
116
112
|
try:
|
|
117
113
|
if action == "launch":
|
|
118
114
|
if args.get("keys", "") != "":
|
|
119
|
-
|
|
120
|
-
"启动虚拟终端时,不能同时指定 keys 参数", OutputType.ERROR
|
|
121
|
-
)
|
|
115
|
+
print("❌ 启动虚拟终端时,不能同时指定 keys 参数")
|
|
122
116
|
return {
|
|
123
117
|
"success": False,
|
|
124
118
|
"stdout": "",
|
|
@@ -127,9 +121,7 @@ class VirtualTTYTool:
|
|
|
127
121
|
|
|
128
122
|
result = self._launch_tty(agent, tty_id)
|
|
129
123
|
if not result["success"]:
|
|
130
|
-
|
|
131
|
-
f"启动虚拟终端 [{tty_id}] 失败", OutputType.ERROR
|
|
132
|
-
)
|
|
124
|
+
print(f"❌ 启动虚拟终端 [{tty_id}] 失败")
|
|
133
125
|
return result
|
|
134
126
|
elif action == "send_keys":
|
|
135
127
|
keys = args.get("keys", "").strip()
|
|
@@ -138,40 +130,32 @@ class VirtualTTYTool:
|
|
|
138
130
|
|
|
139
131
|
result = self._input_command(agent, tty_id, keys, timeout, add_enter)
|
|
140
132
|
if not result["success"]:
|
|
141
|
-
|
|
142
|
-
f"发送按键序列到终端 [{tty_id}] 失败", OutputType.ERROR
|
|
143
|
-
)
|
|
133
|
+
print(f"❌ 发送按键序列到终端 [{tty_id}] 失败")
|
|
144
134
|
return result
|
|
145
135
|
elif action == "output":
|
|
146
136
|
timeout = args.get("timeout", 5.0) # 默认5秒超时
|
|
147
137
|
|
|
148
138
|
result = self._get_output(agent, tty_id, timeout)
|
|
149
139
|
if not result["success"]:
|
|
150
|
-
|
|
151
|
-
f"获取终端 [{tty_id}] 输出失败", OutputType.ERROR
|
|
152
|
-
)
|
|
140
|
+
print(f"❌ 获取终端 [{tty_id}] 输出失败")
|
|
153
141
|
return result
|
|
154
142
|
elif action == "close":
|
|
155
143
|
|
|
156
144
|
result = self._close_tty(agent, tty_id)
|
|
157
145
|
if not result["success"]:
|
|
158
|
-
|
|
159
|
-
f"关闭虚拟终端 [{tty_id}] 失败", OutputType.ERROR
|
|
160
|
-
)
|
|
146
|
+
print(f"❌ 关闭虚拟终端 [{tty_id}] 失败")
|
|
161
147
|
return result
|
|
162
148
|
elif action == "get_screen":
|
|
163
149
|
|
|
164
150
|
result = self._get_screen(agent, tty_id)
|
|
165
151
|
if not result["success"]:
|
|
166
|
-
|
|
167
|
-
f"获取终端 [{tty_id}] 屏幕内容失败", OutputType.ERROR
|
|
168
|
-
)
|
|
152
|
+
print(f"❌ 获取终端 [{tty_id}] 屏幕内容失败")
|
|
169
153
|
return result
|
|
170
154
|
elif action == "list":
|
|
171
155
|
|
|
172
156
|
result = self._list_ttys(agent)
|
|
173
157
|
if not result["success"]:
|
|
174
|
-
|
|
158
|
+
print("❌ 获取虚拟终端列表失败")
|
|
175
159
|
return result
|
|
176
160
|
return {"success": False, "stdout": "", "stderr": "不支持的操作"}
|
|
177
161
|
|
|
@@ -231,6 +215,8 @@ class VirtualTTYTool:
|
|
|
231
215
|
except BlockingIOError:
|
|
232
216
|
continue
|
|
233
217
|
|
|
218
|
+
if output:
|
|
219
|
+
print(f"📥 启动终端时的初始输出 [{tty_id}]:\n{output}")
|
|
234
220
|
return {"success": True, "stdout": output, "stderr": ""}
|
|
235
221
|
|
|
236
222
|
except Exception as e:
|
|
@@ -279,7 +265,7 @@ class VirtualTTYTool:
|
|
|
279
265
|
line = process.stdout.readline()
|
|
280
266
|
if line:
|
|
281
267
|
agent.tty_sessions[tty_id]["output_queue"].put(line)
|
|
282
|
-
except:
|
|
268
|
+
except Exception:
|
|
283
269
|
break
|
|
284
270
|
|
|
285
271
|
output_thread = _threading.Thread(target=read_output, daemon=True)
|
|
@@ -296,6 +282,8 @@ class VirtualTTYTool:
|
|
|
296
282
|
except _queue.Empty:
|
|
297
283
|
continue
|
|
298
284
|
|
|
285
|
+
if output:
|
|
286
|
+
print(f"📥 启动终端时的初始输出 [{tty_id}]:\n{output}")
|
|
299
287
|
return {"success": True, "stdout": output, "stderr": ""}
|
|
300
288
|
|
|
301
289
|
except Exception as e:
|
|
@@ -372,6 +360,8 @@ class VirtualTTYTool:
|
|
|
372
360
|
output += data.decode()
|
|
373
361
|
except BlockingIOError:
|
|
374
362
|
continue
|
|
363
|
+
if output:
|
|
364
|
+
print(f"📥 命令执行后的输出内容 [{tty_id}]:\n{output}")
|
|
375
365
|
return {"success": True, "stdout": output, "stderr": ""}
|
|
376
366
|
|
|
377
367
|
except Exception as e:
|
|
@@ -420,6 +410,8 @@ class VirtualTTYTool:
|
|
|
420
410
|
except Exception: # queue.Empty
|
|
421
411
|
continue
|
|
422
412
|
|
|
413
|
+
if output:
|
|
414
|
+
print(f"📥 命令执行后的输出内容 [{tty_id}]:\n{output}")
|
|
423
415
|
return {"success": True, "stdout": output, "stderr": ""}
|
|
424
416
|
|
|
425
417
|
except Exception as e:
|
|
@@ -472,6 +464,8 @@ class VirtualTTYTool:
|
|
|
472
464
|
break
|
|
473
465
|
except BlockingIOError:
|
|
474
466
|
break
|
|
467
|
+
if output:
|
|
468
|
+
print(f"📥 获取到的输出内容 [{tty_id}]:\n{output}")
|
|
475
469
|
return {"success": True, "stdout": output, "stderr": ""}
|
|
476
470
|
|
|
477
471
|
except Exception as e:
|
|
@@ -503,6 +497,8 @@ class VirtualTTYTool:
|
|
|
503
497
|
except Exception: # queue.Empty
|
|
504
498
|
continue
|
|
505
499
|
|
|
500
|
+
if output:
|
|
501
|
+
print(f"📥 获取到的输出内容 [{tty_id}]:\n{output}")
|
|
506
502
|
return {"success": True, "stdout": output, "stderr": ""}
|
|
507
503
|
|
|
508
504
|
except Exception as e:
|
|
@@ -568,9 +564,35 @@ class VirtualTTYTool:
|
|
|
568
564
|
}
|
|
569
565
|
|
|
570
566
|
try:
|
|
567
|
+
process = agent.tty_sessions[tty_id]["process"]
|
|
571
568
|
# 终止进程
|
|
572
|
-
|
|
573
|
-
|
|
569
|
+
try:
|
|
570
|
+
import subprocess as _subprocess # pylint: disable=import-outside-toplevel
|
|
571
|
+
process.terminate()
|
|
572
|
+
process.wait(timeout=2)
|
|
573
|
+
except _subprocess.TimeoutExpired:
|
|
574
|
+
try:
|
|
575
|
+
process.kill()
|
|
576
|
+
process.wait()
|
|
577
|
+
except Exception:
|
|
578
|
+
pass
|
|
579
|
+
except Exception:
|
|
580
|
+
try:
|
|
581
|
+
process.kill()
|
|
582
|
+
process.wait()
|
|
583
|
+
except Exception:
|
|
584
|
+
pass
|
|
585
|
+
finally:
|
|
586
|
+
# 确保所有文件描述符被关闭
|
|
587
|
+
try:
|
|
588
|
+
if process.stdin:
|
|
589
|
+
process.stdin.close()
|
|
590
|
+
if process.stdout:
|
|
591
|
+
process.stdout.close()
|
|
592
|
+
if process.stderr:
|
|
593
|
+
process.stderr.close()
|
|
594
|
+
except Exception:
|
|
595
|
+
pass
|
|
574
596
|
|
|
575
597
|
# 重置终端数据
|
|
576
598
|
import queue as _queue # pylint: disable=import-outside-toplevel
|
jarvis/jarvis_utils/clipboard.py
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
import platform
|
|
3
3
|
import subprocess
|
|
4
4
|
|
|
5
|
-
from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
|
6
5
|
|
|
7
6
|
|
|
8
7
|
def copy_to_clipboard(text: str) -> None:
|
|
@@ -11,9 +10,9 @@ def copy_to_clipboard(text: str) -> None:
|
|
|
11
10
|
参数:
|
|
12
11
|
text: 要复制的文本
|
|
13
12
|
"""
|
|
14
|
-
|
|
13
|
+
print("ℹ️ --- 剪贴板内容开始 ---")
|
|
15
14
|
print(text)
|
|
16
|
-
|
|
15
|
+
print("ℹ️ --- 剪贴板内容结束 ---")
|
|
17
16
|
|
|
18
17
|
system = platform.system()
|
|
19
18
|
|
|
@@ -33,7 +32,7 @@ def copy_to_clipboard(text: str) -> None:
|
|
|
33
32
|
process.stdin.close()
|
|
34
33
|
return
|
|
35
34
|
except Exception as e:
|
|
36
|
-
|
|
35
|
+
print(f"⚠️ 使用Windows clip命令时出错: {e}")
|
|
37
36
|
|
|
38
37
|
# macOS系统
|
|
39
38
|
elif system == "Darwin":
|
|
@@ -49,7 +48,7 @@ def copy_to_clipboard(text: str) -> None:
|
|
|
49
48
|
process.stdin.close()
|
|
50
49
|
return
|
|
51
50
|
except Exception as e:
|
|
52
|
-
|
|
51
|
+
print(f"⚠️ 使用macOS pbcopy命令时出错: {e}")
|
|
53
52
|
|
|
54
53
|
# Linux系统
|
|
55
54
|
else:
|
|
@@ -68,7 +67,7 @@ def copy_to_clipboard(text: str) -> None:
|
|
|
68
67
|
except FileNotFoundError:
|
|
69
68
|
pass # xsel 未安装,继续尝试下一个
|
|
70
69
|
except Exception as e:
|
|
71
|
-
|
|
70
|
+
print(f"⚠️ 使用xsel时出错: {e}")
|
|
72
71
|
|
|
73
72
|
# 尝试使用 xclip
|
|
74
73
|
try:
|
|
@@ -83,8 +82,6 @@ def copy_to_clipboard(text: str) -> None:
|
|
|
83
82
|
process.stdin.close()
|
|
84
83
|
return
|
|
85
84
|
except FileNotFoundError:
|
|
86
|
-
|
|
87
|
-
"xsel 和 xclip 均未安装, 无法复制到剪贴板", OutputType.WARNING
|
|
88
|
-
)
|
|
85
|
+
print("⚠️ xsel 和 xclip 均未安装, 无法复制到剪贴板")
|
|
89
86
|
except Exception as e:
|
|
90
|
-
|
|
87
|
+
print(f"⚠️ 使用xclip时出错: {e}")
|