mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
[codex] extend code-mode host IPC transport (#30108)
## Summary - add an `EncodedFrame` type so IPC payloads are serialized and size-checked before entering bounded queues - add the V1 `operation/cancel` client-to-host message - pin the new wire shape with protocol tests ## Why The process-owned code-mode host needs bounded, pre-encoded outbound messages and a best-effort cancellation signal. Keeping these wire primitives in a protocol-only change lets their compatibility contract be reviewed independently from either endpoint. ## Stack This is **1 of 4** in the process-owned code-mode session stack. The next PR targets this branch. ## Validation - `just test -p codex-code-mode-protocol` — 22 passed - `just fix -p codex-code-mode-protocol` - `just fmt`
This commit is contained in:
committed by
GitHub
Unverified
parent
adccb464d0
commit
3b78f58fb2
@@ -11,6 +11,36 @@ use tokio::io::AsyncWriteExt;
|
||||
/// Maximum JSON payload size accepted for one IPC frame.
|
||||
pub const MAX_FRAME_BYTES: usize = 64 * 1024 * 1024;
|
||||
|
||||
/// A serialized IPC frame that has already passed the payload size limit.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct EncodedFrame {
|
||||
payload: Vec<u8>,
|
||||
}
|
||||
|
||||
impl EncodedFrame {
|
||||
pub fn encode<T>(message: &T) -> io::Result<Self>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
let payload = serde_json::to_vec(message).map_err(|err| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
format!("failed to encode code-mode IPC frame: {err}"),
|
||||
)
|
||||
})?;
|
||||
if payload.len() > MAX_FRAME_BYTES {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
format!(
|
||||
"code-mode IPC frame length {} exceeds {MAX_FRAME_BYTES} bytes",
|
||||
payload.len()
|
||||
),
|
||||
));
|
||||
}
|
||||
Ok(Self { payload })
|
||||
}
|
||||
}
|
||||
|
||||
/// Decodes JSON messages prefixed by a four-byte little-endian payload length.
|
||||
pub struct FramedReader<R> {
|
||||
reader: R,
|
||||
@@ -72,22 +102,12 @@ where
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
let payload = serde_json::to_vec(message).map_err(|err| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
format!("failed to encode code-mode IPC frame: {err}"),
|
||||
)
|
||||
})?;
|
||||
if payload.len() > MAX_FRAME_BYTES {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
format!(
|
||||
"code-mode IPC frame length {} exceeds {MAX_FRAME_BYTES} bytes",
|
||||
payload.len()
|
||||
),
|
||||
));
|
||||
}
|
||||
let length = u32::try_from(payload.len()).map_err(|_| {
|
||||
self.write_frame(&EncodedFrame::encode(message)?).await
|
||||
}
|
||||
|
||||
/// Writes and flushes a frame encoded before it entered an I/O queue.
|
||||
pub async fn write_frame(&mut self, frame: &EncodedFrame) -> io::Result<()> {
|
||||
let length = u32::try_from(frame.payload.len()).map_err(|_| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
"code-mode IPC frame length exceeds u32",
|
||||
@@ -95,7 +115,7 @@ where
|
||||
})?;
|
||||
|
||||
self.writer.write_all(&length.to_le_bytes()).await?;
|
||||
self.writer.write_all(&payload).await?;
|
||||
self.writer.write_all(&frame.payload).await?;
|
||||
self.writer.flush().await
|
||||
}
|
||||
}
|
||||
|
||||
@@ -365,6 +365,16 @@ fn client_to_host_v1_variants_are_pinned() {
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
assert_wire_round_trip(
|
||||
ClientToHost::CancelRequest {
|
||||
id: request_id(/*value*/ 9),
|
||||
},
|
||||
json!({
|
||||
"type": "operation/cancel",
|
||||
"id": 9,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -132,6 +132,8 @@ pub enum ClientToHost {
|
||||
ClientHello(ClientHello),
|
||||
#[serde(rename = "operation/request")]
|
||||
Request { id: RequestId, request: HostRequest },
|
||||
#[serde(rename = "operation/cancel")]
|
||||
CancelRequest { id: RequestId },
|
||||
#[serde(rename = "delegate/response")]
|
||||
DelegateResponse {
|
||||
id: DelegateRequestId,
|
||||
|
||||
@@ -11,6 +11,7 @@ mod message;
|
||||
mod payload;
|
||||
mod types;
|
||||
|
||||
pub use codec::EncodedFrame;
|
||||
pub use codec::FramedReader;
|
||||
pub use codec::FramedWriter;
|
||||
pub use codec::MAX_FRAME_BYTES;
|
||||
|
||||
Reference in New Issue
Block a user