1use serde::{Deserialize, Serialize};
2use std::collections::HashMap;
3use uuid::Uuid;
4
5use super::{AgentSchema, ToolConfig, ToolSchema, WorkflowSchema};
6use crate::codegen::action_nodes::ActionNodeConfig;
7
8const DEFAULT_ADK_VERSION: &str = "0.6.0";
9
10#[derive(Debug, Clone, Serialize, Deserialize)]
12pub struct ProjectSchema {
13 pub id: Uuid,
14 pub version: String,
15 pub name: String,
16 #[serde(default)]
17 pub description: String,
18 #[serde(default)]
19 pub settings: ProjectSettings,
20 #[serde(default)]
21 pub agents: HashMap<String, AgentSchema>,
22 #[serde(default)]
23 pub tools: HashMap<String, ToolSchema>,
24 #[serde(default)]
25 pub tool_configs: HashMap<String, ToolConfig>,
26 #[serde(default, rename = "actionNodes")]
28 pub action_nodes: HashMap<String, ActionNodeConfig>,
29 #[serde(default)]
30 pub workflow: WorkflowSchema,
31 #[serde(default)]
32 pub created_at: chrono::DateTime<chrono::Utc>,
33 #[serde(default)]
34 pub updated_at: chrono::DateTime<chrono::Utc>,
35}
36
37impl ProjectSchema {
38 pub fn new(name: impl Into<String>) -> Self {
39 let now = chrono::Utc::now();
40 Self {
41 id: Uuid::new_v4(),
42 version: "1.0".to_string(),
43 name: name.into(),
44 description: String::new(),
45 settings: ProjectSettings::default(),
46 agents: HashMap::new(),
47 tools: HashMap::new(),
48 tool_configs: HashMap::new(),
49 action_nodes: HashMap::new(),
50 workflow: WorkflowSchema::default(),
51 created_at: now,
52 updated_at: now,
53 }
54 }
55}
56
57#[derive(Debug, Clone, Serialize, Deserialize)]
59#[serde(rename_all = "camelCase")]
60pub struct ProjectSettings {
61 #[serde(default = "default_model")]
62 pub default_model: String,
63 #[serde(default)]
64 pub env_vars: HashMap<String, String>,
65 #[serde(default)]
67 pub layout_mode: Option<String>,
68 #[serde(default = "default_layout_direction")]
69 pub layout_direction: Option<String>,
70 #[serde(default)]
71 pub show_data_flow_overlay: Option<bool>,
72 #[serde(default = "default_adk_version")]
74 pub adk_version: Option<String>,
75 #[serde(default = "default_rust_edition")]
76 pub rust_edition: Option<String>,
77 #[serde(default)]
79 pub default_provider: Option<String>,
80 #[serde(default = "default_true")]
82 pub autobuild_enabled: Option<bool>,
83 #[serde(default)]
84 pub autobuild_triggers: Option<AutobuildTriggers>,
85 #[serde(default)]
87 pub show_minimap: Option<bool>,
88 #[serde(default)]
89 pub show_timeline: Option<bool>,
90 #[serde(default)]
91 pub console_position: Option<String>,
92 #[serde(default)]
94 pub debug_mode: Option<bool>,
95}
96
97impl Default for ProjectSettings {
98 fn default() -> Self {
99 Self {
100 default_model: default_model(),
101 env_vars: HashMap::new(),
102 layout_mode: None,
103 layout_direction: default_layout_direction(),
104 show_data_flow_overlay: None,
105 adk_version: default_adk_version(),
106 rust_edition: default_rust_edition(),
107 default_provider: None,
108 autobuild_enabled: default_true(),
109 autobuild_triggers: None,
110 show_minimap: None,
111 show_timeline: None,
112 console_position: None,
113 debug_mode: None,
114 }
115 }
116}
117
118#[derive(Debug, Clone, Serialize, Deserialize, Default)]
120#[serde(rename_all = "camelCase")]
121pub struct AutobuildTriggers {
122 #[serde(default = "default_true")]
123 pub on_agent_add: Option<bool>,
124 #[serde(default = "default_true")]
125 pub on_agent_delete: Option<bool>,
126 #[serde(default = "default_true")]
127 pub on_agent_update: Option<bool>,
128 #[serde(default = "default_true")]
129 pub on_tool_add: Option<bool>,
130 #[serde(default = "default_true")]
131 pub on_tool_update: Option<bool>,
132 #[serde(default = "default_true")]
133 pub on_edge_add: Option<bool>,
134 #[serde(default = "default_true")]
135 pub on_edge_delete: Option<bool>,
136}
137
138fn default_model() -> String {
139 "gemini-3.1-flash-lite-preview".to_string()
140}
141
142fn default_adk_version() -> Option<String> {
143 Some(DEFAULT_ADK_VERSION.to_string())
144}
145
146fn default_rust_edition() -> Option<String> {
147 Some("2024".to_string())
148}
149
150fn default_layout_direction() -> Option<String> {
151 Some("LR".to_string())
152}
153
154fn default_true() -> Option<bool> {
155 Some(true)
156}
157
158#[derive(Debug, Clone, Serialize, Deserialize)]
160pub struct ProjectMeta {
161 pub id: Uuid,
162 pub name: String,
163 pub description: String,
164 pub updated_at: chrono::DateTime<chrono::Utc>,
165}
166
167impl From<&ProjectSchema> for ProjectMeta {
168 fn from(p: &ProjectSchema) -> Self {
169 Self {
170 id: p.id,
171 name: p.name.clone(),
172 description: p.description.clone(),
173 updated_at: p.updated_at,
174 }
175 }
176}