Files
codex/codex-rs/core/src/session/time_reminder.rs
rka-oai 752ed90d78 current time reminders impl for system clock (varlatency 2/n) (#28824)
Stacked on #28822.

## Summary

- add a host-injectable current-time provider with a built-in system
implementation
- record UTC developer reminders in history immediately before due model
requests
- keep cadence state per session and force a refresh after compaction

This does NOT include the app server client <-> server clock logic. This
PR is only for the reminder message & system clock that will be used in
prod.

## Testing

- `just test -p codex-core varlatency_`
- `just clippy -p codex-core -p codex-app-server -p codex-mcp-server -p
codex-thread-manager-sample`
- `just fmt`
2026-06-18 19:18:42 +00:00

62 lines
1.8 KiB
Rust

use codex_protocol::error::CodexErr;
use codex_protocol::error::Result as CodexResult;
use super::session::Session;
use super::turn_context::TurnContext;
use crate::context::ContextualUserFragment;
#[derive(Default)]
pub(crate) struct CurrentTimeReminderState {
model_requests_since_delivery: u64,
last_window_id: Option<String>,
}
impl CurrentTimeReminderState {
fn take_reminder_due(&mut self, window_id: &str, interval: u64) -> bool {
self.model_requests_since_delivery = self.model_requests_since_delivery.saturating_add(1);
let reminder_is_due = self.last_window_id.as_deref() != Some(window_id)
|| self.model_requests_since_delivery >= interval;
if reminder_is_due {
self.model_requests_since_delivery = 0;
self.last_window_id = Some(window_id.to_string());
}
reminder_is_due
}
}
pub(super) async fn maybe_record_current_time_reminder(
sess: &Session,
turn_context: &TurnContext,
window_id: &str,
) -> CodexResult<()> {
let Some(config) = turn_context.config.current_time_reminder else {
return Ok(());
};
let reminder_is_due = {
let mut state = sess.state.lock().await;
state
.current_time_reminder
.take_reminder_due(window_id, config.reminder_interval_model_requests)
};
if !reminder_is_due {
return Ok(());
}
let current_time = sess
.services
.time_provider
.current_time(sess.thread_id)
.await
.map_err(|err| CodexErr::Fatal(format!("failed to read current time: {err:#}")))?;
let response_item =
ContextualUserFragment::into(crate::context::CurrentTimeReminder::new(current_time));
sess.record_conversation_items(turn_context, std::slice::from_ref(&response_item))
.await;
Ok(())
}