Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,18 @@

All notable changes to Codex Extras are documented in this file.

## Unreleased

- Add experimental, opt-in session status icons. Use local Codex IPC for live
work and input/approval waits, and bounded log reads for recorded results.
Keep the original chat icons and metadata-only reads by default.
- Show unanswered non-blocking questions, resolve replies independently, and
discard superseded or abandoned questions, including migrated histories.
- Mark new results in green until opened successfully through Codex Extras;
persist review state and protect newer results from stale clicks.
- Use theme-aware status colors and a small gray dot for reviewed, idle, and
unknown states, preserving label alignment. Document protocol limitations.

## 1.1.0

- Add a Codex Chats Activity Bar panel with local chat history, automatic
Expand Down
51 changes: 48 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@ conversations ordered by their most recent activity.

The panel reads Codex's local session index from `$CODEX_HOME/session_index.jsonl`
when `CODEX_HOME` is set, or from `~/.codex/session_index.jsonl` otherwise.
It reads only the small metadata prefix needed to identify each chat's workspace;
transcript contents are not parsed or copied.
By default, it reads only the small metadata prefix needed to identify each
chat's workspace; transcript contents are not parsed or copied. The optional
status-icons mode also reads lifecycle events from a bounded log tail (see Settings).

### New Codex Agent toolbar button

Expand All @@ -47,6 +48,47 @@ The official Codex extension is declared as a dependency and is installed automa
| Setting | Default | Description |
| --- | --- | --- |
| `codexExtras.showNewAgentButton` | `true` | Shows the New Codex Agent button in the editor toolbar. |
| `codexExtras.showSessionStatusIcons` | `false` | Experimental: replaces conversation icons with live task status and recorded completion events. |

Enable **Codex Extras: Show Session Status Icons** for a spinner while working,
a green check mark for a new result to review, a stop icon for interrupted turns,
or an error icon for failed turns. A yellow question mark means an unanswered
non-blocking question; the agent may still be working. It disappears after all
questions have matching replies. Idle and unknown states show a small gray dot,
preserving text alignment; their status remains available in the tooltip.
Sending a new ordinary user message supersedes earlier questions, including
older histories migrated into a single turn;
interrupted or failed turns do not keep abandoned questions active.
A bell means Codex is waiting for input or approval.
A clock means activity is unconfirmed, not that the task has completed.
Changing the setting takes effect immediately.

Opening a green chat through Codex Extras marks that specific result as reviewed
after the open command succeeds and its editor tab exists. Its status icon then
becomes a small gray dot, preserving text alignment. This is saved in VS Code extension storage across reloads. A later
completed turn gets a new green mark; opening an older result cannot consume it.
Failed opens do not mark results as reviewed. Blocking waits take priority over
non-blocking questions, and unanswered questions take priority over other states.

Status icons use theme-aware colors: blue for working, green for new results,
yellow for questions/waiting, orange for interrupted, red for failed, and muted foreground
for unconfirmed activity. Shapes and tooltip labels also identify
each state, so color is not the only cue.

This optional mode reads at most the last 256 KiB of each local session log and
caches the result. Only explicit lifecycle events determine status; assistant
messages and file modification times do not imply completion. File system events
refresh recorded results without polling. A spinner requires a live `active`
state from Codex's internal local IPC channel; logs alone never produce a spinner.
Losing the connection or receiving an owner-disconnection event invalidates live
status immediately. There is no inactivity timeout for a confirmed running task.

The IPC adapter is experimental and was checked against Codex extension
`26.1007.21434` (stream protocol version 11). An incompatible protocol falls back
to unknown/unconfirmed status. This is an observer only: it does not start,
resume, interrupt, or take ownership of tasks. See [status implementation notes](docs/SESSION-STATUS.md).
When disabled, session bodies are not read, no status watcher is registered,
and no IPC connection is opened.

## Install

Expand All @@ -68,7 +110,10 @@ code --install-extension codex-extras-1.1.0.vsix

Codex Extras contains no telemetry or network requests. It reads the local Codex
session index to populate the chat list and opens editor panels provided by the
official Codex extension.
official Codex extension. If status icons are enabled, it also reads a bounded
tail of session logs locally to identify lifecycle events and receives local IPC
state snapshots. Only runtime status and unanswered question IDs are retained from snapshots; conversation
messages are discarded and are never displayed, saved, or sent elsewhere.

## Contributing

Expand Down
1 change: 1 addition & 0 deletions assets/status-neutral.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
92 changes: 92 additions & 0 deletions docs/SESSION-STATUS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# Experimental session status icons

`codexExtras.showSessionStatusIcons` is off by default. The original chat icon,
metadata-only reads, and watcher behavior remain the default.

## Sources of status

- Live state: Codex's internal cross-window IPC, not a separate app-server process.
A different app-server instance cannot reliably report another instance's work.
- Historical results: at most the trailing 256 KiB of a local JSONL session file,
cached by file identity, size, and modification time. Only `event_msg` lifecycle
records count. Unfinished logs always return unconfirmed activity.
- No status polling or inactivity-based completion. File events refresh log
results; IPC messages update runtime status. Reconnection uses a delayed retry
only after the IPC connection closes.

The public app-server protocol documents `thread/status/changed` and runtime
thread status: <https://learn.chatgpt.com/docs/app-server#track-thread-status-changes>.
The installed IDE extension owns a stdio app-server connection and does not
export a public status subscription for other VS Code extensions.

## Internal IPC contract observed locally

Verified with `openai.chatgpt` version `26.1007.21434` on Windows. Sources of
confirmation: installed extension implementation, successful observer handshake,
read-only ownership discovery, and repeated runtime-state snapshots.

- Windows endpoint: `\\.\pipe\codex-ipc`.
- Unix endpoints: `$CODEX_HOME/ipc/ipc.sock` and the legacy per-user socket under
the operating system temporary directory. Unix paths are derived from the
installed implementation; live connectivity was verified on Windows only.
- Framing: 4-byte little-endian byte length followed by UTF-8 JSON.
- Initialize: `initialize`, version 0; receives a client ID.
- Subscribe/unsubscribe: `thread-stream-following-changed`, version 1,
`{hostId: "local", conversationId, following}`.
- Runtime stream: `thread-stream-state-changed`, version 11. Snapshots contain
`change.conversationState.threadRuntimeStatus`. Patches carry base and new
revisions. Retain runtime status and unresolved question IDs, never message text.
- `active` means working; nonempty `activeFlags` means waiting for input/approval.
`idle` means idle, `systemError` means failed, other states are unconfirmed.
- An owner-disconnection event or lost IPC connection clears live states.
- A revision gap requests a fresh snapshot. Unsupported versions cannot retain
a running indicator. Discovery requests are answered with `canHandle: false`.

## Questions and reviewed results

Async questions are `agentMessage` items with `questions`. Their IDs are the JSON
tuple `["request_user_input_async", item.id, questionIndex]`. User and steering
messages carrying `<send_user_message_question_reply>` resolve those exact IDs.
Inspect both `turns` and canonical `turnHistory.history.entitiesByKey`; deduplicate
items and match replies independently of entity order. Retain only unresolved IDs.
Use canonical island entry order (or recorded turn start times), not entity map
insertion order, to expire old questions when a newer ordinary user message appears.
Process messages inside each turn in order as well: older migrated histories may
combine several user follow-ups into a single turn. If rehydration replaced the
original call ID with `item-N`, an answer may resolve it only through a unique,
exact question-title/index match from a later reply in known conversation order.
Stable call IDs never use this fallback, and ambiguous matches remain unresolved.
A structured async reply resolves its IDs without superseding remaining questions.
Questions in interrupted/failed turns are abandoned. If history order cannot be
established, do not guess which prompt supersedes which question.
Question/reply patches request a debounced fresh snapshot; ordinary assistant text
streaming does not trigger snapshot requests. Blocking runtime waits have priority,
then unanswered async questions, then the underlying task state.

A completion's identity is its rollout path plus turn ID (or lifecycle byte offset
for older logs without a turn ID). Opening a green result through Extras records
that identity in `globalState` under `codexExtras.reviewedResults`, only after
`vscode.openWith` resolves and its local conversation tab exists. Capture the
displayed identity before opening so a newer completion cannot be marked reviewed
by a stale click. Reviewed completions use a small gray dot in a 16 px icon slot to
preserve label alignment; a later completion has
a different identity and is green again. No source transcripts are modified.

The adapter never becomes an owner and sends no task-control requests. Receiving
snapshots can temporarily decode conversation data in memory; it keeps no messages
and does not write source logs, configuration, or transcripts.

## Limits

This is an undocumented protocol and may change with Codex updates. A socket
connection and the last runtime state cannot prove progress if an owner remains
connected but stops responding. IPC disconnections are handled immediately;
silent hangs cannot be ruled out. A missing log result remains unknown rather
than becoming a successful completion. Remote hosts and compressed active logs
are not currently supported for status discovery.

Tests cover option toggling, log parsing and bounds, incomplete writes, live
snapshots and runtime patches, waiting states, owner and transport disconnection,
revision mismatch, protocol mismatch, frame bounds, observer-only behavior, async
question/reply matching, and persistent review markers including failed opens and
new completions racing with old editor opens.
Loading