Skip to content

Latest commit

 

History

History
93 lines (69 loc) · 5.68 KB

File metadata and controls

93 lines (69 loc) · 5.68 KB

Resuming an Existing Session in codex-exec

This note outlines what’s involved in letting the codex exec subcommand (implemented in the codex-exec crate) resume a prior session by id, and clarifies where session data is persisted locally.

Goal

  • Add a way to continue an existing session context in non‑interactive exec mode by passing either:
    • --resume-session-id <UUID>: resume the most recent rollout file for that id.
    • --resume-rollout <PATH>: resume from an explicit rollout file path.

Core already supports resuming via a rollout file path (wired through experimental_resume), so this is a thin CLI change.

Where to Integrate

Invocation note: end users run codex exec "...". Internally, the top‑level codex binary’s Exec subcommand delegates to the codex-exec crate. Any new flags added to codex-rs/exec are exposed to users via codex exec automatically.

Implemented:

  • --resume-rollout <PATH> and --resume-session-id <UUID> in codex exec.

  • Initial SessionConfigured is forwarded to stdout in --json mode so callers can capture session_id for subsequent resumes.

  • CLI flags: add to codex-rs/exec/src/cli.rs.

    • --resume-session-id <UUID>
    • --resume-rollout <PATH>
  • Main logic: codex-rs/exec/src/lib.rs::run_main() before loading the Config.

    1. Parse flags.
    2. If --resume-rollout is provided, use it directly.
    3. Else if --resume-session-id is provided, locate the corresponding rollout file under ~/.codex/sessions/**/rollout-*-<uuid>.jsonl:
      • Search in config.codex_home/sessions (resolve config_home before loading full config if needed; it’s usually ~/.codex).
      • If multiple files match, choose the newest by mtime or file name timestamp; otherwise error with a clear message.
    4. Once a rollout path is determined, set experimental_resume = <absolute path> via the standard overrides path (splice a -c experimental_resume=<path> into CliConfigOverrides or set it on ConfigOverrides prior to Config::load_with_cli_overrides).

No core/protocol changes are required: Session::new() already detects resume_path and restores state.

What Core Already Does

  • Session resume plumbing (codex-rs/core/src/codex.rs):

    • If resume_path is set, RolloutRecorder::resume(path, cwd) is invoked.
    • The session id is read from the file’s first line (meta) and replaces the fresh UUID.
    • Prior ResponseItems are replayed into in‑memory history so the agent continues with the same context.
    • A SessionConfiguredEvent is emitted with the final session_id, history metadata, and model info.
  • Rollout persistence (codex-rs/core/src/rollout.rs):

    • Location: ~/.codex/sessions/YYYY/MM/DD/rollout-<timestamp>-<session_id>.jsonl
    • File format:
      • First line: meta JSON with { id, timestamp, instructions, git }.
      • Subsequent lines: serialized ResponseItems (user/assistant messages, tool/tool-output calls, local shell call records, reasoning), plus periodic state records.
    • Writer runs asynchronously; resume reopens the file and continues appending.
  • Cross‑session message history (optional) (codex-rs/core/src/message_history.rs):

    • Location: ~/.codex/history.jsonl
    • Schema per line: { "session_id": "<uuid>", "ts": <unix_seconds>, "text": "<message>" }
    • Controlled by history.persistence in config. exec currently doesn’t auto‑append user prompts here; the TUI does via Op::AddToHistory.
  • Server‑side storage toggle:

    • Each request sets store: !disable_response_storage (codex-rs/core/src/codex.rs). This affects the model provider’s own storage but is independent of local rollout persistence.

Implementation Notes

  • Prefer --resume-rollout for direct control; layer --resume-session-id as convenience.
  • --resume-session-id search strategy:
    • Walk config.codex_home/sessions with a fast glob; match suffix -<uuid>.jsonl.
    • If multiple candidates exist, select the newest (by name timestamp or mtime). If ambiguous, print the list and ask the user to pick via --resume-rollout.
    • If none found, exit with a helpful error.
  • Conflicts: if both flags are provided, prefer --resume-rollout and warn, or reject as an error.
  • CWD rules: Session::new() requires an absolute cwd; the CLI already resolves this in Config.

Example UX

  • Resume by id:
    • codex-exec --resume-session-id 5973b6c0-94b8-487b-a530-2aeb6098ae0e -m gpt-5 "Continue the previous task by …"
  • Resume by file:
    • codex-exec --resume-rollout ~/.codex/sessions/2025/05/07/rollout-2025-05-07T17-24-21-5973b6c0-94b8-487b-a530-2aeb6098ae0e.jsonl -m gpt-5 - < prompt.txt

Edge Cases

  • Invalid UUID: validation should fail early with a clear message.
  • Multiple matches: pick newest or require --resume-rollout to disambiguate.
  • Missing file or unreadable path: clear error and non‑zero exit.
  • Cross‑machine reuse: rollout files reference only serialized conversation; they can be copied across machines, but cwd/git info may not align.
  • Permissions: history file uses 0600; rollouts are created under ~/.codex/sessions with standard FS permissions.

Validation

  • Unit: minimal parsing/selection helpers for locating a rollout by id.
  • E2E (when implementing):
    1. Start a session, exchange a couple of turns.
    2. Capture the session_id from SessionConfiguredEvent.
    3. Run codex-exec with --resume-session-id <id> and confirm restored context affects the model’s next response.

Summary

  • This feature can be implemented entirely in the exec crate by resolving a rollout path and setting experimental_resume before loading Config.
  • Session data is persisted locally in rollout JSONL files; optional cross‑session history is in ~/.codex/history.jsonl.