Files
zclaw_openfang/crates/zclaw-runtime/src/middleware/loop_guard.rs
iven 52bdafa633 refactor(crates): kernel/generation module split + DeerFlow optimizations + middleware + dead code cleanup
- Split zclaw-kernel/kernel.rs (1486 lines) into 9 domain modules
- Split zclaw-kernel/generation.rs (1080 lines) into 3 modules
- Add DeerFlow-inspired middleware: DanglingTool, SubagentLimit, ToolError, ToolOutputGuard
- Add PromptBuilder for structured system prompt assembly
- Add FactStore (zclaw-memory) for persistent fact extraction
- Add task builtin tool for agent task management
- Driver improvements: Anthropic/OpenAI extended thinking, Gemini safety settings
- Replace let _ = with proper log::warn! across SaaS handlers
- Remove unused dependency (url) from zclaw-hands
2026-04-03 00:28:03 +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::AbortLoop("检测到工具调用循环,已自动终止".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),
}
}
}