Files
zclaw_openfang/crates/zclaw-runtime/src/middleware/loop_guard.rs
iven 04c366fe8b feat(runtime): DeerFlow 模式中间件链 Phase 1-4 全部完成
借鉴 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 走旧路径
2026-03-29 23:19:41 +08:00

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),
}
}
}