mirror of
https://github.com/openai/codex.git
synced 2026-11-12 21:20:34 +00:00
Use typed context window IDs throughout thread persistence (#60757)
## What changed Carry `ContextWindowId` through session metadata, compaction checkpoints, rollout recording, and thread creation instead of converting IDs to strings. Add deserialization and JSON schema support while preserving the serialized string format and legacy numeric compaction IDs. Validate deserialized IDs as UUIDv7 values before restoring context windows, preserving the existing handling of unsupported IDs. GitOrigin-RevId: fda329d0654f438171a955c9f75550817c32c047
This commit is contained in:
committed by
copyberry
parent
2b60119af8
commit
4f8205c808
@@ -490,7 +490,7 @@ impl ExternalAgentSessionImporter {
|
||||
history_mode: ThreadHistoryMode::Legacy,
|
||||
history_base: None,
|
||||
subagent_history_start_ordinal: None,
|
||||
initial_window_id: codex_protocol::ContextWindowId::new_uuid_v7().to_string(),
|
||||
initial_window_id: codex_protocol::ContextWindowId::new_uuid_v7(),
|
||||
metadata: ThreadPersistenceMetadata {
|
||||
cwd: Some(cwd.clone()),
|
||||
model_provider: model_provider.clone(),
|
||||
|
||||
@@ -140,7 +140,7 @@ async fn get_conversation_summary_by_thread_id_reads_pathless_store_thread() ->
|
||||
history_mode: Default::default(),
|
||||
history_base: None,
|
||||
subagent_history_start_ordinal: None,
|
||||
initial_window_id: codex_protocol::ContextWindowId::new_uuid_v7().to_string(),
|
||||
initial_window_id: codex_protocol::ContextWindowId::new_uuid_v7(),
|
||||
runtime_workspace_roots: None,
|
||||
metadata: ThreadPersistenceMetadata {
|
||||
cwd: None,
|
||||
|
||||
@@ -302,7 +302,7 @@ async fn thread_list_repeated_cursor_returns_internal_error() -> Result<()> {
|
||||
history_mode: Default::default(),
|
||||
history_base: None,
|
||||
subagent_history_start_ordinal: None,
|
||||
initial_window_id: ContextWindowId::new_uuid_v7().to_string(),
|
||||
initial_window_id: ContextWindowId::new_uuid_v7(),
|
||||
runtime_workspace_roots: None,
|
||||
metadata: ThreadPersistenceMetadata {
|
||||
cwd: Some(codex_home.path().to_path_buf()),
|
||||
@@ -552,7 +552,7 @@ async fn thread_delete_with_non_local_thread_store_does_not_create_local_persist
|
||||
history_mode: Default::default(),
|
||||
history_base: None,
|
||||
subagent_history_start_ordinal: None,
|
||||
initial_window_id: ContextWindowId::new_uuid_v7().to_string(),
|
||||
initial_window_id: ContextWindowId::new_uuid_v7(),
|
||||
runtime_workspace_roots: None,
|
||||
metadata: ThreadPersistenceMetadata {
|
||||
cwd: Some(codex_home.path().to_path_buf()),
|
||||
|
||||
@@ -658,7 +658,7 @@ async fn thread_search_occurrences_reads_paginated_projection() -> Result<()> {
|
||||
history_mode: codex_protocol::protocol::ThreadHistoryMode::Paginated,
|
||||
history_base: None,
|
||||
subagent_history_start_ordinal: None,
|
||||
initial_window_id: ContextWindowId::new_uuid_v7().to_string(),
|
||||
initial_window_id: ContextWindowId::new_uuid_v7(),
|
||||
runtime_workspace_roots: None,
|
||||
metadata: ThreadPersistenceMetadata {
|
||||
cwd: Some(codex_home.path().to_path_buf()),
|
||||
@@ -3068,7 +3068,7 @@ async fn create_paginated_thread(
|
||||
history_mode: codex_protocol::protocol::ThreadHistoryMode::Paginated,
|
||||
history_base: None,
|
||||
subagent_history_start_ordinal: None,
|
||||
initial_window_id: ContextWindowId::new_uuid_v7().to_string(),
|
||||
initial_window_id: ContextWindowId::new_uuid_v7(),
|
||||
runtime_workspace_roots: None,
|
||||
metadata: ThreadPersistenceMetadata {
|
||||
cwd: Some(codex_home.to_path_buf()),
|
||||
@@ -3186,7 +3186,7 @@ async fn seed_pathless_store_thread(
|
||||
history_mode: Default::default(),
|
||||
history_base: None,
|
||||
subagent_history_start_ordinal: None,
|
||||
initial_window_id: ContextWindowId::new_uuid_v7().to_string(),
|
||||
initial_window_id: ContextWindowId::new_uuid_v7(),
|
||||
runtime_workspace_roots: None,
|
||||
metadata: ThreadPersistenceMetadata {
|
||||
cwd: None,
|
||||
|
||||
@@ -76,7 +76,7 @@ async fn timeline_pages_mix_items_and_resolve_the_opening_realtime_session() ->
|
||||
history_mode: ThreadHistoryMode::Paginated,
|
||||
history_base: None,
|
||||
subagent_history_start_ordinal: None,
|
||||
initial_window_id: codex_protocol::ContextWindowId::new_uuid_v7().to_string(),
|
||||
initial_window_id: codex_protocol::ContextWindowId::new_uuid_v7(),
|
||||
runtime_workspace_roots: None,
|
||||
metadata: ThreadPersistenceMetadata {
|
||||
cwd: Some(codex_home.path().to_path_buf()),
|
||||
|
||||
@@ -265,7 +265,7 @@ async fn thread_unarchive_preserves_pathless_store_metadata() -> Result<()> {
|
||||
history_mode: Default::default(),
|
||||
history_base: None,
|
||||
subagent_history_start_ordinal: None,
|
||||
initial_window_id: codex_protocol::ContextWindowId::new_uuid_v7().to_string(),
|
||||
initial_window_id: codex_protocol::ContextWindowId::new_uuid_v7(),
|
||||
runtime_workspace_roots: None,
|
||||
metadata: ThreadPersistenceMetadata {
|
||||
cwd: None,
|
||||
|
||||
@@ -70,9 +70,9 @@ async fn reconstruct_history_uses_replacement_history_verbatim() {
|
||||
guardian_history: None,
|
||||
mcp_resource_origins: None,
|
||||
window_number: Some(42),
|
||||
first_window_id: Some(first_window_id.to_string()),
|
||||
previous_window_id: Some(previous_window_id.to_string()),
|
||||
window_id: Some(window_id.to_string()),
|
||||
first_window_id: Some(first_window_id.clone()),
|
||||
previous_window_id: Some(previous_window_id.clone()),
|
||||
window_id: Some(window_id.clone()),
|
||||
compaction_response_id: None,
|
||||
latest_token_usage_record: None,
|
||||
resume_metadata: None,
|
||||
|
||||
@@ -19,12 +19,9 @@ impl Session {
|
||||
retained_context: Some(history.retained_context().clone()),
|
||||
mcp_resource_origins: self.services.mcp_runtime.resource_origin_checkpoint(),
|
||||
window_number: Some(state.auto_compact_window_number()),
|
||||
first_window_id: Some(window_ids.first_window_id.to_string()),
|
||||
previous_window_id: window_ids
|
||||
.previous_window_id
|
||||
.as_ref()
|
||||
.map(ToString::to_string),
|
||||
window_id: Some(window_ids.window_id.to_string()),
|
||||
first_window_id: Some(window_ids.first_window_id.clone()),
|
||||
previous_window_id: window_ids.previous_window_id.clone(),
|
||||
window_id: Some(window_ids.window_id.clone()),
|
||||
compaction_response_id: None,
|
||||
latest_token_usage_record: state.latest_token_usage_record.clone(),
|
||||
resume_metadata: None,
|
||||
|
||||
@@ -4952,12 +4952,9 @@ impl Session {
|
||||
retained_context: Some(state.history.retained_context().clone()),
|
||||
mcp_resource_origins: self.services.mcp_runtime.resource_origin_checkpoint(),
|
||||
window_number: Some(metadata.window_number),
|
||||
first_window_id: Some(metadata.window_ids.first_window_id.to_string()),
|
||||
previous_window_id: metadata
|
||||
.window_ids
|
||||
.previous_window_id
|
||||
.map(|id| id.to_string()),
|
||||
window_id: Some(metadata.window_ids.window_id.to_string()),
|
||||
first_window_id: Some(metadata.window_ids.first_window_id),
|
||||
previous_window_id: metadata.window_ids.previous_window_id,
|
||||
window_id: Some(metadata.window_ids.window_id),
|
||||
compaction_response_id: metadata.compaction_response_id,
|
||||
latest_token_usage_record: state.latest_token_usage_record.clone(),
|
||||
resume_metadata: Some(CompactionResumeMetadata {
|
||||
|
||||
@@ -659,23 +659,23 @@ fn reconstructed_window_from_compaction(compacted: &CompactedItem) -> Option<Rec
|
||||
number: compacted.window_number?,
|
||||
first_id: compacted
|
||||
.first_window_id
|
||||
.as_deref()
|
||||
.and_then(ContextWindowId::parse),
|
||||
.as_ref()
|
||||
.and_then(ContextWindowId::validated),
|
||||
previous_id: compacted
|
||||
.previous_window_id
|
||||
.as_deref()
|
||||
.and_then(ContextWindowId::parse),
|
||||
.as_ref()
|
||||
.and_then(ContextWindowId::validated),
|
||||
id: compacted
|
||||
.window_id
|
||||
.as_deref()
|
||||
.and_then(ContextWindowId::parse),
|
||||
.as_ref()
|
||||
.and_then(ContextWindowId::validated),
|
||||
})
|
||||
}
|
||||
|
||||
fn reconstructed_window_from_session_context_window(
|
||||
context_window: &SessionContextWindow,
|
||||
) -> Option<ReconstructedWindow> {
|
||||
let id = ContextWindowId::parse(&context_window.window_id)?;
|
||||
let id = context_window.window_id.validated()?;
|
||||
Some(ReconstructedWindow {
|
||||
number: 0,
|
||||
first_id: Some(id.clone()),
|
||||
|
||||
@@ -1461,7 +1461,7 @@ async fn reconstruct_history_restores_initial_window_from_session_meta() {
|
||||
session_id: thread_id.into(),
|
||||
id: thread_id,
|
||||
context_window: Some(SessionContextWindow {
|
||||
window_id: initial_window_id.to_string(),
|
||||
window_id: initial_window_id.clone(),
|
||||
}),
|
||||
..SessionMeta::default()
|
||||
},
|
||||
@@ -1495,7 +1495,7 @@ async fn reconstruct_history_prefers_compacted_window_over_session_meta() {
|
||||
session_id: thread_id.into(),
|
||||
id: thread_id,
|
||||
context_window: Some(SessionContextWindow {
|
||||
window_id: initial_window_id.to_string(),
|
||||
window_id: initial_window_id.clone(),
|
||||
}),
|
||||
..SessionMeta::default()
|
||||
},
|
||||
@@ -1508,9 +1508,9 @@ async fn reconstruct_history_prefers_compacted_window_over_session_meta() {
|
||||
guardian_history: None,
|
||||
mcp_resource_origins: None,
|
||||
window_number: Some(2),
|
||||
first_window_id: Some(compacted_first_window_id.to_string()),
|
||||
previous_window_id: Some(compacted_previous_window_id.to_string()),
|
||||
window_id: Some(compacted_window_id.to_string()),
|
||||
first_window_id: Some(compacted_first_window_id.clone()),
|
||||
previous_window_id: Some(compacted_previous_window_id.clone()),
|
||||
window_id: Some(compacted_window_id.clone()),
|
||||
compaction_response_id: None,
|
||||
latest_token_usage_record: None,
|
||||
resume_metadata: None,
|
||||
@@ -1636,9 +1636,9 @@ async fn bounded_replay_matches_full_replay_after_empty_turn_compactions(
|
||||
])),
|
||||
mcp_resource_origins: None,
|
||||
window_number: Some(window_number as u64),
|
||||
first_window_id: Some(window_ids[0].to_string()),
|
||||
previous_window_id: Some(window_ids[window_number - 1].to_string()),
|
||||
window_id: Some(window_ids[window_number].to_string()),
|
||||
first_window_id: Some(window_ids[0].clone()),
|
||||
previous_window_id: Some(window_ids[window_number - 1].clone()),
|
||||
window_id: Some(window_ids[window_number].clone()),
|
||||
compaction_response_id: None,
|
||||
latest_token_usage_record: None,
|
||||
resume_metadata: current.then(|| codex_history::CompactionResumeMetadata {
|
||||
@@ -1993,7 +1993,7 @@ async fn reconstruct_history_preserves_legacy_compaction_count_with_session_meta
|
||||
session_id: thread_id.into(),
|
||||
id: thread_id,
|
||||
context_window: Some(SessionContextWindow {
|
||||
window_id: initial_window_id.to_string(),
|
||||
window_id: initial_window_id.clone(),
|
||||
}),
|
||||
..SessionMeta::default()
|
||||
},
|
||||
|
||||
@@ -1104,7 +1104,7 @@ impl Session {
|
||||
&& session_configuration.session_source.is_non_root_agent()
|
||||
&& config.features.enabled(Feature::TokenBudget);
|
||||
if restore_child_window && let InitialHistory::Forked(items) = &mut initial_history {
|
||||
let child_window_id = initial_auto_compact_window_ids.window_id.to_string();
|
||||
let child_window_id = initial_auto_compact_window_ids.window_id.clone();
|
||||
for item in items {
|
||||
if let RolloutItem::Compacted(checkpoint) = item {
|
||||
checkpoint.window_number = Some(0);
|
||||
@@ -1241,9 +1241,7 @@ impl Session {
|
||||
ForkPersistence::Referenced { history_base, .. } => *history_base,
|
||||
},
|
||||
subagent_history_start_ordinal: None,
|
||||
initial_window_id: initial_auto_compact_window_ids
|
||||
.window_id
|
||||
.to_string(),
|
||||
initial_window_id: initial_auto_compact_window_ids.window_id.clone(),
|
||||
runtime_workspace_roots: Some(config.workspace_roots.clone()),
|
||||
metadata: ThreadPersistenceMetadata {
|
||||
cwd: Some(config.cwd.to_path_buf()),
|
||||
|
||||
@@ -4922,7 +4922,7 @@ async fn open_thread_persistence(session: &mut Session) -> PathBuf {
|
||||
history_mode: Default::default(),
|
||||
subagent_history_start_ordinal: None,
|
||||
history_base: None,
|
||||
initial_window_id: ContextWindowId::new_uuid_v7().to_string(),
|
||||
initial_window_id: ContextWindowId::new_uuid_v7(),
|
||||
runtime_workspace_roots: None,
|
||||
metadata: ThreadPersistenceMetadata {
|
||||
cwd: Some(config.cwd.to_path_buf()),
|
||||
@@ -8716,7 +8716,7 @@ async fn shutdown_complete_does_not_append_to_thread_store_after_shutdown() {
|
||||
history_mode: Default::default(),
|
||||
subagent_history_start_ordinal: None,
|
||||
history_base: None,
|
||||
initial_window_id: ContextWindowId::new_uuid_v7().to_string(),
|
||||
initial_window_id: ContextWindowId::new_uuid_v7(),
|
||||
runtime_workspace_roots: None,
|
||||
metadata: ThreadPersistenceMetadata {
|
||||
cwd: Some(config.cwd.to_path_buf()),
|
||||
@@ -8855,7 +8855,7 @@ async fn submission_loop_channel_close_runs_full_thread_teardown() -> anyhow::Re
|
||||
history_mode: Default::default(),
|
||||
subagent_history_start_ordinal: None,
|
||||
history_base: None,
|
||||
initial_window_id: ContextWindowId::new_uuid_v7().to_string(),
|
||||
initial_window_id: ContextWindowId::new_uuid_v7(),
|
||||
runtime_workspace_roots: None,
|
||||
metadata: ThreadPersistenceMetadata {
|
||||
cwd: Some(config.cwd.to_path_buf()),
|
||||
@@ -11839,7 +11839,7 @@ async fn attach_in_memory_thread_store(
|
||||
history_mode: Default::default(),
|
||||
subagent_history_start_ordinal: None,
|
||||
history_base: None,
|
||||
initial_window_id: ContextWindowId::new_uuid_v7().to_string(),
|
||||
initial_window_id: ContextWindowId::new_uuid_v7(),
|
||||
runtime_workspace_roots: None,
|
||||
metadata: ThreadPersistenceMetadata {
|
||||
cwd: Some(config.cwd.to_path_buf()),
|
||||
@@ -13395,9 +13395,9 @@ async fn sample_rollout(
|
||||
guardian_history: None,
|
||||
mcp_resource_origins: None,
|
||||
window_number: Some(window_number),
|
||||
first_window_id: Some(window_ids.first_window_id.to_string()),
|
||||
previous_window_id: window_ids.previous_window_id.map(|id| id.to_string()),
|
||||
window_id: Some(window_ids.window_id.to_string()),
|
||||
first_window_id: Some(window_ids.first_window_id),
|
||||
previous_window_id: window_ids.previous_window_id,
|
||||
window_id: Some(window_ids.window_id),
|
||||
compaction_response_id: None,
|
||||
latest_token_usage_record: None,
|
||||
resume_metadata: None,
|
||||
@@ -13430,9 +13430,9 @@ async fn sample_rollout(
|
||||
guardian_history: None,
|
||||
mcp_resource_origins: None,
|
||||
window_number: Some(window_number),
|
||||
first_window_id: Some(window_ids.first_window_id.to_string()),
|
||||
previous_window_id: window_ids.previous_window_id.map(|id| id.to_string()),
|
||||
window_id: Some(window_ids.window_id.to_string()),
|
||||
first_window_id: Some(window_ids.first_window_id),
|
||||
previous_window_id: window_ids.previous_window_id,
|
||||
window_id: Some(window_ids.window_id),
|
||||
compaction_response_id: None,
|
||||
latest_token_usage_record: None,
|
||||
resume_metadata: None,
|
||||
|
||||
@@ -2006,14 +2006,21 @@ async fn spawned_full_history_v2_child_uses_model_precedence_without_dropping_co
|
||||
.as_ref()
|
||||
.is_some_and(|history| !history.is_empty())
|
||||
);
|
||||
let expected_window =
|
||||
codex_protocol::ContextWindowId::parse(window_ids[1]).expect("UUIDv7 child window");
|
||||
assert_eq!(
|
||||
(
|
||||
checkpoint.window_number,
|
||||
checkpoint.first_window_id.as_deref(),
|
||||
checkpoint.previous_window_id.as_deref(),
|
||||
checkpoint.window_id.as_deref(),
|
||||
checkpoint.first_window_id.as_ref(),
|
||||
checkpoint.previous_window_id.as_ref(),
|
||||
checkpoint.window_id.as_ref(),
|
||||
),
|
||||
(Some(0), Some(window_ids[1]), None, Some(window_ids[1]))
|
||||
(
|
||||
Some(0),
|
||||
Some(&expected_window),
|
||||
None,
|
||||
Some(&expected_window)
|
||||
)
|
||||
);
|
||||
assert!(
|
||||
child_request.has_message_with_input_texts("developer", |message| {
|
||||
|
||||
@@ -67,7 +67,7 @@ async fn captures_originals_without_generated_context_or_later_appends() -> anyh
|
||||
history_mode: ThreadHistoryMode::Paginated,
|
||||
history_base: None,
|
||||
subagent_history_start_ordinal: None,
|
||||
initial_window_id: "window-1".into(),
|
||||
initial_window_id: codex_protocol::ContextWindowId::new_uuid_v7(),
|
||||
runtime_workspace_roots: None,
|
||||
metadata: ThreadPersistenceMetadata {
|
||||
cwd: Some(dir.path().to_path_buf()),
|
||||
|
||||
@@ -322,9 +322,9 @@ pub struct CompactedItem {
|
||||
pub retained_context: Option<RetainedContext>,
|
||||
pub mcp_resource_origins: Option<McpResourceOriginCheckpoint>,
|
||||
pub window_number: Option<u64>,
|
||||
pub first_window_id: Option<String>,
|
||||
pub previous_window_id: Option<String>,
|
||||
pub window_id: Option<String>,
|
||||
pub first_window_id: Option<codex_protocol::ContextWindowId>,
|
||||
pub previous_window_id: Option<codex_protocol::ContextWindowId>,
|
||||
pub window_id: Option<codex_protocol::ContextWindowId>,
|
||||
/// Responses API ID for the model-backed compaction request, when one exists.
|
||||
pub compaction_response_id: Option<String>,
|
||||
/// Snapshot of the latest reachable token usage record when this compaction was written.
|
||||
|
||||
@@ -16,6 +16,7 @@ use super::TurnContextItem;
|
||||
use super::WorldStateItem;
|
||||
use crate::RetainedContextEvent;
|
||||
use crate::RetainedUserMessage;
|
||||
use codex_protocol::ContextWindowId;
|
||||
use codex_protocol::ResponseItemId;
|
||||
use codex_protocol::models::ContentItem;
|
||||
use codex_protocol::models::InternalChatMessageMetadataPassthrough;
|
||||
@@ -337,11 +338,11 @@ pub(super) struct CompactedItemWire<'a> {
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
window_number: Option<u64>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
first_window_id: Option<Cow<'a, str>>,
|
||||
first_window_id: Option<Cow<'a, ContextWindowId>>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
previous_window_id: Option<Cow<'a, str>>,
|
||||
previous_window_id: Option<Cow<'a, ContextWindowId>>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
#[schemars(with = "Option<String>")]
|
||||
#[schemars(with = "Option<ContextWindowId>")]
|
||||
window_id: Option<WindowIdWire<'a>>,
|
||||
#[serde(default)]
|
||||
compaction_response_id: Option<Cow<'a, str>>,
|
||||
@@ -380,11 +381,11 @@ impl<'a> From<&'a CompactedItem> for CompactedItemWire<'a> {
|
||||
retained_context: item.retained_context.as_ref().map(Cow::Borrowed),
|
||||
mcp_resource_origins: item.mcp_resource_origins.as_ref().map(Cow::Borrowed),
|
||||
window_number: item.window_number,
|
||||
first_window_id: item.first_window_id.as_deref().map(Cow::Borrowed),
|
||||
previous_window_id: item.previous_window_id.as_deref().map(Cow::Borrowed),
|
||||
first_window_id: item.first_window_id.as_ref().map(Cow::Borrowed),
|
||||
previous_window_id: item.previous_window_id.as_ref().map(Cow::Borrowed),
|
||||
window_id: item
|
||||
.window_id
|
||||
.as_deref()
|
||||
.as_ref()
|
||||
.map(|window_id| WindowIdWire::Id(Cow::Borrowed(window_id))),
|
||||
compaction_response_id: item.compaction_response_id.as_deref().map(Cow::Borrowed),
|
||||
latest_token_usage_record: item.latest_token_usage_record.as_ref().map(Cow::Borrowed),
|
||||
@@ -463,6 +464,6 @@ impl TryFrom<CompactedItemWire<'_>> for CompactedItem {
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(untagged)]
|
||||
enum WindowIdWire<'a> {
|
||||
Id(Cow<'a, str>),
|
||||
Id(Cow<'a, ContextWindowId>),
|
||||
LegacyWindowNumber(u64),
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use anyhow::Result;
|
||||
use codex_protocol::ContextWindowId;
|
||||
use codex_protocol::models::AudioReference;
|
||||
use codex_protocol::models::ConfigurationReasoning;
|
||||
use codex_protocol::models::PermissionProfile;
|
||||
@@ -1047,9 +1048,9 @@ fn compacted_item_serializes_window_number_and_id() -> Result<()> {
|
||||
guardian_history: None,
|
||||
mcp_resource_origins: None,
|
||||
window_number: Some(3),
|
||||
first_window_id: Some("019b3f6e-0000-7000-8000-000000000001".to_string()),
|
||||
previous_window_id: Some("019b3f6e-0000-7000-8000-000000000002".to_string()),
|
||||
window_id: Some("019b3f6e-7a10-7cc3-8b6e-1d09e2f7a001".to_string()),
|
||||
first_window_id: ContextWindowId::parse("019b3f6e-0000-7000-8000-000000000001"),
|
||||
previous_window_id: ContextWindowId::parse("019b3f6e-0000-7000-8000-000000000002"),
|
||||
window_id: ContextWindowId::parse("019b3f6e-7a10-7cc3-8b6e-1d09e2f7a001"),
|
||||
compaction_response_id: None,
|
||||
latest_token_usage_record: None,
|
||||
resume_metadata: None,
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
//! Context window identity used for compaction, rollout restoration, and request metadata.
|
||||
|
||||
use schemars::JsonSchema;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
use std::fmt;
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(derive_more::Debug, Clone, PartialEq, Eq, Serialize)]
|
||||
#[derive(derive_more::Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||
#[debug("{_0}")]
|
||||
#[serde(transparent)]
|
||||
pub struct ContextWindowId(String);
|
||||
@@ -21,6 +23,11 @@ impl ContextWindowId {
|
||||
.filter(|uuid| uuid.get_version_num() == 7)
|
||||
.map(|uuid| Self(uuid.to_string()))
|
||||
}
|
||||
|
||||
/// Validate a deserialized window ID before restoring it.
|
||||
pub fn validated(&self) -> Option<Self> {
|
||||
Self::parse(&self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for ContextWindowId {
|
||||
|
||||
@@ -3448,14 +3448,14 @@ pub enum MultiAgentVersion {
|
||||
V2,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema, TS)]
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
|
||||
pub struct SessionContextWindow {
|
||||
/// UUIDv7 identity of this context window.
|
||||
pub window_id: String,
|
||||
pub window_id: crate::ContextWindowId,
|
||||
}
|
||||
|
||||
impl SessionContextWindow {
|
||||
pub fn new(window_id: String) -> Self {
|
||||
pub fn new(window_id: crate::ContextWindowId) -> Self {
|
||||
Self { window_id }
|
||||
}
|
||||
}
|
||||
@@ -3481,7 +3481,7 @@ pub struct HistoryPosition {
|
||||
/// NOTE: There used to be an `instructions` field here, which stored user_instructions, but we
|
||||
/// now save that on TurnContext. base_instructions stores the base instructions for the session,
|
||||
/// and should be used when there is no config override.
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema, TS)]
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema)]
|
||||
pub struct SessionMeta {
|
||||
/// Scope discovery to the creator. Absent on threads created before account filtering.
|
||||
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
|
||||
@@ -3513,7 +3513,6 @@ pub struct SessionMeta {
|
||||
/// An absent value means unknown; an empty list means no roots.
|
||||
/// Keep native paths parseable across hosts; validate them when restoring settings.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
#[ts(optional)]
|
||||
pub runtime_workspace_roots: Option<Vec<PathBuf>>,
|
||||
pub originator: String,
|
||||
pub cli_version: String,
|
||||
@@ -3602,7 +3601,7 @@ impl Default for SessionMeta {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Debug, Clone, JsonSchema, TS)]
|
||||
#[derive(Serialize, Debug, Clone, JsonSchema)]
|
||||
pub struct SessionMetaLine {
|
||||
#[serde(flatten)]
|
||||
pub meta: SessionMeta,
|
||||
|
||||
@@ -117,7 +117,7 @@ pub enum RolloutRecorderParams {
|
||||
history_mode: ThreadHistoryMode,
|
||||
history_base: Option<HistoryPosition>,
|
||||
subagent_history_start_ordinal: Option<u64>,
|
||||
initial_window_id: Option<String>,
|
||||
initial_window_id: Option<codex_protocol::ContextWindowId>,
|
||||
},
|
||||
Resume {
|
||||
path: PathBuf,
|
||||
@@ -373,7 +373,10 @@ impl RolloutRecorderParams {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_initial_window_id(mut self, initial_window_id: String) -> Self {
|
||||
pub fn with_initial_window_id(
|
||||
mut self,
|
||||
initial_window_id: codex_protocol::ContextWindowId,
|
||||
) -> Self {
|
||||
if let Self::Create {
|
||||
initial_window_id: window_id,
|
||||
..
|
||||
|
||||
@@ -699,7 +699,7 @@ async fn recorder_materializes_on_flush_with_pending_items() -> std::io::Result<
|
||||
let config = test_config(home.path());
|
||||
let session_id = SessionId::default();
|
||||
let thread_id = ThreadId::new();
|
||||
let initial_window_id = codex_protocol::ContextWindowId::new_uuid_v7().to_string();
|
||||
let initial_window_id = codex_protocol::ContextWindowId::new_uuid_v7();
|
||||
let recorder = RolloutRecorder::new(
|
||||
&config,
|
||||
RolloutRecorderParams::new(
|
||||
|
||||
@@ -186,7 +186,7 @@ mod tests {
|
||||
history_mode: ThreadHistoryMode::Legacy,
|
||||
history_base: None,
|
||||
subagent_history_start_ordinal: None,
|
||||
initial_window_id: ContextWindowId::new_uuid_v7().to_string(),
|
||||
initial_window_id: ContextWindowId::new_uuid_v7(),
|
||||
runtime_workspace_roots: None,
|
||||
metadata: ThreadPersistenceMetadata {
|
||||
cwd: None,
|
||||
@@ -463,7 +463,7 @@ mod tests {
|
||||
history_mode,
|
||||
history_base: None,
|
||||
subagent_history_start_ordinal: None,
|
||||
initial_window_id: ContextWindowId::new_uuid_v7().to_string(),
|
||||
initial_window_id: ContextWindowId::new_uuid_v7(),
|
||||
runtime_workspace_roots: None,
|
||||
metadata: thread_metadata(),
|
||||
}
|
||||
|
||||
@@ -2406,7 +2406,7 @@ mod tests {
|
||||
history_mode: ThreadHistoryMode::Legacy,
|
||||
history_base: None,
|
||||
subagent_history_start_ordinal: None,
|
||||
initial_window_id: codex_protocol::ContextWindowId::new_uuid_v7().to_string(),
|
||||
initial_window_id: codex_protocol::ContextWindowId::new_uuid_v7(),
|
||||
runtime_workspace_roots: None,
|
||||
metadata: thread_metadata(),
|
||||
}
|
||||
|
||||
@@ -657,7 +657,7 @@ fn create_thread_params(thread_id: ThreadId) -> CreateThreadParams {
|
||||
history_mode: ThreadHistoryMode::Legacy,
|
||||
history_base: None,
|
||||
subagent_history_start_ordinal: None,
|
||||
initial_window_id: codex_protocol::ContextWindowId::new_uuid_v7().to_string(),
|
||||
initial_window_id: codex_protocol::ContextWindowId::new_uuid_v7(),
|
||||
runtime_workspace_roots: None,
|
||||
metadata: ThreadPersistenceMetadata {
|
||||
cwd: Some(std::env::current_dir().expect("cwd")),
|
||||
|
||||
@@ -368,7 +368,7 @@ async fn create_paginated_thread(store: &LocalThreadStore, thread_id: ThreadId)
|
||||
history_mode: ThreadHistoryMode::Paginated,
|
||||
history_base: None,
|
||||
subagent_history_start_ordinal: None,
|
||||
initial_window_id: "window-1".to_string(),
|
||||
initial_window_id: codex_protocol::ContextWindowId::new_uuid_v7(),
|
||||
runtime_workspace_roots: Some(vec![store.config.codex_home.join("workspace").abs()]),
|
||||
metadata: ThreadPersistenceMetadata {
|
||||
cwd: Some(std::env::current_dir().expect("cwd")),
|
||||
|
||||
@@ -138,7 +138,7 @@ async fn split_homes_support_backfill_listing_and_paginated_history() {
|
||||
Vec::new(),
|
||||
)
|
||||
.with_history_mode(ThreadHistoryMode::Paginated)
|
||||
.with_initial_window_id("window-1".to_string()),
|
||||
.with_initial_window_id(codex_protocol::ContextWindowId::new_uuid_v7()),
|
||||
)
|
||||
.await
|
||||
.expect("create paginated rollout");
|
||||
@@ -775,7 +775,7 @@ async fn paginated_realtime_items_materialize_separately_in_rollout_order() {
|
||||
history_mode: ThreadHistoryMode::Legacy,
|
||||
history_base: None,
|
||||
subagent_history_start_ordinal: None,
|
||||
initial_window_id: "window-1".to_string(),
|
||||
initial_window_id: codex_protocol::ContextWindowId::new_uuid_v7(),
|
||||
runtime_workspace_roots: None,
|
||||
metadata: ThreadPersistenceMetadata {
|
||||
cwd: Some(home.path().to_path_buf()),
|
||||
@@ -3097,7 +3097,7 @@ async fn create_paginated_subagent_thread(
|
||||
history_mode: ThreadHistoryMode::Paginated,
|
||||
history_base,
|
||||
subagent_history_start_ordinal,
|
||||
initial_window_id: "window-1".to_string(),
|
||||
initial_window_id: codex_protocol::ContextWindowId::new_uuid_v7(),
|
||||
runtime_workspace_roots: None,
|
||||
metadata: ThreadPersistenceMetadata {
|
||||
cwd: Some(std::env::current_dir().expect("cwd")),
|
||||
|
||||
@@ -508,7 +508,7 @@ mod tests {
|
||||
history_mode: ThreadHistoryMode::Legacy,
|
||||
history_base: None,
|
||||
subagent_history_start_ordinal: None,
|
||||
initial_window_id: codex_protocol::ContextWindowId::new_uuid_v7().to_string(),
|
||||
initial_window_id: codex_protocol::ContextWindowId::new_uuid_v7(),
|
||||
runtime_workspace_roots: None,
|
||||
metadata: ThreadPersistenceMetadata {
|
||||
cwd: None,
|
||||
|
||||
@@ -113,7 +113,7 @@ pub struct CreateThreadParams {
|
||||
/// First rollout ordinal that belongs to this subagent's projected history.
|
||||
pub subagent_history_start_ordinal: Option<u64>,
|
||||
/// Initial context-window identity captured when the thread was created.
|
||||
pub initial_window_id: String,
|
||||
pub initial_window_id: codex_protocol::ContextWindowId,
|
||||
/// Runtime workspace roots at creation, excluding permission-profile roots.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub runtime_workspace_roots: Option<Vec<AbsolutePathBuf>>,
|
||||
|
||||
Reference in New Issue
Block a user