Skip to main content

everruns_runtime/
backends.rs

1// Public backend contract for the embedded runtime.
2// Decision: runtime extends core's read-only traits with the minimal write
3// operations needed for seeding and message persistence. Trait upcasting +
4// blanket `Arc<T>: T` impls in core let the runtime forward to atoms without
5// shim wrappers.
6
7use crate::in_memory::{InMemorySessionStorageStore, InMemorySessionStore};
8use async_trait::async_trait;
9use everruns_core::agent::Agent;
10use everruns_core::error::Result;
11use everruns_core::events::Event;
12use everruns_core::harness::Harness;
13use everruns_core::memory::{
14    InMemoryAgentStore, InMemoryEventEmitter, InMemoryHarnessStore, InMemoryLlmProviderStore,
15    InMemoryMemoryStore, InMemoryMessageRetriever,
16};
17use everruns_core::memory_store::MemoryStoreBackend;
18use everruns_core::message::Message;
19use everruns_core::message_retriever::{InputMessage, MessageRetriever};
20use everruns_core::session::Session;
21use everruns_core::traits::{
22    AgentStore, EventEmitter, HarnessStore, LlmProviderStore, ModelWithProvider, SessionMutator,
23    SessionStorageStore, SessionStore,
24};
25use everruns_core::typed_id::SessionId;
26use std::sync::Arc;
27
28/// Agent store contract for runtime seeding and lookup.
29#[async_trait]
30pub trait RuntimeAgentStore: AgentStore + Send + Sync {
31    /// Insert or replace an agent definition.
32    async fn add_agent(&self, agent: Agent) -> Result<()>;
33}
34
35/// Harness store contract for runtime seeding and lookup.
36#[async_trait]
37pub trait RuntimeHarnessStore: HarnessStore + Send + Sync {
38    /// Insert or replace a harness definition.
39    async fn add_harness(&self, harness: Harness) -> Result<()>;
40}
41
42/// Session store contract for runtime seeding, lookup, and mutation.
43#[async_trait]
44pub trait RuntimeSessionStore: SessionStore + SessionMutator + Send + Sync {
45    /// Insert or replace a session definition.
46    async fn add_session(&self, session: Session) -> Result<()>;
47}
48
49/// Message store contract for runtime persistence and lookup.
50#[async_trait]
51pub trait RuntimeMessageStore: MessageRetriever + Send + Sync {
52    /// Store a new input message and return the generated message record.
53    async fn add_input_message(
54        &self,
55        session_id: SessionId,
56        input: InputMessage,
57    ) -> Result<Message>;
58
59    /// Persist an existing message record.
60    async fn store_message(&self, session_id: SessionId, message: Message) -> Result<()>;
61}
62
63/// Provider store contract for runtime lookup and default-model configuration.
64#[async_trait]
65pub trait RuntimeProviderStore: LlmProviderStore + Send + Sync {
66    /// Set the runtime default model.
67    async fn set_default_model(&self, model: ModelWithProvider) -> Result<()>;
68}
69
70/// Event sink that supports emission and optional collection.
71///
72/// Every `EventBus` is an `EventEmitter`. Embedders that want to inspect
73/// emitted events override `collected_events`; production hosts inherit the
74/// no-op default.
75#[async_trait]
76pub trait EventBus: EventEmitter {
77    /// Return all collected events. Defaults to an empty `Vec` for buses
78    /// that do not retain events.
79    async fn collected_events(&self) -> Vec<Event> {
80        Vec::new()
81    }
82}
83
84#[async_trait]
85impl<T: EventBus + ?Sized> EventBus for Arc<T> {
86    async fn collected_events(&self) -> Vec<Event> {
87        (**self).collected_events().await
88    }
89}
90
91/// Non-filesystem backend bundle supplied to the embedded runtime.
92///
93/// Use this when you want the public runtime orchestration but your own store
94/// implementations instead of the built-in in-memory ones. Session filesystem
95/// selection is always resolved from `PlatformDefinition`.
96#[derive(Clone)]
97pub struct RuntimeBackends {
98    /// Harness definitions available to the runtime.
99    pub harness_store: Arc<dyn RuntimeHarnessStore>,
100    /// Agent definitions available to the runtime.
101    pub agent_store: Arc<dyn RuntimeAgentStore>,
102    /// Session records and mutable session metadata.
103    pub session_store: Arc<dyn RuntimeSessionStore>,
104    /// Conversation message persistence and retrieval.
105    pub message_store: Arc<dyn RuntimeMessageStore>,
106    /// Model/provider resolution and default-model configuration.
107    pub provider_store: Arc<dyn RuntimeProviderStore>,
108    /// Event sink (emit + optional collection).
109    pub event_bus: Arc<dyn EventBus>,
110    /// Session key/value + secret storage backend.
111    pub storage_store: Arc<dyn SessionStorageStore>,
112    /// Persistent cross-session memory backend.
113    pub memory_store: Arc<dyn MemoryStoreBackend>,
114}
115
116impl RuntimeBackends {
117    /// Backend bundle with in-memory implementations for every store.
118    ///
119    /// Suitable for tests, examples, and the default runtime configuration.
120    /// Use the chainable `with_*` setters to override individual stores.
121    pub fn in_memory() -> Self {
122        let event_bus = Arc::new(InMemoryEventEmitter::new());
123        Self {
124            harness_store: Arc::new(InMemoryHarnessStore::new()),
125            agent_store: Arc::new(InMemoryAgentStore::new()),
126            session_store: Arc::new(InMemorySessionStore::new()),
127            message_store: Arc::new(InMemoryMessageRetriever::new()),
128            provider_store: Arc::new(InMemoryLlmProviderStore::new()),
129            event_bus,
130            storage_store: Arc::new(InMemorySessionStorageStore::new()),
131            memory_store: Arc::new(InMemoryMemoryStore::new()),
132        }
133    }
134
135    pub fn with_harness_store(mut self, store: Arc<dyn RuntimeHarnessStore>) -> Self {
136        self.harness_store = store;
137        self
138    }
139
140    pub fn with_agent_store(mut self, store: Arc<dyn RuntimeAgentStore>) -> Self {
141        self.agent_store = store;
142        self
143    }
144
145    pub fn with_session_store(mut self, store: Arc<dyn RuntimeSessionStore>) -> Self {
146        self.session_store = store;
147        self
148    }
149
150    pub fn with_message_store(mut self, store: Arc<dyn RuntimeMessageStore>) -> Self {
151        self.message_store = store;
152        self
153    }
154
155    pub fn with_provider_store(mut self, store: Arc<dyn RuntimeProviderStore>) -> Self {
156        self.provider_store = store;
157        self
158    }
159
160    pub fn with_event_bus(mut self, bus: Arc<dyn EventBus>) -> Self {
161        self.event_bus = bus;
162        self
163    }
164
165    pub fn with_storage_store(mut self, store: Arc<dyn SessionStorageStore>) -> Self {
166        self.storage_store = store;
167        self
168    }
169
170    pub fn with_memory_store(mut self, store: Arc<dyn MemoryStoreBackend>) -> Self {
171        self.memory_store = store;
172        self
173    }
174}
175
176#[async_trait]
177impl RuntimeAgentStore for InMemoryAgentStore {
178    async fn add_agent(&self, agent: Agent) -> Result<()> {
179        InMemoryAgentStore::add_agent(self, agent).await;
180        Ok(())
181    }
182}
183
184#[async_trait]
185impl RuntimeHarnessStore for InMemoryHarnessStore {
186    async fn add_harness(&self, harness: Harness) -> Result<()> {
187        InMemoryHarnessStore::add_harness(self, harness).await;
188        Ok(())
189    }
190}
191
192#[async_trait]
193impl RuntimeSessionStore for InMemorySessionStore {
194    async fn add_session(&self, session: Session) -> Result<()> {
195        InMemorySessionStore::add_session(self, session).await;
196        Ok(())
197    }
198}
199
200#[async_trait]
201impl RuntimeMessageStore for InMemoryMessageRetriever {
202    async fn add_input_message(
203        &self,
204        session_id: SessionId,
205        input: InputMessage,
206    ) -> Result<Message> {
207        self.add(session_id, input).await
208    }
209
210    async fn store_message(&self, session_id: SessionId, message: Message) -> Result<()> {
211        self.store(session_id, message).await
212    }
213}
214
215#[async_trait]
216impl RuntimeProviderStore for InMemoryLlmProviderStore {
217    async fn set_default_model(&self, model: ModelWithProvider) -> Result<()> {
218        InMemoryLlmProviderStore::set_default_model(self, model).await;
219        Ok(())
220    }
221}
222
223#[async_trait]
224impl EventBus for InMemoryEventEmitter {
225    async fn collected_events(&self) -> Vec<Event> {
226        InMemoryEventEmitter::events(self).await
227    }
228}