初始化提交

This commit is contained in:
chenxin committed 2026-08-21 16:00:13 +08:00
commit 887c1f449e
963 files changed
+166869

No files matched your search

@@ -0,0 +1,10 @@
"""百工工具运行时领域结构(ToolSpec / ToolResult / ToolInput)。
工具的实际编排(``ToolRuntime``)与内置工具注册(``builtins``)已迁至
``application/tool_runtime/``——它们需要协调沙箱(integrations)、司命(modules)、
事件存储(services)等多层,属于应用编排而非纯领域。本目录只保留无 IO 的工具规格数据结构。
"""
from app.modules.tool_runtime.definition import ToolInput, ToolResult, ToolSpec
__all__ = ["ToolInput", "ToolResult", "ToolSpec"]
@@ -0,0 +1,92 @@
"""工具定义:ToolSpec 描述工具元数据与请求构造方式,ToolResult 为执行产出。
字段口径对齐 docs/architecture/service-boundaries.md(工具定义字段、风险分级、
权限策略)。工具的实际执行有两条路径:
- 沙箱路径:``build_request`` 产出沙箱 ExecRequest,由 SandboxClient 执行(文件/shell 类)。
- 直接执行路径:``executor`` 非 None 时由 runtime 注入 http_client、密钥等上下文直接执行
(HTTP 类工具如 fetch_url,不走沙箱)。
本模块是纯领域数据结构(无 IO):``ExecRequest`` 仅在类型注解中引用(``TYPE_CHECKING``),
运行时不依赖 ``integrations``;实际 ExecRequest 的构造在 ``application/tool_runtime/``。
"""
from __future__ import annotations
from collections.abc import Awaitable, Callable
from dataclasses import dataclass, field
from typing import TYPE_CHECKING, Any, Protocol
from app.modules.safety.governor import PermissionPolicy
if TYPE_CHECKING:
# 仅类型注解用:build_request 产出沙箱 ExecRequest,但本模块运行时不依赖 integrations
# (保持 modules 零 IO 依赖);实际构造在 application/tool_runtime/builtins。
from app.integrations.sandbox.models import ExecRequest
ToolInput = dict[str, Any]
RequestBuilder = Callable[[ToolInput], "ExecRequest"]
# 前向引用 ToolResult(定义在下方),避免循环依赖;TYPE_CHECKING 下解析为真实类。
ToolExecutor = Callable[[ToolInput, dict[str, Any] | None], Awaitable["ToolResult"]]
class ToolRuntimeLike(Protocol):
"""Agent loop 所需的最小工具运行时契约。"""
async def execute(
self,
tool: str,
input: ToolInput,
*,
run_id: str | None = None,
character_id: str | None = None,
trace_id: str | None = None,
confirmed: bool = False,
context: dict[str, Any] | None = None,
) -> ToolResult: ...
@dataclass(frozen=True)
class ToolResult:
"""工具执行产出(映射沙箱 ExecResponse 或 executor 直接产出)。"""
ok: bool
exit_code: int | None
stdout: str
stderr: str
duration_ms: int
timeout: bool
truncated: bool
trace_id: str
@dataclass(frozen=True)
class ToolSpec:
"""工具规格:名称、风险、权限策略与请求构造器/执行器。
执行路径二选一:
- ``executor`` 非 None:直接执行,跳过沙箱(HTTP 类工具);``build_request`` 此时可为占位。
- ``executor`` 为 None:走沙箱路径,用 ``build_request`` 构造 ExecRequest。
"""
name: str
description: str
risk_level: str # L0–L4
permission_policy: PermissionPolicy
build_request: RequestBuilder = field(default_factory=lambda: _placeholder_builder)
default_timeout_ms: int = 30_000
side_effect: bool = True
audit_required: bool = True
# 是否按 run/trace 隔离工作目录(文件类工具):runtime 会把 workdir 改写为
# ``<workdir>/<run_key>``,防跨 run 信息泄漏与文件名冲突;run_key 经 sanitize 防路径注入。
isolated_workspace: bool = False
# 非 None 时走直接执行路径(HTTP 类工具),跳过沙箱;context 由 runtime 注入。
executor: ToolExecutor | None = None
# 工具入参 JSON Schema(供 LLM 生成正确参数),None 表示无参数。
input_schema: dict[str, Any] | None = None
def _placeholder_builder(
_input: ToolInput,
) -> ExecRequest: # pragma: no cover - 仅占位,executor 工具不走此路径
"""executor 工具的 build_request 占位:正常不应被调用(runtime 见 executor 非 None 会跳过)。"""
raise NotImplementedError("该工具使用 executor 直接执行,不应调用 build_request")