sycommon-python-lib 0.2.7a11__py3-none-any.whl → 0.2.7a12__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.
- sycommon/agent/deep_agent.py +52 -27
- sycommon/agent/sandbox/file_ops.py +16 -4
- sycommon/agent/sandbox/http_sandbox_backend.py +6 -2
- {sycommon_python_lib-0.2.7a11.dist-info → sycommon_python_lib-0.2.7a12.dist-info}/METADATA +6 -6
- {sycommon_python_lib-0.2.7a11.dist-info → sycommon_python_lib-0.2.7a12.dist-info}/RECORD +8 -8
- {sycommon_python_lib-0.2.7a11.dist-info → sycommon_python_lib-0.2.7a12.dist-info}/WHEEL +0 -0
- {sycommon_python_lib-0.2.7a11.dist-info → sycommon_python_lib-0.2.7a12.dist-info}/entry_points.txt +0 -0
- {sycommon_python_lib-0.2.7a11.dist-info → sycommon_python_lib-0.2.7a12.dist-info}/top_level.txt +0 -0
sycommon/agent/deep_agent.py
CHANGED
|
@@ -1346,46 +1346,67 @@ async def _sync_skills_to_sandbox(
|
|
|
1346
1346
|
版本比较只看沙箱 sandbox_dest/{name}/SKILL.md,无需 MinIO 锚点:
|
|
1347
1347
|
- 沙箱有该技能且 version 一致 → 跳过
|
|
1348
1348
|
- 沙箱没有 / 版本不一致 → 从本地 skills/ 全量上传到沙箱
|
|
1349
|
+
|
|
1350
|
+
性能: 比对与上传均绕过 backend 的懒同步(_skip_lazy_sync=True),
|
|
1351
|
+
避免「比对 read SKILL.md 前先整目录上传」「删除前先上传再删」的往返浪费。
|
|
1352
|
+
多技能的 SKILL.md 比对用 gather 并发; batch_upload 服务端无条件覆盖,
|
|
1353
|
+
无需先删(删除仅在版本不一致时做,用 adelete 走 /delete 而非 /execute)。
|
|
1349
1354
|
"""
|
|
1350
1355
|
if not os.path.isdir(skills_dir):
|
|
1351
1356
|
return
|
|
1352
1357
|
|
|
1353
1358
|
try:
|
|
1354
|
-
#
|
|
1355
|
-
|
|
1356
|
-
tree_result = await backend.atree(sandbox_dest, max_depth=1)
|
|
1357
|
-
if tree_result and tree_result.tree and tree_result.tree.children:
|
|
1358
|
-
for child in tree_result.tree.children:
|
|
1359
|
-
if child.is_dir:
|
|
1360
|
-
existing_dirs.add(child.name)
|
|
1361
|
-
|
|
1362
|
-
skill_count = 0
|
|
1363
|
-
skip_count = 0
|
|
1359
|
+
# 收集本地技能名 + 本地版本(纯本地读,快)
|
|
1360
|
+
local_skills = [] # [(skill_name, local_version, src_path)]
|
|
1364
1361
|
for skill_name in sorted(os.listdir(skills_dir)):
|
|
1365
1362
|
src = os.path.join(skills_dir, skill_name)
|
|
1366
1363
|
if not os.path.isdir(src):
|
|
1367
1364
|
continue
|
|
1368
|
-
|
|
1369
|
-
# 读取本地版本
|
|
1370
|
-
local_skill_md = os.path.join(src, "SKILL.md")
|
|
1371
1365
|
local_version = ""
|
|
1366
|
+
local_skill_md = os.path.join(src, "SKILL.md")
|
|
1372
1367
|
if os.path.isfile(local_skill_md):
|
|
1373
1368
|
try:
|
|
1374
1369
|
with open(local_skill_md, "r", encoding="utf-8") as f:
|
|
1375
1370
|
local_version = _parse_skill_version(f.read())
|
|
1376
1371
|
except Exception:
|
|
1377
1372
|
pass
|
|
1373
|
+
local_skills.append((skill_name, local_version, src))
|
|
1378
1374
|
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1375
|
+
# 获取沙箱 sandbox_dest 下已有的目录列表(一次 atree)
|
|
1376
|
+
existing_dirs = set()
|
|
1377
|
+
tree_result = await backend.atree(sandbox_dest, max_depth=1)
|
|
1378
|
+
if tree_result and tree_result.tree and tree_result.tree.children:
|
|
1379
|
+
for child in tree_result.tree.children:
|
|
1380
|
+
if child.is_dir:
|
|
1381
|
+
existing_dirs.add(child.name)
|
|
1382
|
+
|
|
1383
|
+
# 并发读取所有已存在技能的沙箱 SKILL.md 比对版本(跳过懒同步)
|
|
1384
|
+
async def _read_remote_version(skill_name: str) -> str:
|
|
1385
|
+
if skill_name not in existing_dirs:
|
|
1386
|
+
return ""
|
|
1387
|
+
try:
|
|
1388
|
+
remote_content = await backend.aread(
|
|
1389
|
+
f"{sandbox_dest}/{skill_name}/SKILL.md",
|
|
1390
|
+
_skip_lazy_sync=True)
|
|
1391
|
+
if remote_content and remote_content.file_data:
|
|
1392
|
+
# FileData 是 TypedDict(dict), 用键访问而非属性
|
|
1393
|
+
return _parse_skill_version(
|
|
1394
|
+
remote_content.file_data.get("content", "") or "")
|
|
1395
|
+
except Exception:
|
|
1396
|
+
pass
|
|
1397
|
+
return ""
|
|
1398
|
+
|
|
1399
|
+
remote_versions = await asyncio.gather(
|
|
1400
|
+
*[_read_remote_version(name) for name, _, _ in local_skills]
|
|
1401
|
+
)
|
|
1402
|
+
remote_version_map = {
|
|
1403
|
+
name: rv for (name, _, _), rv in zip(local_skills, remote_versions)
|
|
1404
|
+
}
|
|
1405
|
+
|
|
1406
|
+
skill_count = 0
|
|
1407
|
+
skip_count = 0
|
|
1408
|
+
for skill_name, local_version, src in local_skills:
|
|
1409
|
+
remote_version = remote_version_map.get(skill_name, "")
|
|
1389
1410
|
|
|
1390
1411
|
if remote_version and remote_version == local_version:
|
|
1391
1412
|
SYLogger.debug(
|
|
@@ -1394,10 +1415,13 @@ async def _sync_skills_to_sandbox(
|
|
|
1394
1415
|
skip_count += 1
|
|
1395
1416
|
continue
|
|
1396
1417
|
|
|
1397
|
-
#
|
|
1418
|
+
# 版本不一致或无版本,删除旧目录(走 /delete,跳过懒同步,毫秒级)
|
|
1398
1419
|
if skill_name in existing_dirs:
|
|
1399
1420
|
try:
|
|
1400
|
-
await backend.
|
|
1421
|
+
await backend.adelete(
|
|
1422
|
+
f"{sandbox_dest}/{skill_name}",
|
|
1423
|
+
recursive=True,
|
|
1424
|
+
_skip_lazy_sync=True)
|
|
1401
1425
|
SYLogger.info(
|
|
1402
1426
|
f"[DeepAgent] 技能版本不一致,覆盖: {skill_name} "
|
|
1403
1427
|
f"({remote_version or '无版本'} → {local_version})")
|
|
@@ -1405,7 +1429,7 @@ async def _sync_skills_to_sandbox(
|
|
|
1405
1429
|
SYLogger.warning(
|
|
1406
1430
|
f"[DeepAgent] 删除旧版技能失败: {skill_name}, {e}")
|
|
1407
1431
|
|
|
1408
|
-
# 全量上传整个技能目录到沙箱
|
|
1432
|
+
# 全量上传整个技能目录到沙箱(batch_upload 服务端无条件覆盖)
|
|
1409
1433
|
await backend.async_sync_dirs([(src, f"{sandbox_dest}/{skill_name}")])
|
|
1410
1434
|
backend._synced_skills.add(skill_name)
|
|
1411
1435
|
skill_count += 1
|
|
@@ -1417,7 +1441,8 @@ async def _sync_skills_to_sandbox(
|
|
|
1417
1441
|
# sandbox_dest 是虚拟绝对路径(/skills/system),沙箱 shell 不重映射裸绝对路径,
|
|
1418
1442
|
# 须拼 $_SANDBOX_WORKSPACE 指向真实 workspace 才能命中。否则 chmod 静默失败。
|
|
1419
1443
|
await backend.aexecute(
|
|
1420
|
-
f'chmod -R 555 "$_SANDBOX_WORKSPACE{sandbox_dest}"'
|
|
1444
|
+
f'chmod -R 555 "$_SANDBOX_WORKSPACE{sandbox_dest}"',
|
|
1445
|
+
_skip_lazy_sync=True)
|
|
1421
1446
|
SYLogger.info(f"[DeepAgent] 已设只读: chmod -R 555 {sandbox_dest}")
|
|
1422
1447
|
except Exception as e:
|
|
1423
1448
|
SYLogger.warning(f"[DeepAgent] chmod 只读失败(忽略): {e}")
|
|
@@ -333,11 +333,17 @@ class FileOperationsMixin:
|
|
|
333
333
|
limit: int = 2000,
|
|
334
334
|
*,
|
|
335
335
|
timeout: int = None,
|
|
336
|
+
_skip_lazy_sync: bool = False,
|
|
336
337
|
) -> ReadResult:
|
|
337
|
-
"""异步读取文件内容
|
|
338
|
+
"""异步读取文件内容
|
|
339
|
+
|
|
340
|
+
_skip_lazy_sync=True 时跳过懒同步(供内部技能版本比对用,
|
|
341
|
+
避免 read SKILL.md 触发整目录上传)。
|
|
342
|
+
"""
|
|
338
343
|
try:
|
|
339
344
|
# 按需懒同步:检测是否读取 skill 资源
|
|
340
|
-
|
|
345
|
+
if not _skip_lazy_sync:
|
|
346
|
+
await self._lazy_sync_skill_from_path(file_path)
|
|
341
347
|
|
|
342
348
|
await self._ensure_synced_async()
|
|
343
349
|
SYLogger.info(
|
|
@@ -738,10 +744,16 @@ class FileOperationsMixin:
|
|
|
738
744
|
recursive: bool = False,
|
|
739
745
|
*,
|
|
740
746
|
timeout: int = None,
|
|
747
|
+
_skip_lazy_sync: bool = False,
|
|
741
748
|
) -> DeleteResult:
|
|
742
|
-
"""异步删除文件或文件夹
|
|
749
|
+
"""异步删除文件或文件夹
|
|
750
|
+
|
|
751
|
+
_skip_lazy_sync=True 时跳过懒同步(供内部技能覆盖删除用,
|
|
752
|
+
避免「删之前先把要删的技能上传一遍」的浪费)。
|
|
753
|
+
"""
|
|
743
754
|
try:
|
|
744
|
-
|
|
755
|
+
if not _skip_lazy_sync:
|
|
756
|
+
await self._lazy_sync_skill_from_path(path)
|
|
745
757
|
await self._ensure_synced_async()
|
|
746
758
|
SYLogger.info(f"[Sandbox] 异步删除: {path} (recursive={recursive})")
|
|
747
759
|
result = await self._post_async_with_failover(f"{SANDBOX_API_PREFIX}/delete", {
|
|
@@ -813,17 +813,21 @@ class HTTPSandboxBackend(FileOperationsMixin, SandboxBackendProtocol):
|
|
|
813
813
|
truncated=False
|
|
814
814
|
)
|
|
815
815
|
|
|
816
|
-
async def aexecute(self, command: str, *, timeout: int = None) -> ExecuteResponse:
|
|
816
|
+
async def aexecute(self, command: str, *, timeout: int = None, _skip_lazy_sync: bool = False) -> ExecuteResponse:
|
|
817
817
|
"""异步执行 shell 命令(服务端负责路径隔离和目录初始化)
|
|
818
818
|
|
|
819
819
|
如果命令引用了 /skills/<name>/ 下的资源,
|
|
820
820
|
会自动按需同步该 skill 的整个目录到沙箱。
|
|
821
|
+
|
|
822
|
+
_skip_lazy_sync=True 时跳过懒同步(仅供内部技能同步/删除使用,
|
|
823
|
+
避免删前先传、比对前先传的往返浪费)。
|
|
821
824
|
"""
|
|
822
825
|
command = self._inject_env(command)
|
|
823
826
|
SYLogger.info(f"[Sandbox] aexecute 开始: command={command}")
|
|
824
827
|
|
|
825
828
|
# 按需懒同步:检测命令中是否引用了 skill 资源
|
|
826
|
-
|
|
829
|
+
if not _skip_lazy_sync:
|
|
830
|
+
await self._lazy_sync_skill_from_path(command)
|
|
827
831
|
|
|
828
832
|
await self._ensure_synced_async()
|
|
829
833
|
SYLogger.info(f"[Sandbox] _ensure_synced_async 完成,开始执行命令: {command}")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sycommon-python-lib
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.7a12
|
|
4
4
|
Summary: Add your description here
|
|
5
5
|
Requires-Python: >=3.11
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
@@ -11,14 +11,14 @@ Requires-Dist: anyio==4.14.1
|
|
|
11
11
|
Requires-Dist: decorator==5.3.1
|
|
12
12
|
Requires-Dist: deepagents==0.6.12
|
|
13
13
|
Requires-Dist: elasticsearch==9.4.1
|
|
14
|
-
Requires-Dist: fastapi==0.
|
|
14
|
+
Requires-Dist: fastapi==0.139.0
|
|
15
15
|
Requires-Dist: jinja2==3.1.6
|
|
16
|
-
Requires-Dist: kafka-python==3.0.
|
|
16
|
+
Requires-Dist: kafka-python==3.0.7
|
|
17
17
|
Requires-Dist: langchain==1.3.11
|
|
18
18
|
Requires-Dist: langchain-core==1.4.8
|
|
19
19
|
Requires-Dist: langchain-openai==1.3.3
|
|
20
|
-
Requires-Dist: langfuse==4.
|
|
21
|
-
Requires-Dist: langgraph==1.2.
|
|
20
|
+
Requires-Dist: langfuse==4.13.0
|
|
21
|
+
Requires-Dist: langgraph==1.2.7
|
|
22
22
|
Requires-Dist: langgraph-checkpoint-postgres==3.1.0
|
|
23
23
|
Requires-Dist: langgraph-checkpoint-redis==0.5.0
|
|
24
24
|
Requires-Dist: ldap3==2.9.1
|
|
@@ -32,7 +32,7 @@ Requires-Dist: python-dotenv==1.2.2
|
|
|
32
32
|
Requires-Dist: python-multipart==0.0.32
|
|
33
33
|
Requires-Dist: pyyaml==6.0.3
|
|
34
34
|
Requires-Dist: redis==7.4.0
|
|
35
|
-
Requires-Dist: sentry-sdk[fastapi]==2.
|
|
35
|
+
Requires-Dist: sentry-sdk[fastapi]==2.64.0
|
|
36
36
|
Requires-Dist: sqlalchemy[asyncio]==2.0.51
|
|
37
37
|
Requires-Dist: starlette[full]==1.3.1
|
|
38
38
|
Requires-Dist: tiktoken==0.13.0
|
|
@@ -136,7 +136,7 @@ sycommon/services.py,sha256=CwC_gESafo05Qn41KLQgtulx6PfX7s2FkxlBI-hXve4,24861
|
|
|
136
136
|
sycommon/agent/__init__.py,sha256=mxceAeUifQ-DKvWp7ZEJIFlmOCb5wpYHPGQw3rwEN8I,4378
|
|
137
137
|
sycommon/agent/agent_manager.py,sha256=UhhaekEumT7g4v_Z1UB4jTp13X0n8M8erYaQdkGGWkA,13620
|
|
138
138
|
sycommon/agent/chat_events.py,sha256=t7qWa6OrIWLfqtd1AnqaVP67QWkn1JxpCBTZYQpoLuM,14226
|
|
139
|
-
sycommon/agent/deep_agent.py,sha256=
|
|
139
|
+
sycommon/agent/deep_agent.py,sha256=MtMTTqRTUQ_HPpniGfDkL0t781b_ATxV-btLG5iwSt4,71834
|
|
140
140
|
sycommon/agent/multi_agent_team.py,sha256=IbjwhUMDsW4HMyWr53leWBLeaALO-8iNdxcKL6irfz0,28672
|
|
141
141
|
sycommon/agent/summarization_utils.py,sha256=bqZRFqSekNGlv2mYQPaT_s2QNA5VDTKddi2Va_SkHWc,18376
|
|
142
142
|
sycommon/agent/acp/__init__.py,sha256=vQGMQYAA5-ZaejYmDZ4r4Fklqs17qH3cDXQ5pZlwj-0,1844
|
|
@@ -153,8 +153,8 @@ sycommon/agent/middleware/skill_wl_check.py,sha256=rCJ9F6aWPh8tVQBIPmcq2lKDsfwiJ
|
|
|
153
153
|
sycommon/agent/middleware/skill_write_guard.py,sha256=N7EsHMc87eo5QFLjTxbIcn0kurM1LD3vlfeHSR3jVg4,2557
|
|
154
154
|
sycommon/agent/sandbox/__init__.py,sha256=jR7LlkD4J4Y6QYyRXQClkwmqDBCCPmycV_hQV9p9YHw,4621
|
|
155
155
|
sycommon/agent/sandbox/consistent_hash.py,sha256=8Jgk-W4NAD2-u5_vKRVlPmql_e0Vy4aNORiXOuzvIrs,7277
|
|
156
|
-
sycommon/agent/sandbox/file_ops.py,sha256=
|
|
157
|
-
sycommon/agent/sandbox/http_sandbox_backend.py,sha256=
|
|
156
|
+
sycommon/agent/sandbox/file_ops.py,sha256=knjRqtj_0lGALNXxocg4cCClNuEgd0dtCBtCJsfjbik,33469
|
|
157
|
+
sycommon/agent/sandbox/http_sandbox_backend.py,sha256=ZEAyxEeLR9aJg3REmoeupdsYb5RLarbt7NYoZqPIXxQ,68528
|
|
158
158
|
sycommon/agent/sandbox/minio_sync.py,sha256=HRtw3SwOlgy0G-AsXhWr_1Ob7s-n4Z-9bjpFRfKecTA,23438
|
|
159
159
|
sycommon/agent/sandbox/sandbox_pool.py,sha256=eMn8sLakCWf90l6ni2-333QM8oBdX1CflV-WzneFp_k,9133
|
|
160
160
|
sycommon/agent/sandbox/sandbox_recovery.py,sha256=X-eDODx1tmGMh_iTngV6e1ppfDBHpTdkPreJusN5MHY,7358
|
|
@@ -306,8 +306,8 @@ sycommon/tools/syemail.py,sha256=BDFhgf7WDOQeTcjxJEQdu0dQhnHFPO_p3eI0-Ni3LhQ,561
|
|
|
306
306
|
sycommon/tools/timing.py,sha256=OiiE7P07lRoMzX9kzb8sZU9cDb0zNnqIlY5pWqHcnkY,2064
|
|
307
307
|
sycommon/xxljob/__init__.py,sha256=7eoBlQxv-B39IfRSCY2bkqdGYs1QRe1umAWd88VMEEM,86
|
|
308
308
|
sycommon/xxljob/xxljob_service.py,sha256=1yifwIBNGsCIxLnQjHKiBlbsigc_zvPH-dMTZcNxe-Q,7649
|
|
309
|
-
sycommon_python_lib-0.2.
|
|
310
|
-
sycommon_python_lib-0.2.
|
|
311
|
-
sycommon_python_lib-0.2.
|
|
312
|
-
sycommon_python_lib-0.2.
|
|
313
|
-
sycommon_python_lib-0.2.
|
|
309
|
+
sycommon_python_lib-0.2.7a12.dist-info/METADATA,sha256=emXawvSwauqGcr4C8LfZaoj4SvUBY5PrpJ-iS6a03dc,7962
|
|
310
|
+
sycommon_python_lib-0.2.7a12.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
311
|
+
sycommon_python_lib-0.2.7a12.dist-info/entry_points.txt,sha256=gsR4SssKxDWjRU8ggidzNcdMXDPRSKRS7UaGyNP84Qg,92
|
|
312
|
+
sycommon_python_lib-0.2.7a12.dist-info/top_level.txt,sha256=RgphKrg7nJyZ7irJqbxFr-5H2LUYTvI7ivoWZH2hcD0,29
|
|
313
|
+
sycommon_python_lib-0.2.7a12.dist-info/RECORD,,
|
|
File without changes
|
{sycommon_python_lib-0.2.7a11.dist-info → sycommon_python_lib-0.2.7a12.dist-info}/entry_points.txt
RENAMED
|
File without changes
|
{sycommon_python_lib-0.2.7a11.dist-info → sycommon_python_lib-0.2.7a12.dist-info}/top_level.txt
RENAMED
|
File without changes
|