借鉴 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 走旧路径
62 lines
2.0 KiB
Rust
62 lines
2.0 KiB
Rust
//! Compaction middleware — wraps the existing compaction module.
|
|
|
|
use async_trait::async_trait;
|
|
use zclaw_types::Result;
|
|
use crate::middleware::{AgentMiddleware, MiddlewareContext, MiddlewareDecision};
|
|
use crate::compaction::{self, CompactionConfig};
|
|
use crate::growth::GrowthIntegration;
|
|
use crate::driver::LlmDriver;
|
|
use std::sync::Arc;
|
|
|
|
/// Middleware that compresses conversation history when it exceeds a token threshold.
|
|
pub struct CompactionMiddleware {
|
|
threshold: usize,
|
|
config: CompactionConfig,
|
|
/// Optional LLM driver for async compaction (LLM summarisation, memory flush).
|
|
driver: Option<Arc<dyn LlmDriver>>,
|
|
/// Optional growth integration for memory flushing during compaction.
|
|
growth: Option<GrowthIntegration>,
|
|
}
|
|
|
|
impl CompactionMiddleware {
|
|
pub fn new(
|
|
threshold: usize,
|
|
config: CompactionConfig,
|
|
driver: Option<Arc<dyn LlmDriver>>,
|
|
growth: Option<GrowthIntegration>,
|
|
) -> Self {
|
|
Self { threshold, config, driver, growth }
|
|
}
|
|
}
|
|
|
|
#[async_trait]
|
|
impl AgentMiddleware for CompactionMiddleware {
|
|
fn name(&self) -> &str { "compaction" }
|
|
fn priority(&self) -> i32 { 100 }
|
|
|
|
async fn before_completion(&self, ctx: &mut MiddlewareContext) -> Result<MiddlewareDecision> {
|
|
if self.threshold == 0 {
|
|
return Ok(MiddlewareDecision::Continue);
|
|
}
|
|
|
|
let needs_async = self.config.use_llm || self.config.memory_flush_enabled;
|
|
if needs_async {
|
|
let outcome = compaction::maybe_compact_with_config(
|
|
ctx.messages.clone(),
|
|
self.threshold,
|
|
&self.config,
|
|
&ctx.agent_id,
|
|
&ctx.session_id,
|
|
self.driver.as_ref(),
|
|
self.growth.as_ref(),
|
|
)
|
|
.await;
|
|
ctx.messages = outcome.messages;
|
|
} else {
|
|
ctx.messages = compaction::maybe_compact(ctx.messages.clone(), self.threshold);
|
|
}
|
|
|
|
Ok(MiddlewareDecision::Continue)
|
|
}
|
|
}
|