借鉴 DeerFlow 架构,实现完整中间件链系统: Phase 1 - Agent 中间件链基础设施 - MiddlewareChain Clone 支持 - LoopRunner 双路径集成 (middleware/legacy) - Kernel create_middleware_chain() 工厂方法 Phase 2 - 技能按需注入 - SkillIndexMiddleware (priority 200) - SkillLoadTool 工具 - SkillDetail/SkillIndexEntry 结构体 - KernelSkillExecutor trait 扩展 Phase 3 - Guardrail 安全护栏 - GuardrailMiddleware (priority 400, fail_open) - ShellExecRule / FileWriteRule / WebFetchRule Phase 4 - 记忆闭环统一 - MemoryMiddleware (priority 150, 30s 防抖) - after_completion 双路径调用 中间件注册顺序: 100 Compaction | 150 Memory | 200 SkillIndex 400 Guardrail | 500 LoopGuard | 700 TokenCalibration 向后兼容:Option<MiddlewareChain> 默认 None 走旧路径
58 lines
1.9 KiB
Rust
58 lines
1.9 KiB
Rust
//! Loop guard middleware — extracts loop detection into a middleware hook.
|
|
|
|
use async_trait::async_trait;
|
|
use serde_json::Value;
|
|
use zclaw_types::Result;
|
|
use crate::middleware::{AgentMiddleware, MiddlewareContext, ToolCallDecision};
|
|
use crate::loop_guard::{LoopGuard, LoopGuardConfig, LoopGuardResult};
|
|
use std::sync::Mutex;
|
|
|
|
/// Middleware that detects and blocks repetitive tool-call loops.
|
|
pub struct LoopGuardMiddleware {
|
|
guard: Mutex<LoopGuard>,
|
|
}
|
|
|
|
impl LoopGuardMiddleware {
|
|
pub fn new(config: LoopGuardConfig) -> Self {
|
|
Self {
|
|
guard: Mutex::new(LoopGuard::new(config)),
|
|
}
|
|
}
|
|
|
|
pub fn with_defaults() -> Self {
|
|
Self {
|
|
guard: Mutex::new(LoopGuard::default()),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[async_trait]
|
|
impl AgentMiddleware for LoopGuardMiddleware {
|
|
fn name(&self) -> &str { "loop_guard" }
|
|
fn priority(&self) -> i32 { 500 }
|
|
|
|
async fn before_tool_call(
|
|
&self,
|
|
_ctx: &MiddlewareContext,
|
|
tool_name: &str,
|
|
tool_input: &Value,
|
|
) -> Result<ToolCallDecision> {
|
|
let result = self.guard.lock().unwrap().check(tool_name, tool_input);
|
|
match result {
|
|
LoopGuardResult::CircuitBreaker => {
|
|
tracing::warn!("[LoopGuardMiddleware] Circuit breaker triggered by tool '{}'", tool_name);
|
|
Ok(ToolCallDecision::Block("检测到工具调用循环,已自动终止".to_string()))
|
|
}
|
|
LoopGuardResult::Blocked => {
|
|
tracing::warn!("[LoopGuardMiddleware] Tool '{}' blocked", tool_name);
|
|
Ok(ToolCallDecision::Block("工具调用被循环防护拦截".to_string()))
|
|
}
|
|
LoopGuardResult::Warn => {
|
|
tracing::warn!("[LoopGuardMiddleware] Tool '{}' triggered warning", tool_name);
|
|
Ok(ToolCallDecision::Allow)
|
|
}
|
|
LoopGuardResult::Allowed => Ok(ToolCallDecision::Allow),
|
|
}
|
|
}
|
|
}
|