Remove ghost snapshots (#19481)

## Summary
- Remove `ghost_snapshot` / `GhostCommit` from the Responses API surface
and generated SDK/schema artifacts.
- Keep legacy config loading compatible, but make undo a no-op that
reports the feature is unavailable.
- Clean up core history, compaction, telemetry, rollout, and tests to
stop carrying ghost snapshot items.

## Testing
- Unit tests passed for `codex-protocol`, `codex-core` targeted undo and
compaction flows, `codex-rollout`, and `codex-app-server-protocol`.
- Regenerated config and app-server schemas plus Python SDK artifacts
and verified they match the checked-in outputs.
This commit is contained in:
pakrym-oai
2026-04-27 18:48:57 -07:00
committed by GitHub
Unverified
parent 7e8594fc19
commit 4e05f3053c
43 changed files with 305 additions and 3254 deletions
+1 -8
View File
@@ -103,8 +103,7 @@ impl ContextManager {
{
for item in items {
let item_ref = item.deref();
let is_ghost_snapshot = matches!(item_ref, ResponseItem::GhostSnapshot { .. });
if !is_api_message(item_ref) && !is_ghost_snapshot {
if !is_api_message(item_ref) {
continue;
}
@@ -120,8 +119,6 @@ impl ContextManager {
pub(crate) fn for_prompt(mut self, input_modalities: &[InputModality]) -> Vec<ResponseItem> {
self.normalize_history(input_modalities);
self.items
.retain(|item| !matches!(item, ResponseItem::GhostSnapshot { .. }));
self.items
}
/// Returns raw items in the history.
@@ -403,7 +400,6 @@ impl ContextManager {
| ResponseItem::ImageGenerationCall { .. }
| ResponseItem::CustomToolCall { .. }
| ResponseItem::Compaction { .. }
| ResponseItem::GhostSnapshot { .. }
| ResponseItem::Other => item.clone(),
}
}
@@ -492,7 +488,6 @@ fn is_api_message(message: &ResponseItem) -> bool {
| ResponseItem::WebSearchCall { .. }
| ResponseItem::ImageGenerationCall { .. }
| ResponseItem::Compaction { .. } => true,
ResponseItem::GhostSnapshot { .. } => false,
ResponseItem::Other => false,
}
}
@@ -534,7 +529,6 @@ static ORIGINAL_IMAGE_ESTIMATE_CACHE: LazyLock<BlockingLruCache<[u8; 20], Option
pub(crate) fn estimate_response_item_model_visible_bytes(item: &ResponseItem) -> i64 {
match item {
ResponseItem::GhostSnapshot { .. } => 0,
ResponseItem::Reasoning {
encrypted_content: Some(content),
..
@@ -691,7 +685,6 @@ fn is_model_generated_item(item: &ResponseItem) -> bool {
ResponseItem::FunctionCallOutput { .. }
| ResponseItem::ToolSearchOutput { .. }
| ResponseItem::CustomToolCallOutput { .. }
| ResponseItem::GhostSnapshot { .. }
| ResponseItem::Other => false,
}
}
@@ -1,7 +1,6 @@
use super::*;
use base64::Engine;
use base64::engine::general_purpose::STANDARD as BASE64_STANDARD;
use codex_git_utils::GhostCommit;
use codex_protocol::AgentPath;
use codex_protocol::config_types::ReasoningSummary;
use codex_protocol::models::BaseInstructions;
@@ -594,22 +593,6 @@ fn for_prompt_clears_image_generation_result_when_images_are_unsupported() {
);
}
#[test]
fn get_history_for_prompt_drops_ghost_commits() {
let items = vec![ResponseItem::GhostSnapshot {
ghost_commit: GhostCommit::new(
"ghost-1".to_string(),
/*parent*/ None,
Vec::new(),
Vec::new(),
),
}];
let history = create_history_with_items(items);
let modalities = default_input_modalities();
let filtered = history.for_prompt(&modalities);
assert_eq!(filtered, vec![]);
}
#[test]
fn estimate_token_count_with_base_instructions_uses_provided_text() {
let history = create_history_with_items(vec![assistant_msg("hello from history")]);