use opencode_rs::ClientBuilder;
use opencode_rs::types::event::Event;
use opencode_rs::types::message::{PromptPart, PromptRequest};
use opencode_rs::types::project::ModelRef;
use opencode_rs::types::session::{CreateSessionRequest, UpdateSessionRequest};
use std::time::Duration;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
tracing_subscriber::fmt::init();
println!("=== OpenCode Rust SDK Full Workflow Example ===\n");
println!("1. Creating client...");
let client = ClientBuilder::new()
.base_url("http://127.0.0.1:4096")
.directory(std::env::current_dir()?.to_string_lossy())
.timeout_secs(300)
.build()?;
println!("2. Checking server health...");
let health = client.misc().health().await?;
println!(" Server healthy: {}", health.healthy);
if let Some(version) = &health.version {
println!(" Server version: {}", version);
}
println!("\n3. Creating session...");
let session = client
.sessions()
.create(&CreateSessionRequest {
title: Some("SDK Full Workflow Example".into()),
..Default::default()
})
.await?;
println!(" Created session: {}", session.id);
println!(" Title: {}", session.title);
println!("\n4. Subscribing to session events...");
let mut subscription = client.subscribe_session(&session.id).await?;
println!(" Subscribed successfully");
println!("\n5. Sending prompt...");
let prompt_text = "Write a short haiku about programming";
client
.messages()
.prompt(
&session.id,
&PromptRequest {
parts: vec![PromptPart::Text {
text: prompt_text.into(),
synthetic: None,
ignored: None,
metadata: None,
}],
message_id: None,
model: Some(ModelRef {
provider_id: "kimi-for-coding".into(),
model_id: "kimi-k2-thinking".into(),
}),
agent: None,
no_reply: None,
system: None,
variant: None,
},
)
.await?;
println!(" Prompt sent: \"{}\"", prompt_text);
println!("\n6. Streaming response...\n");
let mut response_text = String::new();
let timeout = Duration::from_secs(60);
let start = std::time::Instant::now();
loop {
if start.elapsed() > timeout {
println!("\n [Timeout reached]");
break;
}
tokio::select! {
event = subscription.recv() => {
match event {
Some(Event::SessionIdle { .. }) => {
println!("\n [Session completed]");
break;
}
Some(Event::SessionError { properties }) => {
eprintln!("\n [Session error: {:?}]", properties.error);
break;
}
Some(Event::MessagePartUpdated { properties }) => {
if let Some(delta) = &properties.delta {
print!("{}", delta);
response_text.push_str(delta);
}
}
Some(Event::ServerHeartbeat { .. }) => {
eprintln!("[DEBUG] Heartbeat received");
}
Some(event) => {
eprintln!("[DEBUG] Other event: {:?}", event);
}
None => {
println!("\n [Stream closed]");
break;
}
}
}
_ = tokio::time::sleep(Duration::from_millis(100)) => {
}
}
}
println!("\n7. Updating session title...");
let updated = client
.sessions()
.update(
&session.id,
&UpdateSessionRequest {
title: Some("Completed Haiku Session".into()),
},
)
.await?;
println!(" New title: {}", updated.title);
println!("\n8. Getting session diff...");
let diff = client.sessions().diff(&session.id).await?;
println!(" Files changed: {}", diff.files.len());
if !diff.diff.is_empty() {
let preview: String = diff.diff.chars().take(100).collect();
println!(" Diff preview: {}...", preview);
}
println!("\n9. Checking todos...");
let todos = client.sessions().todo(&session.id).await?;
println!(" Todos: {}", todos.len());
for todo in &todos {
println!(
" - [{}] {}",
if todo.completed { "x" } else { " " },
todo.content
);
}
println!("\n10. Listing messages...");
let messages = client.messages().list(&session.id).await?;
println!(" Total messages: {}", messages.len());
for msg in &messages {
println!(" - {} (parts: {})", msg.role(), msg.parts.len());
}
println!("\n11. Cleaning up - deleting session...");
client.sessions().delete(&session.id).await?;
println!(" Session deleted");
println!("\n=== Workflow Complete ===");
println!("\nResponse received:\n{}", response_text);
Ok(())
}