mirror of
https://github.com/openai/codex.git
synced 2026-04-29 00:55:38 +00:00
feat(app-server): experimental flag to persist extended history (#11227)
This PR adds an experimental `persist_extended_history` bool flag to app-server thread APIs so rollout logs can retain a richer set of EventMsgs for non-lossy Thread > Turn > ThreadItems reconstruction (i.e. on `thread/resume`). ### Motivation Today, our rollout recorder only persists a small subset (e.g. user message, reasoning, assistant message) of `EventMsg` types, dropping a good number (like command exec, file change, etc.) that are important for reconstructing full item history for `thread/resume`, `thread/read`, and `thread/fork`. Some clients want to be able to resume a thread without lossiness. This lossiness is primarily a UI thing, since what the model sees are `ResponseItem` and not `EventMsg`. ### Approach This change introduces an opt-in `persist_full_history` flag to preserve those events when you start/resume/fork a thread (defaults to `false`). This is done by adding an `EventPersistenceMode` to the rollout recorder: - `Limited` (existing behavior, default) - `Extended` (new opt-in behavior) In `Extended` mode, persist additional `EventMsg` variants needed for non-lossy app-server `ThreadItem` reconstruction. We now store the following ThreadItems that we didn't before: - web search - command execution - patch/file changes - MCP tool calls - image view calls - collab tool outcomes - context compaction - review mode enter/exit For **command executions** in particular, we truncate the output using the existing `truncate_text` from core to store an upper bound of 10,000 bytes, which is also the default value for truncating tool outputs shown to the model. This keeps the size of the rollout file and command execution items returned over the wire reasonable. And we also persist `EventMsg::Error` which we can now map back to the Turn's status and populates the Turn's error metadata. #### Updates to EventMsgs To truly make `thread/resume` non-lossy, we also needed to persist the `status` on `EventMsg::CommandExecutionEndEvent` and `EventMsg::PatchApplyEndEvent`. Previously it was not obvious whether a command failed or was declined (similar for apply_patch). These EventMsgs were never persisted before so I made it a required field.
This commit is contained in:
@@ -1349,6 +1349,14 @@
|
||||
"default": "agent",
|
||||
"description": "Where the command originated. Defaults to Agent for backward compatibility."
|
||||
},
|
||||
"status": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ExecCommandStatus"
|
||||
}
|
||||
],
|
||||
"description": "Completion status for this command execution."
|
||||
},
|
||||
"stderr": {
|
||||
"description": "Captured stderr",
|
||||
"type": "string"
|
||||
@@ -1377,6 +1385,7 @@
|
||||
"exit_code",
|
||||
"formatted_output",
|
||||
"parsed_cmd",
|
||||
"status",
|
||||
"stderr",
|
||||
"stdout",
|
||||
"turn_id",
|
||||
@@ -1805,6 +1814,14 @@
|
||||
"description": "The changes that were applied (mirrors PatchApplyBeginEvent::changes).",
|
||||
"type": "object"
|
||||
},
|
||||
"status": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/PatchApplyStatus"
|
||||
}
|
||||
],
|
||||
"description": "Completion status for this patch application."
|
||||
},
|
||||
"stderr": {
|
||||
"description": "Captured stderr (parser errors, IO failures, etc.).",
|
||||
"type": "string"
|
||||
@@ -1832,6 +1849,7 @@
|
||||
},
|
||||
"required": [
|
||||
"call_id",
|
||||
"status",
|
||||
"stderr",
|
||||
"stdout",
|
||||
"success",
|
||||
@@ -2873,6 +2891,14 @@
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"ExecCommandStatus": {
|
||||
"enum": [
|
||||
"completed",
|
||||
"failed",
|
||||
"declined"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"ExecOutputStream": {
|
||||
"enum": [
|
||||
"stdout",
|
||||
@@ -3400,6 +3426,14 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"PatchApplyStatus": {
|
||||
"enum": [
|
||||
"completed",
|
||||
"failed",
|
||||
"declined"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"PlanItemArg": {
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
@@ -6185,6 +6219,14 @@
|
||||
"default": "agent",
|
||||
"description": "Where the command originated. Defaults to Agent for backward compatibility."
|
||||
},
|
||||
"status": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ExecCommandStatus"
|
||||
}
|
||||
],
|
||||
"description": "Completion status for this command execution."
|
||||
},
|
||||
"stderr": {
|
||||
"description": "Captured stderr",
|
||||
"type": "string"
|
||||
@@ -6213,6 +6255,7 @@
|
||||
"exit_code",
|
||||
"formatted_output",
|
||||
"parsed_cmd",
|
||||
"status",
|
||||
"stderr",
|
||||
"stdout",
|
||||
"turn_id",
|
||||
@@ -6641,6 +6684,14 @@
|
||||
"description": "The changes that were applied (mirrors PatchApplyBeginEvent::changes).",
|
||||
"type": "object"
|
||||
},
|
||||
"status": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/PatchApplyStatus"
|
||||
}
|
||||
],
|
||||
"description": "Completion status for this patch application."
|
||||
},
|
||||
"stderr": {
|
||||
"description": "Captured stderr (parser errors, IO failures, etc.).",
|
||||
"type": "string"
|
||||
@@ -6668,6 +6719,7 @@
|
||||
},
|
||||
"required": [
|
||||
"call_id",
|
||||
"status",
|
||||
"stderr",
|
||||
"stdout",
|
||||
"success",
|
||||
|
||||
@@ -1965,6 +1965,14 @@
|
||||
"default": "agent",
|
||||
"description": "Where the command originated. Defaults to Agent for backward compatibility."
|
||||
},
|
||||
"status": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ExecCommandStatus"
|
||||
}
|
||||
],
|
||||
"description": "Completion status for this command execution."
|
||||
},
|
||||
"stderr": {
|
||||
"description": "Captured stderr",
|
||||
"type": "string"
|
||||
@@ -1993,6 +2001,7 @@
|
||||
"exit_code",
|
||||
"formatted_output",
|
||||
"parsed_cmd",
|
||||
"status",
|
||||
"stderr",
|
||||
"stdout",
|
||||
"turn_id",
|
||||
@@ -2421,6 +2430,14 @@
|
||||
"description": "The changes that were applied (mirrors PatchApplyBeginEvent::changes).",
|
||||
"type": "object"
|
||||
},
|
||||
"status": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/PatchApplyStatus2"
|
||||
}
|
||||
],
|
||||
"description": "Completion status for this patch application."
|
||||
},
|
||||
"stderr": {
|
||||
"description": "Captured stderr (parser errors, IO failures, etc.).",
|
||||
"type": "string"
|
||||
@@ -2448,6 +2465,7 @@
|
||||
},
|
||||
"required": [
|
||||
"call_id",
|
||||
"status",
|
||||
"stderr",
|
||||
"stdout",
|
||||
"success",
|
||||
@@ -3489,6 +3507,14 @@
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"ExecCommandStatus": {
|
||||
"enum": [
|
||||
"completed",
|
||||
"failed",
|
||||
"declined"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"ExecOutputStream": {
|
||||
"enum": [
|
||||
"stdout",
|
||||
@@ -4285,6 +4311,14 @@
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"PatchApplyStatus2": {
|
||||
"enum": [
|
||||
"completed",
|
||||
"failed",
|
||||
"declined"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"PatchChangeKind": {
|
||||
"oneOf": [
|
||||
{
|
||||
|
||||
@@ -3362,6 +3362,14 @@
|
||||
"default": "agent",
|
||||
"description": "Where the command originated. Defaults to Agent for backward compatibility."
|
||||
},
|
||||
"status": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ExecCommandStatus"
|
||||
}
|
||||
],
|
||||
"description": "Completion status for this command execution."
|
||||
},
|
||||
"stderr": {
|
||||
"description": "Captured stderr",
|
||||
"type": "string"
|
||||
@@ -3390,6 +3398,7 @@
|
||||
"exit_code",
|
||||
"formatted_output",
|
||||
"parsed_cmd",
|
||||
"status",
|
||||
"stderr",
|
||||
"stdout",
|
||||
"turn_id",
|
||||
@@ -3818,6 +3827,14 @@
|
||||
"description": "The changes that were applied (mirrors PatchApplyBeginEvent::changes).",
|
||||
"type": "object"
|
||||
},
|
||||
"status": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/v2/PatchApplyStatus"
|
||||
}
|
||||
],
|
||||
"description": "Completion status for this patch application."
|
||||
},
|
||||
"stderr": {
|
||||
"description": "Captured stderr (parser errors, IO failures, etc.).",
|
||||
"type": "string"
|
||||
@@ -3845,6 +3862,7 @@
|
||||
},
|
||||
"required": [
|
||||
"call_id",
|
||||
"status",
|
||||
"stderr",
|
||||
"stdout",
|
||||
"success",
|
||||
@@ -4942,6 +4960,14 @@
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"ExecCommandStatus": {
|
||||
"enum": [
|
||||
"completed",
|
||||
"failed",
|
||||
"declined"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"ExecOneOffCommandParams": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
@@ -6446,6 +6472,14 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"PatchApplyStatus": {
|
||||
"enum": [
|
||||
"completed",
|
||||
"failed",
|
||||
"declined"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"PlanItemArg": {
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
|
||||
@@ -1349,6 +1349,14 @@
|
||||
"default": "agent",
|
||||
"description": "Where the command originated. Defaults to Agent for backward compatibility."
|
||||
},
|
||||
"status": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ExecCommandStatus"
|
||||
}
|
||||
],
|
||||
"description": "Completion status for this command execution."
|
||||
},
|
||||
"stderr": {
|
||||
"description": "Captured stderr",
|
||||
"type": "string"
|
||||
@@ -1377,6 +1385,7 @@
|
||||
"exit_code",
|
||||
"formatted_output",
|
||||
"parsed_cmd",
|
||||
"status",
|
||||
"stderr",
|
||||
"stdout",
|
||||
"turn_id",
|
||||
@@ -1805,6 +1814,14 @@
|
||||
"description": "The changes that were applied (mirrors PatchApplyBeginEvent::changes).",
|
||||
"type": "object"
|
||||
},
|
||||
"status": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/PatchApplyStatus"
|
||||
}
|
||||
],
|
||||
"description": "Completion status for this patch application."
|
||||
},
|
||||
"stderr": {
|
||||
"description": "Captured stderr (parser errors, IO failures, etc.).",
|
||||
"type": "string"
|
||||
@@ -1832,6 +1849,7 @@
|
||||
},
|
||||
"required": [
|
||||
"call_id",
|
||||
"status",
|
||||
"stderr",
|
||||
"stdout",
|
||||
"success",
|
||||
@@ -2873,6 +2891,14 @@
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"ExecCommandStatus": {
|
||||
"enum": [
|
||||
"completed",
|
||||
"failed",
|
||||
"declined"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"ExecOutputStream": {
|
||||
"enum": [
|
||||
"stdout",
|
||||
@@ -3400,6 +3426,14 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"PatchApplyStatus": {
|
||||
"enum": [
|
||||
"completed",
|
||||
"failed",
|
||||
"declined"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"PlanItemArg": {
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
|
||||
@@ -1349,6 +1349,14 @@
|
||||
"default": "agent",
|
||||
"description": "Where the command originated. Defaults to Agent for backward compatibility."
|
||||
},
|
||||
"status": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ExecCommandStatus"
|
||||
}
|
||||
],
|
||||
"description": "Completion status for this command execution."
|
||||
},
|
||||
"stderr": {
|
||||
"description": "Captured stderr",
|
||||
"type": "string"
|
||||
@@ -1377,6 +1385,7 @@
|
||||
"exit_code",
|
||||
"formatted_output",
|
||||
"parsed_cmd",
|
||||
"status",
|
||||
"stderr",
|
||||
"stdout",
|
||||
"turn_id",
|
||||
@@ -1805,6 +1814,14 @@
|
||||
"description": "The changes that were applied (mirrors PatchApplyBeginEvent::changes).",
|
||||
"type": "object"
|
||||
},
|
||||
"status": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/PatchApplyStatus"
|
||||
}
|
||||
],
|
||||
"description": "Completion status for this patch application."
|
||||
},
|
||||
"stderr": {
|
||||
"description": "Captured stderr (parser errors, IO failures, etc.).",
|
||||
"type": "string"
|
||||
@@ -1832,6 +1849,7 @@
|
||||
},
|
||||
"required": [
|
||||
"call_id",
|
||||
"status",
|
||||
"stderr",
|
||||
"stdout",
|
||||
"success",
|
||||
@@ -2873,6 +2891,14 @@
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"ExecCommandStatus": {
|
||||
"enum": [
|
||||
"completed",
|
||||
"failed",
|
||||
"declined"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"ExecOutputStream": {
|
||||
"enum": [
|
||||
"stdout",
|
||||
@@ -3400,6 +3426,14 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"PatchApplyStatus": {
|
||||
"enum": [
|
||||
"completed",
|
||||
"failed",
|
||||
"declined"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"PlanItemArg": {
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
|
||||
@@ -1349,6 +1349,14 @@
|
||||
"default": "agent",
|
||||
"description": "Where the command originated. Defaults to Agent for backward compatibility."
|
||||
},
|
||||
"status": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ExecCommandStatus"
|
||||
}
|
||||
],
|
||||
"description": "Completion status for this command execution."
|
||||
},
|
||||
"stderr": {
|
||||
"description": "Captured stderr",
|
||||
"type": "string"
|
||||
@@ -1377,6 +1385,7 @@
|
||||
"exit_code",
|
||||
"formatted_output",
|
||||
"parsed_cmd",
|
||||
"status",
|
||||
"stderr",
|
||||
"stdout",
|
||||
"turn_id",
|
||||
@@ -1805,6 +1814,14 @@
|
||||
"description": "The changes that were applied (mirrors PatchApplyBeginEvent::changes).",
|
||||
"type": "object"
|
||||
},
|
||||
"status": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/PatchApplyStatus"
|
||||
}
|
||||
],
|
||||
"description": "Completion status for this patch application."
|
||||
},
|
||||
"stderr": {
|
||||
"description": "Captured stderr (parser errors, IO failures, etc.).",
|
||||
"type": "string"
|
||||
@@ -1832,6 +1849,7 @@
|
||||
},
|
||||
"required": [
|
||||
"call_id",
|
||||
"status",
|
||||
"stderr",
|
||||
"stdout",
|
||||
"success",
|
||||
@@ -2873,6 +2891,14 @@
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"ExecCommandStatus": {
|
||||
"enum": [
|
||||
"completed",
|
||||
"failed",
|
||||
"declined"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"ExecOutputStream": {
|
||||
"enum": [
|
||||
"stdout",
|
||||
@@ -3400,6 +3426,14 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"PatchApplyStatus": {
|
||||
"enum": [
|
||||
"completed",
|
||||
"failed",
|
||||
"declined"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"PlanItemArg": {
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { ExecCommandSource } from "./ExecCommandSource";
|
||||
import type { ExecCommandStatus } from "./ExecCommandStatus";
|
||||
import type { ParsedCommand } from "./ParsedCommand";
|
||||
|
||||
export type ExecCommandEndEvent = {
|
||||
@@ -56,4 +57,8 @@ duration: string,
|
||||
/**
|
||||
* Formatted output from the command, as seen by the model.
|
||||
*/
|
||||
formatted_output: string, };
|
||||
formatted_output: string,
|
||||
/**
|
||||
* Completion status for this command execution.
|
||||
*/
|
||||
status: ExecCommandStatus, };
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
// GENERATED CODE! DO NOT MODIFY BY HAND!
|
||||
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
export type ExecCommandStatus = "completed" | "failed" | "declined";
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { FileChange } from "./FileChange";
|
||||
import type { PatchApplyStatus } from "./PatchApplyStatus";
|
||||
|
||||
export type PatchApplyEndEvent = {
|
||||
/**
|
||||
@@ -28,4 +29,8 @@ success: boolean,
|
||||
/**
|
||||
* The changes that were applied (mirrors PatchApplyBeginEvent::changes).
|
||||
*/
|
||||
changes: { [key in string]?: FileChange }, };
|
||||
changes: { [key in string]?: FileChange },
|
||||
/**
|
||||
* Completion status for this patch application.
|
||||
*/
|
||||
status: PatchApplyStatus, };
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
// GENERATED CODE! DO NOT MODIFY BY HAND!
|
||||
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
export type PatchApplyStatus = "completed" | "failed" | "declined";
|
||||
@@ -62,6 +62,7 @@ export type { ExecCommandBeginEvent } from "./ExecCommandBeginEvent";
|
||||
export type { ExecCommandEndEvent } from "./ExecCommandEndEvent";
|
||||
export type { ExecCommandOutputDeltaEvent } from "./ExecCommandOutputDeltaEvent";
|
||||
export type { ExecCommandSource } from "./ExecCommandSource";
|
||||
export type { ExecCommandStatus } from "./ExecCommandStatus";
|
||||
export type { ExecOneOffCommandParams } from "./ExecOneOffCommandParams";
|
||||
export type { ExecOneOffCommandResponse } from "./ExecOneOffCommandResponse";
|
||||
export type { ExecOutputStream } from "./ExecOutputStream";
|
||||
@@ -129,6 +130,7 @@ export type { NewConversationResponse } from "./NewConversationResponse";
|
||||
export type { ParsedCommand } from "./ParsedCommand";
|
||||
export type { PatchApplyBeginEvent } from "./PatchApplyBeginEvent";
|
||||
export type { PatchApplyEndEvent } from "./PatchApplyEndEvent";
|
||||
export type { PatchApplyStatus } from "./PatchApplyStatus";
|
||||
export type { Personality } from "./Personality";
|
||||
export type { PlanDeltaEvent } from "./PlanDeltaEvent";
|
||||
export type { PlanItem } from "./PlanItem";
|
||||
|
||||
@@ -21,4 +21,8 @@ export type ThreadForkParams = {threadId: string, /**
|
||||
path?: string | null, /**
|
||||
* Configuration overrides for the forked thread, if any.
|
||||
*/
|
||||
model?: string | null, modelProvider?: string | null, cwd?: string | null, approvalPolicy?: AskForApproval | null, sandbox?: SandboxMode | null, config?: { [key in string]?: JsonValue } | null, baseInstructions?: string | null, developerInstructions?: string | null};
|
||||
model?: string | null, modelProvider?: string | null, cwd?: string | null, approvalPolicy?: AskForApproval | null, sandbox?: SandboxMode | null, config?: { [key in string]?: JsonValue } | null, baseInstructions?: string | null, developerInstructions?: string | null, /**
|
||||
* If true, persist additional rollout EventMsg variants required to
|
||||
* reconstruct a richer thread history on subsequent resume/fork/read.
|
||||
*/
|
||||
persistExtendedHistory: boolean};
|
||||
|
||||
@@ -30,4 +30,8 @@ history?: Array<ResponseItem> | null, /**
|
||||
path?: string | null, /**
|
||||
* Configuration overrides for the resumed thread, if any.
|
||||
*/
|
||||
model?: string | null, modelProvider?: string | null, cwd?: string | null, approvalPolicy?: AskForApproval | null, sandbox?: SandboxMode | null, config?: { [key in string]?: JsonValue } | null, baseInstructions?: string | null, developerInstructions?: string | null, personality?: Personality | null};
|
||||
model?: string | null, modelProvider?: string | null, cwd?: string | null, approvalPolicy?: AskForApproval | null, sandbox?: SandboxMode | null, config?: { [key in string]?: JsonValue } | null, baseInstructions?: string | null, developerInstructions?: string | null, personality?: Personality | null, /**
|
||||
* If true, persist additional rollout EventMsg variants required to
|
||||
* reconstruct a richer thread history on subsequent resume/fork/read.
|
||||
*/
|
||||
persistExtendedHistory: boolean};
|
||||
|
||||
@@ -10,4 +10,8 @@ export type ThreadStartParams = {model?: string | null, modelProvider?: string |
|
||||
* If true, opt into emitting raw Responses API items on the event stream.
|
||||
* This is for internal use only (e.g. Codex Cloud).
|
||||
*/
|
||||
experimentalRawEvents: boolean};
|
||||
experimentalRawEvents: boolean, /**
|
||||
* If true, persist additional rollout EventMsg variants required to
|
||||
* reconstruct a richer thread history on resume/fork/read.
|
||||
*/
|
||||
persistExtendedHistory: boolean};
|
||||
|
||||
Reference in New Issue
Block a user