funera_core/event_bus/
react_bus.rs1use crate::chat::message::FuneraMessage;
2use serde_json::Value as JsonValue;
3use tokio::sync::broadcast;
4
5#[cfg(feature = "security")]
6use std::path::PathBuf;
7
8#[derive(Debug, Clone)]
9pub struct ToolCallRequest {
10 pub index: usize,
11 pub call_id: String,
12 pub name: String,
13 pub args: JsonValue,
14}
15
16#[derive(Debug, Clone)]
17pub struct ToolCallResponse {
18 pub call_id: String,
19 pub name: String,
20 pub result: String,
21}
22
23#[derive(Debug, Clone)]
24pub struct ToolCallErrorInfo {
25 pub call_id: String,
26 pub name: String,
27 pub error: String,
28}
29
30#[derive(Debug, Clone)]
31pub enum ReactEvent {
32 TurnStart,
33 TurnEnd,
34 MessageQueued(FuneraMessage),
35 ToolExecRequest(ToolCallRequest),
36 ToolExecResponse(Result<ToolCallResponse, ToolCallErrorInfo>),
37 #[cfg(feature = "security")]
39 ToolApprovalRequired {
40 call_id: String,
41 tool_name: String,
42 paths: Vec<PathBuf>,
43 reason: String,
44 },
45}
46
47#[derive(Debug, Clone)]
48pub struct ReactBus {
49 react_tx: broadcast::Sender<ReactEvent>,
50}
51
52impl ReactBus {
53 pub fn new() -> Self {
54 let (react_tx, _) = broadcast::channel(30);
55 Self { react_tx }
56 }
57
58 pub fn subscribe(&self) -> broadcast::Receiver<ReactEvent> {
59 self.react_tx.subscribe()
60 }
61 pub fn sender(&self) -> broadcast::Sender<ReactEvent> {
62 self.react_tx.clone()
63 }
64 pub fn send(&self, event: ReactEvent) -> anyhow::Result<usize> {
65 self.react_tx.send(event).map_err(|e| e.into())
66 }
67}
68
69impl Default for ReactBus {
70 fn default() -> Self {
71 Self::new()
72 }
73}