pub use agent_client_protocol::schema::ProtocolVersion;
pub use agent_client_protocol::schema::v1::{
AgentCapabilities, AuthenticateRequest as AuthenticateParams,
AuthenticateResponse as AuthenticateResult, AvailableCommand, AvailableCommandInput,
AvailableCommandsUpdate, CancelNotification, Content, ContentBlock, ContentChunk,
InitializeRequest as InitializeParams, InitializeResponse as InitializeResult,
LoadSessionRequest as LoadSessionParams, LoadSessionResponse as LoadSessionResult,
NewSessionRequest as NewSessionParams, NewSessionResponse as NewSessionResult, Plan, PlanEntry,
PlanEntryPriority, PlanEntryStatus, PromptCapabilities, PromptRequest as PromptParams,
PromptResponse as PromptResult, SessionNotification, SessionUpdate, StopReason, TextContent,
ToolCall, ToolCallContent, ToolCallStatus, ToolCallUpdate, ToolCallUpdateFields, ToolKind,
UnstructuredCommandInput,
};
use serde_json::{Map, Value};
pub const PROTOCOL_VERSION: ProtocolVersion = ProtocolVersion::V1;
pub fn text_block(text: impl Into<String>) -> ContentBlock {
ContentBlock::Text(TextContent::new(text))
}
pub fn text_chunk(text: impl Into<String>) -> ContentChunk {
ContentChunk::new(text_block(text))
}
pub fn content(text: impl Into<String>) -> ToolCallContent {
ToolCallContent::Content(Content::new(text_block(text)))
}
pub fn meta(value: Value) -> Option<Map<String, Value>> {
match value {
Value::Object(map) => Some(map),
_ => None,
}
}
pub fn prompt_text(blocks: &[ContentBlock]) -> String {
let mut parts = Vec::new();
for block in blocks {
if let ContentBlock::Text(text) = block {
parts.push(text.text.clone());
}
}
parts.join("\n")
}
#[cfg(test)]
mod tests {
use super::*;
use agent_client_protocol::schema::v1::ImageContent;
#[test]
fn sdk_initialize_result_serializes_camel_case() {
let result = InitializeResult::new(PROTOCOL_VERSION).agent_capabilities(
AgentCapabilities::new()
.load_session(true)
.prompt_capabilities(PromptCapabilities::new().embedded_context(true)),
);
let v = serde_json::to_value(&result).unwrap();
assert_eq!(v["protocolVersion"], 1);
assert_eq!(v["agentCapabilities"]["loadSession"], true);
assert_eq!(
v["agentCapabilities"]["promptCapabilities"]["embeddedContext"],
true
);
assert!(v["authMethods"].as_array().unwrap().is_empty());
}
#[test]
fn sdk_message_chunk_uses_snake_case_discriminator() {
let update = SessionUpdate::AgentMessageChunk(text_chunk("hi"));
let v = serde_json::to_value(&update).unwrap();
assert_eq!(v["sessionUpdate"], "agent_message_chunk");
assert_eq!(v["content"]["type"], "text");
assert_eq!(v["content"]["text"], "hi");
}
#[test]
fn prompt_text_concatenates_text_blocks_only() {
let blocks = vec![
text_block("hello"),
ContentBlock::Image(ImageContent::new("image/png", "...")),
text_block("world"),
];
assert_eq!(prompt_text(&blocks), "hello\nworld");
}
}