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