1use crate::traits::graph::GraphAccess;
30use crate::traits::integration::IntegrationAccess;
31use crate::traits::lsp::LspAccess;
32use crate::traits::mcp::McpAccess;
33use crate::traits::memory::MemoryAccess;
34use crate::traits::misc::MiscAccess;
35use crate::traits::model::ModelAccess;
36use crate::traits::orchestration::OrchestrationAccess;
37use crate::traits::policy::PolicyAccess;
38use crate::traits::scheduler::SchedulerAccess;
39use crate::traits::session_control::SessionControlAccess;
40use crate::traits::skill::SkillAccess;
41use crate::traits::subagent::SubagentAccess;
42use crate::traits::tracking::TrackingAccess;
43use crate::traits::worktree::WorktreeAccess;
44
45pub trait AgentAccess:
59 MemoryAccess
60 + GraphAccess
61 + ModelAccess
62 + SkillAccess
63 + PolicyAccess
64 + SchedulerAccess
65 + LspAccess
66 + SessionControlAccess
67 + McpAccess
68 + OrchestrationAccess
69 + SubagentAccess
70 + IntegrationAccess
71 + TrackingAccess
72 + WorktreeAccess
73 + MiscAccess
74 + Send
75{
76}
77
78impl<T> AgentAccess for T where
79 T: MemoryAccess
80 + GraphAccess
81 + ModelAccess
82 + SkillAccess
83 + PolicyAccess
84 + SchedulerAccess
85 + LspAccess
86 + SessionControlAccess
87 + McpAccess
88 + OrchestrationAccess
89 + SubagentAccess
90 + IntegrationAccess
91 + TrackingAccess
92 + WorktreeAccess
93 + MiscAccess
94 + Send
95 + ?Sized
96{
97}
98
99pub struct NullAgent;
113
114impl MemoryAccess for NullAgent {
115 fn memory_tiers<'a>(
116 &'a mut self,
117 ) -> std::pin::Pin<
118 Box<dyn std::future::Future<Output = Result<String, crate::CommandError>> + Send + 'a>,
119 > {
120 Box::pin(async { Ok(String::new()) })
121 }
122
123 fn memory_promote<'a>(
124 &'a mut self,
125 _ids_str: &'a str,
126 ) -> std::pin::Pin<
127 Box<dyn std::future::Future<Output = Result<String, crate::CommandError>> + Send + 'a>,
128 > {
129 Box::pin(async { Ok(String::new()) })
130 }
131
132 fn store_command<'a>(
133 &'a mut self,
134 _args: &'a str,
135 ) -> std::pin::Pin<
136 Box<dyn std::future::Future<Output = Result<String, crate::CommandError>> + Send + 'a>,
137 > {
138 Box::pin(async { Ok(String::new()) })
139 }
140
141 fn guidelines<'a>(
142 &'a mut self,
143 ) -> std::pin::Pin<
144 Box<dyn std::future::Future<Output = Result<String, crate::CommandError>> + Send + 'a>,
145 > {
146 Box::pin(async { Ok(String::new()) })
147 }
148}
149
150impl GraphAccess for NullAgent {
151 fn graph_stats<'a>(
152 &'a mut self,
153 ) -> std::pin::Pin<
154 Box<dyn std::future::Future<Output = Result<String, crate::CommandError>> + Send + 'a>,
155 > {
156 Box::pin(async { Ok(String::new()) })
157 }
158
159 fn graph_entities<'a>(
160 &'a mut self,
161 ) -> std::pin::Pin<
162 Box<dyn std::future::Future<Output = Result<String, crate::CommandError>> + Send + 'a>,
163 > {
164 Box::pin(async { Ok(String::new()) })
165 }
166
167 fn graph_facts<'a>(
168 &'a mut self,
169 _name: &'a str,
170 ) -> std::pin::Pin<
171 Box<dyn std::future::Future<Output = Result<String, crate::CommandError>> + Send + 'a>,
172 > {
173 Box::pin(async { Ok(String::new()) })
174 }
175
176 fn graph_history<'a>(
177 &'a mut self,
178 _name: &'a str,
179 ) -> std::pin::Pin<
180 Box<dyn std::future::Future<Output = Result<String, crate::CommandError>> + Send + 'a>,
181 > {
182 Box::pin(async { Ok(String::new()) })
183 }
184
185 fn graph_communities<'a>(
186 &'a mut self,
187 ) -> std::pin::Pin<
188 Box<dyn std::future::Future<Output = Result<String, crate::CommandError>> + Send + 'a>,
189 > {
190 Box::pin(async { Ok(String::new()) })
191 }
192
193 fn graph_backfill<'a>(
194 &'a mut self,
195 _limit: Option<usize>,
196 _progress_cb: &'a mut (dyn FnMut(String) + Send),
197 ) -> std::pin::Pin<
198 Box<dyn std::future::Future<Output = Result<String, crate::CommandError>> + Send + 'a>,
199 > {
200 Box::pin(async { Ok(String::new()) })
201 }
202
203 fn knowledge_status<'a>(
204 &'a mut self,
205 ) -> std::pin::Pin<
206 Box<dyn std::future::Future<Output = Result<String, crate::CommandError>> + Send + 'a>,
207 > {
208 Box::pin(async { Ok(String::new()) })
209 }
210
211 fn knowledge_rollback<'a>(
212 &'a mut self,
213 _batch_id: &'a str,
214 ) -> std::pin::Pin<
215 Box<dyn std::future::Future<Output = Result<String, crate::CommandError>> + Send + 'a>,
216 > {
217 Box::pin(async { Ok(String::new()) })
218 }
219}
220
221impl ModelAccess for NullAgent {
222 fn handle_caveman<'a>(
223 &'a mut self,
224 _arg: &'a str,
225 ) -> std::pin::Pin<Box<dyn std::future::Future<Output = String> + Send + 'a>> {
226 Box::pin(async { "caveman: unavailable".to_owned() })
227 }
228
229 fn handle_model<'a>(
230 &'a mut self,
231 _arg: &'a str,
232 ) -> std::pin::Pin<Box<dyn std::future::Future<Output = String> + Send + 'a>> {
233 Box::pin(async { String::new() })
234 }
235
236 fn handle_provider<'a>(
237 &'a mut self,
238 _arg: &'a str,
239 ) -> std::pin::Pin<Box<dyn std::future::Future<Output = String> + Send + 'a>> {
240 Box::pin(async { String::new() })
241 }
242
243 fn handle_think_tokens<'a>(
244 &'a mut self,
245 _arg: &'a str,
246 ) -> std::pin::Pin<Box<dyn std::future::Future<Output = String> + Send + 'a>> {
247 Box::pin(async { String::new() })
248 }
249
250 fn handle_reasoning_effort<'a>(
251 &'a mut self,
252 _arg: &'a str,
253 ) -> std::pin::Pin<Box<dyn std::future::Future<Output = String> + Send + 'a>> {
254 Box::pin(async { String::new() })
255 }
256}
257
258impl SkillAccess for NullAgent {
259 fn handle_skill<'a>(
260 &'a mut self,
261 _args: &'a str,
262 ) -> std::pin::Pin<
263 Box<dyn std::future::Future<Output = Result<String, crate::CommandError>> + Send + 'a>,
264 > {
265 Box::pin(async { Ok(String::new()) })
266 }
267
268 fn handle_skills<'a>(
269 &'a mut self,
270 _args: &'a str,
271 ) -> std::pin::Pin<
272 Box<dyn std::future::Future<Output = Result<String, crate::CommandError>> + Send + 'a>,
273 > {
274 Box::pin(async { Ok(String::new()) })
275 }
276
277 fn handle_feedback_command<'a>(
278 &'a mut self,
279 _args: &'a str,
280 ) -> std::pin::Pin<
281 Box<dyn std::future::Future<Output = Result<String, crate::CommandError>> + Send + 'a>,
282 > {
283 Box::pin(async { Ok(String::new()) })
284 }
285}
286
287impl PolicyAccess for NullAgent {
288 fn handle_policy<'a>(
289 &'a mut self,
290 _args: &'a str,
291 ) -> std::pin::Pin<
292 Box<dyn std::future::Future<Output = Result<String, crate::CommandError>> + Send + 'a>,
293 > {
294 Box::pin(async { Ok(String::new()) })
295 }
296}
297
298impl SchedulerAccess for NullAgent {
299 fn list_scheduled_tasks<'a>(
300 &'a mut self,
301 ) -> std::pin::Pin<
302 Box<
303 dyn std::future::Future<Output = Result<Option<String>, crate::CommandError>>
304 + Send
305 + 'a,
306 >,
307 > {
308 Box::pin(async { Ok(None) })
309 }
310}
311
312impl LspAccess for NullAgent {
313 fn lsp_status<'a>(
314 &'a mut self,
315 ) -> std::pin::Pin<
316 Box<dyn std::future::Future<Output = Result<String, crate::CommandError>> + Send + 'a>,
317 > {
318 Box::pin(async { Ok(String::new()) })
319 }
320}
321
322impl SessionControlAccess for NullAgent {
323 fn session_recap<'a>(
324 &'a mut self,
325 ) -> std::pin::Pin<
326 Box<dyn std::future::Future<Output = Result<String, crate::CommandError>> + Send + 'a>,
327 > {
328 Box::pin(async { Ok(String::new()) })
329 }
330
331 fn compact_context<'a>(
332 &'a mut self,
333 ) -> std::pin::Pin<
334 Box<dyn std::future::Future<Output = Result<String, crate::CommandError>> + Send + 'a>,
335 > {
336 Box::pin(async { Ok(String::new()) })
337 }
338
339 fn reset_conversation<'a>(
340 &'a mut self,
341 _keep_plan: bool,
342 _no_digest: bool,
343 ) -> std::pin::Pin<
344 Box<dyn std::future::Future<Output = Result<String, crate::CommandError>> + Send + 'a>,
345 > {
346 Box::pin(async { Ok(String::new()) })
347 }
348
349 fn cache_stats(&self) -> String {
350 String::new()
351 }
352
353 fn session_status<'a>(
354 &'a mut self,
355 ) -> std::pin::Pin<
356 Box<dyn std::future::Future<Output = Result<String, crate::CommandError>> + Send + 'a>,
357 > {
358 Box::pin(async { Ok(String::new()) })
359 }
360
361 fn guardrail_status(&self) -> String {
362 String::new()
363 }
364
365 fn focus_status(&self) -> String {
366 String::new()
367 }
368
369 fn sidequest_status(&self) -> String {
370 String::new()
371 }
372
373 fn load_image<'a>(
374 &'a mut self,
375 _path: &'a str,
376 ) -> std::pin::Pin<
377 Box<dyn std::future::Future<Output = Result<String, crate::CommandError>> + Send + 'a>,
378 > {
379 Box::pin(async { Ok(String::new()) })
380 }
381}
382
383impl McpAccess for NullAgent {
384 fn handle_mcp<'a>(
385 &'a mut self,
386 _args: &'a str,
387 ) -> std::pin::Pin<
388 Box<dyn std::future::Future<Output = Result<String, crate::CommandError>> + Send + 'a>,
389 > {
390 Box::pin(async { Ok(String::new()) })
391 }
392}
393
394impl OrchestrationAccess for NullAgent {
395 fn handle_plan<'a>(
396 &'a mut self,
397 _input: &'a str,
398 ) -> std::pin::Pin<
399 Box<dyn std::future::Future<Output = Result<String, crate::CommandError>> + Send + 'a>,
400 > {
401 Box::pin(async { Ok(String::new()) })
402 }
403
404 fn handle_experiment<'a>(
405 &'a mut self,
406 _input: &'a str,
407 ) -> std::pin::Pin<
408 Box<dyn std::future::Future<Output = Result<String, crate::CommandError>> + Send + 'a>,
409 > {
410 Box::pin(async { Ok(String::new()) })
411 }
412}
413
414impl SubagentAccess for NullAgent {
415 fn handle_agent_dispatch<'a>(
416 &'a mut self,
417 _input: &'a str,
418 ) -> std::pin::Pin<
419 Box<
420 dyn std::future::Future<Output = Result<Option<String>, crate::CommandError>>
421 + Send
422 + 'a,
423 >,
424 > {
425 Box::pin(async { Ok(None) })
426 }
427}
428
429impl IntegrationAccess for NullAgent {
430 fn handle_plugins<'a>(
431 &'a mut self,
432 _args: &'a str,
433 ) -> std::pin::Pin<
434 Box<dyn std::future::Future<Output = Result<String, crate::CommandError>> + Send + 'a>,
435 > {
436 Box::pin(async { Ok(String::new()) })
437 }
438
439 fn handle_acp<'a>(
440 &'a mut self,
441 _args: &'a str,
442 ) -> std::pin::Pin<
443 Box<dyn std::future::Future<Output = Result<String, crate::CommandError>> + Send + 'a>,
444 > {
445 Box::pin(async { Ok(String::new()) })
446 }
447
448 fn handle_cocoon<'a>(
449 &'a mut self,
450 _args: &'a str,
451 ) -> std::pin::Pin<
452 Box<dyn std::future::Future<Output = Result<String, crate::CommandError>> + Send + 'a>,
453 > {
454 Box::pin(async { Ok(String::new()) })
455 }
456}
457
458impl TrackingAccess for NullAgent {
459 fn handle_trajectory(&mut self, _args: &str) -> String {
460 String::new()
461 }
462
463 fn handle_scope(&self, _args: &str) -> String {
464 String::new()
465 }
466}
467
468impl WorktreeAccess for NullAgent {}
469
470impl MiscAccess for NullAgent {
471 fn handle_loop<'a>(
472 &'a mut self,
473 _args: &'a str,
474 ) -> std::pin::Pin<
475 Box<dyn std::future::Future<Output = Result<String, crate::CommandError>> + Send + 'a>,
476 > {
477 Box::pin(async { Ok(String::new()) })
478 }
479
480 fn notify_test<'a>(
489 &'a mut self,
490 ) -> std::pin::Pin<
491 Box<dyn std::future::Future<Output = Result<String, crate::CommandError>> + Send + 'a>,
492 > {
493 Box::pin(async { Ok("Notifications not configured.".to_owned()) })
494 }
495}