claude_agent/client/messages/
types.rs1use std::collections::HashMap;
4
5use serde::{Deserialize, Serialize};
6
7use crate::types::{ToolDefinition, WebFetchTool, WebSearchTool};
8
9#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10pub struct RequestMetadata {
11 #[serde(skip_serializing_if = "Option::is_none")]
12 pub user_id: Option<String>,
13 #[serde(flatten)]
14 pub extra: HashMap<String, serde_json::Value>,
15}
16
17impl RequestMetadata {
18 pub fn generate() -> Self {
19 let session_id = uuid::Uuid::new_v4();
20 let user_hash = format!("{:x}", simple_hash(session_id.as_bytes()));
21 let account_uuid = uuid::Uuid::new_v4();
22 Self {
23 user_id: Some(format!(
24 "user_{}_account_{}_session_{}",
25 user_hash, account_uuid, session_id
26 )),
27 extra: HashMap::new(),
28 }
29 }
30}
31
32fn simple_hash(data: &[u8]) -> u128 {
33 let mut hash: u128 = 0;
34 for (i, &byte) in data.iter().enumerate() {
35 hash = hash.wrapping_add((byte as u128).wrapping_mul((i as u128).wrapping_add(1)));
36 hash = hash.wrapping_mul(31);
37 }
38 hash
39}
40
41#[derive(Debug, Clone, Serialize, Deserialize)]
42#[serde(untagged)]
43pub enum ApiTool {
44 Custom(ToolDefinition),
45 WebSearch(WebSearchTool),
46 WebFetch(WebFetchTool),
47}
48
49impl From<ToolDefinition> for ApiTool {
50 fn from(tool: ToolDefinition) -> Self {
51 Self::Custom(tool)
52 }
53}
54
55impl From<WebSearchTool> for ApiTool {
56 fn from(tool: WebSearchTool) -> Self {
57 Self::WebSearch(tool)
58 }
59}
60
61#[derive(Debug, Clone, Deserialize)]
62pub struct ErrorResponse {
63 #[serde(rename = "type")]
64 pub error_type: String,
65 pub error: ErrorDetail,
66}
67
68impl ErrorResponse {
69 pub fn into_error(self, status: u16) -> crate::Error {
70 crate::Error::Api {
71 message: self.error.message,
72 status: Some(status),
73 error_type: Some(self.error.error_type),
74 }
75 }
76}
77
78#[derive(Debug, Clone, Deserialize)]
79pub struct ErrorDetail {
80 #[serde(rename = "type")]
81 pub error_type: String,
82 pub message: String,
83}
84
85#[cfg(test)]
86mod tests {
87 use super::*;
88
89 #[test]
90 fn test_request_metadata_generate() {
91 let metadata = RequestMetadata::generate();
92 assert!(metadata.user_id.is_some());
93 let user_id = metadata.user_id.unwrap();
94 assert!(user_id.starts_with("user_"));
95 assert!(user_id.contains("_account_"));
96 assert!(user_id.contains("_session_"));
97 }
98}