kernelx_core/interfaces/tui/
app.rs1use super::{model::AppModel, terminal::TerminalManager, types::ChatEvent, update, view};
2use crate::{capabilities::Chat, models::Model, providers::Provider, Result};
3use anyhow::Context;
4use crossterm::event::{self, Event, KeyCode};
5use std::time::Duration;
6use tokio::sync::mpsc;
7
8pub struct App<P: Provider + Chat + Clone + 'static> {
9 terminal: TerminalManager,
10 model: AppModel<P>,
11 tx: mpsc::Sender<ChatEvent>,
12 rx: mpsc::Receiver<ChatEvent>,
13}
14
15impl<P: Provider + Chat + Clone + 'static> App<P> {
16 pub fn new(model: Model<P, dyn Chat>) -> Result<Self> {
17 let model = AppModel::new(model);
18 let (tx, rx) = mpsc::channel(32);
19 Ok(Self {
20 terminal: TerminalManager::new()?,
21 model,
22 tx,
23 rx,
24 })
25 }
26
27 pub async fn run(&mut self) -> Result<()> {
28 let tx = self.tx.clone();
29
30 tokio::spawn(async move {
31 loop {
32 if let Ok(true) = event::poll(Duration::from_millis(100)) {
33 if let Ok(Event::Key(key)) = event::read() {
34 let _ = tx.send(ChatEvent::Input(key.code)).await;
35 }
36 }
37 }
38 });
39
40 while !self.model.should_quit {
41 self.terminal
42 .terminal
43 .draw(|f| view::draw(f, &self.model))
44 .context("Failed to draw terminal")?;
45
46 if let Some(event) = self.rx.recv().await {
47 if let ChatEvent::Input(KeyCode::Enter) = event {
48 if !self.model.input.is_empty() {
49 let input = std::mem::take(&mut self.model.input);
50 self.model.push_message(super::Message::User(input.clone()));
51 let processing_idx = self.model.push_message(super::Message::Processing);
52
53 let tx = self.tx.clone();
54 let chat_state = self.model.chat_state.clone();
55
56 tokio::spawn(async move {
57 let mut chat_state = chat_state.lock().await;
58 match (*chat_state).send_message(input).await {
59 Ok(response) => {
60 let _ = tx
61 .send(ChatEvent::Response {
62 message: response,
63 index: processing_idx,
64 })
65 .await;
66 }
67 Err(e) => {
68 let _ = tx
69 .send(ChatEvent::Error {
70 error: e.to_string(),
71 index: processing_idx,
72 })
73 .await;
74 }
75 }
76 });
77 }
78 } else {
79 update::update(&mut self.model, event);
80 }
81 }
82 }
83
84 Ok(())
85 }
86}