use crate::errors::Result;
use crate::internal::client::InternalClient;
use crate::internal::message_parser::{MessageParser, ParsingMode, parse_with_mode};
use crate::internal::transport::subprocess::QueryPrompt;
use crate::internal::transport::{SubprocessTransport, Transport};
use crate::types::config::ClaudeAgentOptions;
use crate::types::messages::{Message, UserContentBlock};
use futures::stream::{Stream, StreamExt};
use std::pin::Pin;
pub async fn query(
prompt: impl Into<String>,
options: Option<ClaudeAgentOptions>,
) -> Result<Vec<Message>> {
let query_prompt = QueryPrompt::Text(prompt.into());
let opts = options.unwrap_or_default();
let client = InternalClient::new(query_prompt, opts)?;
client.execute().await
}
pub async fn query_stream(
prompt: impl Into<String>,
options: Option<ClaudeAgentOptions>,
) -> Result<Pin<Box<dyn Stream<Item = Result<Message>> + Send>>> {
let query_prompt = QueryPrompt::Text(prompt.into());
let opts = options.unwrap_or_default();
let parsing_mode = opts.parsing_mode;
let mut transport = SubprocessTransport::new(query_prompt, opts)?;
transport.connect().await?;
let stream = async_stream::stream! {
match parsing_mode {
ParsingMode::ZeroCopy => {
let mut message_stream = transport.read_raw_messages();
while let Some(json_result) = message_stream.next().await {
match json_result {
Ok(json) => {
match parse_with_mode(&json, ParsingMode::ZeroCopy) {
Ok(message) => yield Ok(message),
Err(e) => {
yield Err(e);
break;
}
}
}
Err(e) => {
yield Err(e);
break;
}
}
}
}
ParsingMode::Traditional => {
let mut message_stream = transport.read_messages();
while let Some(json_result) = message_stream.next().await {
match json_result {
Ok(json) => {
match MessageParser::parse(json) {
Ok(message) => yield Ok(message),
Err(e) => {
yield Err(e);
break;
}
}
}
Err(e) => {
yield Err(e);
break;
}
}
}
}
}
};
Ok(Box::pin(stream))
}
pub async fn query_with_content(
content: impl Into<Vec<UserContentBlock>>,
options: Option<ClaudeAgentOptions>,
) -> Result<Vec<Message>> {
let content_blocks = content.into();
UserContentBlock::validate_content(&content_blocks)?;
let query_prompt = QueryPrompt::Content(content_blocks);
let opts = options.unwrap_or_default();
let client = InternalClient::new(query_prompt, opts)?;
client.execute().await
}
pub async fn query_stream_with_content(
content: impl Into<Vec<UserContentBlock>>,
options: Option<ClaudeAgentOptions>,
) -> Result<Pin<Box<dyn Stream<Item = Result<Message>> + Send>>> {
let content_blocks = content.into();
UserContentBlock::validate_content(&content_blocks)?;
let query_prompt = QueryPrompt::Content(content_blocks);
let opts = options.unwrap_or_default();
let parsing_mode = opts.parsing_mode;
let mut transport = SubprocessTransport::new(query_prompt, opts)?;
transport.connect().await?;
let stream = async_stream::stream! {
match parsing_mode {
ParsingMode::ZeroCopy => {
let mut message_stream = transport.read_raw_messages();
while let Some(json_result) = message_stream.next().await {
match json_result {
Ok(json) => {
match parse_with_mode(&json, ParsingMode::ZeroCopy) {
Ok(message) => yield Ok(message),
Err(e) => {
yield Err(e);
break;
}
}
}
Err(e) => {
yield Err(e);
break;
}
}
}
}
ParsingMode::Traditional => {
let mut message_stream = transport.read_messages();
while let Some(json_result) = message_stream.next().await {
match json_result {
Ok(json) => {
match MessageParser::parse(json) {
Ok(message) => yield Ok(message),
Err(e) => {
yield Err(e);
break;
}
}
}
Err(e) => {
yield Err(e);
break;
}
}
}
}
}
};
Ok(Box::pin(stream))
}