1use rskit_hook::{Event, EventType};
7use rskit_llm::types::{AssistantMessage, CompletionRequest, CompletionResponse};
8use rskit_tool::ToolInput;
9use rskit_tool::ToolResult;
10
11pub fn on_tool_call_type() -> EventType {
15 EventType::new("on_tool_call")
16}
17
18pub fn pre_tool_call_type() -> EventType {
20 on_tool_call_type()
21}
22
23pub fn on_tool_result_type() -> EventType {
25 EventType::new("on_tool_result")
26}
27
28pub fn post_tool_call_type() -> EventType {
30 on_tool_result_type()
31}
32
33pub fn on_llm_call_type() -> EventType {
35 EventType::new("on_llm_call")
36}
37
38pub fn pre_llm_call_type() -> EventType {
40 on_llm_call_type()
41}
42
43pub fn on_llm_response_type() -> EventType {
45 EventType::new("on_llm_response")
46}
47
48pub fn post_llm_call_type() -> EventType {
50 on_llm_response_type()
51}
52
53pub fn on_error_type() -> EventType {
55 EventType::new("on_error")
56}
57
58pub fn on_turn_start_type() -> EventType {
60 EventType::new("on_turn_start")
61}
62
63pub fn turn_start_type() -> EventType {
65 on_turn_start_type()
66}
67
68pub fn on_turn_complete_type() -> EventType {
70 EventType::new("on_turn_complete")
71}
72
73pub fn turn_end_type() -> EventType {
75 on_turn_complete_type()
76}
77
78pub fn on_event_type() -> EventType {
80 EventType::new("on_event")
81}
82
83pub fn on_mcp_call_type() -> EventType {
85 EventType::new("on_mcp_call")
86}
87
88pub fn on_mcp_result_type() -> EventType {
90 EventType::new("on_mcp_result")
91}
92
93#[derive(Debug, Clone)]
97pub struct OnEvent {
98 pub event: rskit_ai::StreamEventRef,
100}
101
102impl Event for OnEvent {
103 fn event_type(&self) -> EventType {
104 on_event_type()
105 }
106}
107
108#[derive(Debug, Clone)]
110pub struct OnMCPCall {
111 pub method: String,
113}
114
115impl Event for OnMCPCall {
116 fn event_type(&self) -> EventType {
117 on_mcp_call_type()
118 }
119}
120
121#[derive(Debug, Clone)]
123pub struct OnMCPResult {
124 pub method: String,
126 pub result: Option<serde_json::Value>,
128 pub error: Option<String>,
130}
131
132impl Event for OnMCPResult {
133 fn event_type(&self) -> EventType {
134 on_mcp_result_type()
135 }
136}
137
138#[derive(Debug, Clone)]
140pub struct PreToolCall {
141 pub name: String,
143 pub input: ToolInput,
145}
146
147impl Event for PreToolCall {
148 fn event_type(&self) -> EventType {
149 pre_tool_call_type()
150 }
151}
152
153#[derive(Debug, Clone)]
155pub struct PostToolCall {
156 pub name: String,
158 pub input: ToolInput,
160 pub result: Option<ToolResult>,
162 pub error: Option<String>,
164}
165
166impl Event for PostToolCall {
167 fn event_type(&self) -> EventType {
168 post_tool_call_type()
169 }
170}
171
172#[derive(Debug, Clone)]
174pub struct PreLLMCall {
175 pub request: CompletionRequest,
177}
178
179impl Event for PreLLMCall {
180 fn event_type(&self) -> EventType {
181 pre_llm_call_type()
182 }
183}
184
185#[derive(Debug, Clone)]
187pub struct PostLLMCall {
188 pub response: CompletionResponse,
190 pub error: Option<String>,
192}
193
194impl Event for PostLLMCall {
195 fn event_type(&self) -> EventType {
196 post_llm_call_type()
197 }
198}
199
200#[derive(Debug, Clone)]
202pub struct OnError {
203 pub error: String,
205 pub source: String,
207}
208
209impl Event for OnError {
210 fn event_type(&self) -> EventType {
211 on_error_type()
212 }
213}
214
215#[derive(Debug, Clone)]
217pub struct TurnStart {
218 pub turn: u32,
220}
221
222impl Event for TurnStart {
223 fn event_type(&self) -> EventType {
224 turn_start_type()
225 }
226}
227
228#[derive(Debug, Clone)]
230pub struct TurnEnd {
231 pub turn: u32,
233 pub message: AssistantMessage,
235}
236
237impl Event for TurnEnd {
238 fn event_type(&self) -> EventType {
239 turn_end_type()
240 }
241}
242
243#[cfg(test)]
244mod tests {
245 use super::*;
246 use rskit_hook::EventType;
247 use rskit_tool::ToolInput;
248
249 #[test]
250 fn test_pre_tool_call_event() {
251 let event = PreToolCall {
252 name: "calculator".to_string(),
253 input: ToolInput::new(serde_json::json!({"x": 1})).unwrap(),
254 };
255 assert_eq!(event.event_type(), EventType::new("on_tool_call"));
256 assert_eq!(event.name, "calculator");
257 }
258
259 #[test]
260 fn test_post_tool_call_event() {
261 let event = PostToolCall {
262 name: "calculator".to_string(),
263 input: ToolInput::new(serde_json::json!({})).unwrap(),
264 result: None,
265 error: Some("timeout".to_string()),
266 };
267 assert_eq!(event.event_type(), EventType::new("on_tool_result"));
268 }
269
270 #[test]
271 fn test_pre_llm_call_event() {
272 let event = PreLLMCall {
273 request: CompletionRequest {
274 model: "test".to_string(),
275 messages: vec![],
276 max_tokens: None,
277 temperature: None,
278 stream: false,
279 tools: None,
280 tool_choice: None,
281 },
282 };
283 assert_eq!(event.event_type(), EventType::new("on_llm_call"));
284 }
285
286 #[test]
287 fn test_on_error_event() {
288 let event = OnError {
289 error: "boom".to_string(),
290 source: "agent".to_string(),
291 };
292 assert_eq!(event.event_type(), EventType::new("on_error"));
293 }
294
295 #[test]
296 fn test_turn_start_event() {
297 let event = TurnStart { turn: 0 };
298 assert_eq!(event.event_type(), EventType::new("on_turn_start"));
299 assert_eq!(event.turn, 0);
300 }
301
302 #[test]
303 fn test_turn_end_event() {
304 use rskit_llm::types;
305 let event = TurnEnd {
306 turn: 3,
307 message: AssistantMessage {
308 content: types::text_content("done"),
309 tool_calls: vec![],
310 usage: None,
311 },
312 };
313 assert_eq!(event.event_type(), EventType::new("on_turn_complete"));
314 }
315
316 #[test]
317 fn test_event_type_constants() {
318 assert_eq!(pre_tool_call_type(), EventType::new("on_tool_call"));
319 assert_eq!(post_tool_call_type(), EventType::new("on_tool_result"));
320 assert_eq!(pre_llm_call_type(), EventType::new("on_llm_call"));
321 assert_eq!(post_llm_call_type(), EventType::new("on_llm_response"));
322 assert_eq!(on_error_type(), EventType::new("on_error"));
323 assert_eq!(turn_start_type(), EventType::new("on_turn_start"));
324 assert_eq!(turn_end_type(), EventType::new("on_turn_complete"));
325 }
326}