77 lines
1.8 KiB
Rust
77 lines
1.8 KiB
Rust
//! Request/response shapes for the Anthropic Messages API.
|
|
//!
|
|
//! Hand-rolled rather than pulled from an SDK: pydantic-ai has no Rust
|
|
//! equivalent, and the surface area we actually need (text, tool_use,
|
|
//! tool_result, forced tool choice) is small enough to own directly.
|
|
|
|
use serde::{Deserialize, Serialize};
|
|
use serde_json::Value;
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct Message {
|
|
pub role: String,
|
|
pub content: Vec<ContentBlock>,
|
|
}
|
|
|
|
impl Message {
|
|
pub fn user_text(text: impl Into<String>) -> Self {
|
|
Self {
|
|
role: "user".into(),
|
|
content: vec![ContentBlock::Text { text: text.into() }],
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
#[serde(tag = "type", rename_all = "snake_case")]
|
|
pub enum ContentBlock {
|
|
Text {
|
|
text: String,
|
|
},
|
|
ToolUse {
|
|
id: String,
|
|
name: String,
|
|
input: Value,
|
|
},
|
|
ToolResult {
|
|
tool_use_id: String,
|
|
content: String,
|
|
},
|
|
/// Anything else the API sends back (e.g. a `thinking` block) that this
|
|
/// client doesn't act on but must not fail to deserialize.
|
|
#[serde(other)]
|
|
Unknown,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize)]
|
|
pub struct ToolSpec {
|
|
pub name: String,
|
|
pub description: String,
|
|
pub input_schema: Value,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize)]
|
|
#[serde(tag = "type", rename_all = "snake_case")]
|
|
pub enum ToolChoice {
|
|
Auto,
|
|
Tool { name: String },
|
|
}
|
|
|
|
#[derive(Debug, Serialize)]
|
|
pub struct RequestBody<'a> {
|
|
pub model: &'a str,
|
|
pub max_tokens: u32,
|
|
pub system: &'a str,
|
|
pub messages: &'a [Message],
|
|
pub tools: &'a [ToolSpec],
|
|
pub tool_choice: ToolChoice,
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
pub struct ResponseBody {
|
|
#[serde(default)]
|
|
pub content: Vec<ContentBlock>,
|
|
#[serde(default)]
|
|
pub stop_reason: Option<String>,
|
|
}
|