mirror of
https://github.com/openai/codex.git
synced 2026-09-20 12:47:38 +00:00
Add ordinals to paginated rollout records (#32332)
## Why Paginated thread history needs durable ordering so consumers can process a rollout suffix without rebuilding all earlier history. ## What changed - Add optional, zero-based ordinals to `RolloutLine` records in paginated rollouts while leaving legacy rollout serialization unchanged. - Continue ordinals from the last valid record when appending or resuming, including after gaps or an incomplete tail, and reject overflow without appending. - Add a stateless `project_rollout_line` helper that maps canonical turn lifecycle and completed-item records into thread-history change sets. ## Testing - Cover ordinal assignment, legacy compatibility, resume and tail recovery, overflow handling, and thread-history projection for completed, failed, and interrupted turns. GitOrigin-RevId: 3a9bb6cd2a1f674a9f154342e96e9aa3d8330781
This commit is contained in:
@@ -371,6 +371,7 @@ async fn synthetic_call_output_id_is_stable_across_resumes() -> anyhow::Result<(
|
||||
let rollout = vec![
|
||||
RolloutLine {
|
||||
timestamp: "2024-01-01T00:00:00.000Z".to_string(),
|
||||
ordinal: None,
|
||||
item: RolloutItem::SessionMeta(SessionMetaLine {
|
||||
meta: SessionMeta {
|
||||
session_id: thread_id.into(),
|
||||
@@ -388,6 +389,7 @@ async fn synthetic_call_output_id_is_stable_across_resumes() -> anyhow::Result<(
|
||||
},
|
||||
RolloutLine {
|
||||
timestamp: "2024-01-01T00:00:01.000Z".to_string(),
|
||||
ordinal: None,
|
||||
item: RolloutItem::ResponseItem(ResponseItem::FunctionCall {
|
||||
id: Some(ResponseItemId::with_suffix("fc", "existing")),
|
||||
name: "do_it".to_string(),
|
||||
@@ -896,6 +898,7 @@ async fn resume_replays_legacy_js_repl_image_rollout_shapes() {
|
||||
let rollout = vec![
|
||||
RolloutLine {
|
||||
timestamp: "2024-01-01T00:00:00.000Z".to_string(),
|
||||
ordinal: None,
|
||||
item: RolloutItem::SessionMeta(SessionMetaLine {
|
||||
meta: SessionMeta {
|
||||
session_id: thread_id.into(),
|
||||
@@ -913,10 +916,12 @@ async fn resume_replays_legacy_js_repl_image_rollout_shapes() {
|
||||
},
|
||||
RolloutLine {
|
||||
timestamp: "2024-01-01T00:00:01.000Z".to_string(),
|
||||
ordinal: None,
|
||||
item: RolloutItem::ResponseItem(legacy_custom_tool_call),
|
||||
},
|
||||
RolloutLine {
|
||||
timestamp: "2024-01-01T00:00:02.000Z".to_string(),
|
||||
ordinal: None,
|
||||
item: RolloutItem::ResponseItem(ResponseItem::CustomToolCallOutput {
|
||||
id: None,
|
||||
call_id: "legacy-js-call".to_string(),
|
||||
@@ -927,6 +932,7 @@ async fn resume_replays_legacy_js_repl_image_rollout_shapes() {
|
||||
},
|
||||
RolloutLine {
|
||||
timestamp: "2024-01-01T00:00:03.000Z".to_string(),
|
||||
ordinal: None,
|
||||
item: RolloutItem::ResponseItem(ResponseItem::Message {
|
||||
id: None,
|
||||
role: "user".to_string(),
|
||||
@@ -1032,6 +1038,7 @@ async fn resume_replays_image_tool_outputs_with_detail() {
|
||||
let rollout = vec![
|
||||
RolloutLine {
|
||||
timestamp: "2024-01-01T00:00:00.000Z".to_string(),
|
||||
ordinal: None,
|
||||
item: RolloutItem::SessionMeta(SessionMetaLine {
|
||||
meta: SessionMeta {
|
||||
session_id: thread_id.into(),
|
||||
@@ -1049,6 +1056,7 @@ async fn resume_replays_image_tool_outputs_with_detail() {
|
||||
},
|
||||
RolloutLine {
|
||||
timestamp: "2024-01-01T00:00:01.000Z".to_string(),
|
||||
ordinal: None,
|
||||
item: RolloutItem::ResponseItem(ResponseItem::FunctionCall {
|
||||
id: None,
|
||||
name: "view_image".to_string(),
|
||||
@@ -1060,6 +1068,7 @@ async fn resume_replays_image_tool_outputs_with_detail() {
|
||||
},
|
||||
RolloutLine {
|
||||
timestamp: "2024-01-01T00:00:01.500Z".to_string(),
|
||||
ordinal: None,
|
||||
item: RolloutItem::ResponseItem(ResponseItem::FunctionCallOutput {
|
||||
id: None,
|
||||
call_id: function_call_id.to_string(),
|
||||
@@ -1074,6 +1083,7 @@ async fn resume_replays_image_tool_outputs_with_detail() {
|
||||
},
|
||||
RolloutLine {
|
||||
timestamp: "2024-01-01T00:00:02.000Z".to_string(),
|
||||
ordinal: None,
|
||||
item: RolloutItem::ResponseItem(ResponseItem::CustomToolCall {
|
||||
id: None,
|
||||
status: Some("completed".to_string()),
|
||||
@@ -1086,6 +1096,7 @@ async fn resume_replays_image_tool_outputs_with_detail() {
|
||||
},
|
||||
RolloutLine {
|
||||
timestamp: "2024-01-01T00:00:02.500Z".to_string(),
|
||||
ordinal: None,
|
||||
item: RolloutItem::ResponseItem(ResponseItem::CustomToolCallOutput {
|
||||
id: None,
|
||||
call_id: custom_call_id.to_string(),
|
||||
|
||||
@@ -384,10 +384,12 @@ async fn backfill_scans_existing_rollouts() -> Result<()> {
|
||||
let lines = [
|
||||
RolloutLine {
|
||||
timestamp: "2026-01-27T12:00:00Z".to_string(),
|
||||
ordinal: None,
|
||||
item: RolloutItem::SessionMeta(session_meta_line),
|
||||
},
|
||||
RolloutLine {
|
||||
timestamp: "2026-01-27T12:00:01Z".to_string(),
|
||||
ordinal: None,
|
||||
item: RolloutItem::EventMsg(EventMsg::UserMessage(UserMessageEvent {
|
||||
client_id: None,
|
||||
message: "hello from backfill".to_string(),
|
||||
|
||||
Reference in New Issue
Block a user