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}