Skip to content

[codex] support external clock sleeps - #29923

Closed
rka-oai wants to merge 6 commits into
mainfrom
codex/external-clock-sleep
Closed

[codex] support external clock sleeps#29923
rka-oai wants to merge 6 commits into
mainfrom
codex/external-clock-sleep

Conversation

@rka-oai

@rka-oai rka-oai commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Summary

  • add an experimental currentTime/sleep notification and currentTime/wake request for external clocks
  • keep pending sleeps keyed by thread and sleep ID so wakeups are precise, canceled waits are removed, and stale wakes are harmless

Key Decision: I've set currentTime/sleep as a notification, but if we want to be completely safe, I think the right behavior is expect the app server client to "ack" back via {} - but i don't believe there's any existing precedent for this for app server -> client methods (only client -> app server)

@rka-oai
rka-oai marked this pull request as ready for review June 24, 2026 23:35
@rka-oai
rka-oai requested a review from a team as a code owner June 24, 2026 23:35

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 37358928b3

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread codex-rs/app-server/src/current_time.rs
Comment thread codex-rs/app-server/src/current_time.rs Outdated
@rka-oai
rka-oai marked this pull request as draft June 25, 2026 00:11
@rka-oai
rka-oai marked this pull request as ready for review June 25, 2026 00:11

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4e96cf3e82

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread codex-rs/app-server/src/current_time.rs Outdated
Comment on lines +216 to +218
.send_server_notification_to_connections(
&[connection_id],
ServerNotification::CurrentTimeSleep(CurrentTimeSleepParams {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Fail fast when sleep notifications are filtered

If the subscribed client initialized without experimentalApi (or opted out of currentTime/sleep), the transport drops this experimental ServerNotification before it is written, but notify_external_sleep still returns Ok and the sleep future then waits only for a later currentTime/wake. In that configuration a model clock.sleep call hangs indefinitely instead of reporting that the selected client cannot handle external sleeps; please verify the chosen connection can receive this notification, or use an acknowledged request/bounded wait.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not a serious issue for the limited use case here

Comment thread codex-rs/app-server-protocol/src/protocol/v2/current_time.rs Outdated
Comment thread codex-rs/app-server/src/current_time.rs
Comment on lines +115 to +117
result.map_err(|err| {
FunctionCallError::Fatal(format!("failed to sleep: {err:#}"))
})?;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Complete the sleep item on provider errors

With an external clock, time_provider.sleep can now fail after emit_turn_item_started has already published the sleep item (for example, no unambiguous subscribed clock client within the 5s lookup). This ? returns a fatal tool error before emit_turn_item_completed runs, leaving clients with an in-progress sleep item in the live event stream even though the turn fails. Please ensure the started sleep item is completed or failed on this error path.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not a serious issue here either

@rka-oai
rka-oai force-pushed the codex/current-time-sleep-config branch from 15eb0ba to e7572c1 Compare June 25, 2026 00:26
Base automatically changed from codex/current-time-sleep-config to main June 25, 2026 00:49
@rka-oai
rka-oai force-pushed the codex/external-clock-sleep branch 2 times, most recently from 5796b00 to 946eccb Compare June 25, 2026 03:53
@rka-oai
rka-oai changed the base branch from main to codex/time-provider-sleep June 25, 2026 03:53
@rka-oai
rka-oai force-pushed the codex/external-clock-sleep branch 2 times, most recently from 258b1d9 to 0ea6315 Compare June 25, 2026 05:03
Base automatically changed from codex/time-provider-sleep to main June 25, 2026 05:17
@rka-oai
rka-oai force-pushed the codex/external-clock-sleep branch from 0ea6315 to 950b702 Compare June 25, 2026 05:51
let deadline = Instant::now() + EXTERNAL_CLOCK_REQUEST_TIMEOUT;
let connection_id =
wait_for_current_time_connection(thread_state_manager, thread_id, deadline).await?;
outgoing

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This notification is required control flow, but both in-process delivery tiers still classify it as best-effort. Either bounded queue can drop it, after which this future waits forever for a wake the client never saw

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

notiffication should be considered required delivery now (so the bounded queue should wait until delivery).

ClientRequest::Initialize { .. } => {
panic!("Initialize should be handled before initialized request dispatch");
}
ClientRequest::CurrentTimeWake { params, .. } => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have the caller’s connection_id here but throw it away!
Since the sleep was sent to one specific external-clock connection, the pending entry needsto record that owner and reject wakes from other connections. Otherwise a different client can complete the sleep without advancing the clock used by later currentTime/read calls

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done! was originally building for specifically the 1 client case. Agreed its better we account for the general case here 👍

.await??;
let _: CurrentTimeWakeResponse = to_response(wake_response)?;

respond_to_current_time_read(&mut app_server, &thread.id, CURRENT_TIME_AT + 1).await?;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This requests a 12-hour sleep but advances the fake clock by one second, and we never prove the turn was still blocked before wake

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

improved test

@rka-oai
rka-oai requested a review from jif-oai June 25, 2026 10:30

@jif-oai jif-oai left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’m still pretty unconvinced by this shape. currentTime/sleep is required control flow, but modeling it as a notification plus a separate currentTime/wake request makes us rebuild correlation, delivery, cancellation, connection affinity, and stale-wake semantics by hand.
I can imagine the edge cases exploding here.
his should be a server-initiated request that remains pending until the client advances its clock and responds. What do you think?

{
bail!("external sleep can only be woken by the client that received it");
}
let pending_sleep = entries.remove(key);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NIT: This also ACKs a typo or wrong threadId/sleepId

@andmis andmis left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Leaving comments in slack.)

@rka-oai

rka-oai commented Jun 25, 2026

Copy link
Copy Markdown
Contributor Author

Closing as superseded by #30113, which supports external clock sleeps by polling the existing currentTime/read method without adding a separate sleep/wake protocol.

@rka-oai rka-oai closed this Jun 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants