use std::sync::Arc;
use copilot_sdk::*;
fn create_weather_tool() -> (ToolDefinition, ToolHandler) {
let definition = ToolDefinition {
name: "get_weather".to_string(),
description: Some("Get the current weather for a location".to_string()),
parameters: Some(serde_json::json!({
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city name to get weather for"
}
},
"required": ["location"]
})),
};
let handler: ToolHandler = Arc::new(|args, _invocation| {
Box::pin(async move {
let location = args
.get("location")
.and_then(|v| v.as_str())
.unwrap_or("Unknown");
let result = serde_json::json!({
"location": location,
"temperature": 72,
"unit": "fahrenheit",
"condition": "sunny",
"humidity": 45
});
Ok(result)
})
});
(definition, handler)
}
#[tokio::main]
async fn main() -> Result<(), CopilotError> {
let options = CopilotClientOptions {
cli_path: Some("copilot-cli".to_string()), log_level: "info".to_string(),
..Default::default()
};
let client = CopilotClient::new(options);
println!("Starting Copilot client...");
client.start().await?;
println!("Client connected!");
let ping_response = client.ping(Some("hello from Rust SDK")).await?;
println!(
"Ping response: {} (protocol v{})",
ping_response.message,
ping_response.protocol_version.unwrap_or(0)
);
match client.list_models().await {
Ok(models) => {
println!("\nAvailable models:");
for model in &models {
println!(" - {} ({})", model.name, model.id);
}
}
Err(e) => {
println!("Could not list models: {}", e);
}
}
let (weather_def, weather_handler) = create_weather_tool();
let config = SessionConfig {
tools: Some(vec![weather_def.clone()]),
request_permission: Some(false),
request_user_input: Some(false),
..Default::default()
};
let session = client.create_session(config).await?;
println!("\nSession created: {}", session.session_id());
session
.register_tool(&weather_def.name, weather_handler)
.await;
let _all_events_sub = session
.on(|event: SessionEvent| {
match event.event_type.as_str() {
"assistant.message_delta" => {
if let Some(delta) = event.data.get("deltaContent").and_then(|v| v.as_str()) {
print!("{}", delta);
}
}
"tool.execution_start" => {
let tool_name = event
.data
.get("toolName")
.and_then(|v| v.as_str())
.unwrap_or("unknown");
println!("\n[Tool executing: {}]", tool_name);
}
"tool.execution_complete" => {
let success = event
.data
.get("success")
.and_then(|v| v.as_bool())
.unwrap_or(false);
println!("[Tool completed: success={}]", success);
}
"session.idle" => {
println!("\n[Session idle]");
}
"session.error" => {
let msg = event
.data
.get("message")
.and_then(|v| v.as_str())
.unwrap_or("unknown error");
eprintln!("\n[Session error: {}]", msg);
}
_ => {
}
}
})
.await;
let _msg_sub = session
.on_event("assistant.message", |event| {
if let Some(content) = event.assistant_message_content() {
println!("\n\n=== Final Assistant Message ===");
println!("{}", content);
println!("===============================");
}
})
.await;
println!("\nSending message...");
let response = session
.send_and_wait(
MessageOptions {
prompt: "What is the weather in San Francisco? Use the get_weather tool."
.to_string(),
attachments: None,
mode: None,
},
Some(120_000), )
.await?;
match response {
Some(event) => {
if let Some(content) = event.assistant_message_content() {
println!("\nsend_and_wait response: {}", content);
}
}
None => {
println!("\nNo assistant message received.");
}
}
println!("\nSending follow-up...");
let response = session
.send_and_wait(
MessageOptions {
prompt: "Now what about New York?".to_string(),
attachments: None,
mode: None,
},
None, )
.await?;
if let Some(event) = response {
if let Some(content) = event.assistant_message_content() {
println!("\nFollow-up response: {}", content);
}
}
if let Ok(Some(meta)) = client.get_session_metadata(&session.session_id()).await {
println!("Session ID: {}", meta.session_id);
}
println!("\nCleaning up...");
session.destroy().await?;
let errors = client.stop().await?;
if !errors.is_empty() {
eprintln!("Cleanup errors:");
for e in &errors {
eprintln!(" - {}", e);
}
}
println!("Done!");
Ok(())
}