1use std::path::PathBuf;
5
6use serde::{Deserialize, Serialize};
7
8use crate::subagent::{HookDef, MemoryScope, PermissionMode};
9
10fn default_max_tool_iterations() -> usize {
11 10
12}
13
14fn default_auto_update_check() -> bool {
15 true
16}
17
18fn default_focus_compression_interval() -> usize {
19 12
20}
21
22fn default_focus_reminder_interval() -> usize {
23 15
24}
25
26fn default_focus_min_messages_per_focus() -> usize {
27 8
28}
29
30fn default_focus_max_knowledge_tokens() -> usize {
31 4096
32}
33
34fn default_max_tool_retries() -> usize {
35 2
36}
37
38fn default_max_retry_duration_secs() -> u64 {
39 30
40}
41
42fn default_tool_repeat_threshold() -> usize {
43 2
44}
45
46fn default_tool_filter_top_k() -> usize {
47 6
48}
49
50fn default_tool_filter_min_description_words() -> usize {
51 5
52}
53
54fn default_tool_filter_always_on() -> Vec<String> {
55 vec![
56 "memory_search".into(),
57 "memory_save".into(),
58 "load_skill".into(),
59 "bash".into(),
60 "read".into(),
61 "edit".into(),
62 ]
63}
64
65fn default_instruction_auto_detect() -> bool {
66 true
67}
68
69fn default_max_concurrent() -> usize {
70 5
71}
72
73fn default_transcript_enabled() -> bool {
74 true
75}
76
77fn default_transcript_max_files() -> usize {
78 50
79}
80
81#[derive(Debug, Clone, Deserialize, Serialize)]
83#[serde(default)]
84pub struct FocusConfig {
85 pub enabled: bool,
87 #[serde(default = "default_focus_compression_interval")]
89 pub compression_interval: usize,
90 #[serde(default = "default_focus_reminder_interval")]
92 pub reminder_interval: usize,
93 #[serde(default = "default_focus_min_messages_per_focus")]
95 pub min_messages_per_focus: usize,
96 #[serde(default = "default_focus_max_knowledge_tokens")]
99 pub max_knowledge_tokens: usize,
100}
101
102impl Default for FocusConfig {
103 fn default() -> Self {
104 Self {
105 enabled: false,
106 compression_interval: default_focus_compression_interval(),
107 reminder_interval: default_focus_reminder_interval(),
108 min_messages_per_focus: default_focus_min_messages_per_focus(),
109 max_knowledge_tokens: default_focus_max_knowledge_tokens(),
110 }
111 }
112}
113
114#[derive(Debug, Clone, Deserialize, Serialize)]
119#[serde(default)]
120pub struct ToolFilterConfig {
121 pub enabled: bool,
123 #[serde(default = "default_tool_filter_top_k")]
126 pub top_k: usize,
127 #[serde(default = "default_tool_filter_always_on")]
129 pub always_on: Vec<String>,
130 #[serde(default = "default_tool_filter_min_description_words")]
132 pub min_description_words: usize,
133}
134
135impl Default for ToolFilterConfig {
136 fn default() -> Self {
137 Self {
138 enabled: false,
139 top_k: default_tool_filter_top_k(),
140 always_on: default_tool_filter_always_on(),
141 min_description_words: default_tool_filter_min_description_words(),
142 }
143 }
144}
145
146#[derive(Debug, Deserialize, Serialize)]
147pub struct AgentConfig {
148 pub name: String,
149 #[serde(default = "default_max_tool_iterations")]
150 pub max_tool_iterations: usize,
151 #[serde(default = "default_auto_update_check")]
152 pub auto_update_check: bool,
153 #[serde(default)]
155 pub instruction_files: Vec<std::path::PathBuf>,
156 #[serde(default = "default_instruction_auto_detect")]
159 pub instruction_auto_detect: bool,
160 #[serde(default = "default_max_tool_retries")]
162 pub max_tool_retries: usize,
163 #[serde(default = "default_tool_repeat_threshold")]
166 pub tool_repeat_threshold: usize,
167 #[serde(default = "default_max_retry_duration_secs")]
169 pub max_retry_duration_secs: u64,
170 #[serde(default)]
172 pub focus: FocusConfig,
173 #[serde(default)]
175 pub tool_filter: ToolFilterConfig,
176}
177
178#[derive(Debug, Clone, Deserialize, Serialize)]
179#[serde(default)]
180pub struct SubAgentConfig {
181 pub enabled: bool,
182 #[serde(default = "default_max_concurrent")]
184 pub max_concurrent: usize,
185 pub extra_dirs: Vec<PathBuf>,
186 #[serde(default)]
188 pub user_agents_dir: Option<PathBuf>,
189 pub default_permission_mode: Option<PermissionMode>,
191 #[serde(default)]
193 pub default_disallowed_tools: Vec<String>,
194 #[serde(default)]
196 pub allow_bypass_permissions: bool,
197 #[serde(default)]
199 pub default_memory_scope: Option<MemoryScope>,
200 #[serde(default)]
202 pub hooks: SubAgentLifecycleHooks,
203 #[serde(default)]
205 pub transcript_dir: Option<PathBuf>,
206 #[serde(default = "default_transcript_enabled")]
208 pub transcript_enabled: bool,
209 #[serde(default = "default_transcript_max_files")]
211 pub transcript_max_files: usize,
212}
213
214impl Default for SubAgentConfig {
215 fn default() -> Self {
216 Self {
217 enabled: false,
218 max_concurrent: default_max_concurrent(),
219 extra_dirs: Vec::new(),
220 user_agents_dir: None,
221 default_permission_mode: None,
222 default_disallowed_tools: Vec::new(),
223 allow_bypass_permissions: false,
224 default_memory_scope: None,
225 hooks: SubAgentLifecycleHooks::default(),
226 transcript_dir: None,
227 transcript_enabled: default_transcript_enabled(),
228 transcript_max_files: default_transcript_max_files(),
229 }
230 }
231}
232
233#[derive(Debug, Clone, Default, Deserialize, Serialize)]
235#[serde(default)]
236pub struct SubAgentLifecycleHooks {
237 pub start: Vec<HookDef>,
239 pub stop: Vec<HookDef>,
241}