Skip to main content

vtcode_core/a2a/
cli.rs

1//! A2A Protocol CLI commands
2//!
3//! Provides command-line interface for:
4//! - Serving VT Code as an A2A agent
5//! - Discovering remote A2A agents
6//! - Sending tasks to other agents
7//! - Managing A2A agent connections
8
9use clap::{Parser, Subcommand};
10
11/// A2A Protocol commands
12#[derive(Debug, Subcommand, Clone)]
13pub enum A2aCommands {
14    /// Serve VT Code as an A2A agent (requires a2a-server feature)
15    ///
16    /// Starts an HTTP server exposing A2A endpoints:
17    /// - /.well-known/agent-card.json - Agent discovery
18    /// - /a2a - JSON-RPC endpoint for task management
19    /// - /a2a/stream - Server-Sent Events streaming
20    ///
21    /// Examples:
22    ///   vtcode a2a serve --port 8080
23    ///   vtcode a2a serve --host 0.0.0.0 --port 8080
24    Serve {
25        /// Host to bind the server to
26        #[arg(long, default_value = "127.0.0.1")]
27        host: String,
28
29        /// Port to listen on
30        #[arg(short, long, default_value_t = 8080)]
31        port: u16,
32
33        /// Base URL for the agent (used in agent card)
34        #[arg(long)]
35        base_url: Option<String>,
36
37        /// Enable push notifications via webhooks
38        #[arg(long)]
39        enable_push: bool,
40    },
41
42    /// Discover and display information about a remote A2A agent
43    ///
44    /// Fetches and displays the agent card from the remote agent,
45    /// showing capabilities, skills, and supported features.
46    ///
47    /// Examples:
48    ///   vtcode a2a discover <https://agent.example.com>
49    ///   vtcode a2a discover <https://localhost:8080>
50    Discover {
51        /// URL of the remote A2A agent
52        agent_url: String,
53    },
54
55    /// Send a task to a remote A2A agent
56    ///
57    /// Sends a message to a remote agent and returns the task result.
58    /// The agent will process the request and return structured results.
59    ///
60    /// Examples:
61    ///   vtcode a2a send-task <https://agent.example.com> "Help me refactor this code"
62    ///   vtcode a2a send-task <https://localhost:8080> "Explain this error message"
63    SendTask {
64        /// URL of the remote A2A agent
65        agent_url: String,
66
67        /// The task/message to send to the agent
68        message: String,
69
70        /// Wait for task completion and stream progress
71        #[arg(long)]
72        stream: bool,
73
74        /// Optional context ID for conversation tracking
75        #[arg(long)]
76        context_id: Option<String>,
77    },
78
79    /// List active tasks in a running A2A agent
80    ///
81    /// Queries a remote A2A agent for its current and recent tasks.
82    ///
83    /// Examples:
84    ///   vtcode a2a list-tasks <https://agent.example.com>
85    ///   vtcode a2a list-tasks <https://localhost:8080> --context-id my-conversation
86    ListTasks {
87        /// URL of the remote A2A agent
88        agent_url: String,
89
90        /// Filter by context ID
91        #[arg(long)]
92        context_id: Option<String>,
93
94        /// Maximum number of tasks to return
95        #[arg(long, default_value_t = 50)]
96        limit: u32,
97    },
98
99    /// Get details about a specific task
100    ///
101    /// Retrieves the current status, artifacts, and history of a task.
102    ///
103    /// Examples:
104    ///   vtcode a2a get-task <https://agent.example.com> task-123
105    ///   vtcode a2a get-task <https://localhost:8080> task-456
106    GetTask {
107        /// URL of the remote A2A agent
108        agent_url: String,
109
110        /// Task ID to retrieve
111        task_id: String,
112    },
113
114    /// Cancel a running task
115    ///
116    /// Requests cancellation of a task that is currently being processed.
117    ///
118    /// Examples:
119    ///   vtcode a2a cancel-task <https://agent.example.com> task-123
120    CancelTask {
121        /// URL of the remote A2A agent
122        agent_url: String,
123
124        /// Task ID to cancel
125        task_id: String,
126    },
127}
128
129/// A2A CLI configuration options
130#[derive(Debug, Parser)]
131pub struct A2aServeConfig {
132    /// Host to bind the server to
133    #[arg(long, default_value = "127.0.0.1")]
134    pub host: String,
135
136    /// Port to listen on
137    #[arg(short, long, default_value_t = 8080)]
138    pub port: u16,
139
140    /// Base URL for the agent (used in agent card)
141    #[arg(long)]
142    pub base_url: Option<String>,
143
144    /// Enable push notifications via webhooks
145    #[arg(long)]
146    pub enable_push: bool,
147}
148
149#[cfg(test)]
150mod tests {
151    use super::*;
152
153    #[test]
154    fn test_cli_serve_command() {
155        let cmd = A2aCommands::Serve {
156            host: "127.0.0.1".to_string(),
157            port: 8080,
158            base_url: Some("http://localhost:8080".to_string()),
159            enable_push: false,
160        };
161        match cmd {
162            A2aCommands::Serve { port, .. } => assert_eq!(port, 8080),
163            _ => panic!("Wrong command type"),
164        }
165    }
166
167    #[test]
168    fn test_cli_discover_command() {
169        let cmd = A2aCommands::Discover {
170            agent_url: "https://example.com".to_string(),
171        };
172        match cmd {
173            A2aCommands::Discover { agent_url } => {
174                assert_eq!(agent_url, "https://example.com")
175            }
176            _ => panic!("Wrong command type"),
177        }
178    }
179}