pub mod capture;
pub mod discord;
pub mod discord_ws;
pub mod github;
pub mod notification;
pub mod routing;
pub mod slack;
pub mod stream;
pub mod telegram;
pub mod tmux;
pub mod transport;
use async_trait::async_trait;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct IncomingMessage {
pub channel: String,
pub id: String,
pub thread_id: String,
pub author: String,
pub body: String,
pub timestamp: chrono::DateTime<chrono::Utc>,
#[serde(default)]
pub metadata: serde_json::Value,
#[serde(default)]
pub topic_id: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct OutgoingMessage {
pub thread_id: String,
pub body: String,
pub reply_to: Option<String>,
#[serde(default)]
pub metadata: serde_json::Value,
#[serde(default)]
pub topic_id: Option<String>,
}
#[derive(Debug, Clone)]
pub struct OutputChunk {
pub content: String,
pub is_final: bool,
}
#[allow(clippy::double_must_use)] #[async_trait]
pub trait Channel: Send + Sync {
fn name(&self) -> &str;
async fn start(&self) -> anyhow::Result<tokio::sync::mpsc::Receiver<IncomingMessage>>;
async fn send(&self, msg: &OutgoingMessage) -> anyhow::Result<()>;
async fn ack_interaction(&self, _callback_query_id: &str) -> anyhow::Result<()> {
Ok(())
}
async fn health_check(&self) -> anyhow::Result<()>;
}
pub struct ChannelRegistry {
channels: Vec<Box<dyn Channel>>,
}
impl ChannelRegistry {
pub fn new() -> Self {
Self {
channels: Vec::new(),
}
}
pub fn register(&mut self, channel: Box<dyn Channel>) {
tracing::info!(channel = channel.name(), "registered channel");
self.channels.push(channel);
}
pub fn iter(&self) -> impl Iterator<Item = &dyn Channel> {
self.channels.iter().map(|c| c.as_ref())
}
}