mirror of
https://github.com/openai/codex.git
synced 2026-04-28 10:21:06 +03:00
4.3 KiB
4.3 KiB
DOs
- Disable Flaky Tests Properly: Use
#[ignore]with a clear reason and keep doc comments truthful.
/// Verifies the agent retries when SSE ends before `response.completed`.
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
#[ignore] // flaky: race condition; tracked in GH-1234
async fn retries_on_early_close() {
// test body...
}
- Process SSE Incrementally: Handle events as they arrive rather than buffering everything first.
// Good: act on events as they stream in
while let Some(Ok(event)) = stream.next().await {
match event {
// handle events...
_ => {}
}
}
- Wire Delta Events End‑to‑End: Add protocol types, parse SSE fields, and forward deltas through the system.
// protocol.rs
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct AgentMessageDeltaEvent { pub delta: String }
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct AgentReasoningDeltaEvent { pub delta: String }
#[derive(Debug, Clone, Deserialize, Serialize)]
pub enum EventMsg {
AgentMessageDelta(AgentMessageDeltaEvent),
AgentReasoningDelta(AgentReasoningDeltaEvent),
// ...
}
// client.rs (SSE -> ResponseEvent)
match event_type.as_str() {
"response.output_text.delta" => {
if let Some(delta) = event.delta { tx_event.send(Ok(ResponseEvent::OutputTextDelta(delta))).await.ok(); }
}
"response.reasoning_summary_text.delta" => {
if let Some(delta) = event.delta { tx_event.send(Ok(ResponseEvent::ReasoningSummaryDelta(delta))).await.ok(); }
}
_ => {}
}
- Ignore Deltas During Aggregation: Skip deltas when the consumer expects a final, aggregated output.
match Pin::new(self).poll_next(cx) {
Poll::Ready(Some(Ok(ResponseEvent::OutputTextDelta(_))))
| Poll::Ready(Some(Ok(ResponseEvent::ReasoningSummaryDelta(_)))) => {
// aggregation waits for OutputItemDone
continue;
}
_ => {}
}
- Write Precise Test Assertions: Assert on exact lines or structured outputs, not naive substring counts.
let hi_lines = stdout.lines().filter(|line| line.trim() == "hi").count();
assert_eq!(hi_lines, 1, "Expected exactly one line with 'hi'");
- Handle New Variants Explicitly Across Consumers: Update
exec,mcp-server, andtuimatch arms even if only to TODO.
match event.msg {
EventMsg::AgentMessageDelta(AgentMessageDeltaEvent { delta: _ }) => {
// TODO: decide CLI streaming UX
}
EventMsg::AgentReasoningDelta(AgentReasoningDeltaEvent { delta: _ }) => {
// TODO: decide CLI streaming UX
}
_ => {}
}
- Right‑Size Channels (Prefer Constants/Config): Justify capacity changes and make them easy to tune.
const RESPONSE_EVENT_CAP: usize = 1600; // large bursts during delta streaming
let (tx_event, rx_event) = mpsc::channel::<Result<ResponseEvent>>(RESPONSE_EVENT_CAP);
DON’Ts
- Don’t Commit Large Blocks of Commented‑Out Code: Remove or revert; don’t leave dead code in the tree.
// BAD: commented-out file contents
// //! Verifies that the agent retries when...
// use std::time::Duration;
// #[tokio::test] async fn ... {}
- Don’t Buffer the Entire Stream Before Acting: This risks timeouts and hides streaming regressions.
// BAD: buffer first, act later
let mut input = Vec::new();
while let Some(event) = stream.next().await {
input.push(event?);
}
for event in input { /* ... */ }
- Don’t Swallow New Events With Catch‑Alls: Add explicit variants so future changes aren’t silently ignored.
// BAD: hides new protocol messages
match event {
_ => { /* ignored */ }
}
// GOOD: enumerate and handle (or TODO)
match event {
EventMsg::AgentMessageDelta(_) => { /* TODO */ }
EventMsg::AgentReasoningDelta(_) => { /* TODO */ }
_ => {}
}
- Don’t Leave Context‑Free TODOs: Include what/why and a tracking reference so cleanup is actionable.
// BAD
// TODO: support this
// GOOD
// TODO(GH-1234): Stream deltas in TUI; buffer per message ID and repaint incrementally.
- Don’t Mix Unrelated or Mistaken Merges: If a file was merged by mistake, revert it instead of commenting it out.
# Revert an unintended file change cleanly
git checkout origin/main -- codex-rs/core/tests/stream_no_completed.rs