mirror of
https://github.com/openai/codex.git
synced 2026-10-21 17:48:44 +00:00
## What changed - Add `CodeModeCellTiming` notifications for yielded executions, terminal waits, and unavailable cells, with thread, call, and cell identifiers. - Measure how long completed results remain buffered before retrieval and carry `result_buffered_for` through the runtime, stdio protocol, and gRPC response metadata. Immediate delivery reports zero; waits without a completed result report no buffering measurement. - Default missing buffering data to zero for compatibility with older hosts. ## Testing Extend runtime tests to verify buffering duration with a paused clock and retrieval through termination. Add gRPC conversion tests for nanosecond precision, optional metadata, and the distinction between immediate delivery and no completed result. GitOrigin-RevId: 60c0c5a3affa69ac3779bf1812fca50f5748af76
100 lines
3.2 KiB
Rust
100 lines
3.2 KiB
Rust
use std::sync::Arc;
|
|
use std::time::Duration;
|
|
use std::time::Instant;
|
|
|
|
use codex_code_mode_protocol::CellId;
|
|
use codex_code_mode_protocol::RuntimeResponse;
|
|
use codex_code_mode_protocol::StartedCell;
|
|
use codex_code_mode_protocol::host::DelegateRequest;
|
|
use codex_code_mode_protocol::host::RequestId;
|
|
use codex_code_mode_protocol::host::SessionId;
|
|
use pretty_assertions::assert_eq;
|
|
use tokio::sync::Semaphore;
|
|
use tokio::sync::mpsc;
|
|
use tokio::sync::oneshot;
|
|
use tokio::sync::oneshot::error::TryRecvError;
|
|
use tokio_util::sync::CancellationToken;
|
|
|
|
use super::HostPeer;
|
|
use super::MAX_PENDING_DELEGATE_CALLS;
|
|
|
|
fn session_id(value: &str) -> SessionId {
|
|
SessionId::new(value).expect("session ID")
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn start_cell_reports_when_initial_response_is_enqueued() {
|
|
let (outgoing_tx, mut outgoing_rx) = mpsc::channel(/*max_capacity*/ 4);
|
|
let peer = Arc::new(HostPeer::new(outgoing_tx));
|
|
let cell_id = CellId::new("cell-1".to_string());
|
|
let (response_tx, response_rx) = oneshot::channel();
|
|
let started = StartedCell::new(cell_id.clone(), response_rx);
|
|
let active_cell_permits = Arc::new(Semaphore::new(/*permits*/ 1));
|
|
let active_cell_permit = Arc::clone(&active_cell_permits)
|
|
.try_acquire_owned()
|
|
.expect("active cell permit");
|
|
|
|
let mut initial_response_sent = peer.start_cell(
|
|
session_id("session-1"),
|
|
RequestId::new(/*value*/ 1),
|
|
started,
|
|
active_cell_permit,
|
|
Instant::now(),
|
|
);
|
|
assert_eq!(initial_response_sent.try_recv(), Err(TryRecvError::Empty));
|
|
|
|
response_tx
|
|
.send(RuntimeResponse::Result {
|
|
code_mode_host_duration: None,
|
|
cell_id: cell_id.clone(),
|
|
content_items: Vec::new(),
|
|
result_buffered_for: Duration::ZERO,
|
|
error_text: None,
|
|
})
|
|
.expect("initial response receiver");
|
|
initial_response_sent
|
|
.await
|
|
.expect("initial response completion");
|
|
outgoing_rx.recv().await.expect("initial response frame");
|
|
assert_eq!(active_cell_permits.available_permits(), 0);
|
|
|
|
peer.close_cell(session_id("session-1"), cell_id);
|
|
let permit = tokio::time::timeout(
|
|
Duration::from_secs(1),
|
|
Arc::clone(&active_cell_permits).acquire_owned(),
|
|
)
|
|
.await
|
|
.expect("cell permit should be released")
|
|
.expect("cell permit semaphore should remain open");
|
|
drop(permit);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn pending_delegate_limit_rejects_call_without_disconnecting() {
|
|
let (outgoing_tx, _outgoing_rx) = mpsc::channel(/*max_capacity*/ 1);
|
|
let peer = Arc::new(HostPeer::new(outgoing_tx));
|
|
let permits = Arc::clone(&peer.delegate_permits)
|
|
.acquire_many_owned(MAX_PENDING_DELEGATE_CALLS as u32)
|
|
.await
|
|
.expect("delegate permits");
|
|
|
|
let result = peer
|
|
.call(
|
|
session_id("session-1"),
|
|
DelegateRequest::Notify {
|
|
call_id: "call-1".to_string(),
|
|
cell_id: CellId::new("cell-1".to_string()).into(),
|
|
text: "hello".to_string(),
|
|
},
|
|
CancellationToken::new(),
|
|
)
|
|
.await;
|
|
|
|
assert_eq!(
|
|
result,
|
|
Err("code-mode host has too many pending delegate calls".to_string())
|
|
);
|
|
assert!(!peer.is_disconnected());
|
|
drop(permits);
|
|
}
|