Add gRPC-backed code-mode sessions (#38041)

## What changed

- Add `GrpcCodeModeSessionProvider` for opening code-mode sessions over HTTP/2 or an existing `tonic` channel.
- Support execution, waiting, termination, per-session limits, cell-closure callbacks, and graceful shutdown over the gRPC protocol.
- Bound transport waits and error messages, validate host identifiers and responses, and clean up abandoned executions and observers.

## Testing

- Add end-to-end TCP tests covering session persistence, cancellation, concurrent waits, shutdown, cell cleanup, and independent yield limits.
- Add unit coverage for protocol conversion, deadlines, and session lifecycle state.

GitOrigin-RevId: d4729ce608ad4b42a99744b07e1f230e46cb24ec
This commit is contained in:
Channing Conger
2026-08-11 17:31:11 +00:00
committed by copyberry
parent b2543af02b
commit 1e557a554e
20 changed files with 2275 additions and 17 deletions
@@ -18,6 +18,7 @@ use tonic::Request;
use tonic::Status;
use uuid::Uuid;
use super::ExecutionAdmission;
use super::GrpcCodeModeHost;
use super::tests::execute_events;
use super::tests::execute_request;
@@ -125,6 +126,31 @@ async fn rejects_oversized_identifiers_tool_metadata_and_subscription_filters()
assert!(host.state.session(&session_id).is_ok());
}
#[tokio::test]
async fn dropping_execution_before_admission_releases_its_reservation() {
let host = GrpcCodeModeHost::new();
let (session_id, _events) = open_session(&host).await;
let session = host.state.session(&session_id).expect("open session");
let execution_id = "execution-abandoned-before-admission".to_string();
session
.reserve_execution(&execution_id)
.expect("reserve execution");
drop(ExecutionAdmission {
session: Arc::clone(&session),
execution_id: Some(execution_id.clone()),
});
let error = session
.admit_execution(
execution_id,
"cell".to_string(),
host.state.cell_permit().expect("reserve cell permit"),
)
.expect_err("abandoned execution must not admit a runtime cell");
assert_eq!(error.code(), Code::Cancelled);
}
#[tokio::test]
async fn dropping_an_unread_buffered_execution_outcome_retires_its_cell() {
let host = GrpcCodeModeHost::new();
@@ -2,7 +2,7 @@ use codex_code_mode_protocol::grpc as proto;
use tonic::Status;
use uuid::Uuid;
pub(super) const MAX_IDENTIFIER_BYTES: usize = 256;
pub(super) use codex_code_mode_protocol::grpc::MAX_IDENTIFIER_BYTES;
pub(super) const MAX_TOOL_FILTERS: usize = 64;
pub(super) const MAX_TOOL_DEFINITIONS: usize = 1_024;
pub(super) const MAX_TOOL_DESCRIPTION_BYTES: usize = 16 * 1_024;