1use adk_artifact::ArtifactService;
33use adk_core::{Agent, AgentLoader, Result};
34use adk_server::{create_app, ServerConfig};
35use adk_session::InMemorySessionService;
36use clap::{Parser, Subcommand};
37use std::sync::Arc;
38
39#[derive(Parser)]
41#[command(name = "agent")]
42#[command(about = "ADK Agent", long_about = None)]
43struct Cli {
44 #[command(subcommand)]
45 command: Option<Commands>,
46}
47
48#[derive(Subcommand)]
49enum Commands {
50 Chat,
52 Serve {
54 #[arg(long, default_value_t = 8080)]
56 port: u16,
57 },
58}
59
60pub struct SingleAgentLoader {
62 agent: Arc<dyn Agent>,
63}
64
65impl SingleAgentLoader {
66 pub fn new(agent: Arc<dyn Agent>) -> Self {
68 Self { agent }
69 }
70}
71
72#[async_trait::async_trait]
73impl AgentLoader for SingleAgentLoader {
74 async fn load_agent(&self, _name: &str) -> Result<Arc<dyn Agent>> {
75 Ok(self.agent.clone())
76 }
77
78 fn list_agents(&self) -> Vec<String> {
79 vec![self.agent.name().to_string()]
80 }
81
82 fn root_agent(&self) -> Arc<dyn Agent> {
83 self.agent.clone()
84 }
85}
86
87pub struct Launcher {
91 agent: Arc<dyn Agent>,
92 app_name: Option<String>,
93 artifact_service: Option<Arc<dyn ArtifactService>>,
94}
95
96impl Launcher {
97 pub fn new(agent: Arc<dyn Agent>) -> Self {
99 Self { agent, app_name: None, artifact_service: None }
100 }
101
102 pub fn app_name(mut self, name: impl Into<String>) -> Self {
104 self.app_name = Some(name.into());
105 self
106 }
107
108 pub fn with_artifact_service(mut self, service: Arc<dyn ArtifactService>) -> Self {
110 self.artifact_service = Some(service);
111 self
112 }
113
114 pub async fn run(self) -> Result<()> {
119 let cli = Cli::parse();
120
121 match cli.command.unwrap_or(Commands::Chat) {
122 Commands::Chat => self.run_console().await,
123 Commands::Serve { port } => self.run_serve(port).await,
124 }
125 }
126
127 async fn run_console(self) -> Result<()> {
129 use adk_runner::{Runner, RunnerConfig};
130 use adk_session::{CreateRequest, SessionService};
131 use futures::StreamExt;
132 use std::collections::HashMap;
133 use std::io::{self, BufRead, Write};
134
135 let app_name = self.app_name.unwrap_or_else(|| self.agent.name().to_string());
136 let user_id = "user".to_string();
137
138 let session_service = Arc::new(InMemorySessionService::new());
139
140 let session = session_service
142 .create(CreateRequest {
143 app_name: app_name.clone(),
144 user_id: user_id.clone(),
145 session_id: None,
146 state: HashMap::new(),
147 })
148 .await?;
149
150 let session_id = session.id().to_string();
151
152 let runner = Runner::new(RunnerConfig {
154 app_name,
155 agent: self.agent,
156 session_service,
157 artifact_service: self.artifact_service,
158 memory_service: None,
159 })?;
160
161 println!("š¤ Agent ready! Type your questions (or 'exit' to quit).\n");
162
163 let stdin = io::stdin();
164 let mut stdout = io::stdout();
165
166 loop {
167 print!("You: ");
168 stdout.flush()?;
169
170 let mut input = String::new();
171 let bytes_read = stdin.lock().read_line(&mut input)?;
172
173 if bytes_read == 0 {
175 println!("\nš Goodbye!");
176 break;
177 }
178
179 let input = input.trim();
180
181 if input == "exit" || input == "quit" {
182 println!("š Goodbye!");
183 break;
184 }
185
186 if input.is_empty() {
187 continue;
188 }
189
190 let content = adk_core::Content::new("user").with_text(input);
191 let mut events = runner.run(user_id.clone(), session_id.clone(), content).await?;
192
193 print!("Assistant: ");
194 stdout.flush()?;
195
196 let mut current_agent = String::new();
197
198 while let Some(event) = events.next().await {
199 match event {
200 Ok(evt) => {
201 if !evt.author.is_empty()
203 && evt.author != "user"
204 && evt.author != current_agent
205 {
206 if !current_agent.is_empty() {
207 println!();
208 }
209 current_agent = evt.author.clone();
210 println!("\n[Agent: {}]", current_agent);
211 print!("Assistant: ");
212 stdout.flush()?;
213 }
214
215 if let Some(target) = &evt.actions.transfer_to_agent {
217 println!("\nš [Transfer requested to: {}]", target);
218 }
219
220 if let Some(content) = evt.llm_response.content {
221 for part in content.parts {
222 if let Some(text) = part.text() {
223 print!("{}", text);
224 stdout.flush()?;
225 }
226 }
227 }
228 }
229 Err(e) => eprintln!("\nError: {}", e),
230 }
231 }
232 println!("\n");
233 }
234
235 Ok(())
236 }
237
238 async fn run_serve(self, port: u16) -> Result<()> {
240 if let Err(e) = adk_telemetry::init_telemetry("adk-server") {
242 eprintln!("Warning: Failed to initialize telemetry: {}", e);
243 }
244
245 let session_service = Arc::new(InMemorySessionService::new());
246 let agent_loader = Arc::new(SingleAgentLoader::new(self.agent));
247
248 let config = ServerConfig::new(agent_loader, session_service)
249 .with_artifact_service_opt(self.artifact_service);
250
251 let app = create_app(config);
252
253 let addr = format!("0.0.0.0:{}", port);
254 let listener = tokio::net::TcpListener::bind(&addr).await?;
255
256 println!("š ADK Server starting on http://localhost:{}", port);
257 println!("š± Open http://localhost:{} in your browser", port);
258 println!("Press Ctrl+C to stop\n");
259
260 axum::serve(listener, app).await?;
261
262 Ok(())
263 }
264}