1mod claude;
2mod codex;
3mod droid;
4mod test;
5
6pub use claude::ClaudeCode;
7pub use codex::Codex;
8pub use droid::Droid;
9pub use test::TestAgent;
10
11use crate::error::{Result, WagnerError};
12use crate::model::Engine;
13use std::path::{Path, PathBuf};
14
15pub trait Agent: Send + Sync {
16 fn name(&self) -> &str;
17 fn engine(&self) -> Engine;
18 fn launch_command(&self, session_id: &str) -> String;
19 fn predict_jsonl_path(&self, session_id: &str, cwd: &Path) -> Option<PathBuf>;
20 fn resume_command(&self, session_id: &str) -> String;
21}
22
23#[derive(Debug, Clone)]
24pub enum AgentChoice {
25 Claude(ClaudeCode),
26 Codex(Codex),
27 Droid(Droid),
28}
29
30impl AgentChoice {
31 pub fn from_key(key: &str) -> Result<Self> {
32 match key {
33 "claude" | "claude-code" => Ok(Self::Claude(ClaudeCode::new())),
34 "codex" => Ok(Self::Codex(Codex::new())),
35 "droid" => Ok(Self::Droid(Droid::new())),
36 _ => Err(WagnerError::InvalidAgent(key.to_string())),
37 }
38 }
39}
40
41impl Agent for AgentChoice {
42 fn name(&self) -> &str {
43 match self {
44 Self::Claude(agent) => agent.name(),
45 Self::Codex(agent) => agent.name(),
46 Self::Droid(agent) => agent.name(),
47 }
48 }
49
50 fn engine(&self) -> Engine {
51 match self {
52 Self::Claude(agent) => agent.engine(),
53 Self::Codex(agent) => agent.engine(),
54 Self::Droid(agent) => agent.engine(),
55 }
56 }
57
58 fn launch_command(&self, session_id: &str) -> String {
59 match self {
60 Self::Claude(agent) => agent.launch_command(session_id),
61 Self::Codex(agent) => agent.launch_command(session_id),
62 Self::Droid(agent) => agent.launch_command(session_id),
63 }
64 }
65
66 fn predict_jsonl_path(&self, session_id: &str, cwd: &Path) -> Option<PathBuf> {
67 match self {
68 Self::Claude(agent) => agent.predict_jsonl_path(session_id, cwd),
69 Self::Codex(agent) => agent.predict_jsonl_path(session_id, cwd),
70 Self::Droid(agent) => agent.predict_jsonl_path(session_id, cwd),
71 }
72 }
73
74 fn resume_command(&self, session_id: &str) -> String {
75 match self {
76 Self::Claude(agent) => agent.resume_command(session_id),
77 Self::Codex(agent) => agent.resume_command(session_id),
78 Self::Droid(agent) => agent.resume_command(session_id),
79 }
80 }
81}