发布

  • feat: record messages from user in ~/.codex/history.jsonl (#939)

    frostbyte_neo 发布于 2025-05-15 23:26:23 +00:00

    This is a large change to support a "history" feature like you would
    expect in a shell like Bash.

    History events are recorded in $CODEX_HOME/history.jsonl. Because it
    is a JSONL file, it is straightforward to append new entries (as opposed
    to the TypeScript file that uses $CODEX_HOME/history.json, so to be
    valid JSON, each new entry entails rewriting the entire file). Because
    it is possible for there to be multiple instances of Codex CLI writing
    to history.jsonl at once, we use advisory file locking when working
    with history.jsonl in codex-rs/core/src/message_history.rs.

    Because we believe history is a sufficiently useful feature, we enable
    it by default. Though to provide some safety, we set the file
    permissions of history.jsonl to be o600 so that other users on the
    system cannot read the user's history. We do not yet support a default
    list of SENSITIVE_PATTERNS as the TypeScript CLI does:

    https://github.com/openai/codex/blob/376742b870d001be33e57b1a41cdeeb16b6c6933/codex-cli/src/utils/storage/command-history.ts#L10-L17

    We are going to take a more conservative approach to this list in the
    Rust CLI. For example, while /\b[A-Za-z0-9-_]{20,}\b/ might exclude
    sensitive information like API tokens, it would also exclude valuable
    information such as references to Git commits.

    As noted in the updated documentation, users can opt-out of history by
    adding the following to config.toml:

    [history]
    persistence = "none" 
    

    Because history.jsonl could, in theory, be quite large, we take a[n
    arguably overly pedantic] approach in reading history entries into
    memory. Specifically, we start by telling the client the current number
    of entries in the history file (history_entry_count) as well as the
    inode (history_log_id) of history.jsonl (see the new fields on
    SessionConfiguredEvent).

    The client is responsible for keeping new entries in memory to create a
    "local history," but if the user hits up enough times to go "past" the
    end of local history, then the client should use the new
    GetHistoryEntryRequest in the protocol to fetch older entries.
    Specifically, it should pass the history_log_id it was given
    originally and work backwards from history_entry_count. (It should
    really fetch history in batches rather than one-at-a-time, but that is
    something we can improve upon in subsequent PRs.)

    The motivation behind this crazy scheme is that it is designed to defend
    against:

    • The history.jsonl being truncated during the session such that the
      index into the history is no longer consistent with what had been read
      up to that point. We do not yet have logic to enforce a max_bytes for
      history.jsonl, but once we do, we will aspire to implement it in a way
      that should result in a new inode for the file on most systems.
    • New items from concurrent Codex CLI sessions amending to the history.
      Because, in absence of truncation, history.jsonl is an append-only
      log, so long as the client reads backwards from history_entry_count,
      it should always get a consistent view of history. (That said, it will
      not be able to read new commands from concurrent sessions, but perhaps
      we will introduce a / command to reload latest history or something
      down the road.)

    Admittedly, my testing of this feature thus far has been fairly light. I
    expect we will find bugs and introduce enhancements/fixes going forward.

    下载附件