feat: response-viewer (eye) support for Codex sessions#152
Merged
Ark0N merged 2 commits intoJul 12, 2026
Conversation
The response-viewer (eye) currently reads only ~/.claude/projects — for
Codex panes it falls back to a raw terminal-buffer dump. This adds a
Codex-aware reader with exact per-pane rollout attribution.
Locating THIS pane's rollout (~/.codex/sessions/**), in confidence order:
1. history match — Session tracks the pane's last Enter
(codexLastSubmitAt); correlating it against ~/.codex/history.jsonl
{session_id, ts} entries identifies the thread the pane is ACTUALLY
on, surviving /resume, /new and /fork typed inside the codex TUI.
An entry is credited to the pane whose Enter is closest, so menu
keystrokes in other panes can't steal attribution.
2. originator match — codex panes are spawned with
CODEX_INTERNAL_ORIGINATOR_OVERRIDE=codeman_<sessionId>, which codex
(verified on 0.144.1) writes into session_meta.originator of every
rollout it creates.
3. resume-id match — resumed rollouts keep their original session_meta
(codex appends without rewriting), but the uuid is in the filename.
4. cwd+mtime heuristic — case-blind compare (codex records launch-time
path case) and rollouts claimed by other panes are excluded.
Reader details: user turns come from event_msg/user_message (real input
only — AGENTS.md / environment_context injections never appear there),
deduped against legacy response_item rows per-text so mixed-version
rollouts keep full history; image inputs render an [image xN]
placeholder; session_meta identity is cached per path (write-once).
Frontend: thread role label follows session mode (Codex/Gemini/
OpenCode); the terminal-buffer fallback is Claude-only — TUI modes show
a clear placeholder instead of a repaint dump.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…(PR Ark0N#152) - Add test/routes/session-routes-codex-last-response.test.ts (app.inject + temp CODEX_HOME fixture rollouts): originator match beats cwd fallback when two panes share a dir, cwd fallback excludes sibling-claimed/foreign-cwd rollouts, resume-uuid filename match, history.jsonl pin outranks originator, event_msg/legacy user-turn dedup keeps old-codex turns, injected-context filtering, image placeholder, envelope shape ({success:true,data:{text, timestamp[,messages]}}), and a Claude-mode regression guard (codex reader never consulted for claude sessions) - Replace clear-at-cap Map caches (codexHistoryPinCache, codexRolloutMetaCache) with the repo-standard LRUMap so a full cache wipe can't thrash hot entries on large rollout collections - Join multi-block assistant/user text with a blank line instead of no separator (extractCodexBlockText) - Re-enable the terminal-buffer eye fallback for shell sessions (they have no transcript source at all); TUI modes keep the clear placeholder Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Owner
|
Merged — thank you @pirronewantlux529-coder, and welcome as a first-time contributor! 🎉 The 4-layer Codex rollout resolution (history pin → originator → resume-UUID → cwd fallback) is genuinely thoughtful work, and the reviewers found the parser logic sound. Review added the missing test coverage (10 route tests over fixture rollouts covering pin/originator/uuid precedence, dedup, injected-context filtering, and a Claude-mode regression guard) plus small hardening (LRU caches, multi-block text joins). Hope to see more from you! 🙏 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The response-viewer currently only reads Claude transcripts from
~/.claude/projects. For Codex panes the eye falls back to a raw terminal-buffer dump (TUI repaint garbage), and there is no way to see the last response or the conversation thread cleanly.A naive fix (match rollouts in
~/.codex/sessions/**by cwd + newest mtime) breaks as soon as two Codex panes share a working directory — each pane's eye shows whatever pane wrote last. We ran that variant privately for two weeks; this PR is the design that survived real-world usage.Design: locating THIS pane's rollout
In order of confidence:
Sessionnow tracks the pane's last Enter (codexLastSubmitAt, bothwrite()andwriteViaMux()paths). Correlating it against~/.codex/history.jsonl{session_id, ts}entries identifies the thread the pane is actually on — the only signal that survives/resume,/newand/forktyped inside the codex TUI itself. An entry is credited to the pane whose Enter is closest among all codex panes, so a menu keystroke elsewhere can't steal attribution. Resolved pins are cached per (session, submitAt).CODEX_INTERNAL_ORIGINATOR_OVERRIDE=codeman_<sessionId>; codex (verified on 0.144.1) writes the value intosession_meta.originatorof every rollout it creates, including new files after/new. Newest match wins.session_meta(codex appends without rewriting it), so originator matching can't see them; but the rollout uuid is in the filename andcodexConfig.resumeSessionIdis known (validated as UUID first)./mntpaths vary on WSL), and rollouts claimed by other panes' originators are excluded, so an idle pane can't display a sibling's thread.Reader quality
event_msg/user_message— codex emits one per real user input, and injected context (AGENTS.md,environment_context, …) never appears there, so no fragile filtering heuristics. Legacyresponse_itemuser rows are deduped per-text against the event set, so mixed-version rollouts (old turns without event_msg) keep full history.[image ×N]placeholder instead of silently vanishing.session_metaidentity is parsed once per rollout and cached (it is write-once — verified that resume appends without touching it), so repeat eye clicks cost stats + head reads of new files only.?context=fullreturns the whole user/assistant thread, same shape as the Claude path.Frontend
_cleanTerminalBufferknows Claude CLI output, but for TUI modes it produced repaint garbage; those now show a clear placeholder.Testing
Verified on codex-cli 0.144.1, tmux backend, two machines (WSL2):
codex resume <id>panes resolve via filename uuid./newinside a resumed pane: originator match takes over (newest wins)./resumetyped inside the TUI, then a new message: history match follows the pane to the resumed thread.tsc,prettier,npm run buildall clean.Note:
CODEX_INTERNAL_ORIGINATOR_OVERRIDEis an internal codex interface; if a future codex stops honoring it, layers 1/3/4 still function — the design degrades gracefully.🤖 Generated with Claude Code