Documentation
¶
Overview ¶
Package tools 的 ToolCapability 协议 -- Agent Tool Safety Protocol.
升华改进(ELEVATED): 定义 Agent Tool Safety Protocol. 文件/数据库/API 三种操作统一为同一套能力声明. 支持 DryRun 的工具会被 Agent 优先选择(因为更安全). 替代方案:所有工具一视同仁,不声明能力(无法区分安全等级).
三个层次:
Level 0: 不支持 DryRun 也不可逆 → Agent 调用前警告 Level 1: Reversible(可回滚)→ Saga 补偿模式 Level 2: DryRun(可预览)→ 先试再做,最安全
Package tools defines the Tool interface (what the engine dispatches) and the capability hooks (DryRunnable / Reversible / MetadataProvider / CapabilityProvider) that let consumers describe tool-level properties to the engine and to UIs/auditors.
Consumer integration surfaces fall into three shapes. For the full taxonomy see `docs/api-reference.md` section "API 消费形态 / API Consumption Patterns".
Synchronous callback — form 3:
- Tool.Execute: engine dispatches the tool with a Request and blocks for *Result. Custom tools implement this — SDK consumers inject via engine.Config.Tools.
Pull — form 2 (metadata / capability description):
- MetadataProvider.Metadata() Metadata — engine reads to classify tool safety (destructive / read-only)
- CapabilityProvider.Capability() ToolCapability — lists AffectedResources / UndoMethod / MinConfidence so UIs can render preview UX
- DryRunnable.DryRun(input) (*DryRunResult, error) — consumer-provided preview of tool effects without executing
- Reversible.Undo(result) / UndoInfo — enables operation history / undo
Package tools 定义 Tool 接口 (引擎分发工具的入口) 和能力钩子 (DryRunnable / Reversible / MetadataProvider / CapabilityProvider), 让消费者向引擎和 UI / 审计面声明工具级属性.
消费者接入面分三种形态. 完整分类见 `docs/api-reference.md` "API 消费形态 / API Consumption Patterns" 章节.
同步回调 (callback) —— 形态三:
- Tool.Execute: 引擎传 Request 阻塞等 *Result. 自定义工具实现此接口, SDK 消费者经 engine.Config.Tools 注入.
调取 (pull) —— 形态二 (元数据 / 能力描述):
- MetadataProvider.Metadata() Metadata —— 引擎据此分类工具安全性 (破坏性 / 只读)
- CapabilityProvider.Capability() ToolCapability —— 列出 AffectedResources / UndoMethod / MinConfidence, 供 UI 渲染预览 UX
- DryRunnable.DryRun(input) —— 消费者提供的工具效果预览, 不真正执行
- Reversible.Undo(result) / UndoInfo —— 支持操作历史 / 撤销
Package tools 定义工具系统的核心接口和注册表.
工具系统的类型定义和接口. 原项目的工具系统有以下问题:
- Tool 定义和 UI 渲染耦合(renderToolResultMessage 直接返回 JSX)
- 并发安全性通过每个工具的 isConcurrencySafe() 方法判断,散落各处
- 权限检查混在工具内部和外部两层
Go 版本的设计:
- Tool 接口只关心执行逻辑,不关心 UI
- 并发安全性和只读性作为元数据声明,由编排器统一调度
- 权限检查完全由 PermissionEngine 负责,工具不参与
Index ¶
- Constants
- func CheckConfidenceGate(cap ToolCapability, input json.RawMessage) (pass bool, errMsg string, stripped json.RawMessage)
- func IsDryRunnable(t Tool) bool
- func IsReversible(t Tool) bool
- func RegisterDeferredTool(name string)
- func WithWorkdir(ctx context.Context, dir string) context.Context
- func WorkdirFromContext(ctx context.Context) string
- type CapabilityProvider
- type DeferredRegistry
- func (dr *DeferredRegistry) ActivateTool(name string)
- func (dr *DeferredRegistry) ActiveTools() []Tool
- func (dr *DeferredRegistry) IsDeferred(name string) bool
- func (dr *DeferredRegistry) Registry() *Registry
- func (dr *DeferredRegistry) ResetActivations()
- func (dr *DeferredRegistry) SearchTools(query string) []Tool
- func (dr *DeferredRegistry) Threshold() int
- func (dr *DeferredRegistry) WithAlwaysLoad(names ...string) *DeferredRegistry
- type DryRunResult
- type DryRunnable
- type Metadata
- type MetadataProvider
- type Orchestrator
- type ProgressFunc
- type Registry
- func (r *Registry) All() []Tool
- func (r *Registry) Count() int
- func (r *Registry) Filter(names []string) []Tool
- func (r *Registry) Get(name string) (Tool, bool)
- func (r *Registry) MetadataFor(name string) (Metadata, bool)
- func (r *Registry) Names() []string
- func (r *Registry) Register(t Tool) error
- func (r *Registry) Unregister(name string) bool
- type Result
- type ResultProcessor
- type Reversible
- type Tool
- type ToolCall
- type ToolCallResult
- type ToolCapability
- type UndoInfo
Constants ¶
const ConfidenceInputField = "_flyto_confidence"
ConfidenceInputField is the reserved JSON key the LLM uses to self-report tool-call confidence (0-100). Prefix underscore marks it as a framework field, not a tool business parameter; the orchestrator strips it before Execute so tool InputSchema contracts stay intact.
ConfidenceInputField 是 LLM 自报工具调用置信度 (0-100) 的 JSON 保留字段. 下划线前缀表示这是框架字段而非工具业务参数; orchestrator 在 Execute 前 剥除, 工具 InputSchema 契约不被侵入.
Variables ¶
This section is empty.
Functions ¶
func CheckConfidenceGate ¶
func CheckConfidenceGate(cap ToolCapability, input json.RawMessage) (pass bool, errMsg string, stripped json.RawMessage)
CheckConfidenceGate enforces ToolCapability.MinConfidence against the `_flyto_confidence` reserved field in the input JSON. Returns:
- pass=true, errMsg="", stripped: input with the reserved field removed, safe to hand to the tool.
- pass=false, errMsg=reason: caller returns a tool-level error.
Gate semantics:
- cap.MinConfidence == 0: always pass, input returned unchanged (no parse, no allocation).
- cap.MinConfidence > 0 and field missing: fail with "requires _flyto_confidence (0-100) in input, min=N".
- cap.MinConfidence > 0 and field < threshold: fail with "confidence M below required N".
- cap.MinConfidence > 0 and field >= threshold: pass, field stripped.
Input must be a JSON object. Non-object / invalid JSON returns pass=true unchanged when gate disabled; when gate enabled, returns fail (cannot locate the reserved field).
CheckConfidenceGate 按 ToolCapability.MinConfidence 校验 input JSON 中的 `_flyto_confidence` 保留字段. 返回:
- pass=true, errMsg="", stripped: 剥除保留字段后的 input, 可直接给工具.
- pass=false, errMsg=理由: 调用方返工具级错误.
Gate 语义:
- cap.MinConfidence == 0: 永远放行, input 原样返回 (不解析不分配).
- cap.MinConfidence > 0 且字段缺失: 失败 "requires _flyto_confidence (0-100) in input, min=N".
- cap.MinConfidence > 0 且字段 < 阈值: 失败 "confidence M below required N".
- cap.MinConfidence > 0 且字段 >= 阈值: 放行, 字段剥除.
input 必须是 JSON 对象. 非对象 / 无效 JSON: gate disabled 时原样放行; gate enabled 时视为失败 (无法定位保留字段).
func RegisterDeferredTool ¶
func RegisterDeferredTool(name string)
RegisterDeferredTool 在全局默认核心工具列表中注册新工具名.
升华改进(ELEVATED): 可注册的动态白名单-- 第三方工具库可以将自己的核心工具(如仓储场景的 ScanBarcode)注册到始终加载列表, 无需 fork 源码修改 defaultAlwaysLoadTools. 替代方案(原方案):硬编码 map 字面量,第三方只能 fork 改源码.
注意:此函数修改全局状态.如需按 Engine 实例定制,请使用 NewDeferredRegistry + WithAlwaysLoad.
func WithWorkdir ¶
WithWorkdir 派生一个携带 dir 的 context, 供 cwd 感知工具在 Execute 开头 读取. dir 空串视为 "无覆盖" — 直接返回原 ctx 不污染调用链.
WithWorkdir derives a context carrying dir, to be read by cwd-aware tools at Execute start. An empty dir is treated as "no override" — the original ctx is returned unchanged to keep the call chain clean.
func WorkdirFromContext ¶
WorkdirFromContext 返回 WithWorkdir 设置的 cwd, 未设置返回 "". 工具实现 模式: cwd := WorkdirFromContext(ctx); if cwd == "" { cwd = t.cwd }.
WorkdirFromContext returns the cwd set by WithWorkdir, or "" if absent. Tool implementation pattern: cwd := WorkdirFromContext(ctx); if cwd == "" { cwd = t.cwd }.
Types ¶
type CapabilityProvider ¶
type CapabilityProvider interface {
Capability() ToolCapability
}
CapabilityProvider 工具能力声明(可选接口). 精妙之处(CLEVER): 和 MetadataProvider 对称设计-- Metadata 描述"工具是什么",Capability 描述"工具能做什么安全措施".
Shape: pull. Engine / audit UI reads Capability() to learn which resources the tool affects, whether undo is supported, and the minimum confidence required.
形态: 调取 (pull). 引擎 / 审计 UI 读 Capability() 得知工具影响哪些资源 / 是否支持撤销 / 最低置信度要求.
type DeferredRegistry ¶
type DeferredRegistry struct {
// contains filtered or unexported fields
}
DeferredRegistry 包装 Registry,支持延迟加载. 当注册的工具数量超过阈值时,非核心工具会被延迟加载.
func NewDeferredRegistry ¶
func NewDeferredRegistry(registry *Registry, threshold int) *DeferredRegistry
NewDeferredRegistry 创建一个支持延迟加载的注册表包装器.
registry 是底层工具注册表,threshold 为启用延迟加载的工具数量阈值. threshold <= 0 使用默认值(15).
func (*DeferredRegistry) ActivateTool ¶
func (dr *DeferredRegistry) ActivateTool(name string)
ActivateTool 将一个延迟工具激活. 激活后的工具在后续的 ActiveTools 调用中会被包含.
func (*DeferredRegistry) ActiveTools ¶
func (dr *DeferredRegistry) ActiveTools() []Tool
ActiveTools 返回当前活跃的工具列表.
如果工具总数不超过阈值,返回所有工具. 否则只返回始终加载的工具 + 已激活的延迟工具.
func (*DeferredRegistry) IsDeferred ¶
func (dr *DeferredRegistry) IsDeferred(name string) bool
IsDeferred 检查指定工具是否处于延迟加载状态.
返回 true 表示该工具存在但未激活(即延迟中). 如果工具不存在或已激活,返回 false.
func (*DeferredRegistry) Registry ¶
func (dr *DeferredRegistry) Registry() *Registry
Registry 返回底层注册表.
func (*DeferredRegistry) ResetActivations ¶
func (dr *DeferredRegistry) ResetActivations()
ResetActivations 重置所有已激活的延迟工具. 通常在新会话开始时调用.
func (*DeferredRegistry) SearchTools ¶
func (dr *DeferredRegistry) SearchTools(query string) []Tool
SearchTools 搜索延迟加载的工具.
根据查询字符串匹配工具名称,描述和搜索提示词. 返回匹配的工具列表(不包含已激活和始终加载的工具).
func (*DeferredRegistry) Threshold ¶
func (dr *DeferredRegistry) Threshold() int
Threshold 返回当前延迟加载阈值.
func (*DeferredRegistry) WithAlwaysLoad ¶
func (dr *DeferredRegistry) WithAlwaysLoad(names ...string) *DeferredRegistry
WithAlwaysLoad 将额外的工具名加入当前 DeferredRegistry 实例的始终加载列表.
升华改进(ELEVATED): 实例级核心工具定制-- 不同租户(仓储/医疗/编程)各自的"核心工具"不同,通过此方法按实例注入, 不污染其他实例也不修改全局状态. 替代方案(原方案):只有包级 RegisterDeferredTool(影响全局,不支持多租户隔离).
返回 *DeferredRegistry 自身,支持链式调用.
type DryRunResult ¶
type DryRunResult struct {
// WouldAffect is a human-readable description of what will be
// affected (e.g. file path, table name, endpoint URL). Consumed by
// preview UI to show "this will touch X" before approval.
//
// WouldAffect 是会影响什么的人类可读描述 (如文件路径 / 表名 /
// endpoint URL). 预览 UI 消费用于批准前展示 "即将影响 X".
WouldAffect string
// Preview is the detailed preview payload (e.g. unified diff, change
// summary, SQL plan). Shown to the human operator / presented to the
// LLM in an approval loop.
//
// Preview 是详细预览载荷 (如 unified diff / 变更摘要 / SQL plan).
// 展示给人类操作员 / 在审批循环中展示给 LLM.
Preview string
// EstimatedImpact is a structured extension slot (map[string]any) for
// consumer-specific impact metrics -- row counts, byte deltas,
// estimated cost, etc. Schema is consumer-defined; engine does not
// interpret it. Similar extension shape as ShadowResult.Meta and
// ReplayEvent.Meta.
//
// EstimatedImpact 是结构化扩展槽 (map[string]any), 给消费端特定的
// 影响指标 -- 行数 / byte 增量 / 预估成本等. schema 由消费端定义,
// 引擎不解读. 扩展形状同 ShadowResult.Meta / ReplayEvent.Meta.
EstimatedImpact map[string]any
}
DryRunResult is the return shape of DryRunnable.DryRun. All three fields are external pull-API surface: engine / preview UI / safety dashboard call DryRun and read them directly. Engine does not internally read these fields (no in-tree consumer), which is expected -- DryRun is the pre-execution preview contract, not an internal wire.
DryRunResult 是 DryRunnable.DryRun 的返回形状. 三个字段均为外部调取 (pull) API 表面: 引擎 / 预览 UI / 安全面板调 DryRun 后直接读. 引擎内部 不读这些字段 (无 in-tree consumer), 属预期行为 -- DryRun 是预执行 预览契约, 不走内部 wire.
type DryRunnable ¶
type DryRunnable interface {
// DryRun 模拟执行,返回"会发生什么"但不真正执行
DryRun(ctx context.Context, input json.RawMessage) (*DryRunResult, error)
}
DryRunnable 支持模拟执行的工具(可选接口). 精妙之处(CLEVER): 用可选接口而非修改 Tool 接口,不破坏现有实现. 现有的 10+ 个工具都不需要改动,只有需要 DryRun 能力的工具才实现这个接口.
Shape: synchronous callback. Engine / preview UI calls DryRun to get a preview of effects without executing; tool author implements to compute diff / impact without side effects.
形态: 同步回调. 引擎 / 预览 UI 调 DryRun 得到效果预览而不执行; 工具作者 实现此方法计算 diff / 影响范围而不产生副作用.
type Metadata ¶
type Metadata struct {
// ConcurrencySafe 表示该工具是否可以与其他工具并行执行.
// true: Glob,Grep,FileRead 等只读工具
// false: FileEdit,FileWrite,Bash(可能有副作用)等
ConcurrencySafe bool
// ReadOnly declares this tool has no side effects (pure queries /
// read-only FS access). Informational metadata: external SDK / TUI /
// audit consumers render a "read-only" label; evolve's tool generator
// may auto-set it.
//
// Not part of permission decisions -- permission path is driven by
// PermissionClass (above). No in-tree consumer reads this field for
// permission logic today.
//
// ReadOnly 声明该工具不产生副作用 (纯查询 / 只读 FS 访问).
// Informational 元数据: 外部 SDK / TUI / audit 消费层据此渲染 "只读"
// 标签, evolve 工具生成器也可据此自动设置.
//
// 不参与权限决策 -- 权限路径由 PermissionClass 驱动 (见上方).
// 本字段当前无 in-tree 消费者读取做权限判断.
ReadOnly bool
// Destructive declares the tool may cause irreversible damage (rm -rf,
// git push --force, DROP TABLE). Informational metadata: audit / UI
// render warning icons; reports count "N destructive calls this session".
//
// Not part of permission decisions -- same constraint as ReadOnly.
//
// Destructive 声明该工具可能造成不可逆破坏 (rm -rf / git push --force /
// DROP TABLE 等). Informational 元数据: audit / UI 据此渲染警告图标,
// 审计报表统计 "本 session 破坏性调用 N 次".
//
// 不参与权限决策 -- 约束同 ReadOnly.
Destructive bool
// Aliases 工具的别名列表(向后兼容用).
Aliases []string
// SearchHint 搜索提示词(3-10 字),用于 ToolSearch 延迟加载时的匹配.
SearchHint string
// PermissionClass 声明工具的权限检查类型.
// 权限引擎据此分派正确的安全检查逻辑,避免权限系统硬编码工具名.
//
// 升华改进(ELEVATED): P0-2 修复核心--工具自描述权限语义,
// 第三方工具注册时 tools.Registry 自动调用 permission.RegisterToolClass.
// 有效取值(见 permission 包中的 PermClass* 常量):
// "bash" - 命令执行类(子命令分割 + 危险命令检测)
// "file" - 文件操作类(路径权限 + 危险路径检测)
// "webfetch" - Web 请求类(域名权限检查)
// "readonly" - 只读类(直接放行)
// "generic" - 通用(默认,规则匹配后 Ask)
// "" - 未声明,权限系统使用内置 fallback(向后兼容)
PermissionClass string
// AuditOperation 声明工具的审计操作类型.
// 用于 AuditObserver 将工具事件翻译为 AuditEntry.Operation 字段.
//
// 升华改进(ELEVATED): P1 L1191 修复 - 与 PermissionClass 同源模式, 工具自描述
// 跨切面语义 (权限 + 审计), 消费者 (flysafe / flyto-platform-common / 新工具作者)
// 注册自定义工具时不需要 fork 引擎修改 audit_observer.operationFromTool 的
// switch.例如第三方 "DatabaseWrite" / "SlackSend" / "K8sApply" 工具通过
// Metadata{AuditOperation: "write"} 声明, 审计记录立即正确.
//
// 常用取值 (任意自定义字符串也合法, 由消费者与其审计后端约定):
// "write" - 写入 (文件写, DB 写, 消息发送)
// "edit" - 修改 (文件编辑, DB 更新)
// "read" - 读取 (文件读, DB 查询, glob, grep)
// "execute" - 命令执行 (bash, 子进程)
// "delete" - 删除 (文件删, DB 删)
// "invoke" - 通用调用 (默认值, 无副作用)
// "" - 未声明, AuditObserver 回退到启发式 (基于工具名匹配)
//
// 替代方案 A: <保留硬编码 switch, 不加 Metadata 字段> - 否决:
// 违反开闭原则, 消费者加新工具必须 fork 引擎.
// 替代方案 B: <新增全局 RegisterAuditOperation(name, op) 函数> - 否决:
// 引入平行于 Metadata 的第二种注册路径, 与既有 PermissionClass 风格不一致.
// 替代方案 C: <AuditObserver 构造时注入 operationMapper func> - 否决:
// 消费者要事先知道所有工具名, 插件动态注册场景不适用.
AuditOperation string
// RequiresCheckpoint 表示该工具执行前需要等待外部确认.
//
// 升华改进(ELEVATED): 早期实现 中"Human checkpoint"只是提示词里的文字建议,
// 模型自己决定要不要暂停--不可靠(模型可能忽略).
// 我们在工具声明层强制暂停:RequiresCheckpoint=true 的工具,
// 引擎在执行前必须经过 CheckpointHandlerFn 放行,handler 未注册默认拒绝.
//
// 适用场景(不可逆操作):
// - 发送消息(邮件,IM,短信)
// - 删除数据(DROP TABLE,rm -rf)
// - 生产部署(kubectl apply,terraform apply)
// - 资金操作(转账,支付)
//
// 替代方案:<在 prompt 中写"执行前问用户">
// - 否决:依赖模型遵守,不可靠;且无法在 SDK 嵌入模式下触发程序级回调.
RequiresCheckpoint bool
// RequiresReverseThinking flags this tool as one whose call benefits
// from a reverse-thinking pass before execution: producing a
// counterfactual.Deliverable (hidden assumptions / failure scenarios /
// verdict / verdict_reason) that is persisted alongside the call for
// audit and evolve.Reflector replay.
//
// Boundary with RequiresCheckpoint: RequiresCheckpoint asks "should a
// human approve this call?"; RequiresReverseThinking asks "should the
// agent challenge its own recommendation before this call?". Both can
// be true simultaneously (high-stakes calls deserve both); core does
// not impose ordering -- the consuming hook chain (e.g.
// platform/common/safetychain) decides whether reverse-think runs
// before / after / instead-of the human checkpoint.
//
// Suitable when (non-trivial design space, not every irreversible op):
// - Tool selects between competing strategies (route planning,
// carrier choice, policy parameter)
// - Tool encodes a decision whose failure mode is non-obvious
// (settlement matching, fraud judgment)
// - Tool calls a downstream system whose schema may shift
// (third-party API, partner integration)
//
// Avoid when: the tool is a pure mechanical operation (file read,
// arithmetic, well-defined CRUD); reverse-think on these is overhead
// without insight.
//
// Default false. When false, no reverse-thinking pass is invoked
// regardless of any hooks layered on; opt-in is per-tool.
//
// ELEVATED rationale: rule of two with RequiresCheckpoint -- both are
// "self-describing tool flags consumed by hooks / handlers above core",
// adding one alongside the existing one is cheaper than introducing a
// new metadata category.
//
// 替代方案 (已否决):
// A. 引擎级 ReverseThinkingGate 接口 (TODO L569 原方案 8 模块完整版)
// -- 否决: 与 hooks / permission / validator / staging / RequiresCheckpoint
// 5 套现有 gate 重叠, 业界零先例 (调研: Claude Agent SDK / OpenAI
// Assistants / Vertex ADK / LangGraph / AutoGen / CrewAI / Semantic
// Kernel / Cline 全部走 prompt-level + tool desc + 开发者自填策略).
// B. 仅写 prompt 层引导, 不加字段
// -- 否决: prompt 易丢, 无法在 SDK 嵌入模式下程序级判定; 且
// Deliverable 持久化无锚点字段.
//
// RequiresReverseThinking 标记本工具调用前应走反向思维 pass: 产 counterfactual
// .Deliverable (hidden_assumptions / failure_scenarios / verdict /
// verdict_reason) 与调用一同持久化供审计和 evolve.Reflector 重放.
//
// 与 RequiresCheckpoint 边界: RequiresCheckpoint 问 "需要人确认吗?";
// RequiresReverseThinking 问 "agent 应不应该挑战自己的建议?". 两者可同时
// true (高风险调用值得两道); core 不规定顺序 -- 消费 hook 链
// (例如 platform/common/safetychain) 决定 reverse-think 在 checkpoint
// 之前 / 之后 / 替代.
//
// 适用场景 (非平凡设计空间, 不是所有不可逆操作):
// - 工具在多个候选策略中选择 (路由规划 / 承运商选择 / 策略参数)
// - 工具编码失败模式不直观的决策 (账单匹配 / 反欺诈判定)
// - 工具调下游 schema 可能漂移的系统 (三方 API / 合作方集成)
//
// 不适用: 纯机械操作 (文件读 / 算术 / 良定义 CRUD); 反向思维只是开销
// 没有洞察.
//
// 默认 false. false 时无论上层挂多少 hook 都不触发反向思维; 按工具 opt-in.
//
// 升华理由 (ELEVATED): 与 RequiresCheckpoint 走 rule of two -- 两者都是
// "core 之上 hook / handler 消费的自描述工具 flag", 在已有字段旁加同源字段
// 比新增 metadata 类别更便宜.
RequiresReverseThinking bool
}
Metadata 是工具的元数据声明. 工具可以选择实现 MetadataProvider 接口来声明这些属性. 如果不实现,编排器使用保守默认值(不可并发,非只读,非破坏性).
对应原项目中 isConcurrencySafe(),isReadOnly(),isDestructive() 等方法.
func GetMetadata ¶
GetMetadata 安全获取工具的元数据. 如果工具未实现 MetadataProvider,返回保守默认值.
type MetadataProvider ¶
type MetadataProvider interface {
Metadata() Metadata
}
MetadataProvider 是工具的可选接口. 实现此接口的工具可以声明并发安全性等元数据.
Shape: pull. Engine reads Metadata() at orchestration decisions (can run in parallel? is destructive? requires checkpoint?).
形态: 调取 (pull). 引擎在编排决策时读 Metadata() (能否并发? 是否破坏性? 要不要 checkpoint?).
type Orchestrator ¶
type Orchestrator struct {
// contains filtered or unexported fields
}
Orchestrator 负责工具调用的并发调度.
func NewOrchestrator ¶
func NewOrchestrator(registry *Registry, maxConcurrency int) *Orchestrator
NewOrchestrator 创建一个工具编排器.
func NewOrchestratorWithResultProcessor ¶
func NewOrchestratorWithResultProcessor(registry *Registry, maxConcurrency int, processor ResultProcessor) *Orchestrator
NewOrchestratorWithResultProcessor 创建一个带大结果处理器的工具编排器. processor 为 nil 时退化为无处理行为,向后兼容.
func (*Orchestrator) ExecuteBatch ¶
func (o *Orchestrator) ExecuteBatch( ctx context.Context, calls []ToolCall, results chan<- ToolCallResult, )
ExecuteBatch 执行一批工具调用. 自动根据工具的并发安全性分组,安全的并行执行,不安全的串行执行.
对应原项目中 runTools() 异步生成器. 原项目用 yield 逐个返回结果,Go 版本通过 results channel 推送.
type Registry ¶
type Registry struct {
// contains filtered or unexported fields
}
Registry 是工具注册表. 对应原项目中 assembleToolPool() 和 tools 数组的功能, 但作为独立的,线程安全的数据结构存在.
原项目的工具池在每次 getCommands() 时重新组装(带 memoize 缓存), 且内置工具和 MCP 工具的合并逻辑散落在多处. Go 版本统一用 Registry 管理,支持运行时动态注册/注销.
func (*Registry) MetadataFor ¶
MetadataFor 按名称查询工具的 Metadata (支持别名). 返回 (Metadata, true) 表示工具存在; (Metadata{}, false) 表示未注册.
工具未实现 MetadataProvider 时 GetMetadata 返回零值 Metadata, 调用方据此判断"已注册但未声明元数据".
升华改进(ELEVATED): 与 Get() 对称, 但只暴露元数据不暴露 Tool 实例. 用于跨切面关注 (audit / permission / policy) 查询语义标签 - AuditObserver 据此决定 operationFromTool, 不再硬编码 switch.
type Result ¶
type Result struct {
// Output 是工具的文本输出.
Output string
// IsError 标记输出是否为错误信息.
IsError bool
// Data 是结构化数据输出(可选).
// 用于工具间传递结构化信息.
Data any
// UndoInfo 撤销信息(由 Reversible 工具填充).
// 升华改进(ELEVATED): 撤销信息嵌入 Result 而非单独返回--
// 这样编排器在收集工具结果时自然就拿到了撤销信息,不需要额外调用.
// 替代方案:在 Orchestrator 中单独调用 GenerateUndo(多一次调用,时序更复杂).
UndoInfo *UndoInfo
}
Result 是工具执行的结果.
type ResultProcessor ¶
type ResultProcessor interface {
ProcessResult(toolUseID, toolName, output string) (processedOutput string, storedPath string)
}
ResultProcessor 是大结果处理的接口. Orchestrator 通过此接口处理工具输出,避免直接依赖 engine 包.
type Reversible ¶
type Reversible interface {
// GenerateUndo 基于执行结果生成撤销信息
GenerateUndo(ctx context.Context, input json.RawMessage, result *Result) (*UndoInfo, error)
}
Reversible 可撤销的工具(可选接口). 精妙之处(CLEVER): Saga 补偿模式--每个正向操作生成对应的补偿操作. 回滚时倒序执行所有补偿操作,和分布式事务的 Saga 模式一样.
Shape: synchronous callback. Engine calls GenerateUndo synchronously after execution to capture an undo record; later the engine can replay the undo to revert.
形态: 同步回调. 引擎在执行后同步调 GenerateUndo 拿撤销记录; 之后引擎 可回放撤销做回退.
type Tool ¶
type Tool interface {
// Name 返回工具的唯一标识符.
Name() string
// Description 返回工具的描述(提供给模型的说明).
// 可以是动态的,根据当前上下文返回不同内容.
Description(ctx context.Context) string
// InputSchema 返回工具的 JSON Schema 输入定义.
// 模型根据此 schema 生成工具调用参数.
InputSchema() json.RawMessage
// Execute 执行工具逻辑.
// input 是模型生成的 JSON 参数(已通过 schema 验证).
// 返回 Result 和可能的错误.
//
// ctx 携带取消信号,对应原 TS 项目的 AbortController.
// progress 回调用于报告长时间任务的进度.
Execute(ctx context.Context, input json.RawMessage, progress ProgressFunc) (*Result, error)
}
Tool 是所有工具必须实现的接口. 对应原项目中 Tool<Input, Output, P> 泛型类型.
Go 版本简化为统一的 JSON 输入/输出,避免泛型复杂度. 类型安全由每个工具内部的 json.Unmarshal 保证.
Shape: synchronous callback. Engine dispatches via Execute with a JSON input and blocks for *Result; custom tool authors inject via engine.Config.Tools. Description / InputSchema / Name are pull-side metadata read by engine at registration / prompt assembly time.
形态: 同步回调. 引擎经 Execute 传 JSON 输入阻塞等 *Result; 自定义工具 作者经 engine.Config.Tools 注入. Description / InputSchema / Name 是 pull 侧元数据, 引擎在注册 / 拼 prompt 时读.
type ToolCall ¶
type ToolCall struct {
ID string // API 生成的工具调用 ID
Name string // 工具名称
Input json.RawMessage // 工具输入参数(JSON)
}
ToolCall 表示模型发起的一次工具调用请求.
type ToolCallResult ¶
type ToolCallResult struct {
ID string // 对应的工具调用 ID
Name string // 工具名称
Output string // 工具输出(可能被截断, 见 Truncated)
IsError bool // 是否出错
// Truncated marks that Output is a short summary and the full result
// has been persisted to StoredPath.
//
// Truncated 标记 Output 是短摘要, 完整结果已落盘到 StoredPath.
Truncated bool
// StoredPath is where the ResultProcessor persisted the full output.
// Empty when Truncated is false. Path shape is consumer-defined
// (local path / sandbox path / object-storage key).
//
// SECURITY: path may carry sandbox-internal structure. Downstream
// observers / SSE bridges treat it as caller-specific, untrusted data
// (e.g. do not log to shared destinations without review). Same
// constraint applies in flyto.ToolResultEvent.StoredPath and
// OperationEntry.StoredPath; all three share one trust boundary.
//
// StoredPath 是 ResultProcessor 落盘完整输出的位置. Truncated=false 时
// 为空串. Path shape 由消费层定义 (本地路径 / sandbox 路径 / 对象存储
// key).
//
// 安全: path 可能带 sandbox 内部结构. 下游 observer / SSE bridge 当作
// 调用方特定的不可信数据对待 (未审查前不写入共享目的地). 此约束同样
// 适用于 flyto.ToolResultEvent.StoredPath 和 OperationEntry.StoredPath,
// 三者共享同一条信任边界.
StoredPath string
UndoInfo *UndoInfo // 撤销信息(由 Reversible 工具生成)
// Data is the structured payload that the tool's Result.Data carries
// through to the engine. Primary consumer (2026-04): engine wraps an
// *tools/builtin.ImageResult into an array-form tool_result so vision
// models see the real image bytes (see engine.go tool_result
// construction). Future non-image structured payloads (e.g. document,
// chart) can plug in without another field.
//
// Orchestrator preserves the reference verbatim -- no copy, no
// serialization. Consumers MUST type-assert (`if img, ok := res.Data.(*ImageResult); ok`)
// and handle the nil case.
//
// Data 是工具 Result.Data 透传到引擎的结构化载荷. 主消费者 (2026-04):
// 引擎把 *tools/builtin.ImageResult 包成 array-form tool_result 让 vision
// 模型真读到图 (见 engine.go tool_result 构造点). 未来非图结构化载荷
// (文档 / 图表 / 结构化表格) 可直接沿用, 不用再加字段.
//
// Orchestrator 原样透传引用 -- 不拷贝不序列化. 消费方必须 type-assert
// (`if img, ok := res.Data.(*ImageResult); ok`) 并处理 nil 情况.
Data any
}
ToolCallResult 表示一次工具调用的结果.
Truncated / StoredPath surface the large-result handling decision so downstream consumers (engine → flyto.ToolResultEvent / OperationEntry / SSE bridge → UI / audit sink) can honor the "click to open full content" affordance and keep audit logs pointing at the authoritative artifact. When the orchestrator's pluggable ResultProcessor rewrites Output to a short summary, these fields are the only breadcrumb back to the full result.
Truncated / StoredPath 把大结果处理决策透传给下游消费者 (engine → flyto.ToolResultEvent / OperationEntry / SSE bridge → UI / 审计 sink), 让消费者能兑现 "点击查看完整内容" 入口并让审计日志指向权威产物. 当 orchestrator 的可插拔 ResultProcessor 把 Output 重写成短摘要时, 这两个 字段是回溯完整结果的唯一线索.
type ToolCapability ¶
type ToolCapability struct {
// DryRun 是否支持模拟执行(不产生副作用)
DryRun bool
// Reversible 执行后是否可撤销
Reversible bool
// UndoMethod is an informational static declaration of how this tool
// can be undone: "tool" / "manual" / "" (irreversible). This is a
// surface for external audit UI / tool panels to show rollback
// category before execution; the engine's actual rollback path reads
// UndoInfo.ToolName (dynamic, captured by Reversible.GenerateUndo at
// execute time), not this field. Static vs dynamic are complementary,
// not redundant: static lets the UI render "this tool is reversible"
// without running; dynamic carries the concrete undo input per call.
//
// UndoMethod 是工具如何被撤销的 informational 静态声明: "tool" / "manual"
// / "" (不可逆). 此字段面向外部审计 UI / 工具面板, 让其在执行前就能
// 展示回滚分类; 引擎真实 rollback 路径读 UndoInfo.ToolName (动态, 由
// Reversible.GenerateUndo 执行时捕获), 不读本字段. 静态和动态互补非
// 冗余: 静态让 UI 不跑也能渲染 "此工具可撤销"; 动态携带每次调用的
// 具体撤销参数.
UndoMethod string
// UndoToolName is the informational static name of the undo tool
// when UndoMethod="tool". Same static-vs-dynamic split as UndoMethod:
// external UI / audit consumers read this field to show "undo is
// handled by tool X" pre-execution; the engine dispatches undo via
// UndoInfo.ToolName (dynamic, same value in practice but sourced
// per-call by GenerateUndo).
//
// UndoToolName 是 UndoMethod="tool" 时撤销工具的 informational 静态名.
// 和 UndoMethod 同构的静态-动态分层: 外部 UI / 审计消费者读本字段
// 在执行前展示 "由工具 X 撤销"; 引擎执行 undo 时派发 UndoInfo.ToolName
// (动态值, 通常同值但按次由 GenerateUndo 提供).
UndoToolName string
// MinConfidence is the minimum self-reported confidence the engine
// requires before dispatching this tool (0-100). Zero disables the
// gate entirely (all calls pass).
//
// Wire (2026-04-21):
// - engine.buildToolDefs appends a "[Safety] requires _flyto_confidence
// in input, min=N" hint to Description for tools with MinConfidence>0,
// so the LLM sees the contract in the tool definition itself.
// - orchestrator.executeSingle calls CheckConfidenceGate before
// Execute. The gate parses the `_flyto_confidence` reserved field
// from input JSON, rejects calls below the threshold with a
// tool-level error (letting the LLM retry with a reconsidered
// value), and strips the field before handing input to the tool
// (so tool InputSchema stays clean).
// - Missing _flyto_confidence when MinConfidence>0 is treated as
// gate-fail (not implicit 100) -- LLM must explicitly self-assess
// for high-risk tools.
//
// MinConfidence 是引擎派发本工具前要求的最低自评置信度 (0-100). 零值
// 完全 disable gate (所有调用放行).
//
// Wire (2026-04-21):
// - engine.buildToolDefs 对 MinConfidence>0 的工具, 在 Description 末
// 尾追加 "[Safety] 需要在 input 中附 _flyto_confidence, 最低 N" 提示,
// 让 LLM 在工具定义层就看到契约.
// - orchestrator.executeSingle 在 Execute 前调 CheckConfidenceGate.
// Gate 从 input JSON 解析保留字段 `_flyto_confidence`, 低于阈值返工具
// 级错误 (让 LLM 重新评估), 放行前剥除该字段 (保持工具 InputSchema
// 干净).
// - MinConfidence>0 而 _flyto_confidence 缺失视为 gate-fail (非隐式 100)
// -- LLM 必须为高风险工具显式自评.
MinConfidence int
// AffectedResources is a human-readable list of resource categories
// the tool touches (e.g. ["file"], ["database","network"]). Pure
// informational surface for tool panels / audit UI to classify tools
// by blast radius. Engine does not read this field; consumers walk
// CapabilityProvider externally.
//
// AffectedResources 是工具触及的资源类别人类可读列表 (如 ["file"] /
// ["database","network"]). 纯 informational, 给工具面板 / 审计 UI 按
// 影响范围分类. 引擎不读本字段, 外部消费者走 CapabilityProvider 调取.
AffectedResources []string
}
ToolCapability 声明工具的安全能力.
func GetCapability ¶
func GetCapability(t Tool) ToolCapability
GetCapability 安全获取工具能力. 如果工具未实现 CapabilityProvider,返回零值(不支持 DryRun,不可逆).
func (ToolCapability) SafetyLevel ¶
func (c ToolCapability) SafetyLevel() int
SafetyLevel 返回工具的安全等级. Level 2: DryRun(最安全),Level 1: Reversible,Level 0: 两者都不支持.
type UndoInfo ¶
type UndoInfo struct {
// ToolName 用哪个工具撤销
ToolName string
// Input 撤销工具的输入
Input map[string]any
// Description is a human-readable summary of the undo action shown to
// external operators (rollback UI / audit logs). The engine does not
// read this field during RollbackMessage -- it is purely a consumer
// surface.
//
// Description 是向外部操作员展示的撤销动作人类可读摘要 (rollback UI /
// 审计日志). 引擎在 RollbackMessage 过程中不读本字段 -- 纯消费者表面.
Description string
// Irreversible 标记为不可逆(某些操作执行后无法撤销)
Irreversible bool
// ManualGuide 不可逆时的人工处理指南
ManualGuide string
}
UndoInfo is the dynamic undo record captured by Reversible.GenerateUndo at execute time. ToolName / Input / Irreversible / ManualGuide are read by the engine's rollback path (OperationLog.RollbackMessage → UndoExecutor.ExecuteUndo). Description is an external pull-API field: external rollback UI / audit sinks render it to the operator; no internal assert site in the engine itself.
UndoInfo 是 Reversible.GenerateUndo 在执行时捕获的动态撤销记录. ToolName / Input / Irreversible / ManualGuide 由引擎 rollback 路径 (OperationLog.RollbackMessage → UndoExecutor.ExecuteUndo) 读取. Description 是外部调取 (pull) API 字段: 外部 rollback UI / 审计 sink 渲染给操作员, 引擎内部无断言点.