#![allow(missing_docs)]
pub mod bridge;
pub mod session;
pub mod types;
use std::future::Future;
use std::pin::Pin;
use std::sync::Arc;
use crate::agent::events::OnEvent;
use crate::error::Error;
use crate::llm::{OnApproval, OnText};
use crate::memory::Memory;
use crate::tool::builtins::OnQuestion;
pub struct MediaAttachment {
pub media_type: String,
pub data: Vec<u8>,
pub caption: Option<String>,
}
pub trait ChannelBridge: Send + Sync {
fn make_on_text(self: Arc<Self>) -> Arc<OnText>;
fn make_on_event(self: Arc<Self>) -> Arc<OnEvent>;
fn make_on_approval(self: Arc<Self>) -> Arc<OnApproval>;
fn make_on_question(self: Arc<Self>) -> Arc<OnQuestion>;
}
pub struct RunTaskInput {
pub task_text: String,
pub bridge: Arc<dyn ChannelBridge>,
pub memory: Option<Arc<dyn Memory>>,
pub user_namespace: Option<String>,
pub attachments: Vec<MediaAttachment>,
}
pub type RunTask = dyn Fn(RunTaskInput) -> Pin<Box<dyn Future<Output = Result<String, Error>> + Send>>
+ Send
+ Sync;
pub type ConsolidateSession =
dyn Fn(i64) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send>> + Send + Sync;
pub fn chunk_message(text: &str, max_len: usize) -> Vec<&str> {
if text.len() <= max_len {
return vec![text];
}
let mut chunks = Vec::new();
let mut remaining = text;
while !remaining.is_empty() {
if remaining.len() <= max_len {
chunks.push(remaining);
break;
}
let split_at = remaining[..max_len].rfind('\n').unwrap_or_else(|| {
let mut pos = max_len;
while pos > 0 && !remaining.is_char_boundary(pos) {
pos -= 1;
}
pos
});
let split_at = if split_at == 0 {
max_len.min(remaining.len())
} else {
split_at
};
chunks.push(&remaining[..split_at]);
remaining = &remaining[split_at..];
if remaining.starts_with('\n') {
remaining = &remaining[1..];
}
}
chunks
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn channel_bridge_is_object_safe() {
fn _assert(_: &Arc<dyn ChannelBridge>) {}
}
#[test]
fn run_task_input_accepts_dyn_bridge() {
fn _assert(bridge: Arc<dyn ChannelBridge>) {
let _input = RunTaskInput {
task_text: String::new(),
bridge,
memory: None,
user_namespace: None,
attachments: Vec::new(),
};
}
}
}