Skip to content

fix(cli): Codex 0.160 sessions reach the chat view again - #640

Merged
jonwiggins merged 3 commits into
mainfrom
fix/codex-0160-transcripts
Oct 5, 2026
Merged

jonwiggins merged 3 commits into
mainfrom
fix/codex-0160-transcripts

Conversation

@jonwiggins

@jonwiggins jonwiggins commented Oct 5, 2026 •

Copy link
Copy Markdown
Owner

What

Local Codex sessions showed an empty chat view since Codex 0.160: no thread id, no transcript, no backfill. Two independent breakages, both in the daemon:

  • Session discovery. Codex 0.160 moved the TUI behind a machine-wide app-server daemon that holds every rollout open. The terminal's own process tree holds none, so the lsof / /proc lookup found nothing. A Codex holding no rollout is now matched by what the rollouts say about themselves: the session in the terminal's dir that started with its codex process (ps etime vs session_meta.timestamp), else the one written to since (a resume), never one another terminal already follows; the match sticks to the process so a later session in the same dir doesn't steal it.
  • Rollout format. 0.160 replaced the user_message / agent_message / agent_reasoning events with one item_completed per thread item. The parser reads UserMessage / AgentMessage / Reasoning items (tool items are skipped: their response items carry the call and output) and unwraps the JSON output framing 0.160 puts on code-mode commands.

Pre-0.160 rollouts and the in-tree lookup keep working.

Verification

  • pnpm --filter @optio/cli test (210): new cases for the 0.160 item shape built from real rollout lines, etime parsing, the dir+time match, and a two-terminal finder scenario under an app-server daemon.
  • Live on an isolated daemon (test-daemon.sh) against a private test API: a spawned Codex 0.160 reported its thread id within seconds; both turns of a conversation streamed into GET /api/local/terminals/:id/transcript.

Rebuild the CLI and restart optio local up to pick it up.

Also: attention and chat for Codex

  • Attention. A Codex terminal stayed working after it finished because its TUI keeps repainting (clock, footer), so the silence heuristic never fired and the chat view said "The agent is working — your message will queue". The rollout marks every turn, so the transcript poll now reports task_started / task_complete / turn_aborted and attention takes them with a hook's authority (working / needs_you, reason stop): Codex's equivalent of Claude Code's UserPromptSubmit / Stop.
  • Chat submit. A message from the chat view typed into Codex and added a newline instead of sending: the text and its Enter arrived in one write, and Codex's paste-burst detection reads an Enter within 120 ms of a burst as a newline. POST /api/local/terminals/:id/input now writes the message and the Enter 250 ms apart (a bare Enter or text without one is unchanged). The iOS and Android composers go through the same route.

Live-checked on the isolated daemon: needs_you within seconds of each turn's end, a chat-style text\r starts the next turn, both turns in the transcript. API image rebuilt and rolled out on the local cluster.

Also: chat replies keep their line breaks

The conversation view rendered an agent's reply as markdown, which folds single newlines into a paragraph (a haiku came out on one line). Assistant rows now render with remark-breaks (breaks on LogMarkdown); the log viewer is unchanged.

Codex 0.160 moved the TUI behind a machine-wide app-server daemon that holds
every rollout open, so the terminal's own process tree holds none and the
daemon never found the session: no thread id, no transcript, no backfill. It
also replaced the user_message / agent_message / agent_reasoning events with
one item_completed per thread item, which the parser skipped.

A Codex holding no rollout is now matched by what the rollouts say: the
session in the terminal's dir that started with its codex process (ps etime
vs session_meta.timestamp), else the one written to since (a resume), never
one another terminal follows; the match sticks to the process. The parser
reads UserMessage / AgentMessage / Reasoning items, and unwraps the JSON
output framing 0.160 puts on code-mode commands.

Live-checked on an isolated daemon: a spawned Codex reports its thread id
within seconds and both turns of a conversation stream into the transcript.
…o Codex

A Codex terminal stayed "working" after it finished: its TUI keeps
repainting (clock, footer), so the silence heuristic never fired, and the
chat composer showed "your message will queue" against an idle agent. The
rollout marks every turn, so the transcript poll now reports task_started /
task_complete / turn_aborted and attention takes them with a hook's
authority (working / needs_you, reason stop) — Codex's equivalent of Claude
Code's UserPromptSubmit / Stop.

A message sent from the chat view never submitted to Codex: the text and its
Enter arrived in one write, Codex's paste-burst detection read the burst as
a paste and the Enter within 120 ms of it as a newline. The input route now
writes the message and the Enter 250 ms apart.

Live-checked on an isolated daemon: needs_you within seconds of each turn's
end, a chat-style `text\r` starts the next turn, both turns in the transcript.
The conversation view rendered an agent's reply as markdown, which folds
single newlines into a paragraph: a haiku, list-like lines, and short
answers written for a terminal came out on one line. The assistant rows
now render with remark-breaks (`breaks` on LogMarkdown); the log viewer's
rendering is unchanged.
@jonwiggins
jonwiggins merged commit 5c535b7 into main Oct 5, 2026
13 checks passed
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.

1 participant