Skip to main content

crabtalk_runtime/engine/
mod.rs

1//! Runtime — agent registry, conversation management, and hook orchestration.
2//!
3//! [`Runtime`] holds agents as immutable definitions and conversations as
4//! per-conversation `Arc<Mutex<Conversation>>` containers. Tool schemas and
5//! handlers are registered by the caller at construction. Execution methods
6//! (`send_to`, `stream_to`) take a conversation ID, lock the conversation,
7//! clone the agent, and run with the conversation's history.
8
9use crate::{Config, Conversation};
10use memory::Memory;
11use std::{
12    collections::BTreeMap,
13    sync::{Arc, atomic::AtomicU64},
14};
15use tokio::sync::{Mutex, RwLock, watch};
16pub use topic::SwitchOutcome;
17pub(super) use topic::TopicRouter;
18use wcore::{Agent, ToolRegistry, model::Model};
19
20mod agents;
21mod conversation;
22mod execution;
23mod topic;
24
25/// Shared handle to the standalone memory store. Used by compaction to
26/// write Archive entries and by session resume to pull their content
27/// back as the replayed prefix.
28pub type SharedMemory = Arc<parking_lot::RwLock<Memory>>;
29
30#[derive(Clone)]
31pub(super) struct ConvSlot {
32    pub(super) agent: String,
33    pub(super) created_by: String,
34    pub(super) inner: Arc<Mutex<Conversation>>,
35}
36
37impl ConvSlot {
38    pub(super) fn parts(&self) -> (String, String, Arc<Mutex<Conversation>>) {
39        (
40            self.agent.clone(),
41            self.created_by.clone(),
42            self.inner.clone(),
43        )
44    }
45}
46
47/// The crabtalk runtime.
48pub struct Runtime<C: Config> {
49    pub model: Model<C::Provider>,
50    pub env: Arc<C::Env>,
51    storage: Arc<C::Storage>,
52    memory: SharedMemory,
53    agents: parking_lot::RwLock<BTreeMap<String, Agent<C::Provider>>>,
54    ephemeral_agents: RwLock<BTreeMap<String, Agent<C::Provider>>>,
55    conversations: RwLock<BTreeMap<u64, ConvSlot>>,
56    pub(super) topics: RwLock<BTreeMap<(String, String), TopicRouter>>,
57    next_conversation_id: AtomicU64,
58    pub tools: ToolRegistry,
59    steering: RwLock<BTreeMap<u64, watch::Sender<Option<String>>>>,
60}
61
62impl<C: Config> Runtime<C> {
63    /// Create a new runtime with the given model, env, storage, memory, and tools.
64    pub fn new(
65        model: Model<C::Provider>,
66        env: Arc<C::Env>,
67        storage: Arc<C::Storage>,
68        memory: SharedMemory,
69        tools: ToolRegistry,
70    ) -> Self {
71        Self {
72            model,
73            env,
74            storage,
75            memory,
76            agents: parking_lot::RwLock::new(BTreeMap::new()),
77            ephemeral_agents: RwLock::new(BTreeMap::new()),
78            conversations: RwLock::new(BTreeMap::new()),
79            topics: RwLock::new(BTreeMap::new()),
80            next_conversation_id: AtomicU64::new(1),
81            tools,
82            steering: RwLock::new(BTreeMap::new()),
83        }
84    }
85
86    /// Access the persistence backend.
87    pub fn storage(&self) -> &Arc<C::Storage> {
88        &self.storage
89    }
90
91    /// Access the shared memory store.
92    pub fn memory(&self) -> &SharedMemory {
93        &self.memory
94    }
95}