agent_core_runtime/client/providers/
common.rs1use crate::client::models::{Content, Message};
4use std::sync::atomic::{AtomicU64, Ordering};
5
6static ID_COUNTER: AtomicU64 = AtomicU64::new(0);
8
9pub fn generate_unique_id(prefix: &str) -> String {
12 use std::time::{SystemTime, UNIX_EPOCH};
13 let counter = ID_COUNTER.fetch_add(1, Ordering::SeqCst);
14 let timestamp = SystemTime::now()
15 .duration_since(UNIX_EPOCH)
16 .unwrap_or_default()
17 .as_millis();
18 format!("{}{}_{}", prefix, timestamp, counter)
19}
20
21pub fn escape_json_string(s: &str) -> String {
23 let mut result = String::with_capacity(s.len());
24 for c in s.chars() {
25 match c {
26 '"' => result.push_str(r#"\""#),
27 '\\' => result.push_str(r#"\\"#),
28 '\n' => result.push_str(r#"\n"#),
29 '\r' => result.push_str(r#"\r"#),
30 '\t' => result.push_str(r#"\t"#),
31 c if c.is_control() => {
32 result.push_str(&format!(r#"\u{:04x}"#, c as u32));
33 }
34 c => result.push(c),
35 }
36 }
37 result
38}
39
40pub fn extract_text_content(msg: &Message) -> String {
42 msg.content
43 .iter()
44 .filter_map(|c| match c {
45 Content::Text(t) => Some(t.as_str()),
46 Content::Image(_) | Content::ToolUse(_) | Content::ToolResult(_) => None,
47 })
48 .collect::<Vec<_>>()
49 .join("\n")
50}
51
52#[cfg(test)]
53mod tests {
54 use super::*;
55
56 #[test]
57 fn test_escape_json_string() {
58 assert_eq!(escape_json_string(r#"hello"world"#), r#"hello\"world"#);
59 assert_eq!(escape_json_string("line1\nline2"), r#"line1\nline2"#);
60 assert_eq!(escape_json_string("tab\there"), r#"tab\there"#);
61 assert_eq!(escape_json_string(r#"back\slash"#), r#"back\\slash"#);
62 }
63
64 #[test]
65 fn test_generate_unique_id() {
66 let id1 = generate_unique_id("test_");
67 let id2 = generate_unique_id("test_");
68 let id3 = generate_unique_id("other_");
69
70 assert!(id1.starts_with("test_"));
71 assert!(id2.starts_with("test_"));
72 assert!(id3.starts_with("other_"));
73 assert_ne!(id1, id2); }
75
76 #[test]
77 fn test_extract_text_content() {
78 let msg = Message::user("Hello world");
79 assert_eq!(extract_text_content(&msg), "Hello world");
80 }
81
82 #[test]
83 fn test_extract_text_content_multiple() {
84 let msg = Message::with_content(
85 crate::client::models::Role::User,
86 vec![
87 Content::Text("First".to_string()),
88 Content::Text("Second".to_string()),
89 ],
90 );
91 assert_eq!(extract_text_content(&msg), "First\nSecond");
92 }
93}