mirror of
https://github.com/fabro-sh/fabro.git
synced 2026-09-06 08:18:58 +00:00
Add regression tests for Anthropic beta headers and Gemini thought_signature
Covers two recent runtime failures that lacked test coverage: - Anthropic: assert deprecated beta header values are not sent - Gemini: test function call parsing/translation with and without thoughtSignature Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
94326f5438
commit
e992b57ced
2 changed files with 103 additions and 0 deletions
|
|
@ -1881,6 +1881,33 @@ mod tests {
|
|||
assert_eq!(result["source"]["media_type"], "application/pdf");
|
||||
}
|
||||
|
||||
/// Regression test: deprecated beta header values must not be sent.
|
||||
/// The Anthropic API rejects requests containing these old headers.
|
||||
#[test]
|
||||
fn beta_header_rejects_deprecated_values() {
|
||||
let deprecated = [
|
||||
"extended-thinking-2025-04-14",
|
||||
"max-tokens-3-5-sonnet-2025-04-14",
|
||||
];
|
||||
|
||||
// No user headers — only cache header should appear
|
||||
let header = build_beta_header(None, true).unwrap_or_default();
|
||||
for dep in &deprecated {
|
||||
assert!(!header.contains(dep), "default header must not contain deprecated value {dep}");
|
||||
}
|
||||
|
||||
// With a valid user header
|
||||
let opts = serde_json::json!({
|
||||
"anthropic": {
|
||||
"beta_headers": ["interleaved-thinking-2025-05-14"]
|
||||
}
|
||||
});
|
||||
let header = build_beta_header(Some(&opts), true).unwrap_or_default();
|
||||
for dep in &deprecated {
|
||||
assert!(!header.contains(dep), "header with user values must not contain deprecated value {dep}");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn audio_produces_text_fallback() {
|
||||
let part = ContentPart::Audio(crate::types::AudioData {
|
||||
|
|
|
|||
|
|
@ -1259,6 +1259,82 @@ mod tests {
|
|||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_part_function_call() {
|
||||
let part = serde_json::json!({
|
||||
"functionCall": {
|
||||
"name": "get_weather",
|
||||
"args": {"location": "NYC"}
|
||||
}
|
||||
});
|
||||
let result = parse_part(&part).expect("should parse function call");
|
||||
match result {
|
||||
ContentPart::ToolCall(tc) => {
|
||||
assert_eq!(tc.name, "get_weather");
|
||||
assert_eq!(tc.arguments, serde_json::json!({"location": "NYC"}));
|
||||
assert!(tc.provider_metadata.is_none());
|
||||
}
|
||||
other => panic!("expected ToolCall, got {other:?}"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_part_function_call_with_thought_signature() {
|
||||
let part = serde_json::json!({
|
||||
"functionCall": {
|
||||
"name": "get_weather",
|
||||
"args": {"location": "NYC"}
|
||||
},
|
||||
"thoughtSignature": "abc123sig"
|
||||
});
|
||||
let result = parse_part(&part).expect("should parse function call with thought signature");
|
||||
match result {
|
||||
ContentPart::ToolCall(tc) => {
|
||||
assert_eq!(tc.name, "get_weather");
|
||||
let meta = tc.provider_metadata.expect("provider_metadata should be set");
|
||||
assert_eq!(meta["thoughtSignature"], "abc123sig");
|
||||
}
|
||||
other => panic!("expected ToolCall, got {other:?}"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn translate_messages_function_call_includes_thought_signature() {
|
||||
let mut tc = ToolCall::new("call-1", "get_weather", serde_json::json!({"location": "NYC"}));
|
||||
tc.provider_metadata = Some(serde_json::json!({"thoughtSignature": "sig456"}));
|
||||
|
||||
let msg = Message {
|
||||
role: Role::Assistant,
|
||||
content: vec![ContentPart::ToolCall(tc)],
|
||||
name: None,
|
||||
tool_call_id: None,
|
||||
};
|
||||
let contents = translate_messages(&[&msg]);
|
||||
assert_eq!(contents.len(), 1);
|
||||
|
||||
let part = &contents[0].parts[0];
|
||||
assert!(part.get("functionCall").is_some());
|
||||
assert_eq!(part["thoughtSignature"], "sig456");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn translate_messages_function_call_without_thought_signature() {
|
||||
let tc = ToolCall::new("call-1", "get_weather", serde_json::json!({"location": "NYC"}));
|
||||
|
||||
let msg = Message {
|
||||
role: Role::Assistant,
|
||||
content: vec![ContentPart::ToolCall(tc)],
|
||||
name: None,
|
||||
tool_call_id: None,
|
||||
};
|
||||
let contents = translate_messages(&[&msg]);
|
||||
assert_eq!(contents.len(), 1);
|
||||
|
||||
let part = &contents[0].parts[0];
|
||||
assert!(part.get("functionCall").is_some());
|
||||
assert!(part.get("thoughtSignature").is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_part_thought_false_is_regular_text() {
|
||||
let part = serde_json::json!({"text": "Regular text", "thought": false});
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue