fix: add strict:false to Responses API tools and gpt-5.4 to known models (#8636)

Signed-off-by: Bradley Axen <baxen@squareup.com>
This commit is contained in:
Bradley Axen
2026-04-21 15:32:24 -07:00
committed by GitHub
parent 7325fbdae3
commit ab0c40d26a
11 changed files with 474 additions and 130 deletions
+18 -11
View File
@@ -422,10 +422,12 @@ pub async fn run_load_mode<C: Connection>() {
}
pub async fn run_load_model<C: Connection>() {
// Use a Chat Completions model so the canned SSE fixtures parse correctly.
// TODO: add a Responses API mock to OpenAiFixture for responses-routed models.
let expected_session_id = C::expected_session_id();
let openai = OpenAiFixture::new(
vec![(
r#""model":"o4-mini""#.into(),
r#""model":"gpt-4.1""#.into(),
include_str!("../acp_test_data/openai_basic.txt"),
)],
expected_session_id.clone(),
@@ -437,7 +439,7 @@ pub async fn run_load_model<C: Connection>() {
expected_session_id.set(&session.session_id().0);
let session_id = session.session_id().0.to_string();
conn.set_model(&session_id, "o4-mini").await.unwrap();
conn.set_model(&session_id, "gpt-4.1").await.unwrap();
let output = session
.prompt("what is 1+1", PermissionDecision::Cancel)
@@ -446,7 +448,7 @@ pub async fn run_load_model<C: Connection>() {
assert_eq!(output.text, "2");
let SessionData { models, .. } = conn.load_session(&session_id, vec![]).await.unwrap();
assert_eq!(&*models.unwrap().current_model_id.0, "o4-mini");
assert_eq!(&*models.unwrap().current_model_id.0, "gpt-4.1");
}
pub async fn run_load_session_mcp<C: Connection>() {
@@ -773,12 +775,14 @@ enum SetModelVia {
}
async fn run_model_set_impl<C: Connection>(via: SetModelVia) {
// Use a Chat Completions model so the canned SSE fixtures parse correctly.
// TODO: add a Responses API mock to OpenAiFixture for responses-routed models.
let expected_session_id = C::expected_session_id();
let openai = OpenAiFixture::new(
vec![
// Session B prompt with switched model
(
r#""model":"o4-mini""#.into(),
r#""model":"gpt-4.1""#.into(),
include_str!("../acp_test_data/openai_basic.txt"),
),
// Session A prompt with default model
@@ -803,23 +807,23 @@ async fn run_model_set_impl<C: Connection>(via: SetModelVia) {
..
} = conn.new_session().await.unwrap();
// Session B: switch to o4-mini
// Session B: switch to gpt-4.1
let SessionData {
session: mut session_b,
..
} = conn.new_session().await.unwrap();
let session_id = &session_b.session_id().0;
match via {
SetModelVia::Dedicated => conn.set_model(session_id, "o4-mini").await.unwrap(),
SetModelVia::Dedicated => conn.set_model(session_id, "gpt-4.1").await.unwrap(),
SetModelVia::ConfigOption => conn
.set_config_option(session_id, "model", "o4-mini")
.set_config_option(session_id, "model", "gpt-4.1")
.await
.unwrap(),
}
let set_model_notifs = session_b.notifications();
// Prompt B — expects o4-mini
// Prompt B — expects gpt-4.1
expected_session_id.set(&session_b.session_id().0);
let output = session_b
.prompt("what is 1+1", PermissionDecision::Cancel)
@@ -1152,13 +1156,16 @@ pub async fn run_prompt_mcp<C: Connection>() {
}
pub async fn run_prompt_model_mismatch<C: Connection>() {
// Start the connection where the current model is not desired.
// Start the connection where the current model differs from TEST_MODEL.
// Use a Chat Completions model so the canned SSE fixtures parse correctly.
// TODO: add a Responses API mock to OpenAiFixture so we can test with
// responses-routed models like o4-mini here.
let config = TestConnectionConfig {
current_model: "o4-mini".to_string(),
current_model: "gpt-4.1".to_string(),
..Default::default()
};
// Server starts on o4-mini; client is configured with TEST_MODEL.
// Server starts on gpt-4.1; client is configured with TEST_MODEL.
// If session_model is seeded from the response, stream() detects the
// mismatch and sends set_model(TEST_MODEL) before prompting.
let BasicSession { conn: _, .. } = new_basic_session::<C>(config).await;
@@ -250,6 +250,9 @@ fn test_developer_fs_requests_use_acp_session_id() {
)
.await;
let config = TestConnectionConfig {
// gpt-5-nano routes to the Responses API; use a Chat Completions
// model so the canned SSE fixtures are parsed correctly.
current_model: "gpt-4.1".to_string(),
read_text_file: Some(Arc::new(move |req| {
*seen_session_id_clone.lock().unwrap() = Some(req.session_id.0.to_string());
Ok(sacp::schema::ReadTextFileResponse::new(
@@ -48,12 +48,13 @@ fn create_test_provider(mock_server_url: &str) -> Box<dyn Provider> {
async fn setup_mock_server() -> (MockServer, HeaderCapture, Box<dyn Provider>) {
let mock_server = MockServer::start().await;
let capture = HeaderCapture::new();
let capture_clone = capture.clone();
let chat_capture = capture.clone();
let responses_capture = capture.clone();
Mock::given(method("POST"))
.and(path("/v1/chat/completions"))
.respond_with(move |req: &Request| {
capture_clone.capture_session_header(req);
chat_capture.capture_session_header(req);
// Return SSE streaming format
let sse_response = format!(
"data: {}\n\ndata: {}\n\ndata: [DONE]\n\n",
@@ -85,6 +86,57 @@ async fn setup_mock_server() -> (MockServer, HeaderCapture, Box<dyn Provider>) {
.mount(&mock_server)
.await;
Mock::given(method("POST"))
.and(path("/v1/responses"))
.respond_with(move |req: &Request| {
responses_capture.capture_session_header(req);
let sse_response = format!(
"data: {}\n\ndata: {}\n\ndata: {}\n\ndata: [DONE]\n\n",
json!({
"type": "response.created",
"sequence_number": 1,
"response": {
"id": "resp_test",
"object": "response",
"created_at": 1755133833,
"status": "in_progress",
"model": "gpt-5-nano",
"output": []
}
}),
json!({
"type": "response.output_text.delta",
"sequence_number": 2,
"item_id": "msg_test",
"output_index": 0,
"content_index": 0,
"delta": "Hi there! How can I help you today?"
}),
json!({
"type": "response.completed",
"sequence_number": 3,
"response": {
"id": "resp_test",
"object": "response",
"created_at": 1755133833,
"status": "completed",
"model": "gpt-5-nano",
"output": [],
"usage": {
"input_tokens": 8,
"output_tokens": 10,
"total_tokens": 18
}
}
})
);
ResponseTemplate::new(200)
.set_body_string(sse_response)
.insert_header("content-type", "text/event-stream")
})
.mount(&mock_server)
.await;
let provider = create_test_provider(&mock_server.uri());
(mock_server, capture, provider)
}