Use websocket v2 as model-preferred websocket protocol (#12838)

This commit is contained in:
pakrym-oai 2026-02-25 16:35:53 -08:00 committed by GitHub
parent a1cd78c818
commit 4fedef88e0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 30 additions and 10 deletions

View file

@ -395,8 +395,8 @@ impl ModelClient {
/// This combines provider capability and feature gating; both must be true for websocket paths
/// to be eligible.
///
/// If websockets are only enabled via model preference (no explicit feature flag), default to
/// v1 behavior.
/// If websockets are only enabled via model preference (no explicit feature flag), prefer the
/// current v2 behavior.
pub fn active_ws_version(&self, model_info: &ModelInfo) -> Option<ResponsesWebsocketVersion> {
if !self.state.provider.supports_websockets
|| self.state.disable_websockets.load(Ordering::Relaxed)
@ -406,7 +406,7 @@ impl ModelClient {
match self.state.responses_websocket_version {
Some(version) => Some(version),
None if model_info.prefer_websockets => Some(ResponsesWebsocketVersion::V1),
None if model_info.prefer_websockets => Some(ResponsesWebsocketVersion::V2),
None => None,
}
}

View file

@ -300,7 +300,7 @@ async fn responses_websocket_request_prewarm_is_reused_even_with_header_changes(
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn responses_websocket_prewarm_uses_model_preference_when_feature_disabled() {
async fn responses_websocket_prewarm_uses_v2_when_model_prefers_websockets_and_feature_disabled() {
skip_if_no_network!();
let server = start_websocket_server(vec![vec![vec![
@ -324,20 +324,40 @@ async fn responses_websocket_prewarm_uses_model_preference_when_feature_disabled
.await
.expect("websocket prewarm failed");
// V1 prewarm only preconnects and should not issue a request.
// V2 prewarm issues a request on the websocket connection.
assert_eq!(server.handshakes().len(), 1);
assert_eq!(server.single_connection().len(), 0);
assert_eq!(server.single_connection().len(), 1);
let handshake = server.single_handshake();
let openai_beta_header = handshake
.header(OPENAI_BETA_HEADER)
.expect("missing OpenAI-Beta header");
assert!(
openai_beta_header
.split(',')
.map(str::trim)
.any(|value| value == WS_V2_BETA_HEADER_VALUE)
);
assert!(
!openai_beta_header
.split(',')
.map(str::trim)
.any(|value| value == OPENAI_BETA_RESPONSES_WEBSOCKETS)
);
stream_until_complete(&mut client_session, &harness, &prompt).await;
assert_eq!(server.handshakes().len(), 1);
let connection = server.single_connection();
assert_eq!(connection.len(), 1);
let turn = connection
let prewarm = connection
.first()
.expect("missing turn request")
.expect("missing prewarm request")
.body_json();
assert_eq!(turn["type"].as_str(), Some("response.create"));
assert_eq!(turn["input"], serde_json::to_value(&prompt.input).unwrap());
assert_eq!(prewarm["type"].as_str(), Some("response.create"));
assert_eq!(
prewarm["input"],
serde_json::to_value(&prompt.input).unwrap()
);
server.shutdown().await;
}