mirror of
https://github.com/openai/codex.git
synced 2026-04-29 00:55:38 +00:00
Compare full request for websockets incrementality (#11343)
Tools can dynamically change mid-turn now. We need to be more thorough about reusing incremental connections.
This commit is contained in:
@@ -22,6 +22,7 @@ use codex_otel::metrics::MetricsConfig;
|
||||
use codex_protocol::ThreadId;
|
||||
use codex_protocol::account::PlanType;
|
||||
use codex_protocol::config_types::ReasoningSummary;
|
||||
use codex_protocol::models::BaseInstructions;
|
||||
use codex_protocol::openai_models::ModelInfo;
|
||||
use codex_protocol::openai_models::ReasoningEffort as ReasoningEffortConfig;
|
||||
use codex_protocol::user_input::UserInput;
|
||||
@@ -603,6 +604,42 @@ async fn responses_websocket_creates_on_non_prefix() {
|
||||
server.shutdown().await;
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn responses_websocket_creates_when_non_input_request_fields_change() {
|
||||
skip_if_no_network!();
|
||||
|
||||
let server = start_websocket_server(vec![vec![
|
||||
vec![ev_response_created("resp-1"), ev_completed("resp-1")],
|
||||
vec![ev_response_created("resp-2"), ev_completed("resp-2")],
|
||||
]])
|
||||
.await;
|
||||
|
||||
let harness = websocket_harness(&server).await;
|
||||
let mut client_session = harness.client.new_session();
|
||||
let prompt_one =
|
||||
prompt_with_input_and_instructions(vec![message_item("hello")], "base instructions one");
|
||||
let prompt_two = prompt_with_input_and_instructions(
|
||||
vec![message_item("hello"), message_item("second")],
|
||||
"base instructions two",
|
||||
);
|
||||
|
||||
stream_until_complete(&mut client_session, &harness, &prompt_one).await;
|
||||
stream_until_complete(&mut client_session, &harness, &prompt_two).await;
|
||||
|
||||
let connection = server.single_connection();
|
||||
assert_eq!(connection.len(), 2);
|
||||
let second = connection.get(1).expect("missing request").body_json();
|
||||
|
||||
assert_eq!(second["type"].as_str(), Some("response.create"));
|
||||
assert_eq!(second.get("previous_response_id"), None);
|
||||
assert_eq!(
|
||||
second["input"],
|
||||
serde_json::to_value(&prompt_two.input).expect("serialize full input")
|
||||
);
|
||||
|
||||
server.shutdown().await;
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn responses_websocket_v2_creates_with_previous_response_id_on_prefix() {
|
||||
skip_if_no_network!();
|
||||
@@ -637,6 +674,43 @@ async fn responses_websocket_v2_creates_with_previous_response_id_on_prefix() {
|
||||
server.shutdown().await;
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn responses_websocket_v2_creates_without_previous_response_id_when_non_input_fields_change()
|
||||
{
|
||||
skip_if_no_network!();
|
||||
|
||||
let server = start_websocket_server(vec![vec![
|
||||
vec![ev_response_created("resp-1"), ev_completed("resp-1")],
|
||||
vec![ev_response_created("resp-2"), ev_completed("resp-2")],
|
||||
]])
|
||||
.await;
|
||||
|
||||
let harness = websocket_harness_with_v2(&server, true).await;
|
||||
let mut session = harness.client.new_session();
|
||||
let prompt_one =
|
||||
prompt_with_input_and_instructions(vec![message_item("hello")], "base instructions one");
|
||||
let prompt_two = prompt_with_input_and_instructions(
|
||||
vec![message_item("hello"), message_item("second")],
|
||||
"base instructions two",
|
||||
);
|
||||
|
||||
stream_until_complete(&mut session, &harness, &prompt_one).await;
|
||||
stream_until_complete(&mut session, &harness, &prompt_two).await;
|
||||
|
||||
let connection = server.single_connection();
|
||||
assert_eq!(connection.len(), 2);
|
||||
let second = connection.get(1).expect("missing request").body_json();
|
||||
|
||||
assert_eq!(second["type"].as_str(), Some("response.create"));
|
||||
assert_eq!(second.get("previous_response_id"), None);
|
||||
assert_eq!(
|
||||
second["input"],
|
||||
serde_json::to_value(&prompt_two.input).expect("serialize full input")
|
||||
);
|
||||
|
||||
server.shutdown().await;
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn responses_websocket_v2_after_error_uses_full_create_without_previous_response_id() {
|
||||
skip_if_no_network!();
|
||||
@@ -778,6 +852,14 @@ fn prompt_with_input(input: Vec<ResponseItem>) -> Prompt {
|
||||
prompt
|
||||
}
|
||||
|
||||
fn prompt_with_input_and_instructions(input: Vec<ResponseItem>, instructions: &str) -> Prompt {
|
||||
let mut prompt = prompt_with_input(input);
|
||||
prompt.base_instructions = BaseInstructions {
|
||||
text: instructions.to_string(),
|
||||
};
|
||||
prompt
|
||||
}
|
||||
|
||||
fn websocket_provider(server: &WebSocketTestServer) -> ModelProviderInfo {
|
||||
ModelProviderInfo {
|
||||
name: "mock-ws".into(),
|
||||
|
||||
Reference in New Issue
Block a user