tirea_agentos/composition/registry/
traits.rs

1use crate::composition::AgentDefinition;
2use crate::contracts::runtime::tool_call::Tool;
3use crate::contracts::runtime::AgentBehavior;
4use genai::chat::ChatOptions;
5use genai::Client;
6use std::collections::HashMap;
7use std::sync::Arc;
8
9#[derive(Debug, thiserror::Error)]
10pub enum ToolRegistryError {
11    #[error("tool id already registered: {0}")]
12    ToolIdConflict(String),
13
14    #[error("tool id mismatch: key={key} descriptor.id={descriptor_id}")]
15    ToolIdMismatch { key: String, descriptor_id: String },
16}
17
18pub trait ToolRegistry: Send + Sync {
19    fn len(&self) -> usize;
20
21    fn is_empty(&self) -> bool {
22        self.len() == 0
23    }
24
25    fn get(&self, id: &str) -> Option<Arc<dyn Tool>>;
26
27    fn ids(&self) -> Vec<String>;
28
29    fn snapshot(&self) -> HashMap<String, Arc<dyn Tool>>;
30}
31
32#[derive(Debug, thiserror::Error)]
33pub enum ProviderRegistryError {
34    #[error("provider id already registered: {0}")]
35    ProviderIdConflict(String),
36
37    #[error("provider id must be non-empty")]
38    EmptyProviderId,
39}
40
41pub trait ProviderRegistry: Send + Sync {
42    fn len(&self) -> usize;
43
44    fn is_empty(&self) -> bool {
45        self.len() == 0
46    }
47
48    fn get(&self, id: &str) -> Option<Client>;
49
50    fn ids(&self) -> Vec<String>;
51
52    fn snapshot(&self) -> HashMap<String, Client>;
53}
54
55#[derive(Debug, thiserror::Error)]
56pub enum BehaviorRegistryError {
57    #[error("behavior id already registered: {0}")]
58    BehaviorIdConflict(String),
59
60    #[error("behavior id mismatch: key={key} behavior.id()={behavior_id}")]
61    BehaviorIdMismatch { key: String, behavior_id: String },
62}
63
64pub trait BehaviorRegistry: Send + Sync {
65    fn len(&self) -> usize;
66
67    fn is_empty(&self) -> bool {
68        self.len() == 0
69    }
70
71    fn get(&self, id: &str) -> Option<Arc<dyn AgentBehavior>>;
72
73    fn ids(&self) -> Vec<String>;
74
75    fn snapshot(&self) -> HashMap<String, Arc<dyn AgentBehavior>>;
76}
77
78#[derive(Debug, thiserror::Error)]
79pub enum AgentRegistryError {
80    #[error("agent id already registered: {0}")]
81    AgentIdConflict(String),
82}
83
84pub trait AgentRegistry: Send + Sync {
85    fn len(&self) -> usize;
86
87    fn is_empty(&self) -> bool {
88        self.len() == 0
89    }
90
91    fn get(&self, id: &str) -> Option<AgentDefinition>;
92
93    fn ids(&self) -> Vec<String>;
94
95    fn snapshot(&self) -> HashMap<String, AgentDefinition>;
96}
97
98#[derive(Debug, Clone)]
99pub struct ModelDefinition {
100    pub provider: String,
101    pub model: String,
102    pub chat_options: Option<ChatOptions>,
103}
104
105impl ModelDefinition {
106    pub fn new(provider: impl Into<String>, model: impl Into<String>) -> Self {
107        Self {
108            provider: provider.into(),
109            model: model.into(),
110            chat_options: None,
111        }
112    }
113
114    pub fn with_chat_options(mut self, opts: ChatOptions) -> Self {
115        self.chat_options = Some(opts);
116        self
117    }
118}
119
120#[derive(Debug, thiserror::Error)]
121pub enum ModelRegistryError {
122    #[error("model id already registered: {0}")]
123    ModelIdConflict(String),
124
125    #[error("provider id must be non-empty")]
126    EmptyProviderId,
127
128    #[error("model name must be non-empty")]
129    EmptyModelName,
130}
131
132pub trait ModelRegistry: Send + Sync {
133    fn len(&self) -> usize;
134
135    fn is_empty(&self) -> bool {
136        self.len() == 0
137    }
138
139    fn get(&self, id: &str) -> Option<ModelDefinition>;
140
141    fn ids(&self) -> Vec<String>;
142
143    fn snapshot(&self) -> HashMap<String, ModelDefinition>;
144}
145
146/// Bundle-level contributor for registry composition.
147///
148/// A bundle contributes either direct definitions (maps) and/or registry sources.
149/// The orchestrator composes these contributions into concrete
150/// in-memory/composite registries with deterministic conflict checks.
151pub trait RegistryBundle: Send + Sync {
152    /// Stable bundle identifier for diagnostics.
153    fn id(&self) -> &str;
154
155    fn agent_definitions(&self) -> HashMap<String, AgentDefinition> {
156        HashMap::new()
157    }
158
159    fn agent_registries(&self) -> Vec<Arc<dyn AgentRegistry>> {
160        Vec::new()
161    }
162
163    fn tool_definitions(&self) -> HashMap<String, Arc<dyn Tool>> {
164        HashMap::new()
165    }
166
167    fn tool_registries(&self) -> Vec<Arc<dyn ToolRegistry>> {
168        Vec::new()
169    }
170
171    fn behavior_definitions(&self) -> HashMap<String, Arc<dyn AgentBehavior>> {
172        HashMap::new()
173    }
174
175    fn behavior_registries(&self) -> Vec<Arc<dyn BehaviorRegistry>> {
176        Vec::new()
177    }
178
179    fn provider_definitions(&self) -> HashMap<String, Client> {
180        HashMap::new()
181    }
182
183    fn provider_registries(&self) -> Vec<Arc<dyn ProviderRegistry>> {
184        Vec::new()
185    }
186
187    fn model_definitions(&self) -> HashMap<String, ModelDefinition> {
188        HashMap::new()
189    }
190
191    fn model_registries(&self) -> Vec<Arc<dyn ModelRegistry>> {
192        Vec::new()
193    }
194}