Files
codex/codex-rs/core/src/current_time.rs
rka-oai f66d793a2d [codex] route sleep through time providers (#29973)
## Summary

- add a cancellable sleep operation to `TimeProvider`
- route `clock.sleep` through the configured provider
- extend the supported sleep duration to 12 hours
- complete the sleep turn item before propagating provider failures

## Why

This isolates the core clock abstraction needed by external clock
integrations. Existing system and app-server behavior remains wall-clock
based in this PR; the stacked follow-up supplies app-server sleeps from
an external clock.
2026-06-24 22:17:43 -07:00

56 lines
1.8 KiB
Rust

use std::future::Future;
use std::pin::Pin;
use std::sync::Arc;
use std::time::Duration;
use anyhow::Result;
use anyhow::anyhow;
use chrono::DateTime;
use chrono::Utc;
use codex_features::CurrentTimeSource;
use codex_protocol::ThreadId;
use crate::config::CurrentTimeReminderConfig;
pub type TimeFuture<'a> = Pin<Box<dyn Future<Output = Result<DateTime<Utc>>> + Send + 'a>>;
pub type SleepFuture<'a> = Pin<Box<dyn Future<Output = Result<()>> + Send + 'a>>;
/// Host integration boundary for reading and waiting on the current time.
pub trait TimeProvider: Send + Sync {
fn current_time(&self, thread_id: ThreadId) -> TimeFuture<'_>;
/// Waits for the given duration on this provider's clock.
///
/// Dropping the returned future cancels the wait.
fn sleep(&self, thread_id: ThreadId, duration: Duration) -> SleepFuture<'_>;
}
pub(crate) struct SystemTimeProvider;
impl TimeProvider for SystemTimeProvider {
fn current_time(&self, _thread_id: ThreadId) -> TimeFuture<'_> {
Box::pin(async { Ok(Utc::now()) })
}
fn sleep(&self, _thread_id: ThreadId, duration: Duration) -> SleepFuture<'_> {
Box::pin(async move {
tokio::time::sleep(duration).await;
Ok(())
})
}
}
pub(crate) fn resolve_time_provider(
config: Option<&CurrentTimeReminderConfig>,
external_provider: Option<Arc<dyn TimeProvider>>,
) -> Result<Arc<dyn TimeProvider>> {
match config.map(|config| config.clock_source).unwrap_or_default() {
CurrentTimeSource::System => Ok(Arc::new(SystemTimeProvider)),
CurrentTimeSource::External => external_provider.ok_or_else(|| {
anyhow!(
"features.current_time_reminder.clock_source is external, but no external current-time provider is available"
)
}),
}
}