Commit Graph
13 Commits
Author SHA1 Message Date
Owen Lin 095ac4f131 Keep SQLite history projection moving past invalid records (#42369)
## Why

A malformed or discontinuous rollout record can otherwise block later valid
thread history from being materialized in SQLite.

## What changed

- Skip malformed JSON, unknown records, missing or regressed ordinals, ordinal
  gaps, and invalid timestamps while advancing the projection checkpoint.
- Keep unknown-record ordinals available for a subsequent valid retry.
- Record projection outcomes and anomaly kinds with OpenTelemetry counters.

## Testing

- Cover malformed lines, missing, duplicate, and forward-gap ordinals, and valid
  retries after unknown records.

GitOrigin-RevId: 9ae616b44513e35a1fa209e54f05f0612abcbd86
2026-09-02 21:29:57 +00:00
jif 1cc81ca89a Support compression for shared rollout lineages (#41357)
## Why

Rollout compression skips files that participate in paginated fork lineages because lineage readers rely on byte offsets into the original JSONL. This prevents shared rollout history from being compressed.

## What changed

- Add a seekable rollout reader that preserves logical JSONL offsets for plain and zstd-compressed files without materializing compressed data beside the rollout.
- Use the reader for lineage validation, model-context replay, and SQLite history projection, including when compression races with a read.
- Add the opt-in `local_thread_store_shared_compression` feature. The default mode continues to leave shared lineages uncompressed for compatibility, while the new mode includes referenced sources and fork pointers.
- Record the uncompressed size in new zstd frames so common prefix-bound checks can avoid decoding the full file.

## Testing

Add coverage for seekable compressed reads, prefix validation across zstd frame shapes, compressed lineage replay and projection, concurrent forks, and compression-mode behavior.

GitOrigin-RevId: 83e519f7eabf7448977eff37c55899858cc17a07
2026-08-28 16:04:26 +00:00
guinness-oai 41ca88e95c Persist realtime events in the thread timeline (#40508)
## Why

Clients need a bounded view of realtime conversations that preserves the order of speech, agent work, and turn lifecycle events without loading the full thread history.

## What changed

- Persist realtime session boundaries, transcript segments, and promoted agent items in paginated thread rollouts.
- Add the experimental `thread/timeline/list` API to page ordinary items, realtime items, and turn boundaries in canonical rollout order. Include `activeRealtimeSessionAtPageStart` so each page can be rendered independently.
- Emit typed `thread/realtime/item/started`, `thread/realtime/item/transcript/delta`, and `thread/realtime/item/completed` notifications around durable realtime items.
- Keep the existing `thread/items/list` response and legacy thread history behavior unchanged.

## Testing

- Cover mixed timeline pagination, realtime-session state at page boundaries, rollout replay, subagent history prefixes, transcript streaming, steering, and promoted agent artifacts.

GitOrigin-RevId: faa2c420192d63e060e8fb32446e3c797422656e
2026-08-25 01:03:20 +00:00
Tamir Duberstein 2bd8727a0c Preserve floating-point values when decoding rollout lines (#38399)
## Why

Serde's generic buffering for flattened and internally tagged fields is incompatible with `serde_json`'s `arbitrary_precision` representation. As a result, persisted rollout items containing nested floating-point values can fail to decode.

## What changed

- Decode the rollout envelope at the JSON persistence boundary before deserializing the item payload.
- Use the shared decoder for both session resume and thread-history projection.
- Cover token-count floats, response-item metadata, field ordering, and ignored metadata in the decoder compatibility test.

GitOrigin-RevId: 59c7f6fbcf83162b5ed6980a69381fe45fc20a0a
2026-08-13 16:03:20 +00:00
Adam Perry @ OpenAI 63002bdb26 Extract persisted history types into a dedicated crate (#37871)
## What changed

- Add `codex-history` for model-history and persisted-rollout domain types, including `RolloutItem`, `RolloutLine`, `CompactedItem`, and initial/resumed history state.
- Re-export the persisted types from `codex-rollout` and update consumers to use the new crate boundary instead of `codex-protocol`.
- Preserve existing rollout serialization, including legacy numeric compacted-window IDs.

## Testing

- Add `codex-history` tests for rollout JSON round trips, compacted-history compatibility, persisted history modes, and multi-agent version selection.

GitOrigin-RevId: 944daa9297ddd231d3aebbdcb05fff4adf8b4e1b
2026-08-10 19:26:52 +00:00
Owen Lin 6256a7ccc7 Make thread history projection resilient to malformed rollouts (#36188)
## Why

A failed rollout append can leave a rejected line before a valid same-ordinal
retry. Advancing the byte checkpoint past that line without also advancing the
ordinal checkpoint can prevent subsequent history from being projected.

## What changed

- Defer rejected and unknown rollout lines until a later valid ordinal shows
  whether they were replaced by a retry or consumed an ordinal.
- Advance skipped ordinal ranges together with the durable byte checkpoint,
  while rejecting gaps that cannot be explained by rejected lines.
- Prefer item event timestamps and parse the rollout timestamp only when an
  item needs it as a fallback.

## Testing

Added coverage for same-ordinal retries, inferred ordinal gaps, unknown and
malformed records, invalid fallback timestamps, and unexplained gaps.

GitOrigin-RevId: 374beda316c605d562bd9526abed19916598d69f
2026-07-30 16:49:12 +00:00
jif 88ec932e96 Handle fractional rate limits in thread history projection (#36083)
## Why

Paginated thread history could reject valid rollout records when rate-limit
percentages were encoded as floating-point JSON values, preventing later final
answers from being projected.

## What changed

Deserialize each rollout line through `serde_json::Value` before converting it
to `RolloutLine`, preserving floating-point rate-limit values during history
materialization.

## Testing

Added coverage for projecting fractional, integral, very small, and large
floating-point rate-limit percentages across both catch-up materialization and
subsequent history appends.

GitOrigin-RevId: 68da907987ffe59f4a3033ef90f3b88c39734cb1
2026-07-30 04:55:09 +00:00
Owen Lin fa1d4c40d0 Gate paginated thread history on the state database (#35787)
## Why

Local thread stores without an initialized state database should not implicitly
create SQLite files or partially delete threads that have materialized history.

## What changed

- Report paginated history listing as unsupported when no state database is
  available, and skip history projection and materialization in that mode.
- Reject paginated forks without a state database.
- Validate access to materialized history before deleting rollout files, so a
  failed deletion preserves both the rollout and its history rows.

## Testing

Added coverage that a store without a state database creates no SQLite files
and preserves materialized history when deletion is unsupported. Existing
projection tests now initialize the state runtime explicitly.

GitOrigin-RevId: 2eaa0f5f0de8d5e4d84375ec50b310746a0ee68e
2026-07-28 16:00:39 +00:00
Owen Lin 05f000263b Support paginated thread forks (#35220)
## Why

`thread/fork` rejected threads using paginated history, so they could not use the same fork workflow as legacy threads.

## What changed

- Create paginated forks by referencing a frozen source-history prefix while persisting only child-owned records in the new rollout.
- Support latest, `lastTurnId`, and `beforeTurnId` boundaries, including inherited lineage, model-context reconstruction, interruption markers, and approval-reviewer inheritance.
- Make paginated reads and occurrence search traverse referenced history while excluding source records added after the fork.
- Coordinate fork preparation with archive and delete operations, and materialize compressed rollouts before they become fork references.

## Testing

Added app-server and thread-store coverage for boundary selection, active turns, inherited reads and search, compressed lineage, and concurrent source lifecycle operations.

GitOrigin-RevId: 66052d69517d7fb97a3b7817ab77a39c5ad995fd
2026-07-24 17:31:55 +00:00
Owen Lin 175f82147f Record rollout boundaries for materialized turns (#34562)
## What changed

- Store the starting byte offset and terminal ordinal and byte offset for each turn projected into SQLite.
- Advance offsets across blank and rejected physical lines while leaving incomplete trailing lines for the next materialization pass.
- Stop later rollout records from changing a turn after it reaches a terminal state.

## Testing

- Cover active and completed turn positions, trailing partial lines, skipped invalid lines, subagent history prefixes, and records received after terminal state.

GitOrigin-RevId: a7da2f0b00c0bf47b841db874c79a0d495c18acd
2026-07-21 15:10:42 +00:00
Owen Lin 2be648ba4a Preserve paginated history for spawned subagents (#33432)
## What changed

- Inherit paginated history mode when spawning or forking a subagent from a paginated parent.
- Load the parent's model context when forking and persist it as an inherited rollout prefix, while excluding that prefix from the child's projected turns, items, and metadata.
- Record the boundary between inherited context and child history, and reject partially initialized paginated subagent rollouts on resume.
- Resume paginated subagents from their stored model context instead of legacy rollout history.

## Testing

Added coverage for fresh and forked paginated subagents, compacted-history forks, model-context resume, inherited-prefix projection, metadata isolation, and incomplete-prefix detection.

GitOrigin-RevId: e57dc37c29aa4aaaf57b052b991be591d730e5ba
2026-07-15 21:25:24 +00:00
Owen Lin b24aa20107 Resume thread history projection from its SQLite checkpoint (#32928)
## Why

Thread history JSONL is the durable source of truth, while SQLite is a rebuildable view. If a SQLite projection fails after a durable append, the next write must catch up the unprojected suffix instead of skipping it.

## What changed

- Start materialization at the byte offset stored in `thread_history_projection_state`.
- Project only complete newline-terminated rollout records, leaving a trailing partial record for a later pass.
- Preserve validation for missing files, invalid offsets, and missing or out-of-order ordinals without advancing projection state.

## Testing

Add coverage for catching up after projection failure, avoiding replay when already synchronized, retaining partial lines, and rejecting invalid suffixes without changing SQLite state.

GitOrigin-RevId: 8a7200a77edd5411ddf5fe31ab6af5ee287ed7d7
2026-07-14 02:22:57 +00:00
Owen Lin 0ef9fa4d65 Materialize paginated thread history in SQLite (#32923)
## What changed

- Project durable paginated rollout records into rebuildable SQLite tables for turns, items, and projection progress while keeping JSONL as the source of truth.
- Add cursor-based local reads for turn summaries and thread or per-turn items, including archived-thread and history-mode validation.
- Serialize writes, shutdown, and deletion per thread so projection updates cannot race cleanup, and remove projected rows when a thread is deleted.
- Preserve stable item ordering while updating repeated snapshots and expose structured turn error details.

## Testing

- Cover projection, snapshot updates, summary recovery, pagination, failure handling, shutdown flushing, legacy-mode rejection, and deletion races.

GitOrigin-RevId: 34533185ece7f1f5690004c7f12b0f1f34dc2640
2026-07-14 02:00:39 +00:00