From e31f2f4292557e34339c4bf99707b9621770c3c7 Mon Sep 17 00:00:00 2001 From: kbennett15 <75271761+kbennett15@users.noreply.github.com> Date: Wed, 19 Aug 2026 21:32:40 +0000 Subject: [PATCH] =?UTF-8?q?feat(aws=5Fbedrock):=20route=20OpenAI=20GPT-5.6?= =?UTF-8?q?=20(sol/terra/luna)=20via=20Bedrock=20=E2=80=A6=20(#10502)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: kbennett15 <75271761+kbennett15@users.noreply.github.com> --- crates/goose/src/providers/bedrock.rs | 67 +++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/crates/goose/src/providers/bedrock.rs b/crates/goose/src/providers/bedrock.rs index 12af8a4ba..931f416e3 100644 --- a/crates/goose/src/providers/bedrock.rs +++ b/crates/goose/src/providers/bedrock.rs @@ -48,6 +48,9 @@ pub const BEDROCK_KNOWN_MODELS: &[&str] = &[ "us.anthropic.claude-opus-4-1-20250805-v1:0", "openai.gpt-5.5", "openai.gpt-5.4", + "openai.gpt-5.6-sol", + "openai.gpt-5.6-terra", + "openai.gpt-5.6-luna", ]; pub const BEDROCK_DEFAULT_MAX_RETRIES: usize = 6; @@ -1212,6 +1215,70 @@ mod tests { assert_eq!(body["model"].as_str().unwrap(), "openai.gpt-5.5"); } + #[tokio::test] + async fn test_mantle_stream_returns_text_message_gpt_5_6() { + use futures::StreamExt; + use wiremock::matchers::{header, method, path}; + use wiremock::{Mock, MockServer, ResponseTemplate}; + + let server = MockServer::start().await; + + let sse_body = [ + r#"data: {"type":"response.output_text.delta","sequence_number":1,"item_id":"msg_1","output_index":0,"content_index":0,"delta":"Hello"}"#, + r#"data: {"type":"response.output_text.delta","sequence_number":2,"item_id":"msg_1","output_index":0,"content_index":0,"delta":" world"}"#, + "data: [DONE]", + ] + .join("\n"); + + Mock::given(method("POST")) + .and(path("/openai/v1/responses")) + .and(header("authorization", "Bearer test-token")) + .respond_with(ResponseTemplate::new(200).set_body_raw(sse_body, "text/event-stream")) + .mount(&server) + .await; + + let sdk_config = aws_config::SdkConfig::builder() + .behavior_version(aws_config::BehaviorVersion::latest()) + .region(aws_config::Region::new("us-east-1")) + .build(); + + let model = ModelConfig::new("openai.gpt-5.6-terra"); + let provider = BedrockProvider { + client: Client::new(&sdk_config), + retry_config: RetryConfig::default(), + name: "aws_bedrock".to_string(), + region: Some("us-east-1".to_string()), + bearer_token: Some("test-token".to_string()), + http_client: reqwest::Client::new(), + mantle_base_url: Some(format!("{}/openai/v1/responses", server.uri())), + }; + + let messages = vec![crate::conversation::message::Message::user().with_text("hi")]; + let mut stream = provider + .stream(&model.clone(), "", &messages, &[]) + .await + .unwrap(); + + let mut text = String::new(); + while let Some(item) = stream.next().await { + let (msg, _usage) = item.unwrap(); + if let Some(m) = msg { + for c in m.content { + if let MessageContent::Text(t) = c { + text.push_str(&t.text); + } + } + } + } + + assert_eq!(text, "Hello world"); + + let received = server.received_requests().await.unwrap(); + assert_eq!(received.len(), 1); + let body: serde_json::Value = serde_json::from_slice(&received[0].body).unwrap(); + assert_eq!(body["model"].as_str().unwrap(), "openai.gpt-5.6-terra"); + } + // ── ConverseStream event processing ────────────────────────────────── use crate::conversation::message::MessageContent;