provider/codex: detect turn completion via OSC 9 notification & update default model to luna - #11
Conversation
Codex 0.153.2 emits an OSC 9 notification when a turn completes (agent-turn-complete). Previously, triggerCodex sent Ctrl-C as early as 4 seconds simply because the initial TUI screen rendering went quiet, terminating the process before Codex finished session initialization and submitted the prompt. By passing: -c tui.notifications=["agent-turn-complete"] -c tui.notification_method="osc9" -c tui.notification_condition="always" we can deterministically detect turn completion even in a focused PTY environment. In addition: - Fallback TERM to xterm-256color if unset or dumb, preventing TUI launch failures under cron or non-interactive daemon environments. - Maintain the 45s timeout fallback as a safety net. - Add regression test using mock codex script without external quotas. - Document the notification flags and updated output in README.
In Codex 0.153.2, selecting gpt-5.4-mini displays an interactive model migration dialog on startup, preventing automated turns from starting when relying on the default model without explicit configuration. Update the default Codex model from gpt-5.4-mini to gpt-5.6-luna in the built-in config defaults, template TOML, documentation, and tests.
Native Windows scopelimitping's existing Accordingly, the end-to-end completion detection in this PR is treated as unsupported and unverified on native Windows. The Unix PTY regression test is skipped there; a successful Windows build is not evidence that TUI pings or completion detection work. Codex CLI itself has a Windows ANSI-output path for OSC 9, but that alone does not resolve limitping's PTY limitation. Native Windows support would require a supported process/terminal transport and end-to-end testing. This PR does not add that support or introduce the existing limitation. WSL running Linux binaries uses the Linux PTY path and is separate from native Windows execution. |
Summary
Improve automated Codex/Spark TUI pings by avoiding premature stopping and a startup model-migration dialog. Related to #8.
Problem
Codex pings were not reliably reaching the point of completing a request.
Previously, limitping inferred completion from quiet PTY output: once at least four seconds had elapsed since startup and output had been quiet for at least 2.5 seconds, it sent Ctrl-C to stop the TUI. A pause during startup could satisfy this condition before Codex submitted the prompt. In that case, the CLI was stopped before it sent the ping at all.
Even when the prompt had been submitted, quiet output did not establish that the response had finished or the API request had succeeded. The same stopping heuristic could interrupt an in-progress turn and report a successful-looking ping.
During testing with Codex 0.153.2, the default
gpt-5.4-minialso displayed a model-migration dialog that required user input and blocked automated pings.Solution
Commit 1: Wait for TUI turn completion
TERMvalue when it is unset ordumb.Why use OSC 9 rather than screen text?
We also tried detecting text rendered in the PTY, but judged that approach unstable and sensitive to changes in Codex's TUI wording and layout. This PR therefore uses OSC 9 notifications as the single completion-detection mechanism.
Unlike matching screen text or a particular response, this relies on Codex CLI's notification feature and the OSC 9 sequence framing. We consider that a more robust boundary: the notification message itself can change without affecting detection.
The trade-off is that the normal completion path now depends on Codex CLI emitting its turn-completion notification. If Codex stops emitting it, notification detection will fail and limitping will stop the TUI through the 45-second fallback instead. We expect a user-facing notification feature to be less likely to disappear than individual TUI text, but that is an expectation, not a compatibility guarantee.
How the completion notification works
Checked against Codex CLI
rust-v0.153.2source:agent-turn-completenotification when it is returning to user input rather than starting queued input or continuing an active goal. This is a lifecycle event, not a guess based on quiet terminal output. See turn completion.ESC ] 9 ; <message> BELto stdout, which limitping reads through its PTY. The message is a preview of the final response (or a fallback label); limitping recognizes the notification sequence, not specific response text such asPONG. The notification is read directly from the PTY output; no desktop notification service is required. See notification text and OSC 9 output.alwaysoverride.The PR passes these settings to the child Codex process:
tui.notifications=["agent-turn-complete"]tui.notification_method="osc9"tui.notification_condition="always"Codex's event filter and focus gate implement these controls. On receipt, limitping sends Ctrl-C to close the interactive TUI. The 45-second fallback still applies if no notification arrives; receiving a notification does not itself prove quota activation.
Commit 2: Update the default Codex model
gpt-5.4-minitogpt-5.6-lunato avoid the observed startup dialog.Claude behavior is unchanged. This PR does not verify server-side quota activation or require a completion notification for every successful exit. Quota verification is handled separately in #12; #13 connects completion evidence to stricter result reporting.
Checks
gofmt -l .prints nothinggo build ./...go vet ./...go test ./...(also tested with-race)Safety
CI regression tests verify OSC 9 completion-notification detection through a real PTY on both Linux and macOS, using a fake Codex process. They check that the notification stops the TUI before the fallback timeout and that terminal setup is applied. The test runs with the race detector in the Linux test suite and a dedicated macOS job; both have passed. No Codex credentials or live model requests are required. This covers the PTY notification-handling path, not end-to-end behavior with the real Codex CLI or server-side quota activation. The test is skipped on native Windows.