aient 1.1.23__py3-none-any.whl → 1.1.25__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.
- aient/core/request.py +2 -2
- aient/plugins/config.py +18 -4
- aient/plugins/excute_command.py +8 -9
- aient/plugins/readonly.py +23 -0
- aient/plugins/write_file.py +5 -2
- aient/prompt/agent.py +107 -0
- aient/utils/scripts.py +161 -2
- {aient-1.1.23.dist-info → aient-1.1.25.dist-info}/METADATA +1 -1
- {aient-1.1.23.dist-info → aient-1.1.25.dist-info}/RECORD +12 -11
- {aient-1.1.23.dist-info → aient-1.1.25.dist-info}/WHEEL +0 -0
- {aient-1.1.23.dist-info → aient-1.1.25.dist-info}/licenses/LICENSE +0 -0
- {aient-1.1.23.dist-info → aient-1.1.25.dist-info}/top_level.txt +0 -0
aient/core/request.py
CHANGED
@@ -341,7 +341,7 @@ async def get_vertex_gemini_payload(request, engine, provider, api_key=None):
|
|
341
341
|
else:
|
342
342
|
location = gemini1
|
343
343
|
|
344
|
-
if "gemini-2.5-pro-exp-03-25" == original_model:
|
344
|
+
if "gemini-2.5-pro-exp-03-25" == original_model or "gemini-2.5-pro-preview-06-05" == original_model:
|
345
345
|
location = gemini2_5_pro_exp
|
346
346
|
|
347
347
|
if "google-vertex-ai" in provider.get("base_url", ""):
|
@@ -362,7 +362,7 @@ async def get_vertex_gemini_payload(request, engine, provider, api_key=None):
|
|
362
362
|
else:
|
363
363
|
url = f"https://aiplatform.googleapis.com/v1/publishers/google/models/{original_model}:{gemini_stream}?key={api_key}"
|
364
364
|
headers.pop("Authorization", None)
|
365
|
-
elif "gemini-2.5-pro-exp-03-25" == original_model:
|
365
|
+
elif "gemini-2.5-pro-exp-03-25" == original_model or "gemini-2.5-pro-preview-06-05" == original_model:
|
366
366
|
url = "https://aiplatform.googleapis.com/v1/projects/{PROJECT_ID}/locations/{LOCATION}/publishers/google/models/{MODEL_ID}:{stream}".format(
|
367
367
|
LOCATION=await location.next(),
|
368
368
|
PROJECT_ID=project_id,
|
aient/plugins/config.py
CHANGED
@@ -8,10 +8,25 @@ from ..utils.prompt import search_key_word_prompt
|
|
8
8
|
async def get_tools_result_async(function_call_name, function_full_response, function_call_max_tokens, engine, robot, api_key, api_url, use_plugins, model, add_message, convo_id, language):
|
9
9
|
function_response = ""
|
10
10
|
function_to_call = None
|
11
|
+
call_args = json.loads(function_full_response)
|
11
12
|
if function_call_name in registry.tools:
|
12
13
|
function_to_call = registry.tools[function_call_name]
|
14
|
+
call_args_name_list = call_args.keys()
|
15
|
+
required_args = registry.tools_info[function_call_name].args
|
16
|
+
invalid_args = [arg_name for arg_name in call_args_name_list if arg_name not in required_args]
|
17
|
+
if invalid_args:
|
18
|
+
function_response = (
|
19
|
+
"function_response:"
|
20
|
+
"<tool_error>"
|
21
|
+
f"无效的参数: {invalid_args}"
|
22
|
+
f"{function_call_name} 只允许使用以下参数: {required_args}"
|
23
|
+
"</tool_error>"
|
24
|
+
)
|
25
|
+
yield function_response
|
26
|
+
return
|
27
|
+
|
13
28
|
if function_call_name == "get_search_results":
|
14
|
-
prompt =
|
29
|
+
prompt = call_args["query"]
|
15
30
|
yield "message_search_stage_1"
|
16
31
|
llm = robot(api_key=api_key, api_url=api_url, engine=engine, use_plugins=use_plugins)
|
17
32
|
keywords = (await llm.ask_async(search_key_word_prompt.format(source=prompt), model=model)).split("\n")
|
@@ -38,11 +53,10 @@ async def get_tools_result_async(function_call_name, function_full_response, fun
|
|
38
53
|
function_response = "无法找到相关信息,停止使用 tools"
|
39
54
|
|
40
55
|
elif function_to_call:
|
41
|
-
prompt = json.loads(function_full_response)
|
42
56
|
if inspect.iscoroutinefunction(function_to_call):
|
43
|
-
function_response = await function_to_call(**
|
57
|
+
function_response = await function_to_call(**call_args)
|
44
58
|
else:
|
45
|
-
function_response = function_to_call(**
|
59
|
+
function_response = function_to_call(**call_args)
|
46
60
|
|
47
61
|
function_response = (
|
48
62
|
f"function_response:{function_response}"
|
aient/plugins/excute_command.py
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
import subprocess
|
2
2
|
from .registry import register_tool
|
3
|
+
from ..utils.scripts import sandbox
|
3
4
|
|
4
5
|
import re
|
5
|
-
import html
|
6
6
|
import os
|
7
|
+
import html
|
7
8
|
import select
|
8
9
|
|
9
10
|
# 检查是否在 Unix-like 系统上 (pty 模块主要用于 Unix)
|
@@ -99,17 +100,15 @@ def excute_command(command):
|
|
99
100
|
# 在 Unix-like 系统上使用 pty 以支持 tqdm 等库的 ANSI 转义序列
|
100
101
|
master_fd, slave_fd = pty.openpty()
|
101
102
|
|
102
|
-
process =
|
103
|
+
process = sandbox.Popen(
|
103
104
|
command,
|
104
105
|
shell=True,
|
105
|
-
stdin=subprocess.PIPE,
|
106
|
+
stdin=subprocess.PIPE,
|
106
107
|
stdout=slave_fd,
|
107
|
-
stderr=slave_fd,
|
108
|
-
close_fds=True,
|
109
|
-
# bufsize=1, # 移除此行:pty 通常处理字节,且 bufsize=1 会导致 stdin 的二进制模式警告
|
110
|
-
# universal_newlines=True # pty 通常处理字节,解码在读取端进行
|
108
|
+
stderr=slave_fd,
|
109
|
+
close_fds=True,
|
111
110
|
)
|
112
|
-
os.close(slave_fd)
|
111
|
+
os.close(slave_fd)
|
113
112
|
|
114
113
|
# print(f"--- 开始执行命令 (PTY): {command} ---")
|
115
114
|
while True:
|
@@ -142,7 +141,7 @@ def excute_command(command):
|
|
142
141
|
else:
|
143
142
|
# 在非 Unix 系统上,回退到原始的 subprocess.PIPE 行为
|
144
143
|
# tqdm 进度条可能不会像在终端中那样动态更新
|
145
|
-
process =
|
144
|
+
process = sandbox.Popen(
|
146
145
|
command,
|
147
146
|
shell=True,
|
148
147
|
stdout=subprocess.PIPE,
|
@@ -0,0 +1,23 @@
|
|
1
|
+
from ..utils.scripts import sandbox
|
2
|
+
|
3
|
+
from .registry import register_tool
|
4
|
+
|
5
|
+
@register_tool()
|
6
|
+
def set_readonly_path(path: str):
|
7
|
+
"""
|
8
|
+
将指定的文件或目录路径设置为只读。
|
9
|
+
|
10
|
+
这个函数将一个路径添加到只读路径列表中。一旦被设置为只读,
|
11
|
+
任何对该路径的写操作都将被禁止。
|
12
|
+
|
13
|
+
Args:
|
14
|
+
path (str): 需要设置为只读的文件或目录的路径。
|
15
|
+
|
16
|
+
Returns:
|
17
|
+
str: 操作成功或失败的提示信息。
|
18
|
+
"""
|
19
|
+
status = sandbox.add_readonly_path(path)
|
20
|
+
if status == "Success":
|
21
|
+
return f"路径 '{path}' 已成功设置为只读。"
|
22
|
+
else:
|
23
|
+
return f"系统未启用该功能,无法设置只读路径。"
|
aient/plugins/write_file.py
CHANGED
@@ -61,8 +61,11 @@ Example: Requesting to write to frontend-config.json
|
|
61
61
|
content = "\n\n" + content
|
62
62
|
|
63
63
|
# 写入文件
|
64
|
-
|
65
|
-
|
64
|
+
try:
|
65
|
+
with open(path, mode, encoding='utf-8') as file:
|
66
|
+
file.write(unescape_html(content))
|
67
|
+
except PermissionError as e:
|
68
|
+
return f"写入文件失败: {e}"
|
66
69
|
|
67
70
|
return f"已成功写入文件:{path}"
|
68
71
|
|
aient/prompt/agent.py
CHANGED
@@ -138,6 +138,113 @@ instruction_system_prompt = """
|
|
138
138
|
|
139
139
|
当前时间:{current_time}
|
140
140
|
|
141
|
+
你的输出必须符合以下步骤,以生成最终指令:
|
142
|
+
|
143
|
+
1. **回顾与分析 (Review & Analyze):**
|
144
|
+
- 回顾工作智能体的历史对话,分析当前任务的进度和已完成的步骤。其中user就是你发送给工作智能体的指令。assistant就是工作智能体的回复。
|
145
|
+
- 根据任务目标和当前进度,分析还需要哪些步骤。明确最终目标与当前状态之间的差距。
|
146
|
+
|
147
|
+
2. **推理 (Reasoning):**
|
148
|
+
- **自我批判与修正:** 检查工作智能体是否陷入困境或偏离轨道。如果你的上一条指令效果不佳/非预期,分析原因并调整策略,思考可能的原因和解决方案。
|
149
|
+
- **规划:** 构思一个或多个能够完成任务的行动序列(即指令序列)。
|
150
|
+
- **假设生成与检验:** 评估每个规划的潜在结果和可行性。如果主要方案存在风险,请准备备选方案。
|
151
|
+
- **工具调用:** 检查工作智能体可以使用哪些工具,然后确定需要调用哪些工具。请明确要求工作智能体使用特定工具。如果工作智能体不清楚工具的参数,请直接告诉它。
|
152
|
+
|
153
|
+
3. **生成指令 (Generate Instructions):**
|
154
|
+
- 基于以上推理,选择最优的行动方案,并将其转化为对工作智能体清晰、明确、可执行的指令。
|
155
|
+
- 将最终指令放入 `<instructions>` 标签中。
|
156
|
+
|
157
|
+
你的回复格式如下:
|
158
|
+
|
159
|
+
{{1. 回顾与分析}}
|
160
|
+
|
161
|
+
{{2. 推理过程
|
162
|
+
- 自我批判与修正: ...
|
163
|
+
- 规划: ...
|
164
|
+
- 假设生成与检验: ...
|
165
|
+
- 工具调用: ...
|
166
|
+
}}
|
167
|
+
|
168
|
+
<instructions>
|
169
|
+
{{work_agent_instructions}}
|
170
|
+
</instructions>
|
171
|
+
|
172
|
+
工具使用规范如下:
|
173
|
+
|
174
|
+
Tool uses are formatted using XML-style tags.
|
175
|
+
The **actual name of the tool** (e.g., `read_file`, `edit_file`) must be used as the main XML tag.
|
176
|
+
Do **NOT** use literal placeholder strings like `<tool_name>`, `<parameter1_name>`, or `<tool_name1>` as actual XML tags. These are for illustration only. Always use the specific tool name and its defined parameter names.
|
177
|
+
|
178
|
+
Here's how to structure a single tool call. Replace `actual_tool_name_here` with the specific tool's name, and `parameter_name` with actual parameter names for that tool:
|
179
|
+
|
180
|
+
<actual_tool_name_here>
|
181
|
+
<parameter_name>value</parameter_name>
|
182
|
+
<another_parameter_name>another_value</another_parameter_name>
|
183
|
+
...
|
184
|
+
</actual_tool_name_here>
|
185
|
+
|
186
|
+
For example, to use the `read_file` tool:
|
187
|
+
|
188
|
+
<read_file>
|
189
|
+
<file_path>/path/to/file.txt</file_path>
|
190
|
+
</read_file>
|
191
|
+
|
192
|
+
If you need to call multiple tools in one turn, list each tool call's XML structure sequentially. For example:
|
193
|
+
|
194
|
+
<actual_tool_name1_here>
|
195
|
+
<parameter1_name>value1</parameter1_name>
|
196
|
+
...
|
197
|
+
</actual_tool_name1_here>
|
198
|
+
|
199
|
+
...
|
200
|
+
<actual_tool_name2_here>
|
201
|
+
<parameter1_name>value1</parameter1_name>
|
202
|
+
...
|
203
|
+
</actual_tool_name2_here>
|
204
|
+
|
205
|
+
When calling tools in parallel, multiple different or the same tools can be invoked simultaneously.
|
206
|
+
|
207
|
+
bash命令使用 excute_command 工具指示工作智能体。禁止使用 bash 代码块。
|
208
|
+
|
209
|
+
For example:
|
210
|
+
|
211
|
+
错误示范:
|
212
|
+
```bash
|
213
|
+
cd /Users/yanyuming/Downloads/GitHub
|
214
|
+
git clone https://github.com/bartbussmann/BatchTopK.git
|
215
|
+
```
|
216
|
+
|
217
|
+
正确示范:
|
218
|
+
<excute_command>
|
219
|
+
<command>
|
220
|
+
cd /path/to/directory
|
221
|
+
git clone https://github.com/username/project-name.git
|
222
|
+
</command>
|
223
|
+
</excute_command>
|
224
|
+
|
225
|
+
工作智能体仅可以使用如下工具:
|
226
|
+
<tools>
|
227
|
+
{tools_list}
|
228
|
+
</tools>
|
229
|
+
|
230
|
+
<work_agent_conversation_start>
|
231
|
+
"""
|
232
|
+
|
233
|
+
old_instruction_system_prompt = """
|
234
|
+
你是一个指令生成器,负责指导另一个智能体完成任务。
|
235
|
+
你需要分析工作智能体的对话历史,并生成下一步指令。
|
236
|
+
根据任务目标和当前进度,提供清晰明确的指令。
|
237
|
+
持续引导工作智能体直到任务完成。
|
238
|
+
如果你给出了工具调用明确的指令,但是assistant没有通过xml格式调用工具,却认为自己已经调用了,请提醒他必须自己使用xml格式调用。
|
239
|
+
|
240
|
+
你需要称呼工作智能体为“你”,指令禁止使用疑问句,必须使用祈使句。
|
241
|
+
所有回复必须使用中文。
|
242
|
+
运行工作智能体的系统信息:{os_version}
|
243
|
+
你的工作目录为:{workspace_path},请在指令中使用绝对路径。所有操作必须基于工作目录。
|
244
|
+
禁止在工作目录之外进行任何操作。你当前运行目录不一定就是工作目录。禁止默认你当前就在工作目录。
|
245
|
+
|
246
|
+
当前时间:{current_time}
|
247
|
+
|
141
248
|
你的输出必须符合以下步骤:
|
142
249
|
|
143
250
|
1. 首先分析当前对话历史。其中user就是你发送给工作智能体的指令。assistant就是工作智能体的回复。
|
aient/utils/scripts.py
CHANGED
@@ -202,6 +202,158 @@ def parse_tools_from_cursor_prompt(text):
|
|
202
202
|
print(f"解析 JSON 时出错: {e}")
|
203
203
|
return []
|
204
204
|
|
205
|
+
import sys
|
206
|
+
import shlex
|
207
|
+
import builtins
|
208
|
+
import subprocess
|
209
|
+
|
210
|
+
# --- 沙箱配置 ---
|
211
|
+
# 从环境变量 'SANDBOX_READONLY_PATHS' 读取只读路径列表(可以是文件或目录)。
|
212
|
+
# 示例: export SANDBOX_READONLY_PATHS="/path/to/file.txt:/path/to/dir"
|
213
|
+
readonly_paths_str = os.getenv('SANDBOX_READONLY_PATHS', '')
|
214
|
+
READONLY_PATHS = [p for p in readonly_paths_str.split(os.pathsep) if p]
|
215
|
+
|
216
|
+
# --- 子进程注入代码 (更智能的版本) ---
|
217
|
+
INJECTION_CODE = """
|
218
|
+
import builtins
|
219
|
+
import os
|
220
|
+
import sys
|
221
|
+
import runpy
|
222
|
+
|
223
|
+
# 1. 从环境变量中获取沙箱规则并设置补丁
|
224
|
+
# 子进程从和父进程完全相同的环境变量中读取配置
|
225
|
+
readonly_paths_str = os.getenv('SANDBOX_READONLY_PATHS', '')
|
226
|
+
readonly_paths = [os.path.abspath(p) for p in readonly_paths_str.split(os.pathsep) if p]
|
227
|
+
original_open = builtins.open
|
228
|
+
|
229
|
+
def _is_path_protected(target_path):
|
230
|
+
abs_target_path = os.path.abspath(target_path)
|
231
|
+
for readonly_path in readonly_paths:
|
232
|
+
if abs_target_path == readonly_path or abs_target_path.startswith(readonly_path + os.sep):
|
233
|
+
return True
|
234
|
+
return False
|
235
|
+
|
236
|
+
def _sandboxed_open(file, mode='r', *args, **kwargs):
|
237
|
+
is_write_mode = 'w' in mode or 'a' in mode or 'x' in mode or '+' in mode
|
238
|
+
if is_write_mode and _is_path_protected(file):
|
239
|
+
raise PermissionError(f"路径 '{file}' 被设为只读,禁止写入。")
|
240
|
+
return original_open(file, mode, *args, **kwargs)
|
241
|
+
|
242
|
+
builtins.open = _sandboxed_open
|
243
|
+
|
244
|
+
# 2. 智能判断原始命令是脚本还是模块,并执行
|
245
|
+
original_argv = sys.argv[1:]
|
246
|
+
if original_argv and original_argv[0] == '-m':
|
247
|
+
sys.argv = original_argv[1:]
|
248
|
+
runpy.run_module(sys.argv[0], run_name='__main__')
|
249
|
+
elif original_argv:
|
250
|
+
target_path = original_argv[0]
|
251
|
+
sys.argv = original_argv
|
252
|
+
# 使用原始的 open 来读取要执行的脚本,因为它本身不应受沙箱限制
|
253
|
+
with original_open(target_path, 'r') as f:
|
254
|
+
code = compile(f.read(), target_path, 'exec')
|
255
|
+
exec(code, {'__name__': '__main__'})
|
256
|
+
else:
|
257
|
+
pass
|
258
|
+
"""
|
259
|
+
|
260
|
+
class Sandbox:
|
261
|
+
"""一个通过猴子补丁实现文件访问控制的沙箱,支持向子进程注入。"""
|
262
|
+
def __init__(self, readonly_paths):
|
263
|
+
self._readonly_paths = [os.path.abspath(p) for p in readonly_paths]
|
264
|
+
self._original_open = builtins.open
|
265
|
+
self.is_active = bool(self._readonly_paths) # 如果没有只读路径,则沙箱不激活
|
266
|
+
|
267
|
+
def _is_path_protected(self, target_path):
|
268
|
+
"""检查给定路径是否位于或就是只读路径之一"""
|
269
|
+
abs_target_path = os.path.abspath(target_path)
|
270
|
+
for readonly_path in self._readonly_paths:
|
271
|
+
if abs_target_path == readonly_path or abs_target_path.startswith(readonly_path + os.sep):
|
272
|
+
return True
|
273
|
+
return False
|
274
|
+
|
275
|
+
def _sandboxed_open(self, file, mode='r', *args, **kwargs):
|
276
|
+
"""我们自己编写的、带安全检查的 open 函数代理"""
|
277
|
+
is_write_mode = 'w' in mode or 'a' in mode or 'x' in mode or '+' in mode
|
278
|
+
if is_write_mode and self._is_path_protected(file):
|
279
|
+
raise PermissionError(f"路径 '{file}' 被设为只读,禁止写入。")
|
280
|
+
return self._original_open(file, mode, *args, **kwargs)
|
281
|
+
|
282
|
+
def enable(self):
|
283
|
+
"""应用猴子补丁,全局启用沙箱。"""
|
284
|
+
if not self.is_active:
|
285
|
+
return
|
286
|
+
builtins.open = self._sandboxed_open
|
287
|
+
|
288
|
+
def disable(self):
|
289
|
+
"""恢复原始的 open 函数,全局禁用沙箱。"""
|
290
|
+
if not self.is_active:
|
291
|
+
return
|
292
|
+
builtins.open = self._original_open
|
293
|
+
|
294
|
+
def add_readonly_path(self, path: str):
|
295
|
+
"""动态添加一个新的只读路径。如果沙箱因此从非激活状态变为激活状态,则会启用沙箱。"""
|
296
|
+
if not path:
|
297
|
+
return "Fail"
|
298
|
+
|
299
|
+
was_active = self.is_active
|
300
|
+
|
301
|
+
abs_path = os.path.abspath(path)
|
302
|
+
if abs_path not in self._readonly_paths:
|
303
|
+
self._readonly_paths.append(abs_path)
|
304
|
+
self.is_active = True # 确保沙箱被激活
|
305
|
+
|
306
|
+
# 如果沙箱之前未激活,但现在因为添加了路径而激活了,则启用它
|
307
|
+
if not was_active and self.is_active:
|
308
|
+
self.enable()
|
309
|
+
|
310
|
+
return "Success"
|
311
|
+
|
312
|
+
def __enter__(self):
|
313
|
+
"""进入 'with' 块时,应用猴子补丁"""
|
314
|
+
self.enable()
|
315
|
+
return self
|
316
|
+
|
317
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
318
|
+
"""退出 'with' 块时,恢复原始的 open 函数"""
|
319
|
+
self.disable()
|
320
|
+
|
321
|
+
def Popen(self, args, **kwargs):
|
322
|
+
"""
|
323
|
+
一个 subprocess.Popen 的安全替代品。
|
324
|
+
如果沙箱未激活,则直接调用原始的 Popen。
|
325
|
+
否则,它会向启动的 Python 子进程中注入沙箱逻辑。
|
326
|
+
对于非 Python 命令,它会直接穿透执行并打印警告。
|
327
|
+
"""
|
328
|
+
if not self.is_active:
|
329
|
+
return subprocess.Popen(args, **kwargs)
|
330
|
+
|
331
|
+
if kwargs.get('shell') and isinstance(args, str):
|
332
|
+
cmd_list = shlex.split(args)
|
333
|
+
elif isinstance(args, list):
|
334
|
+
cmd_list = args
|
335
|
+
else:
|
336
|
+
cmd_list = [args]
|
337
|
+
|
338
|
+
print(f"\n沙箱:拦截到 Popen 请求: {cmd_list}")
|
339
|
+
|
340
|
+
command_name = os.path.basename(cmd_list[0])
|
341
|
+
# 子进程的沙箱配置由环境变量继承,这里无需再手动设置
|
342
|
+
if command_name.startswith('python'):
|
343
|
+
injected_args = [sys.executable, '-c', INJECTION_CODE] + cmd_list[1:]
|
344
|
+
print(f"沙箱:识别为 Python 命令,构造注入命令...")
|
345
|
+
kwargs_no_shell = kwargs.copy()
|
346
|
+
kwargs_no_shell['shell'] = False
|
347
|
+
return subprocess.Popen(injected_args, **kwargs_no_shell)
|
348
|
+
else:
|
349
|
+
print(f"⚠️ 沙箱警告:命令 '{command_name}' 非 Python 命令,将直接执行,不受沙箱保护。")
|
350
|
+
return subprocess.Popen(args, **kwargs)
|
351
|
+
|
352
|
+
# --- 全局沙箱实例 ---
|
353
|
+
# 沙箱现在会自动从环境变量中读取配置
|
354
|
+
sandbox = Sandbox(readonly_paths=READONLY_PATHS)
|
355
|
+
sandbox.enable() # 在模块加载时全局启用沙箱
|
356
|
+
|
205
357
|
from dataclasses import dataclass
|
206
358
|
from typing import List, Callable, Optional, TypeVar, Generic, Union, Dict, Any
|
207
359
|
|
@@ -496,7 +648,7 @@ def parse_function_xml(xml_content: str, check_line_start: bool = True) -> List[
|
|
496
648
|
tag_inner_content = xml_content[tag_end+1:end_pos]
|
497
649
|
|
498
650
|
# 如果是普通辅助标签(如tool_call),则在其内部寻找函数调用
|
499
|
-
if tag_name in ["tool_call", "function_call", "tool", "function"]:
|
651
|
+
if tag_name in ["tool_call", "function_call", "tool", "function", "tools"]:
|
500
652
|
# 递归处理内部内容,此时不再检查行首条件
|
501
653
|
nested_functions = parse_function_xml(tag_inner_content, check_line_start=False)
|
502
654
|
result_functions.extend(nested_functions)
|
@@ -740,7 +892,14 @@ if __name__ == "__main__":
|
|
740
892
|
|
741
893
|
请提供前两个 `excute_command` 的执行结果。
|
742
894
|
"""
|
743
|
-
|
895
|
+
test_xml = """
|
896
|
+
好的,我现在执行第一步。
|
897
|
+
<tools>
|
898
|
+
<list_directory>
|
899
|
+
<path>/Downloads/GitHub/beswarm/work/test</path>
|
900
|
+
</list_directory>
|
901
|
+
</tools>
|
902
|
+
"""
|
744
903
|
print(parse_function_xml(test_xml))
|
745
904
|
|
746
905
|
# 运行本文件:python -m beswarm.aient.src.aient.utils.scripts
|
@@ -4,7 +4,7 @@ aient/core/.gitignore,sha256=5JRRlYYsqt_yt6iFvvzhbqh2FTUQMqwo6WwIuFzlGR8,13
|
|
4
4
|
aient/core/__init__.py,sha256=NxjebTlku35S4Dzr16rdSqSTWUvvwEeACe8KvHJnjPg,34
|
5
5
|
aient/core/log_config.py,sha256=kz2_yJv1p-o3lUQOwA3qh-LSc3wMHv13iCQclw44W9c,274
|
6
6
|
aient/core/models.py,sha256=g6rUcNwSTHwmBzt1epsu_2Re8YRFKVCSXRUIFJZpAb4,7432
|
7
|
-
aient/core/request.py,sha256=
|
7
|
+
aient/core/request.py,sha256=Zp5Q6iZp3OWZt95cZLh0VmbwvF18jXQB88UfA_3AKt8,67279
|
8
8
|
aient/core/response.py,sha256=YphzhA9jtQKzWb3L4XGTp9xJZ2FOzHr1aAMTsi896FQ,33201
|
9
9
|
aient/core/utils.py,sha256=zidsBUBd3KskzcxQcPB1y5x1RhtWcbZeWvmgb4LAadA,27318
|
10
10
|
aient/core/test/test_base_api.py,sha256=pWnycRJbuPSXKKU9AQjWrMAX1wiLC_014Qc9hh5C2Pw,524
|
@@ -22,24 +22,25 @@ aient/models/groq.py,sha256=eXfSOaPxgQEtk4U8qseArN8rFYOFBfMsPwRcDW1nERo,8790
|
|
22
22
|
aient/models/vertex.py,sha256=qVD5l1Q538xXUPulxG4nmDjXE1VoV4yuAkTCpIeJVw0,16795
|
23
23
|
aient/plugins/__init__.py,sha256=p3KO6Aa3Lupos4i2SjzLQw1hzQTigOAfEHngsldrsyk,986
|
24
24
|
aient/plugins/arXiv.py,sha256=yHjb6PS3GUWazpOYRMKMzghKJlxnZ5TX8z9F6UtUVow,1461
|
25
|
-
aient/plugins/config.py,sha256=
|
26
|
-
aient/plugins/excute_command.py,sha256
|
25
|
+
aient/plugins/config.py,sha256=QGyI9LlNaU36GUpY531o7UbTFBB39u7LfS6rrx_RTWw,7103
|
26
|
+
aient/plugins/excute_command.py,sha256=-Meu3CcC8U8Oc2lYf4OpaVQQ3YrIjBmpPEJVgONDkyI,10313
|
27
27
|
aient/plugins/get_time.py,sha256=Ih5XIW5SDAIhrZ9W4Qe5Hs1k4ieKPUc_LAd6ySNyqZk,654
|
28
28
|
aient/plugins/image.py,sha256=ZElCIaZznE06TN9xW3DrSukS7U3A5_cjk1Jge4NzPxw,2072
|
29
29
|
aient/plugins/list_directory.py,sha256=JZVuImecMSfEv6jLqii-0uQJ1UCsrpMNmYlwW3PEDg4,1374
|
30
30
|
aient/plugins/read_file.py,sha256=Lv03AW-gWGzM2esos2vLTXHcceczdTqEO7_vqFT4yoY,8302
|
31
31
|
aient/plugins/read_image.py,sha256=4FbIiMNVFUQpNyiH5ApGSRvOD9ujcXGyuqlGTJMd7ac,4017
|
32
|
+
aient/plugins/readonly.py,sha256=qK5-kBM3NDH1b-otFxFHpAjV5BXEY_e7cTWBcpP7G5k,710
|
32
33
|
aient/plugins/registry.py,sha256=YknzhieU_8nQ3oKlUSSWDB4X7t2Jx0JnqT2Jd9Xsvfk,3574
|
33
34
|
aient/plugins/run_python.py,sha256=dgcUwBunMuDkaSKR5bToudVzSdrXVewktDDFUz_iIOQ,4589
|
34
35
|
aient/plugins/websearch.py,sha256=llxy1U0vJiNMiKvamMr4p7IruLb3nnDR4YErz8TYimc,15215
|
35
|
-
aient/plugins/write_file.py,sha256=
|
36
|
+
aient/plugins/write_file.py,sha256=ndMsQhfMuobvgbFuesxb17zIk9cQIYTd9Gdr6yiiZec,3896
|
36
37
|
aient/prompt/__init__.py,sha256=GBtn6-JDT8KHFCcuPpfSNE_aGddg5p4FEyMCy4BfwGs,20
|
37
|
-
aient/prompt/agent.py,sha256=
|
38
|
+
aient/prompt/agent.py,sha256=ebHYebxbgL-WEAKUs1NPNwxlUMucF3GNNoy3eNZrtIo,29737
|
38
39
|
aient/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
39
40
|
aient/utils/prompt.py,sha256=UcSzKkFE4-h_1b6NofI6xgk3GoleqALRKY8VBaXLjmI,11311
|
40
|
-
aient/utils/scripts.py,sha256=
|
41
|
-
aient-1.1.
|
42
|
-
aient-1.1.
|
43
|
-
aient-1.1.
|
44
|
-
aient-1.1.
|
45
|
-
aient-1.1.
|
41
|
+
aient/utils/scripts.py,sha256=9ihTL2W3z5q6Qh6ZqCYplTEoonL4oSj8MBzpRbvc5IE,35329
|
42
|
+
aient-1.1.25.dist-info/licenses/LICENSE,sha256=XNdbcWldt0yaNXXWB_Bakoqnxb3OVhUft4MgMA_71ds,1051
|
43
|
+
aient-1.1.25.dist-info/METADATA,sha256=Vl_t8k-8RDWtEcGzqhvbrto7O-MxZ4uHnajBG_T6Ndk,4968
|
44
|
+
aient-1.1.25.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
45
|
+
aient-1.1.25.dist-info/top_level.txt,sha256=3oXzrP5sAVvyyqabpeq8A2_vfMtY554r4bVE-OHBrZk,6
|
46
|
+
aient-1.1.25.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|