[codex] Add interruptible sleep tool (#28429)

## Why

Models sometimes need to pause briefly while waiting for external work,
but using a shell command for that delay ties the wait to a process and
does not naturally resume when new turn input arrives.

## What changed

- add a built-in `sleep` tool behind the under-development `sleep_tool`
feature
- accept a bounded `duration_ms` argument, matching the millisecond
convention used by unified exec
- end the sleep early when either steered user input or mailbox input
arrives
- include elapsed wall-clock time in completed and interrupted outputs
- emit a dedicated core `SleepItem` through `item/started` and
`item/completed`
- expose the sleep item as app-server v2 `ThreadItem::Sleep` and retain
it in reconstructed thread history
- regenerate the configuration schema for the new feature flag
- regenerate app-server JSON and TypeScript schema fixtures

## Test plan

- `just test -p codex-core sleep_tool_follows_feature_gate`
- `just test -p codex-core any_new_input_interrupts_sleep`
- `just test -p codex-app-server-protocol`
- `just test -p codex-app-server
sleep_emits_started_and_completed_items`
This commit is contained in:
pakrym-oai
2026-06-15 21:39:21 -07:00
committed by GitHub
parent 022f1221e8
commit 08901fc8e1
37 changed files with 1099 additions and 19 deletions
@@ -356,6 +356,13 @@ pub enum ThreadItem {
ImageView { id: String, path: AbsolutePathBuf },
#[serde(rename_all = "camelCase")]
#[ts(rename_all = "camelCase")]
Sleep {
id: String,
#[ts(type = "number")]
duration_ms: u64,
},
#[serde(rename_all = "camelCase")]
#[ts(rename_all = "camelCase")]
ImageGeneration {
id: String,
status: String,
@@ -400,6 +407,7 @@ impl ThreadItem {
| ThreadItem::SubAgentActivity { id, .. }
| ThreadItem::WebSearch { id, .. }
| ThreadItem::ImageView { id, .. }
| ThreadItem::Sleep { id, .. }
| ThreadItem::ImageGeneration { id, .. }
| ThreadItem::EnteredReviewMode { id, .. }
| ThreadItem::ExitedReviewMode { id, .. }
@@ -837,6 +845,10 @@ impl From<CoreTurnItem> for ThreadItem {
id: image.id,
path: image.path,
},
CoreTurnItem::Sleep(sleep) => ThreadItem::Sleep {
id: sleep.id,
duration_ms: sleep.duration_ms,
},
CoreTurnItem::ImageGeneration(image) => ThreadItem::ImageGeneration {
id: image.id,
status: image.status,