Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions codex-rs/core/src/guardian/review_session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use std::time::Duration;
use anyhow::anyhow;
use codex_analytics::GuardianReviewAnalyticsResult;
use codex_analytics::GuardianReviewSessionKind;
use codex_protocol::ThreadId;
use codex_protocol::config_types::AutoCompactTokenLimitScope;
use codex_protocol::config_types::Personality;
use codex_protocol::config_types::ReasoningSummary as ReasoningSummaryConfig;
Expand All @@ -20,6 +21,7 @@ use codex_protocol::protocol::InitialHistory;
use codex_protocol::protocol::Op;
use codex_protocol::protocol::RolloutItem;
use codex_protocol::protocol::SandboxPolicy;
use codex_protocol::protocol::SessionSource;
use codex_protocol::protocol::SubAgentSource;
use codex_protocol::protocol::TokenUsage;
use serde_json::Value;
Expand Down Expand Up @@ -183,6 +185,20 @@ impl GuardianReviewSessionReuseKey {
}
}

pub(crate) fn prompt_cache_key_override_for_review_session(
session_source: &SessionSource,
parent_thread_id: Option<ThreadId>,
) -> Option<String> {
let SessionSource::SubAgent(SubAgentSource::Other(name)) = session_source else {
return None;
};
if name != GUARDIAN_REVIEWER_NAME {
return None;
}
let parent_thread_id = parent_thread_id?;
Some(format!("guardian:{parent_thread_id}"))
}

impl GuardianReviewSession {
async fn shutdown(&self) {
self.cancel_token.cancel();
Expand Down Expand Up @@ -1160,6 +1176,43 @@ mod tests {
);
}

#[tokio::test]
async fn guardian_prompt_cache_key_is_scoped_to_parent_thread() {
let session_source =
SessionSource::SubAgent(SubAgentSource::Other(GUARDIAN_REVIEWER_NAME.to_string()));
let parent_thread_id = ThreadId::new();
let key =
prompt_cache_key_override_for_review_session(&session_source, Some(parent_thread_id))
.expect("guardian prompt cache key");

assert_eq!(key, format!("guardian:{parent_thread_id}"));
assert!(
key.len() <= 64,
"guardian prompt cache key should fit the Responses API limit"
);
assert_eq!(
key,
prompt_cache_key_override_for_review_session(&session_source, Some(parent_thread_id))
.expect("same guardian prompt cache key")
);
assert_ne!(
key,
prompt_cache_key_override_for_review_session(&session_source, Some(ThreadId::new()))
.expect("different parent guardian prompt cache key")
);
assert_eq!(
None,
prompt_cache_key_override_for_review_session(
&SessionSource::Cli,
Some(parent_thread_id)
)
);
assert_eq!(
None,
prompt_cache_key_override_for_review_session(&session_source, None)
);
}

#[tokio::test]
async fn guardian_review_session_compact_scope_change_invalidates_cached_session() {
let parent_config = crate::config::test_config().await;
Expand Down
Loading