refactor(agent): unify tools behind API gateway and provider skills

This commit is contained in:
jxxghp
2026-08-31 16:57:46 +08:00
parent fe688aee9c
commit fdba2c7d64
204 changed files with 8282 additions and 24158 deletions

View File

@@ -1,6 +1,8 @@
"""插件持久化数据查询与写用例。"""
"""插件持久化数据查询、投影与写用例。"""
from typing import Protocol
import json
from collections.abc import Callable
from typing import Any, Optional, Protocol
from app.schemas.common import JsonData
@@ -57,3 +59,89 @@ class DeletePluginDataCommand:
except Exception:
self._unit_of_work.rollback()
raise
DEFAULT_PLUGIN_DATA_PREVIEW_CHARS = 12_000
MAX_PLUGIN_DATA_PREVIEW_CHARS = 50_000
PLUGIN_DATA_KEY_PREVIEW_LIMIT = 50
PLUGIN_DATA_TRUNCATION_SUFFIX = "\n...(插件数据内容过长,已截断)"
def clamp_preview_chars(max_chars: Optional[int]) -> int:
"""约束插件数据预览长度,避免结果无限膨胀。"""
if max_chars is None:
return DEFAULT_PLUGIN_DATA_PREVIEW_CHARS
return max(512, min(int(max_chars), MAX_PLUGIN_DATA_PREVIEW_CHARS))
def build_preview_payload(value: Any, max_chars: Optional[int]) -> tuple[bool, int, int, str]:
"""稳定序列化插件数据并生成有界预览。"""
serialized = json.dumps(value, ensure_ascii=False, indent=2, default=str)
preview_limit = clamp_preview_chars(max_chars)
if len(serialized) <= preview_limit:
return False, len(serialized), len(serialized), serialized
preview = serialized[:preview_limit] + PLUGIN_DATA_TRUNCATION_SUFFIX
return True, len(serialized), len(preview), preview
class PluginDataQueryService:
"""查询已安装插件数据并对大结果执行稳定裁剪。"""
def __init__(
self,
repository: PluginDataQueryRepository,
snapshot: Callable[[str], Optional[dict[str, Any]]],
) -> None:
"""注入插件数据仓储和安装态快照查询函数。"""
self._repository = repository
self._snapshot = snapshot
async def query(
self,
plugin_id: str,
*,
key: Optional[str] = None,
max_chars: Optional[int] = None,
) -> dict[str, Any]:
"""读取单键或全部数据,并返回上下文安全的投影。"""
plugin = self._snapshot(plugin_id)
if plugin is None:
raise ValueError(f"插件 {plugin_id} 不存在")
if key:
value = await self._repository.get(plugin_id, key)
if value is None:
return {
**plugin,
"key": key,
"found": False,
"message": f"插件 {plugin_id} 没有数据项 {key}",
}
truncated, total_chars, returned_chars, preview = build_preview_payload(value, max_chars)
result = {
**plugin,
"key": key,
"found": True,
"truncated": truncated,
"total_chars": total_chars,
"returned_chars": returned_chars,
}
result["value_preview" if truncated else "value"] = preview if truncated else value
return result
data = await self._repository.list(plugin_id)
keys = list(data)
result = {
**plugin,
"count": len(data),
"keys": keys[:PLUGIN_DATA_KEY_PREVIEW_LIMIT],
"keys_truncated": len(keys) > PLUGIN_DATA_KEY_PREVIEW_LIMIT,
}
truncated, total_chars, returned_chars, preview = build_preview_payload(data, max_chars)
result.update(
{
"truncated": truncated,
"total_chars": total_chars,
"returned_chars": returned_chars,
"data_preview" if truncated else "data": (preview if truncated else data),
}
)
return result