agent_core/agent/
router.rs

1// Message router for TUI-Controller communication
2//
3// InputRouter reads user input from the TUI and forwards it to the controller.
4// The controller-to-TUI direction is handled by the event callback in the agent.
5
6use std::sync::Arc;
7
8use crate::controller::LLMController;
9use tokio_util::sync::CancellationToken;
10
11use super::messages::channels::ToControllerRx;
12
13/// Routes messages from the TUI to the controller.
14///
15/// This component runs as an async task and reads from the `from_tui` channel,
16/// forwarding each message to the controller via `send_input()`.
17pub struct InputRouter {
18    controller: Arc<LLMController>,
19    from_tui: ToControllerRx,
20    cancel_token: CancellationToken,
21}
22
23impl InputRouter {
24    /// Creates a new input router.
25    ///
26    /// # Arguments
27    /// * `controller` - The LLM controller to forward messages to
28    /// * `from_tui` - Channel receiver for messages from the TUI
29    /// * `cancel_token` - Token for graceful shutdown
30    pub fn new(
31        controller: Arc<LLMController>,
32        from_tui: ToControllerRx,
33        cancel_token: CancellationToken,
34    ) -> Self {
35        Self {
36            controller,
37            from_tui,
38            cancel_token,
39        }
40    }
41
42    /// Runs the input router event loop.
43    ///
44    /// This method will run until either:
45    /// - The cancel token is triggered
46    /// - The `from_tui` channel is closed
47    pub async fn run(mut self) {
48        tracing::info!("InputRouter started");
49
50        loop {
51            tokio::select! {
52                _ = self.cancel_token.cancelled() => {
53                    tracing::info!("InputRouter cancelled");
54                    break;
55                }
56                msg = self.from_tui.recv() => {
57                    match msg {
58                        Some(payload) => {
59                            if let Err(e) = self.controller.send_input(payload).await {
60                                tracing::error!("Failed to send input to controller: {}", e);
61                            }
62                        }
63                        None => {
64                            tracing::info!("TUI channel closed");
65                            break;
66                        }
67                    }
68                }
69            }
70        }
71
72        tracing::info!("InputRouter stopped");
73    }
74}