1use pe_core::message::ToolCall;
11
12pub trait ToolCallInterceptor: Send + Sync {
30 fn intercept(&self, call: ToolCall) -> ToolCall;
32}
33
34pub struct PassthroughInterceptor;
36
37impl ToolCallInterceptor for PassthroughInterceptor {
38 fn intercept(&self, call: ToolCall) -> ToolCall {
39 call
40 }
41}
42
43#[cfg(test)]
44mod tests {
45 use super::*;
46
47 #[test]
48 fn passthrough_interceptor_returns_unchanged() {
49 let interceptor = PassthroughInterceptor;
50 let call = ToolCall {
51 id: "tc_1".into(),
52 name: "search".into(),
53 args: serde_json::json!({"query": "test"}),
54 };
55
56 let result = interceptor.intercept(call.clone());
57 assert_eq!(result.id, "tc_1");
58 assert_eq!(result.name, "search");
59 assert_eq!(result.args, serde_json::json!({"query": "test"}));
60 }
61
62 struct PrefixInterceptor {
63 prefix: String,
64 }
65
66 impl ToolCallInterceptor for PrefixInterceptor {
67 fn intercept(&self, mut call: ToolCall) -> ToolCall {
68 call.name = format!("{}_{}", self.prefix, call.name);
69 call
70 }
71 }
72
73 #[test]
74 fn custom_interceptor_modifies_call() {
75 let interceptor = PrefixInterceptor {
76 prefix: "safe".into(),
77 };
78 let call = ToolCall {
79 id: "tc_2".into(),
80 name: "delete".into(),
81 args: serde_json::json!({}),
82 };
83
84 let result = interceptor.intercept(call);
85 assert_eq!(result.name, "safe_delete");
86 assert_eq!(result.id, "tc_2");
87 }
88}