Skip to main content

rootcx_types/
lib.rs

1use serde::{Deserialize, Serialize};
2use serde_json::Value as JsonValue;
3
4#[derive(Debug, Clone, Serialize, Deserialize)]
5pub struct OsStatus {
6    pub runtime: RuntimeStatus,
7    pub postgres: PostgresStatus,
8    pub forge: ForgeStatus,
9}
10
11impl OsStatus {
12    pub fn offline() -> Self {
13        Self {
14            runtime: RuntimeStatus { version: String::new(), state: ServiceState::Offline },
15            postgres: PostgresStatus { state: ServiceState::Offline, port: None, data_dir: None },
16            forge: ForgeStatus { state: ServiceState::Offline, port: None },
17        }
18    }
19}
20
21#[derive(Debug, Clone, Serialize, Deserialize)]
22pub struct ForgeStatus {
23    pub state: ServiceState,
24    pub port: Option<u16>,
25}
26
27#[derive(Debug, Clone, Serialize, Deserialize)]
28pub struct RuntimeStatus {
29    pub version: String,
30    pub state: ServiceState,
31}
32
33#[derive(Debug, Clone, Serialize, Deserialize)]
34pub struct PostgresStatus {
35    pub state: ServiceState,
36    pub port: Option<u16>,
37    pub data_dir: Option<String>,
38}
39
40#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
41#[serde(rename_all = "lowercase")]
42pub enum ServiceState {
43    Online,
44    Offline,
45    Starting,
46    Stopping,
47    Error,
48}
49
50#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
51#[serde(rename_all = "lowercase")]
52pub enum AppType {
53    #[default]
54    App,
55    Integration,
56    Agent,
57}
58
59#[derive(Debug, Clone, Serialize, Deserialize)]
60#[serde(rename_all = "camelCase")]
61pub struct ActionDefinition {
62    pub id: String,
63    pub name: String,
64    #[serde(default)]
65    pub description: String,
66    #[serde(default)]
67    pub input_schema: Option<JsonValue>,
68    #[serde(default)]
69    pub output_schema: Option<JsonValue>,
70}
71
72#[derive(Debug, Clone, Serialize, Deserialize)]
73#[serde(rename_all = "camelCase")]
74pub struct AppManifest {
75    pub app_id: String,
76    pub name: String,
77    #[serde(default = "default_version")]
78    pub version: String,
79    #[serde(default)]
80    pub description: String,
81    #[serde(default, rename = "type")]
82    pub app_type: AppType,
83    #[serde(default)]
84    pub permissions: Option<PermissionsContract>,
85    #[serde(default)]
86    pub data_contract: Vec<EntityContract>,
87    #[serde(default, skip_serializing_if = "Vec::is_empty")]
88    pub actions: Vec<ActionDefinition>,
89    #[serde(default, skip_serializing_if = "Option::is_none")]
90    pub config_schema: Option<JsonValue>,
91    #[serde(default, skip_serializing_if = "Option::is_none")]
92    pub user_auth: Option<JsonValue>,
93    #[serde(default, skip_serializing_if = "Vec::is_empty")]
94    pub webhooks: Vec<String>,
95    /// Free-form usage instructions surfaced to AI via list_integrations tool
96    #[serde(default, skip_serializing_if = "Option::is_none")]
97    pub instructions: Option<String>,
98    /// Trigger: auto-invoke this agent on entity events
99    #[serde(default, skip_serializing_if = "Option::is_none")]
100    pub trigger: Option<TriggerConfig>,
101    /// Declarative cron schedules synced on deploy
102    #[serde(default, skip_serializing_if = "Vec::is_empty")]
103    pub crons: Vec<CronDefinition>,
104    #[serde(default, skip_serializing_if = "Option::is_none")]
105    pub icon: Option<String>,
106}
107
108#[derive(Debug, Clone, Serialize, Deserialize)]
109#[serde(rename_all = "camelCase")]
110pub struct CronDefinition {
111    pub name: String,
112    pub schedule: String,
113    #[serde(default, skip_serializing_if = "Option::is_none")]
114    pub timezone: Option<String>,
115    #[serde(default, skip_serializing_if = "Option::is_none")]
116    pub method: Option<String>,
117    #[serde(default, skip_serializing_if = "Option::is_none")]
118    pub payload: Option<JsonValue>,
119    #[serde(default = "default_overlap_policy")]
120    pub overlap_policy: String,
121}
122
123fn default_overlap_policy() -> String { "skip".into() }
124
125#[derive(Debug, Clone, Serialize, Deserialize)]
126#[serde(rename_all = "camelCase")]
127pub struct TriggerConfig {
128    pub app_id: String,
129    pub entity: String,
130    pub on: Vec<String>,
131}
132
133fn default_version() -> String {
134    "0.0.1".to_string()
135}
136
137#[derive(Debug, Clone, Serialize, Deserialize)]
138#[serde(rename_all = "camelCase")]
139pub struct EntityContract {
140    pub entity_name: String,
141    pub fields: Vec<FieldContract>,
142    #[serde(default, skip_serializing_if = "Option::is_none")]
143    pub identity_kind: Option<String>,
144    #[serde(default, skip_serializing_if = "Option::is_none")]
145    pub identity_key: Option<String>,
146}
147
148#[derive(Debug, Clone, Serialize, Deserialize)]
149#[serde(rename_all = "camelCase")]
150pub struct FieldContract {
151    pub name: String,
152    #[serde(rename = "type")]
153    pub field_type: String,
154    #[serde(default)]
155    pub required: bool,
156    #[serde(default)]
157    pub default_value: Option<JsonValue>,
158    #[serde(default)]
159    pub enum_values: Option<Vec<String>>,
160    #[serde(default)]
161    pub references: Option<FieldReference>,
162    #[serde(default)]
163    pub is_primary_key: Option<bool>,
164    #[serde(default, skip_serializing_if = "Option::is_none")]
165    pub on_delete: Option<OnDeletePolicy>,
166}
167
168#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
169#[serde(rename_all = "snake_case")]
170pub enum OnDeletePolicy {
171    Cascade,
172    Restrict,
173    SetNull,
174}
175
176#[derive(Debug, Clone, Serialize, Deserialize)]
177pub struct FieldReference {
178    pub entity: String,
179    pub field: String,
180}
181
182#[derive(Debug, Clone, Serialize, Deserialize)]
183#[serde(rename_all = "camelCase")]
184pub struct InstalledApp {
185    pub id: String,
186    pub name: String,
187    pub version: String,
188    pub status: String,
189    #[serde(rename = "type", default)]
190    pub app_type: AppType,
191    pub entities: Vec<String>,
192    #[serde(default)]
193    pub has_frontend: bool,
194    #[serde(default, skip_serializing_if = "Option::is_none")]
195    pub icon: Option<String>,
196}
197
198#[derive(Debug, Clone, Serialize, Deserialize)]
199#[serde(rename_all = "camelCase")]
200pub struct PermissionsContract {
201    #[serde(default)]
202    pub permissions: Vec<PermissionDeclaration>,
203}
204
205#[derive(Debug, Clone, Serialize, Deserialize)]
206pub struct PermissionDeclaration {
207    pub key: String,
208    #[serde(default)]
209    pub description: String,
210}
211
212#[derive(Debug, Clone, Serialize, Deserialize)]
213pub struct SchemaChange {
214    pub entity: String,
215    pub change_type: String,
216    pub column: String,
217    pub detail: Option<String>,
218}
219
220#[derive(Debug, Clone, Serialize, Deserialize)]
221pub struct SchemaVerification {
222    pub compliant: bool,
223    pub changes: Vec<SchemaChange>,
224}
225
226#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
227#[serde(rename_all = "lowercase")]
228pub enum ProviderType {
229    Anthropic,
230    OpenAI,
231    Bedrock,
232}
233
234#[derive(Debug, Clone, Serialize, Deserialize)]
235#[serde(rename_all = "camelCase")]
236pub struct AgentDefinition {
237    pub name: String,
238    #[serde(default)]
239    pub description: Option<String>,
240    #[serde(default)]
241    pub system_prompt: Option<String>,
242    #[serde(default)]
243    pub memory: Option<AgentMemory>,
244    #[serde(default)]
245    pub limits: Option<AgentLimits>,
246    #[serde(default)]
247    pub supervision: Option<SupervisionConfig>,
248}
249
250#[derive(Debug, Clone, Serialize, Deserialize)]
251pub struct AgentMemory {
252    pub enabled: bool,
253}
254
255#[derive(Debug, Clone, Serialize, Deserialize)]
256#[serde(rename_all = "camelCase")]
257pub struct AgentLimits {
258    #[serde(default)]
259    pub max_turns: Option<u32>,
260    #[serde(default)]
261    pub max_context_tokens: Option<u64>,
262    #[serde(default)]
263    pub keep_recent_messages: Option<u32>,
264}
265
266#[derive(Debug, Clone, Serialize, Deserialize)]
267#[serde(rename_all = "camelCase")]
268pub struct SupervisionConfig {
269    pub mode: SupervisionMode,
270    #[serde(default)]
271    pub policies: Vec<SupervisionPolicy>,
272}
273
274#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
275#[serde(rename_all = "lowercase")]
276pub enum SupervisionMode {
277    Autonomous,
278    Supervised,
279    Strict,
280}
281
282#[derive(Debug, Clone, Serialize, Deserialize)]
283#[serde(rename_all = "camelCase")]
284pub struct SupervisionPolicy {
285    pub action: String,
286    #[serde(default)]
287    pub entity: Option<String>,
288    #[serde(default)]
289    pub requires: Option<String>,
290    #[serde(default)]
291    pub rate_limit: Option<RateLimit>,
292}
293
294#[derive(Debug, Clone, Serialize, Deserialize)]
295pub struct RateLimit {
296    pub max: u32,
297    pub window: String,
298}
299
300#[derive(Debug, Clone, Serialize, Deserialize)]
301#[serde(rename_all = "camelCase")]
302pub struct McpServerConfig {
303    pub name: String,
304    pub transport: McpTransport,
305}
306
307#[derive(Debug, Clone, Serialize, Deserialize)]
308#[serde(tag = "type", rename_all = "lowercase")]
309pub enum McpTransport {
310    Stdio { command: String, #[serde(default)] args: Vec<String> },
311    Http { url: String, #[serde(default)] headers: std::collections::HashMap<String, String> },
312    #[deprecated = "use Http"]
313    Sse { url: String, #[serde(default)] headers: std::collections::HashMap<String, String> },
314    Cli { install: String },
315}
316
317#[derive(Debug, Clone, Serialize, Deserialize)]
318#[serde(rename_all = "camelCase")]
319pub struct ToolDescriptor {
320    pub name: String,
321    pub description: String,
322    pub input_schema: serde_json::Value,
323}
324
325#[derive(Debug, Clone, Serialize, Deserialize)]
326#[serde(rename_all = "lowercase")]
327pub enum Role {
328    User,
329    Assistant,
330}
331
332#[derive(Debug, Clone, Serialize, Deserialize)]
333#[serde(tag = "type", rename_all = "snake_case")]
334pub enum ContentBlock {
335    Text { text: String },
336    ToolUse { id: String, name: String, input: serde_json::Value },
337    ToolResult { tool_use_id: String, content: String, #[serde(default)] is_error: bool },
338}
339
340#[derive(Debug, Clone, Serialize, Deserialize)]
341pub struct ChatMessage {
342    pub role: Role,
343    pub content: Vec<ContentBlock>,
344}
345
346#[derive(Debug, Clone, Serialize, Deserialize)]
347pub struct ToolDef {
348    pub name: String,
349    pub description: String,
350    pub input_schema: serde_json::Value,
351}
352