Skip to main content

funera_core/
middleware.rs

1//! # Middleware — agent 事件拦截与处理管道
2//!
3//! 提供对 ReAct 循环**内部**的可插拔拦截机制,作用于 `process_token_stream` 和
4//! `handle_turn_finish` 之后、数据写入 session 历史之前。
5//!
6//! 分为两类:
7//!
8//! | 类型 | 特征 | 执行方式 | 影响事件流 |
9//! |------|------|----------|------------|
10//! | [`InspectorMiddleware`] | 只读观察 | `tokio::spawn` 后台并行 | ❌ 不等待,不阻塞 |
11//! | [`MutatorMiddleware`] | 可变处理 | 同步顺序执行 | ✅ 可 Pass/Modify/Block |
12//!
13//! ## 架构位置
14//!
15//! ```text
16//! LLM Stream → process_token_stream → 聚合结果
17//!                                         │
18//!                          create E events │
19//!                                         ▼
20//!                              [middleware chain]
21//!                           Pass / Modify / Block
22//!                                  │
23//!                         ┌────────┴────────┐
24//!                         ▼                 ▼
25//!                    session 历史         event_tx (通知/callback)
26//!                    (下一轮用)           (聚合生成 ChatResponse)
27//! ```
28//!
29//! Middleware 直接操作 session 写入前的数据,因此修改会**持久化**到下一轮
30//! ReAct 循环的历史上下文中。
31//!
32//! ## 快速使用 (在 `funera-orchestrate` 层)
33//!
34//! ```rust,no_run
35//! # use funera_core::middleware::{MiddlewareChain, InspectorMiddleware, MutatorMiddleware,
36//! #     InspectorError, MutatorAction, ErrorsDisabled};
37//! // 1. 定义 Inspector
38//! struct Logger;
39//! impl InspectorMiddleware<String> for Logger {
40//!     fn name(&self) -> &str { "log" }
41//!     fn inspect(&self, _: &String) -> Result<(), InspectorError> { Ok(()) }
42//! }
43//!
44//! // 2. 定义 Mutator
45//! struct Censor;
46//! impl MutatorMiddleware<String> for Censor {
47//!     fn name(&self) -> &str { "censor" }
48//!     fn process(&self, s: String) -> MutatorAction<String> { MutatorAction::Pass }
49//! }
50//!
51//! // 3. 构建链
52//! let chain = MiddlewareChain::<String>::new()
53//!     .with_inspectors((Logger,))
54//!     .with_mutator(Censor);
55//!
56//! // 4. 执行(由 react_loop 内部调用)
57//! let result = chain.process("hello".into());
58//! ```
59//!
60//! ## Typestate 错误通道
61//!
62//! 错误通道通过 typestate 管理:默认 `ErrorsDisabled`,调用
63//! [`MiddlewareChain::activate_error_channel`] 后变为 `ErrorsEnabled`,编译期防止重复激活。
64//!
65//! ```rust,no_run
66//! # use funera_core::middleware::{MiddlewareChain, ErrorsEnabled, InspectorMiddleware, InspectorError};
67//! # struct Insp;
68//! # impl InspectorMiddleware<String> for Insp {
69//! #     fn name(&self) -> &str { "i" }
70//! #     fn inspect(&self, _: &String) -> Result<(), InspectorError> { Ok(()) }
71//! # }
72//! let chain = MiddlewareChain::<String>::new()
73//!     .with_inspector(Insp);
74//! let (enabled, error_rx) = chain.activate_error_channel();
75//! // enabled 的类型是 MiddlewareChain<String, ErrorsEnabled>
76//! // 无法再次调用 activate_error_channel()
77//! ```
78
79use std::marker::PhantomData;
80use std::sync::Arc;
81
82use serde_json::Value as JsonValue;
83use tokio::sync::mpsc;
84
85use crate::chat::message::{MsgVariant, Role};
86
87// ═══════════════════════════════════════════════════════════════
88// Inspector — 只读观察,后台并行,不等待
89// ═══════════════════════════════════════════════════════════════
90
91/// Inspector 错误的类型别名。
92///
93/// 任何实现了 `std::error::Error + Send + Sync + 'static` 的类型都可以作为
94/// inspector 错误返回。
95pub type InspectorError = Box<dyn std::error::Error + Send + Sync + 'static>;
96
97/// 只读检查器——接收 `&Evt`,后台并行执行,不阻塞事件流。
98///
99/// Inspector 通过 `tokio::spawn` 并发执行,其错误通过异步 error channel 报告,
100/// 不会影响 Mutator 阶段的事件处理。
101///
102/// # 示例
103///
104/// ```rust,no_run
105/// # use funera_core::middleware::{InspectorMiddleware, InspectorError};
106/// struct TokenLogger;
107/// impl InspectorMiddleware<String> for TokenLogger {
108///     fn name(&self) -> &str { "token_logger" }
109///     fn inspect(&self, event: &String) -> Result<(), InspectorError> {
110///         eprintln!("[inspector] event: {event}");
111///         Ok(())
112///     }
113/// }
114/// ```
115pub trait InspectorMiddleware<Evt>: Send + Sync {
116    /// 返回此 inspector 的唯一标识名称。
117    fn name(&self) -> &str;
118
119    /// 检查事件(只读),返回 `Ok(())` 或错误(通过 error channel 报告)。
120    ///
121    /// Inspect 的返回值**不会**影响事件流——即使返回 `Err`,事件也会继续传递。
122    fn inspect(&self, event: &Evt) -> Result<(), InspectorError>;
123}
124
125// ═══════════════════════════════════════════════════════════════
126// Mutator — 可变处理,顺序执行,可放行/修改/阻止
127// ═══════════════════════════════════════════════════════════════
128
129/// Mutator 对事件的处理决策。
130pub enum MutatorAction<Evt> {
131    /// 不做任何修改,事件原样放行。
132    Pass,
133    /// 将事件替换为新的值。
134    Modify(Evt),
135    /// 阻止事件继续传递,并附上原因。
136    Block { reason: String },
137}
138
139/// 可变处理器——接收 `Evt`,选择放行/修改/阻止。
140///
141/// 与 [`InspectorMiddleware`] 不同,mutator 在事件流程中**同步顺序执行**,
142/// 其返回的 [`MutatorAction`] 直接决定事件是否继续传递。
143///
144/// # 示例
145///
146/// ```rust,no_run
147/// # use funera_core::middleware::{MutatorMiddleware, MutatorAction};
148/// struct Censor;
149/// impl MutatorMiddleware<String> for Censor {
150///     fn name(&self) -> &str { "censor" }
151///     fn process(&self, event: String) -> MutatorAction<String> {
152///         if event.contains("bad") {
153///             MutatorAction::Modify(event.replace("bad", "***"))
154///         } else {
155///             MutatorAction::Block { reason: "contains bad word".into() }
156///         }
157///     }
158/// }
159/// ```
160pub trait MutatorMiddleware<Evt>: Send + Sync {
161    /// 返回此 mutator 的唯一标识名称。
162    fn name(&self) -> &str;
163
164    /// 处理事件。支持三种决策:
165    /// - [`MutatorAction::Pass`]:放行,事件不变
166    /// - [`MutatorAction::Modify`]:替换事件
167    /// - [`MutatorAction::Block`]:阻止后续传递
168    fn process(&self, event: Evt) -> MutatorAction<Evt>;
169}
170
171// ═══════════════════════════════════════════════════════════════
172// 注册 trait — Bevy 风格 tuple(不提供 blanket impl,避免冲突)
173// ═══════════════════════════════════════════════════════════════
174
175/// 将一组 inspector 转换为 `Vec<Arc<dyn InspectorMiddleware>>`。
176///
177/// 该 trait 为元组 `(A,)` 到 `(A, B, ..., L, M)`(arity 1..=12)实现,
178/// 用于 [`MiddlewareChain::with_inspectors`]。
179///
180/// 单值 inspector 应使用 [`MiddlewareChain::with_inspector`]。
181pub trait IntoInspectors<Evt> {
182    /// 将 self 转换为 inspector 向量。
183    fn into_inspectors(self) -> Vec<Arc<dyn InspectorMiddleware<Evt>>>;
184}
185
186/// 将一组 mutator 转换为 `Vec<Arc<dyn MutatorMiddleware>>`。
187///
188/// 该 trait 为元组 `(A,)` 到 `(A, B, ..., L, M)`(arity 1..=12)实现,
189/// 用于 [`MiddlewareChain::with_mutators`]。
190///
191/// 单值 mutator 应使用 [`MiddlewareChain::with_mutator`]。
192pub trait IntoMutators<Evt> {
193    /// 将 self 转换为 mutator 向量。
194    fn into_mutators(self) -> Vec<Arc<dyn MutatorMiddleware<Evt>>>;
195}
196
197// ── tuple impls (arity 1..=12) ───────────────────────────
198
199macro_rules! impl_into_inspectors_tuple {
200    ($($T:ident),+) => {
201        impl<Evt, $($T: InspectorMiddleware<Evt> + 'static),+> IntoInspectors<Evt>
202            for ($($T,)+)
203        {
204            #[allow(non_snake_case)]
205            fn into_inspectors(self) -> Vec<Arc<dyn InspectorMiddleware<Evt>>> {
206                let ($($T,)+) = self;
207                vec![$(Arc::new($T) as Arc<dyn InspectorMiddleware<Evt>>),+]
208            }
209        }
210    };
211}
212
213macro_rules! impl_into_mutators_tuple {
214    ($($T:ident),+) => {
215        impl<Evt, $($T: MutatorMiddleware<Evt> + 'static),+> IntoMutators<Evt>
216            for ($($T,)+)
217        {
218            #[allow(non_snake_case)]
219            fn into_mutators(self) -> Vec<Arc<dyn MutatorMiddleware<Evt>>> {
220                let ($($T,)+) = self;
221                vec![$(Arc::new($T) as Arc<dyn MutatorMiddleware<Evt>>),+]
222            }
223        }
224    };
225}
226
227impl_into_inspectors_tuple!(A);
228impl_into_inspectors_tuple!(A, B);
229impl_into_inspectors_tuple!(A, B, C);
230impl_into_inspectors_tuple!(A, B, C, D);
231impl_into_inspectors_tuple!(A, B, C, D, F);
232impl_into_inspectors_tuple!(A, B, C, D, F, G);
233impl_into_inspectors_tuple!(A, B, C, D, F, G, H);
234impl_into_inspectors_tuple!(A, B, C, D, F, G, H, I);
235impl_into_inspectors_tuple!(A, B, C, D, F, G, H, I, J);
236impl_into_inspectors_tuple!(A, B, C, D, F, G, H, I, J, K);
237impl_into_inspectors_tuple!(A, B, C, D, F, G, H, I, J, K, L);
238impl_into_inspectors_tuple!(A, B, C, D, F, G, H, I, J, K, L, M);
239
240impl_into_mutators_tuple!(A);
241impl_into_mutators_tuple!(A, B);
242impl_into_mutators_tuple!(A, B, C);
243impl_into_mutators_tuple!(A, B, C, D);
244impl_into_mutators_tuple!(A, B, C, D, F);
245impl_into_mutators_tuple!(A, B, C, D, F, G);
246impl_into_mutators_tuple!(A, B, C, D, F, G, H);
247impl_into_mutators_tuple!(A, B, C, D, F, G, H, I);
248impl_into_mutators_tuple!(A, B, C, D, F, G, H, I, J);
249impl_into_mutators_tuple!(A, B, C, D, F, G, H, I, J, K);
250impl_into_mutators_tuple!(A, B, C, D, F, G, H, I, J, K, L);
251impl_into_mutators_tuple!(A, B, C, D, F, G, H, I, J, K, L, M);
252
253// ═══════════════════════════════════════════════════════════════
254// MiddlewareLayer + MiddlewareChain (typestate)
255// ═══════════════════════════════════════════════════════════════
256
257/// 中间件链中的一层。
258///
259/// 每层可以是 inspector(内部并行)或 mutator(内部顺序)。
260pub enum MiddlewareLayer<Evt> {
261    /// Inspector 层——此层内的所有 inspector 通过 `tokio::spawn` 并行执行。
262    Inspector(Vec<Arc<dyn InspectorMiddleware<Evt>>>),
263    /// Mutator 层——此层内的所有 mutator 按注册顺序依次执行。
264    Mutator(Vec<Arc<dyn MutatorMiddleware<Evt>>>),
265}
266
267// ── Typestate markers ─────────────────────────────────────────
268
269/// 错误通道**尚未**启用的 typestate 标记。
270///
271/// 在此状态下,调用 [`MiddlewareChain::activate_error_channel`] 可激活
272/// 错误通道并转换为 [`ErrorsEnabled`] 状态。
273pub struct ErrorsDisabled;
274
275/// 错误通道**已**启用的 typestate 标记。
276///
277/// 在此状态下,`activate_error_channel` 不可用(编译期保证)。
278/// 可以通过 [`MiddlewareChain::error_sender`] 获取已有 sender。
279pub struct ErrorsEnabled;
280
281/// 中间件链——按注册顺序逐层执行。
282///
283/// 链中的每一层可以是 inspector 或 mutator,通过构建方法指定。
284/// 参数 `ErrState` 是 typestate 标记,默认 [`ErrorsDisabled`]。
285///
286/// ## 执行模型
287///
288/// 1. **Inspector 层**:同一层内的 inspector 通过 `tokio::spawn` 并行执行,
289///    不等待其完成。错误通过 error channel 异步报告。
290///    *无 tokio 运行时*:降级为同步执行。
291/// 2. **Mutator 层**:同一层内的 mutator 按注册顺序依次执行。
292///    遇到 [`MutatorAction::Block`] 立即终止整条链。
293///
294/// ## Typestate 错误通道
295///
296/// ```rust,no_run
297/// # use funera_core::middleware::{MiddlewareChain, ErrorsEnabled, InspectorMiddleware, InspectorError};
298/// # struct Insp;
299/// # impl InspectorMiddleware<String> for Insp {
300/// #     fn name(&self) -> &str { "i" }
301/// #     fn inspect(&self, _: &String) -> Result<(), InspectorError> { Ok(()) }
302/// # }
303/// // 默认状态:ErrorsDisabled
304/// let chain = MiddlewareChain::<String>::new()
305///     .with_inspector(Insp);
306///
307/// // 激活错误通道后变为 ErrorsEnabled
308/// let (chain, rx) = chain.activate_error_channel();
309/// // chain:  MiddlewareChain<String, ErrorsEnabled>
310/// ```
311pub struct MiddlewareChain<Evt, ErrState = ErrorsDisabled> {
312    layers: Vec<MiddlewareLayer<Evt>>,
313    error_tx: Option<mpsc::UnboundedSender<(String, InspectorError)>>,
314    _err: PhantomData<ErrState>,
315}
316
317// ── 仅 ErrorsDisabled:new + activate ─────────────────────────
318
319impl<Evt: Clone + Send + 'static> MiddlewareChain<Evt, ErrorsDisabled> {
320    /// 创建一个新的空中间件链(`ErrorsDisabled` 状态)。
321    ///
322    /// 链初始为空,需要通过 `with_inspector`、`with_mutators` 等方法填充。
323    pub fn new() -> Self {
324        Self {
325            layers: Vec::new(),
326            error_tx: None,
327            _err: PhantomData,
328        }
329    }
330
331    /// 启用错误通道并获取 receiver。
332    ///
333    /// 调用后链的状态变为 [`ErrorsEnabled`],inspector 执行中的错误将通过
334    /// 返回的 receiver 异步送达。此方法**仅可调用一次**(编译期由 typestate 保证)。
335    ///
336    /// 如果不需要跟踪 inspector 错误,可以忽略返回值中的 receiver。
337    ///
338    /// # 示例
339    ///
340    /// ```rust,no_run
341    /// # use funera_core::middleware::{MiddlewareChain, InspectorMiddleware, InspectorError};
342    /// # struct Insp;
343    /// # impl InspectorMiddleware<String> for Insp {
344    /// #     fn name(&self) -> &str { "i" }
345    /// #     fn inspect(&self, _: &String) -> Result<(), InspectorError> { Ok(()) }
346    /// # }
347    /// let chain = MiddlewareChain::<String>::new()
348    ///     .with_inspector(Insp);
349    /// let (_chain, mut error_rx) = chain.activate_error_channel();
350    /// ```
351    pub fn activate_error_channel(
352        self,
353    ) -> (
354        MiddlewareChain<Evt, ErrorsEnabled>,
355        mpsc::UnboundedReceiver<(String, InspectorError)>,
356    ) {
357        let (tx, rx) = mpsc::unbounded_channel();
358        let chain = MiddlewareChain::<Evt, ErrorsEnabled> {
359            layers: self.layers,
360            error_tx: Some(tx),
361            _err: PhantomData,
362        };
363        (chain, rx)
364    }
365}
366
367impl<Evt: Clone + Send + 'static> Default for MiddlewareChain<Evt, ErrorsDisabled> {
368    fn default() -> Self {
369        Self::new()
370    }
371}
372
373// ── 构建方法:两种状态均可用 ──────────────────────────────────
374
375impl<Evt: Clone + Send + 'static, S> MiddlewareChain<Evt, S> {
376    /// 添加单个 inspector 作为独立的一层。
377    ///
378    /// 每个 `with_inspector` 调用创建一个新层,与其他层按注册顺序执行。
379    /// 同一层内的 inspector 通过 `tokio::spawn` 后台并行。
380    pub fn with_inspector(mut self, i: impl InspectorMiddleware<Evt> + 'static) -> Self {
381        self.layers
382            .push(MiddlewareLayer::Inspector(vec![Arc::new(i)]));
383        self
384    }
385
386    /// 添加一组 inspector 作为同一层(并行)。
387    ///
388    /// 接受 Bevy 风格的 tuple `(A, B, C)`,所有 inspector 将在同一层内并行执行。
389    ///
390    /// # 示例
391    ///
392    /// ```rust,no_run
393    /// # use funera_core::middleware::{MiddlewareChain, InspectorMiddleware, InspectorError};
394    /// # struct A; impl InspectorMiddleware<String> for A {
395    /// #     fn name(&self) -> &str { "A" }
396    /// #     fn inspect(&self, _: &String) -> Result<(), InspectorError> { Ok(()) }
397    /// # }
398    /// # struct B; impl InspectorMiddleware<String> for B {
399    /// #     fn name(&self) -> &str { "B" }
400    /// #     fn inspect(&self, _: &String) -> Result<(), InspectorError> { Ok(()) }
401    /// # }
402    /// let chain = MiddlewareChain::<String>::new()
403    ///     .with_inspectors((A, B));  // A 和 B 并行执行
404    /// ```
405    pub fn with_inspectors(mut self, i: impl IntoInspectors<Evt>) -> Self {
406        let v = i.into_inspectors();
407        if !v.is_empty() {
408            self.layers.push(MiddlewareLayer::Inspector(v));
409        }
410        self
411    }
412
413    /// 从迭代器批量添加已装箱的 inspector。
414    pub fn with_inspectors_from_iter(
415        mut self,
416        iter: impl IntoIterator<Item = Arc<dyn InspectorMiddleware<Evt>>>,
417    ) -> Self {
418        let v: Vec<_> = iter.into_iter().collect();
419        if !v.is_empty() {
420            self.layers.push(MiddlewareLayer::Inspector(v));
421        }
422        self
423    }
424
425    /// 添加单个 mutator 作为独立的一层。
426    ///
427    /// 每个 `with_mutator` 调用创建一个新层。同一层内的 mutator 按顺序执行。
428    pub fn with_mutator(mut self, m: impl MutatorMiddleware<Evt> + 'static) -> Self {
429        self.layers
430            .push(MiddlewareLayer::Mutator(vec![Arc::new(m)]));
431        self
432    }
433
434    /// 添加一组 mutator 作为同一层(顺序执行)。
435    ///
436    /// 接受 Bevy 风格的 tuple `(A, B, C)`,所有 mutator 按注册顺序依次执行。
437    ///
438    /// # 示例
439    ///
440    /// ```rust,no_run
441    /// # use funera_core::middleware::{MiddlewareChain, MutatorMiddleware, MutatorAction};
442    /// # struct Censor; impl MutatorMiddleware<String> for Censor {
443    /// #     fn name(&self) -> &str { "censor" }
444    /// #     fn process(&self, s: String) -> MutatorAction<String> { MutatorAction::Pass }
445    /// # }
446    /// # struct Blocker; impl MutatorMiddleware<String> for Blocker {
447    /// #     fn name(&self) -> &str { "blocker" }
448    /// #     fn process(&self, s: String) -> MutatorAction<String> { MutatorAction::Pass }
449    /// # }
450    /// let chain = MiddlewareChain::<String>::new()
451    ///     .with_mutators((Censor, Blocker));  // Censor 先,Blocker 后
452    /// ```
453    pub fn with_mutators(mut self, m: impl IntoMutators<Evt>) -> Self {
454        let v = m.into_mutators();
455        if !v.is_empty() {
456            self.layers.push(MiddlewareLayer::Mutator(v));
457        }
458        self
459    }
460
461    /// 从迭代器批量添加已装箱的 mutator。
462    pub fn with_mutators_from_iter(
463        mut self,
464        iter: impl IntoIterator<Item = Arc<dyn MutatorMiddleware<Evt>>>,
465    ) -> Self {
466        let v: Vec<_> = iter.into_iter().collect();
467        if !v.is_empty() {
468            self.layers.push(MiddlewareLayer::Mutator(v));
469        }
470        self
471    }
472
473    /// 链中是否没有任何 middleware 层。
474    pub fn is_empty(&self) -> bool {
475        self.layers.is_empty()
476    }
477
478    /// 返回 middleware 层的数量。
479    pub fn len(&self) -> usize {
480        self.layers.len()
481    }
482
483    /// 按注册顺序逐层执行。
484    ///
485    /// ## 执行流程
486    ///
487    /// - **Inspector 层**:`tokio::spawn` 后台并发执行,不等待,错误进入 error channel。
488    ///   如果当前没有 tokio 运行时,降级为同步执行。
489    /// - **Mutator 层**:同步顺序执行。遇到 `Block` 立即短路,返回 `Err(MiddlewareBlocked)`。
490    ///
491    /// ## 返回值
492    ///
493    /// - `Ok(event)` — 经过所有 layer 处理后的最终事件
494    /// - `Err(MiddlewareBlocked)` — 被 mutator 阻止
495    pub fn process(&self, event: Evt) -> Result<Evt, MiddlewareBlocked> {
496        let mut current = event;
497        for layer in &self.layers {
498            match layer {
499                MiddlewareLayer::Inspector(inspectors) => {
500                    current = self.run_inspectors(inspectors, current);
501                }
502                MiddlewareLayer::Mutator(mutators) => {
503                    current = self.run_mutators(mutators, current)?;
504                }
505            }
506        }
507        Ok(current)
508    }
509
510    fn run_inspectors(&self, inspectors: &[Arc<dyn InspectorMiddleware<Evt>>], event: Evt) -> Evt {
511        if let Ok(handle) = tokio::runtime::Handle::try_current() {
512            for insp in inspectors {
513                let name = insp.name().to_string();
514                let evt = event.clone();
515                let tx = self.error_tx.clone();
516                let insp = Arc::clone(insp);
517                handle.spawn(async move {
518                    if let Err(e) = insp.inspect(&evt)
519                        && let Some(tx) = tx
520                    {
521                        let _ = tx.send((name, e));
522                    }
523                });
524            }
525        } else {
526            for insp in inspectors {
527                if let (Some(tx), Err(e)) = (&self.error_tx, insp.inspect(&event)) {
528                    let _ = tx.send((insp.name().to_string(), e));
529                }
530            }
531        }
532        event
533    }
534
535    fn run_mutators(
536        &self,
537        mutators: &[Arc<dyn MutatorMiddleware<Evt>>],
538        event: Evt,
539    ) -> Result<Evt, MiddlewareBlocked> {
540        let mut current = event;
541        for m in mutators {
542            match m.process(current.clone()) {
543                MutatorAction::Pass => {}
544                MutatorAction::Modify(e) => current = e,
545                MutatorAction::Block { reason } => {
546                    return Err(MiddlewareBlocked {
547                        middleware_name: m.name().to_string(),
548                        reason,
549                    });
550                }
551            }
552        }
553        Ok(current)
554    }
555}
556
557// ── ErrorsEnabled: 暴露 error channel ─────────────────────────
558
559impl<Evt: Clone + Send + 'static> MiddlewareChain<Evt, ErrorsEnabled> {
560    /// 返回底层 error channel 的 sender,可用于外部发送错误。
561    ///
562    /// 返回的 sender 是 `Option`——如果 chain 构造时未激活错误通道则为 `None`。
563    pub fn error_sender(&self) -> Option<mpsc::UnboundedSender<(String, InspectorError)>> {
564        self.error_tx.clone()
565    }
566}
567
568// ═══════════════════════════════════════════════════════════════
569// MiddlewareBlocked
570// ═══════════════════════════════════════════════════════════════
571
572/// 事件被 mutator 阻止时的错误信息。
573#[derive(Debug, Clone)]
574pub struct MiddlewareBlocked {
575    /// 阻止事件的 mutator 名称。
576    pub middleware_name: String,
577    /// 阻止原因。
578    pub reason: String,
579}
580
581impl std::fmt::Display for MiddlewareBlocked {
582    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
583        write!(
584            f,
585            "[middleware:{}] event blocked: {}",
586            self.middleware_name, self.reason
587        )
588    }
589}
590
591// ═══════════════════════════════════════════════════════════════
592// MiddlewareEvent — ReAct loop 每轮产出的可过滤事件
593// ═══════════════════════════════════════════════════════════════
594
595/// 用于 `react_loop` 向上层通知事件的可调用对象。
596///
597/// 由 `funera-orchestrate` 提供实现(封装 callbacks + event_tx),
598/// `react_loop` 在每轮聚合数据后调用此函数发出已过滤的事件。
599pub type EventSenderFn<E> = Box<dyn Fn(E) + Send + Sync>;
600
601/// ReAct 循环每轮产出的中间件事件。
602///
603/// `react_loop` 在 `process_token_stream` 和 `handle_turn_finish` 后
604/// 将聚合结果转换为 `MiddlewareEvent`,经过 middleware chain 过滤后:
605/// - 发出到上层(`event_tx` + callbacks)
606/// - 转换为 `FuneraMessage` 存入 session 历史
607///
608/// 由 `AgentEvent`(`funera-orchestrate`)实现此 trait。
609pub trait MiddlewareEvent: Clone + Send + 'static {
610    /// 工具错误类型。
611    type Error: std::fmt::Display + Send + Sync + 'static + From<String>;
612
613    /// Factory:assistant 聚合文本回复。
614    fn assistant_text(content: String, reasoning: Option<String>) -> Self;
615
616    /// Factory:单个工具调用请求。
617    fn tool_call_request(call_id: Arc<str>, name: String, args: JsonValue) -> Self;
618
619    /// Factory:单个工具执行结果。
620    fn tool_response(call_id: Arc<str>, name: String, result: Result<String, Self::Error>) -> Self;
621
622    /// Factory:turn 开始。
623    fn turn_start() -> Self;
624
625    /// Factory:turn 结束,携带 finish_reason。
626    fn turn_end(finish_reason: Option<String>) -> Self;
627
628    /// Factory:会话结束。
629    fn done() -> Self;
630
631    /// 转换为 session 历史消息。
632    ///
633    /// 返回 `Some((role, variant))` 用于构造 `FuneraMessage`。
634    /// 不可转换的事件(如 `TurnStart`、`TurnEnd`、`Done`)返回 `None`。
635    fn into_session_message(self) -> Option<(Role, MsgVariant)>;
636}
637
638#[cfg(test)]
639mod tests {
640    use super::*;
641
642    struct NoopInspector;
643
644    impl InspectorMiddleware<String> for NoopInspector {
645        fn name(&self) -> &str {
646            "noop"
647        }
648        fn inspect(&self, _event: &String) -> Result<(), InspectorError> {
649            Ok(())
650        }
651    }
652
653    struct UpperMutator;
654
655    impl MutatorMiddleware<String> for UpperMutator {
656        fn name(&self) -> &str {
657            "upper"
658        }
659        fn process(&self, event: String) -> MutatorAction<String> {
660            MutatorAction::Modify(event.to_uppercase())
661        }
662    }
663
664    struct BlockMutator;
665
666    impl MutatorMiddleware<String> for BlockMutator {
667        fn name(&self) -> &str {
668            "blocker"
669        }
670        fn process(&self, _event: String) -> MutatorAction<String> {
671            MutatorAction::Block {
672                reason: "blocked".into(),
673            }
674        }
675    }
676
677    struct PassMutator;
678
679    impl MutatorMiddleware<String> for PassMutator {
680        fn name(&self) -> &str {
681            "pass"
682        }
683        fn process(&self, _event: String) -> MutatorAction<String> {
684            MutatorAction::Pass
685        }
686    }
687
688    #[test]
689    fn new_chain_is_empty() {
690        let chain = MiddlewareChain::<String>::new();
691        assert!(chain.is_empty());
692    }
693
694    #[test]
695    fn single_mutator_modify() {
696        let chain = MiddlewareChain::<String>::new().with_mutator(UpperMutator);
697        let result = chain.process("hello".into()).unwrap();
698        assert_eq!(result, "HELLO");
699    }
700
701    #[test]
702    fn single_mutator_pass() {
703        let chain = MiddlewareChain::<String>::new().with_mutator(PassMutator);
704        let result = chain.process("hello".into()).unwrap();
705        assert_eq!(result, "hello");
706    }
707
708    #[test]
709    fn single_mutator_block() {
710        let chain = MiddlewareChain::<String>::new().with_mutator(BlockMutator);
711        let err = chain.process("hello".into()).unwrap_err();
712        assert_eq!(err.middleware_name, "blocker");
713        assert_eq!(err.reason, "blocked");
714    }
715
716    #[test]
717    fn pass_then_modify() {
718        let chain = MiddlewareChain::<String>::new().with_mutators((PassMutator, UpperMutator));
719        let result = chain.process("hello".into()).unwrap();
720        assert_eq!(result, "HELLO");
721    }
722
723    #[test]
724    fn modify_then_block() {
725        let chain = MiddlewareChain::<String>::new().with_mutators((UpperMutator, BlockMutator));
726        let err = chain.process("hello".into()).unwrap_err();
727        assert_eq!(err.middleware_name, "blocker");
728    }
729
730    #[test]
731    fn tuple_arity_3() {
732        let chain = MiddlewareChain::<String>::new().with_mutators((
733            UpperMutator,
734            PassMutator,
735            PassMutator,
736        ));
737        let result = chain.process("hello".into()).unwrap();
738        assert_eq!(result, "HELLO");
739    }
740
741    #[test]
742    fn inspector_without_tokio_is_noop() {
743        let chain = MiddlewareChain::<String>::new()
744            .with_inspector(NoopInspector)
745            .with_mutator(UpperMutator);
746        let result = chain.process("hello".into()).unwrap();
747        assert_eq!(result, "HELLO");
748    }
749
750    #[test]
751    fn activate_error_channel_transitions_state() {
752        let chain = MiddlewareChain::<String>::new();
753        let (_enabled, _rx) = chain.activate_error_channel();
754    }
755
756    #[test]
757    fn with_inspectors_tuple() {
758        let chain =
759            MiddlewareChain::<String>::new().with_inspectors((NoopInspector, NoopInspector));
760        assert_eq!(chain.len(), 1);
761    }
762
763    #[test]
764    fn single_inspector_tuple() {
765        let chain = MiddlewareChain::<String>::new().with_inspectors((NoopInspector,));
766        assert_eq!(chain.len(), 1);
767    }
768
769    #[test]
770    fn chain_with_tokio_spawns_inspectors() {
771        let rt = tokio::runtime::Builder::new_current_thread()
772            .build()
773            .unwrap();
774        rt.block_on(async {
775            let chain = MiddlewareChain::<String>::new().with_inspector(NoopInspector);
776            let result = chain.process("hi".into()).unwrap();
777            assert_eq!(result, "hi");
778        });
779    }
780}