use serde_json::{json, Value};
#[test]
fn test_filter_thinking_blocks() {
let messages = json!([
{"role": "user", "content": "你好"},
{"role": "assistant", "content": [
{"type": "thinking", "thinking": "让我思考...", "signature": "abc123"},
{"type": "text", "text": "你好!"}
]},
{"role": "user", "content": "继续"}
]);
let expected = json!([
{"role": "user", "content": [{"type": "text", "text": "你好"}]},
{"role": "assistant", "content": [{"type": "text", "text": "你好!"}]},
{"role": "user", "content": [{"type": "text", "text": "继续"}]}
]);
let filtered = filter_thinking_from_messages(&messages, true);
assert_eq!(filtered, expected);
}
#[test]
fn test_keep_thinking_blocks_for_official_api() {
let messages = json!([
{"role": "assistant", "content": [
{"type": "thinking", "thinking": "思考内容", "signature": "sig"},
{"type": "text", "text": "回复"}
]}
]);
let filtered = filter_thinking_from_messages(&messages, false);
assert!(filtered[0]["content"].as_array().unwrap().len() == 2);
}
#[test]
fn test_empty_signature_handling() {
let thinking_block = json!({
"type": "thinking",
"thinking": "思考内容",
"signature": ""
});
let sig = thinking_block["signature"].as_str().unwrap_or("");
assert!(sig.is_empty());
let obj = build_thinking_object("思考内容", "");
assert!(obj.get("signature").is_none() || obj["signature"].as_str().unwrap().is_empty());
}
#[test]
fn test_sse_thinking_delta_parsing() {
let sse_event = json!({
"type": "content_block_delta",
"index": 0,
"delta": {
"type": "thinking_delta",
"thinking": "思考片段"
}
});
assert_eq!(sse_event["delta"]["type"], "thinking_delta");
assert_eq!(sse_event["delta"]["thinking"], "思考片段");
}
#[test]
fn test_content_block_start_thinking() {
let event = json!({
"type": "content_block_start",
"index": 0,
"content_block": {
"type": "thinking",
"signature": "",
"thinking": ""
}
});
assert_eq!(event["content_block"]["type"], "thinking");
assert!(event["content_block"]["signature"].as_str().unwrap().is_empty());
}
fn filter_thinking_from_messages(messages: &Value, filter_thinking: bool) -> Value {
messages
.as_array()
.unwrap()
.iter()
.map(|msg| {
let role = msg["role"].as_str().unwrap();
let content = if let Some(blocks) = msg["content"].as_array() {
let filtered_blocks: Vec<Value> = blocks
.iter()
.filter(|b| {
if filter_thinking && b["type"].as_str() == Some("thinking") {
return false;
}
true
})
.map(|b| {
if b["type"].as_str() == Some("text") {
json!({"type": "text", "text": b["text"].as_str().unwrap_or("")})
} else if b["type"].as_str() == Some("thinking") {
build_thinking_object(
b["thinking"].as_str().unwrap_or(""),
b["signature"].as_str().unwrap_or("")
)
} else {
b.clone()
}
})
.collect();
json!(filtered_blocks)
} else if let Some(text) = msg["content"].as_str() {
json!([{"type": "text", "text": text}])
} else {
msg["content"].clone()
};
json!({"role": role, "content": content})
})
.collect::<Vec<_>>()
.into()
}
fn build_thinking_object(thinking: &str, signature: &str) -> Value {
let mut obj = json!({"type": "thinking", "thinking": thinking});
if !signature.is_empty() {
obj["signature"] = json!(signature);
}
obj
}