mirror of
https://github.com/openai/codex.git
synced 2026-10-30 19:18:49 +00:00
Add a dual-WebSocket transport for code mode (#36812)
## Why Large nested-tool callbacks can occupy a WebSocket and delay unrelated session operations on the same code-mode connection. ## What changed - Negotiate the optional `dual-websocket-v1` capability and pair a second, token-scoped WebSocket with the control connection. - Route nested-tool callbacks and their results over the bulk socket while keeping session operations, notifications, and execution responses on the control socket. Reject messages sent on the wrong lane. - Preserve the single-connection transport when the capability is unavailable, and bound pairing, queued callbacks, and deferred cross-socket messages. - Defer callbacks that arrive before their execution-started response, and return delegate errors without disconnecting the connection. ## Testing Add protocol, transport, driver, and WebSocket integration coverage for capability negotiation, lane routing, pairing failures, out-of-order messages, and progress during large concurrent tool results. GitOrigin-RevId: fa4504653e7cbf3c4ec930ae57aa0a41345bad66
This commit is contained in:
committed by
copyberry
parent
b258c028fe
commit
60c722e075
@@ -12,6 +12,7 @@ use super::ProtocolVersion;
|
||||
use super::RequestId;
|
||||
use super::SessionId;
|
||||
use super::SupportedProtocolVersions;
|
||||
use super::TransportLane;
|
||||
use super::WireCellId;
|
||||
use super::WireExecuteRequest;
|
||||
use super::WireNestedToolCall;
|
||||
@@ -105,6 +106,8 @@ impl std::error::Error for ClientHelloError {}
|
||||
pub struct HostHello {
|
||||
selected_version: ProtocolVersion,
|
||||
capabilities: CapabilitySet,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
bulk_connection_token: Option<String>,
|
||||
}
|
||||
|
||||
impl HostHello {
|
||||
@@ -112,9 +115,15 @@ impl HostHello {
|
||||
Self {
|
||||
selected_version,
|
||||
capabilities,
|
||||
bulk_connection_token: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_bulk_connection_token(mut self, token: String) -> Self {
|
||||
self.bulk_connection_token = Some(token);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn selected_version(&self) -> ProtocolVersion {
|
||||
self.selected_version
|
||||
}
|
||||
@@ -122,6 +131,10 @@ impl HostHello {
|
||||
pub fn capabilities(&self) -> &CapabilitySet {
|
||||
&self.capabilities
|
||||
}
|
||||
|
||||
pub fn bulk_connection_token(&self) -> Option<&str> {
|
||||
self.bulk_connection_token.as_deref()
|
||||
}
|
||||
}
|
||||
|
||||
/// Messages sent from a client to the code-mode host.
|
||||
@@ -141,6 +154,30 @@ pub enum ClientToHost {
|
||||
},
|
||||
}
|
||||
|
||||
impl ClientToHost {
|
||||
/// Keeps notification acknowledgments with control traffic and tool results on the bulk lane.
|
||||
pub fn transport_lane(&self) -> TransportLane {
|
||||
match self {
|
||||
Self::DelegateResponse {
|
||||
result:
|
||||
WireResult::Ok {
|
||||
value: DelegateResponse::NotificationDelivered,
|
||||
},
|
||||
..
|
||||
}
|
||||
| Self::ClientHello(_)
|
||||
| Self::Request { .. }
|
||||
| Self::CancelRequest { .. } => TransportLane::Control,
|
||||
Self::DelegateResponse { .. } => TransportLane::Bulk,
|
||||
}
|
||||
}
|
||||
|
||||
/// Validates the message families accepted by each paired socket.
|
||||
pub fn allows_transport_lane(&self, lane: TransportLane) -> bool {
|
||||
self.transport_lane() == lane
|
||||
}
|
||||
}
|
||||
|
||||
/// Messages sent from the code-mode host to a client.
|
||||
#[derive(Debug, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(deny_unknown_fields, tag = "type", rename_all_fields = "camelCase")]
|
||||
@@ -174,6 +211,33 @@ pub enum HostToClient {
|
||||
},
|
||||
}
|
||||
|
||||
impl HostToClient {
|
||||
/// Keeps notifications with control traffic and nested-tool callbacks on the bulk lane.
|
||||
pub fn transport_lane(&self) -> TransportLane {
|
||||
match self {
|
||||
Self::DelegateRequest {
|
||||
request: DelegateRequest::InvokeTool { .. },
|
||||
..
|
||||
}
|
||||
| Self::CancelDelegateRequest { .. } => TransportLane::Bulk,
|
||||
Self::DelegateRequest {
|
||||
request: DelegateRequest::Notify { .. },
|
||||
..
|
||||
}
|
||||
| Self::HostHello(_)
|
||||
| Self::HandshakeRejected { .. }
|
||||
| Self::Response { .. }
|
||||
| Self::InitialResponse { .. }
|
||||
| Self::CellClosed { .. } => TransportLane::Control,
|
||||
}
|
||||
}
|
||||
|
||||
/// Rejects messages received on the wrong paired socket.
|
||||
pub fn allows_transport_lane(&self, lane: TransportLane) -> bool {
|
||||
self.transport_lane() == lane
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(deny_unknown_fields, tag = "method", rename_all_fields = "camelCase")]
|
||||
pub enum HostRequest {
|
||||
|
||||
Reference in New Issue
Block a user