Remove WebSocket transport from code-mode hosts (#40692)

## What changed

- Accept only `http://` and `https://` gRPC endpoints for app server
  `--code-mode-host` connections.
- Limit the standalone code-mode host to stdio and gRPC listeners.
- Remove the WebSocket session provider, dual-WebSocket negotiation, transport
  lanes, and related dependencies and tests.
- Keep coverage for shared and prewarmed gRPC hosts and reject WebSocket host
  URLs in CLI parsing tests.

GitOrigin-RevId: 8792604e79ffd54ce776074a4dc3f7d55e63752a
This commit is contained in:
Ruslan Nigmatullin
2026-08-25 20:37:15 +00:00
committed by copyberry
parent 9be8d6e1c3
commit 725b3a44f8
31 changed files with 153 additions and 2766 deletions
@@ -22,7 +22,6 @@ use super::ProtocolVersion;
use super::RequestId;
use super::SessionId;
use super::SupportedProtocolVersions;
use super::TransportLane;
use super::WireCellId;
use super::WireContentItem;
use super::WireExecuteRequest;
@@ -75,130 +74,6 @@ where
);
}
#[test]
fn dual_websocket_hello_preserves_the_pairing_token() {
assert_wire_round_trip(
HostToClient::HostHello(
HostHello::new(
ProtocolVersion::V1,
CapabilitySet::try_new([capability("dual-websocket-v1")])
.expect("valid capabilities"),
)
.with_bulk_connection_token("pairing-token".to_string()),
),
json!({
"type": "connection/ready",
"selectedVersion": 1,
"capabilities": ["dual-websocket-v1"],
"bulkConnectionToken": "pairing-token",
}),
);
}
#[test]
fn message_families_use_dedicated_transport_lanes() {
for (message, lane) in [
(
ClientToHost::CancelRequest {
id: request_id(/*value*/ 1),
},
TransportLane::Control,
),
(
ClientToHost::DelegateResponse {
id: delegate_request_id(/*value*/ 1),
result: WireResult::Ok {
value: DelegateResponse::NotificationDelivered,
},
},
TransportLane::Control,
),
(
ClientToHost::DelegateResponse {
id: delegate_request_id(/*value*/ 2),
result: WireResult::Ok {
value: DelegateResponse::ToolResult {
result: json!({ "value": "tool result" }),
},
},
},
TransportLane::Bulk,
),
(
ClientToHost::DelegateResponse {
id: delegate_request_id(/*value*/ 3),
result: WireResult::Err {
message: "delegate failed".to_string(),
},
},
TransportLane::Bulk,
),
] {
assert_eq!(message.transport_lane(), lane);
assert!(message.allows_transport_lane(lane));
assert!(!message.allows_transport_lane(match lane {
TransportLane::Control => TransportLane::Bulk,
TransportLane::Bulk => TransportLane::Control,
}));
}
for (message, lane) in [
(
HostToClient::Response {
id: request_id(/*value*/ 1),
result: WireResult::Err {
message: "x".repeat(128 * 1024),
},
},
TransportLane::Control,
),
(
HostToClient::DelegateRequest {
id: delegate_request_id(/*value*/ 1),
session_id: session_id(),
request: DelegateRequest::Notify {
call_id: "call-1".to_string(),
cell_id: cell_id("cell-1"),
text: "important".to_string(),
},
},
TransportLane::Control,
),
(
HostToClient::DelegateRequest {
id: delegate_request_id(/*value*/ 2),
session_id: session_id(),
request: DelegateRequest::InvokeTool {
invocation: WireNestedToolCall {
cell_id: cell_id("cell-1"),
runtime_tool_call_id: "runtime-call-1".to_string(),
tool_name: WireToolName {
name: "tool".to_string(),
namespace: None,
},
tool_kind: WireToolKind::Function,
input: None,
},
},
},
TransportLane::Bulk,
),
(
HostToClient::CancelDelegateRequest {
id: delegate_request_id(/*value*/ 1),
},
TransportLane::Bulk,
),
] {
assert_eq!(message.transport_lane(), lane);
assert!(message.allows_transport_lane(lane));
assert!(!message.allows_transport_lane(match lane {
TransportLane::Control => TransportLane::Bulk,
TransportLane::Bulk => TransportLane::Control,
}));
}
}
fn execute_request() -> WireExecuteRequest {
WireExecuteRequest {
tool_call_id: "call-1".to_string(),
@@ -12,7 +12,6 @@ use super::ProtocolVersion;
use super::RequestId;
use super::SessionId;
use super::SupportedProtocolVersions;
use super::TransportLane;
use super::WireCellId;
use super::WireExecuteRequest;
use super::WireNestedToolCall;
@@ -107,8 +106,6 @@ 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 {
@@ -116,15 +113,9 @@ 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
}
@@ -132,10 +123,6 @@ 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.
@@ -155,30 +142,6 @@ 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")]
@@ -212,33 +175,6 @@ 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 {
+1 -12
View File
@@ -1,8 +1,7 @@
//! Messages and framing for the code-mode host boundary.
//!
//! Protocol version 1 multiplexes session operations and delegate callbacks by
//! request ID over one ordered connection. WebSocket peers can negotiate a
//! separate bulk connection without changing the existing inner messages.
//! request ID over one ordered connection.
mod codec;
mod error;
@@ -13,19 +12,9 @@ mod types;
/// Maximum number of unresolved delegate callbacks allowed per host connection.
pub const MAX_PENDING_DELEGATE_CALLS: usize = 1_024;
/// Optional second WebSocket carrying delegate callbacks and their responses.
pub const DUAL_WEBSOCKET_CAPABILITY: &str = "dual-websocket-v1";
/// Negotiated support for cell execution resource limits on `session/open`.
pub const SESSION_RESOURCE_LIMITS_CAPABILITY: &str = "session-cell-execution-resource-limits";
/// Selects one socket of a negotiated dual-WebSocket connection.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum TransportLane {
Control,
Bulk,
}
pub use codec::EncodedFrame;
pub use codec::FramedReader;
pub use codec::FramedWriter;