From 01e21c7f913eaf7dffc3d6a31501418ff2104c8b Mon Sep 17 00:00:00 2001 From: Ruben Fiszel Date: Tue, 12 May 2026 07:00:58 +0000 Subject: [PATCH] fix: preserve negative integers in Bedrock tool schema conversion (#9116) json_to_document cast any i64 to u64 via `as` and wrapped in PosInt. Negative integers in a tool's JSON schema (e.g. "default": -1, "minimum": -1) became huge unsigned values like 18446744073709551615, which Bedrock rejected with `tools.N.custom.input_schema: int too big to convert`. Try as_u64 first to preserve full u64 range, fall back to as_i64 for negatives via NegInt, then as_f64. Co-authored-by: Claude Opus 4.7 (1M context) --- backend/windmill-ai/src/ai_bedrock.rs | 36 +++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/backend/windmill-ai/src/ai_bedrock.rs b/backend/windmill-ai/src/ai_bedrock.rs index 49166978e8..c05094b8f4 100644 --- a/backend/windmill-ai/src/ai_bedrock.rs +++ b/backend/windmill-ai/src/ai_bedrock.rs @@ -326,8 +326,10 @@ pub fn json_to_document(value: serde_json::Value) -> aws_smithy_types::Document } Value::Array(arr) => Document::Array(arr.into_iter().map(json_to_document).collect()), Value::Number(num) => { - if let Some(i) = num.as_i64() { - Document::Number(aws_smithy_types::Number::PosInt(i as u64)) + if let Some(u) = num.as_u64() { + Document::Number(aws_smithy_types::Number::PosInt(u)) + } else if let Some(i) = num.as_i64() { + Document::Number(aws_smithy_types::Number::NegInt(i)) } else if let Some(f) = num.as_f64() { Document::Number(aws_smithy_types::Number::Float(f)) } else { @@ -844,6 +846,36 @@ mod tests { } } + #[test] + fn json_to_document_preserves_negative_integers() { + let value = serde_json::json!(-1); + let doc = json_to_document(value); + assert!(matches!( + doc, + aws_smithy_types::Document::Number(aws_smithy_types::Number::NegInt(-1)) + )); + } + + #[test] + fn json_to_document_handles_large_u64_above_i64_max() { + let value = serde_json::json!(u64::MAX); + let doc = json_to_document(value); + assert!(matches!( + doc, + aws_smithy_types::Document::Number(aws_smithy_types::Number::PosInt(u)) if u == u64::MAX + )); + } + + #[test] + fn json_to_document_handles_positive_integers() { + let value = serde_json::json!(42); + let doc = json_to_document(value); + assert!(matches!( + doc, + aws_smithy_types::Document::Number(aws_smithy_types::Number::PosInt(42)) + )); + } + #[test] fn openai_messages_to_bedrock_adds_cache_points_when_enabled() { let messages = vec![