add examples, end-to-end tests, and Cargo.lock
Three examples: - basic.rs: query() one-shot prompt + cost reporting. - with_options.rs: system_prompt, model selection, effort, permission mode. - interactive.rs: Client multi-turn session with two back-to-back sends. Integration tests in tests/transport_end_to_end.rs spawn a tiny POSIX shell script (tests/fake_cli/fake-claude.sh) as a stand-in for the real claude CLI. The fake answers -v with a version, reads one user-message frame on stdin, and emits a fixed assistant + result pair on stdout, then blocks on stdin until close. This proves the spawn / write / read / disconnect lifecycle works without an authenticated claude install. Coverage: - query() round-trip: stream yields Assistant then Result. - Client round-trip: connect + send + drain to Result + disconnect. - CLI-not-found surfaces as a typed Error::CliNotFound. Cargo.lock is committed since this is, in practice, both a library and a binary (the examples link the crate). Locking dev-deps avoids surprise churn in CI.
This commit is contained in:
parent
ef1d8fdd31
commit
1ed4d8211f
6 changed files with 795 additions and 0 deletions
52
examples/interactive.rs
Normal file
52
examples/interactive.rs
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
//! Multi-turn [`Client`] example.
|
||||
//!
|
||||
//! Sends two prompts back-to-back without re-spawning the CLI subprocess —
|
||||
//! mirrors the Python SDK's `ClaudeSDKClient` async-context pattern.
|
||||
//!
|
||||
//! Run:
|
||||
//!
|
||||
//! ```sh
|
||||
//! cargo run --example interactive
|
||||
//! ```
|
||||
|
||||
use claude_agent_sdk::{ClaudeAgentOptions, Client, ContentBlock, Message};
|
||||
use tokio_stream::StreamExt;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
let mut client = Client::new(ClaudeAgentOptions::new().with_max_turns(1)).await?;
|
||||
client.connect().await?;
|
||||
let mut stream = client.messages();
|
||||
|
||||
client.send("Say 'one'.").await?;
|
||||
drain_until_result(&mut stream, "turn 1").await?;
|
||||
|
||||
client.send("Say 'two'.").await?;
|
||||
drain_until_result(&mut stream, "turn 2").await?;
|
||||
|
||||
client.disconnect().await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn drain_until_result(
|
||||
stream: &mut (impl tokio_stream::Stream<Item = claude_agent_sdk::Result<Message>> + Unpin),
|
||||
label: &str,
|
||||
) -> anyhow::Result<()> {
|
||||
while let Some(item) = stream.next().await {
|
||||
match item? {
|
||||
Message::Assistant(a) => {
|
||||
for block in &a.message.content {
|
||||
if let ContentBlock::Text(t) = block {
|
||||
println!("[{label}] Claude: {}", t.text);
|
||||
}
|
||||
}
|
||||
}
|
||||
Message::Result(_) => {
|
||||
println!("[{label}] done");
|
||||
return Ok(());
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue