middleware

package
v0.5.10 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 13, 2026 License: Apache-2.0 Imports: 9 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrPermissionDenied = errors.New("runtime: tool call denied by permission policy")

ErrPermissionDenied 是权限拒绝的标准错误。

Functions

This section is empty.

Types

type Budget

type Budget struct {
	// Limits 三维上限。
	Limits BudgetLimits
	// Cost 成本估算函数;nil 时禁用成本维度。
	Cost CostFunc
	// Now 可注入的时钟,便于测试;nil 时使用 time.Now。
	Now func() time.Time
}

Budget 是运行时预算的**单一 fail-closed 强制点**,统一覆盖 token / 墙钟 / 成本三个维度。

设计要点:

  • 单一所有权:成本估算来自注入的 CostFunc(消费 security/cost),Budget 不重复实现计费。
  • fail-closed:任一维度超限即在 BeforeLLM 返回错误,由中间件链中断本次 LLM 调用。
  • 零配置兼容:三个维度全为 0 时永不超限,行为与"无预算"一致。

线程安全:Budget 自身无可变状态(墙钟起始时间存于各自 State),不同 run 可并发使用同一实例。

func (Budget) AfterLLM

AfterLLM 无操作(预算检查在 BeforeLLM 完成)。

func (Budget) AfterTool

AfterTool 无操作。

func (Budget) BeforeLLM

func (b Budget) BeforeLLM(ctx context.Context, state *hruntime.State) error

BeforeLLM 在每次 LLM 调用前检查三维预算:先发 BudgetChecked 事件, 若任一维度超限则发 BudgetExceeded 事件并返回 fail-closed 错误。

func (Budget) BeforeTool

BeforeTool 无操作。

func (Budget) Finalize

func (Budget) Finalize(context.Context, *hruntime.State) error

Finalize 无操作。

type BudgetControl

type BudgetControl struct {
	// contains filtered or unexported fields
}

BudgetControl 是预算的单一抽象:内部组合 Budget(per-run)与 CostControl(cross-run), 把"预算"用一个中间件表达。各 hook 依次委托两者,任一返回错误即 fail-closed。

func NewBudgetControl

func NewBudgetControl(cfg BudgetControlConfig) BudgetControl

NewBudgetControl 用统一配置构造预算控制中间件。

等价于同时挂 Budget{Limits,Cost} 与 CostControl{Record},但作为单一中间件挂载:

agent.WithMiddleware(middleware.NewBudgetControl(cfg))

func (BudgetControl) AfterLLM

func (b BudgetControl) AfterLLM(ctx context.Context, state *hruntime.State, resp *llm.CompletionResponse) error

AfterLLM 依次执行 per-run 维度与跨 run 累计记账/封顶。

func (BudgetControl) AfterTool

func (b BudgetControl) AfterTool(ctx context.Context, state *hruntime.State, call llm.ToolCall, result hruntime.ToolResult) error

AfterTool 依次委托两者。

func (BudgetControl) BeforeLLM

func (b BudgetControl) BeforeLLM(ctx context.Context, state *hruntime.State) error

BeforeLLM 依次执行 per-run 上限检查与跨 run 维度的 BeforeLLM。

func (BudgetControl) BeforeTool

func (b BudgetControl) BeforeTool(ctx context.Context, state *hruntime.State, call llm.ToolCall) error

BeforeTool 依次委托两者。

func (BudgetControl) Finalize

func (b BudgetControl) Finalize(ctx context.Context, state *hruntime.State) error

Finalize 依次委托两者。

type BudgetControlConfig

type BudgetControlConfig struct {
	// Limits 单次 run 的 token/墙钟/成本上限(per-run 维度)。
	Limits BudgetLimits
	// Cost 单次 run 的成本估算函数(per-run 成本维度,可选;消费 security/cost)。
	Cost CostFunc
	// Record 跨 run 累计记账 + 超限 fail-closed(cross-run 维度,可选;消费 security/cost)。
	Record RecordUsageFunc
}

BudgetControlConfig 是统一预算配置。零值字段表示对应维度关闭。

type BudgetLimits

type BudgetLimits struct {
	// MaxTokens 累计 token 上限,0 表示不限。
	MaxTokens int
	// MaxDuration 单次 run 墙钟耗时上限,0 表示不限。
	MaxDuration time.Duration
	// MaxCostUSD 累计成本上限(美元),0 表示不限。
	MaxCostUSD float64
}

BudgetLimits 定义运行时预算的三个维度上限。任一维度取 0 表示该维度不限。

维度说明:

  • MaxTokens: 累计 token 用量上限(消耗型,达到即超限)
  • MaxDuration: 单次 run 墙钟耗时上限(达到即超限)
  • MaxCostUSD: 累计成本上限(美元,消耗型,达到即超限)

type Compaction

type Compaction struct {
	// MaxTokens 触发压缩的 token 阈值;<= 0 表示关闭。
	MaxTokens int
	// KeepRecent 内置压缩保留的最近非 system 消息条数;<= 0 时默认 6。
	KeepRecent int
	// Count token 估算函数;nil 时用内置粗估。
	Count TokenCounter
	// Compact 压缩函数;nil 时用内置「保留 system + 最近 KeepRecent」。
	Compact Compactor
}

Compaction 是上下文压缩中间件:在每次 LLM 调用前估算消息历史 token,超过阈值即压缩 state.Messages,并发 ContextCompacted{before,after} 事件。

设计要点:

  • 阈值 MaxTokens <= 0 时**完全关闭**(默认行为与无此中间件一致)。
  • token 估算(Count)与压缩策略(Compact)均可注入;默认估算为粗估、默认压缩为 「保留 system + 最近 KeepRecent 条」截断(不需 LLM);摘要式压缩由调用方注入 Compact。
  • 压缩可能丢弃中间的 assistant/tool 配对,但 runner 在发送前会 sanitize 孤立 tool message(见 runner.sanitizeToolCallSequence),故协议序列仍合规。

线程安全:Compaction 自身无可变状态,可被多个并发 run 复用。

func (Compaction) AfterLLM

AfterLLM 无操作。

func (Compaction) AfterTool

AfterTool 无操作。

func (Compaction) BeforeLLM

func (c Compaction) BeforeLLM(ctx context.Context, state *hruntime.State) error

BeforeLLM 估算当前历史 token,超阈值则压缩并发 ContextCompacted 事件。

func (Compaction) BeforeTool

BeforeTool 无操作。

func (Compaction) Finalize

Finalize 无操作。

type Compactor

type Compactor func(ctx context.Context, messages []llm.Message) []llm.Message

Compactor 把消息历史压缩为更短的等价历史。以依赖注入方式提供,使「摘要式压缩」 (需 LLM)等策略可插拔;nil 时 Compaction 用内置策略「保留全部 system + 最近 N 条」。

type CostControl

type CostControl struct {
	// Record 跨 run 累计记账 + fail-closed 检查函数;nil 时本中间件为 no-op。
	Record RecordUsageFunc
}

CostControl 是"跨 run 累计预算"的 fail-closed 强制点。

与 Budget 的分工(二者可叠加使用):

  • Budget 按**单次 run** 的 State.Usage 检查 token/墙钟/成本;对多 run 的 agent (PlanExecute/Reflection 等,每次内部 LLM 调用是独立 run)退化为"每调用各自封顶"。
  • CostControl 经注入的 RecordUsageFunc 把每次调用用量写入**跨 run 共享累加器**, 故对多 run agent 实现"agent 全程累计封顶"——这正是 Budget per-run 模型补不上的语义。

工作方式:在 AfterLLM(本次 LLM 调用已返回)把 resp.Usage 记入累加器;若累计成本突破 预算,累加器返回错误,本中间件发 BudgetExceeded 事件并 fail-closed 中断本次 run。 由于累加器在 agent 的多次 run 间共享,超限会在"累计跨过预算的那一次调用"处触发。

线程安全:CostControl 自身无可变状态;并发安全性由注入的 RecordUsageFunc(累加器)负责。

func (CostControl) AfterLLM

func (c CostControl) AfterLLM(ctx context.Context, state *hruntime.State, resp *llm.CompletionResponse) error

AfterLLM 把本次 LLM 调用的用量记入跨 run 累加器;累计超预算时 fail-closed。

func (CostControl) AfterTool

AfterTool 无操作。

func (CostControl) BeforeLLM

BeforeLLM 无操作(累计记账在 AfterLLM 完成)。

func (CostControl) BeforeTool

BeforeTool 无操作。

func (CostControl) Finalize

Finalize 无操作。

type CostFunc

type CostFunc func(state *hruntime.State) float64

CostFunc 从当前运行状态估算累计成本(美元)。

它以依赖注入方式提供,使 runtime/middleware **不必硬依赖** security/cost: 成本估算的所有权仍在 security/cost.Controller.EstimateCost,Budget 只是 唯一的"强制点",消费其估算结果。这实现了"预算单一所有权 + 单一强制点"。 传入 nil 表示禁用成本维度。

type Permission

type Permission struct {
	Checker hruntime.Permission
}

Permission delegates tool checks to a runtime permission port.

func (Permission) AfterLLM

func (Permission) BeforeLLM

func (Permission) BeforeTool

func (p Permission) BeforeTool(ctx context.Context, state *hruntime.State, call llm.ToolCall) error

func (Permission) Finalize

type PermissionDecision

type PermissionDecision int

PermissionDecision 是 Hook 的判定结果。

const (
	DecisionDefer PermissionDecision = iota // 交给 mode 策略决定
	DecisionAllow                           // 覆盖:放行
	DecisionDeny                            // 覆盖:拒绝
)

type PermissionHook

type PermissionHook func(ctx context.Context, state *hruntime.State, call llm.ToolCall) PermissionDecision

PermissionHook 在工具执行前调用,可覆盖判定(Allow/Deny)或 Defer 给 mode 策略。

注:受 Middleware.BeforeTool 接口(只返 error)所限,Hook 暂不能改写将被执行的 call input(input 变更需 runner 侧支持);本版仅支持判定覆盖。

type PermissionMode

type PermissionMode int

PermissionMode 是五级权限模式。

零值 PermissionModeDefault = 旧行为(委托 Checker,无则放行),保证默认与 0.4.8 等价。

const (
	// PermissionModeDefault 旧行为:委托 Checker(无 Checker 则放行)。向后兼容默认。
	PermissionModeDefault PermissionMode = iota
	// PermissionModeReadOnly 仅放行只读类工具,写/危险一律拒绝。
	PermissionModeReadOnly
	// PermissionModeWorkspaceWrite 放行只读 + 工作区写,危险类(shell/exec/删除等)拒绝。
	PermissionModeWorkspaceWrite
	// PermissionModeDangerFullAccess 放行一切(含危险类)。
	PermissionModeDangerFullAccess
	// PermissionModePrompt 每次工具调用征询 Prompt 回调批准;无回调则 fail-closed 拒绝。
	PermissionModePrompt
	// PermissionModeAllow 放行一切(语义同 full,但不做危险分类)。
	PermissionModeAllow
)

func (PermissionMode) String

func (m PermissionMode) String() string

type PolicyPermission

type PolicyPermission struct {
	Mode     PermissionMode      // 权限模式
	Classify ToolClassifier      // nil→内置启发式
	Hook     PermissionHook      // nil→无 Hook
	Prompt   PromptFunc          // Prompt 模式征询;nil→fail-closed deny
	Checker  hruntime.Permission // Default 模式委托(向后兼容)
}

PolicyPermission 是五级权限模式中间件,实现「请求→Hook 覆盖→mode 策略→分类→判定」 五步决策链,并发 PermissionRequested/Approved/Denied 事件。

默认(Mode=Default)行为与旧 Permission 等价(委托 Checker / 放行),可叠加/替换旧中间件。

func (PolicyPermission) AfterLLM

func (PolicyPermission) AfterTool

func (PolicyPermission) BeforeLLM

func (PolicyPermission) BeforeTool

func (p PolicyPermission) BeforeTool(ctx context.Context, state *hruntime.State, call llm.ToolCall) error

func (PolicyPermission) Finalize

type PromptFunc

type PromptFunc func(ctx context.Context, call llm.ToolCall) bool

PromptFunc 在 Prompt 模式下征询批准(返回 true=批准)。

type ReasoningSanitizer

type ReasoningSanitizer struct{}

ReasoningSanitizer strips model-private reasoning tags from final content.

func (ReasoningSanitizer) AfterLLM

func (ReasoningSanitizer) AfterTool

func (ReasoningSanitizer) BeforeLLM

func (ReasoningSanitizer) BeforeTool

func (ReasoningSanitizer) Finalize

type RecordUsageFunc

type RecordUsageFunc func(model string, usage llm.Usage) error

RecordUsageFunc 把一次 LLM 调用的用量记入**跨 run 共享累加器**,并在累计预算耗尽时 返回错误(fail-closed)。

它以依赖注入方式提供(裸 func 签名),使 runtime/middleware 不必反向依赖 security/cost: 累计账的所有权仍在注入方(通常是 security/cost.Controller.RecordUsageFunc()),CostControl 只负责在步边界调用它并据其返回值 fail-closed。传入 nil 时 CostControl 退化为 no-op。

type TokenCounter

type TokenCounter func(messages []llm.Message) int

TokenCounter 估算一段消息历史的 token 数。以依赖注入方式提供,使中间件不硬依赖 具体 tokenizer;nil 时 Compaction 退化为内置粗估(按字符数 /4 + 每条固定开销)。

type ToolClass

type ToolClass int

ToolClass 是工具的危险等级分类。

const (
	ToolRead      ToolClass = iota // 只读
	ToolWrite                      // 写(工作区内)
	ToolDangerous                  // 危险(shell/exec/删除/网络等)
)

type ToolClassifier

type ToolClassifier func(call llm.ToolCall) ToolClass

ToolClassifier 把一次工具调用分类为危险等级;nil 时用内置按工具名启发式分类。

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL