use crate::{Config, Conversation};
use memory::Memory;
use std::{
collections::BTreeMap,
sync::{Arc, atomic::AtomicU64},
};
use tokio::sync::{Mutex, RwLock, watch};
pub use topic::SwitchOutcome;
pub(super) use topic::TopicRouter;
use wcore::{Agent, ToolRegistry, model::Model};
mod agents;
mod conversation;
mod execution;
mod topic;
pub type SharedMemory = Arc<parking_lot::RwLock<Memory>>;
#[derive(Clone)]
pub(super) struct ConvSlot {
pub(super) agent: String,
pub(super) created_by: String,
pub(super) inner: Arc<Mutex<Conversation>>,
}
impl ConvSlot {
pub(super) fn parts(&self) -> (String, String, Arc<Mutex<Conversation>>) {
(
self.agent.clone(),
self.created_by.clone(),
self.inner.clone(),
)
}
}
pub struct Runtime<C: Config> {
pub model: Model<C::Provider>,
pub env: Arc<C::Env>,
storage: Arc<C::Storage>,
memory: SharedMemory,
agents: parking_lot::RwLock<BTreeMap<String, Agent<C::Provider>>>,
ephemeral_agents: RwLock<BTreeMap<String, Agent<C::Provider>>>,
conversations: RwLock<BTreeMap<u64, ConvSlot>>,
pub(super) topics: RwLock<BTreeMap<(String, String), TopicRouter>>,
next_conversation_id: AtomicU64,
pub tools: ToolRegistry,
steering: RwLock<BTreeMap<u64, watch::Sender<Option<String>>>>,
}
impl<C: Config> Runtime<C> {
pub fn new(
model: Model<C::Provider>,
env: Arc<C::Env>,
storage: Arc<C::Storage>,
memory: SharedMemory,
tools: ToolRegistry,
) -> Self {
Self {
model,
env,
storage,
memory,
agents: parking_lot::RwLock::new(BTreeMap::new()),
ephemeral_agents: RwLock::new(BTreeMap::new()),
conversations: RwLock::new(BTreeMap::new()),
topics: RwLock::new(BTreeMap::new()),
next_conversation_id: AtomicU64::new(1),
tools,
steering: RwLock::new(BTreeMap::new()),
}
}
pub fn storage(&self) -> &Arc<C::Storage> {
&self.storage
}
pub fn memory(&self) -> &SharedMemory {
&self.memory
}
}