mirror of
https://github.com/openai/codex.git
synced 2026-11-14 21:40:39 +00:00
Defer Guardian context limits to request preparation (#61185)
## What changed Preserve original root conversation evidence, retained instructions, assistant context, and verified answers until request preparation. Apply shared section preparation to both synchronous and asynchronous reviews, preserving fixed limits and omission notices while allowing elastic preparation to use the originals. Cache the fixed root view for reuse. Split classifier setup from final input assembly and normalize new images before deduplication and token accounting, preserving committed history. ## Testing Extend tests for fixed and elastic preparation across both review profiles, original root evidence after handoff, and image normalization during retained-request preparation. GitOrigin-RevId: 86c83384c1f5be3707622d675fc54b4c8e1ddc0a
This commit is contained in:
@@ -1304,17 +1304,13 @@ impl CodexThread {
|
||||
.authorization_version(history.as_ref())
|
||||
}
|
||||
|
||||
/// Returns bounded root conversation evidence and its authorization version atomically.
|
||||
/// Captures root originals and authorization before request-size preparation.
|
||||
pub async fn guardian_root_snapshot(&self) -> Option<GuardianRootSnapshot> {
|
||||
let mut snapshot = self
|
||||
.session
|
||||
self.session
|
||||
.services
|
||||
.agent_control
|
||||
.get_guardian_package(self.session.thread_id)
|
||||
.await?;
|
||||
// Async consumers need only the bounded projection, not the sync source snapshot.
|
||||
snapshot.request_candidates = None;
|
||||
Some(snapshot)
|
||||
.await
|
||||
}
|
||||
|
||||
/// Refresh the thread's layer-backed user config state from a caller-supplied
|
||||
|
||||
@@ -4270,16 +4270,10 @@ impl Config {
|
||||
FeatureToml::Enabled(_) => None,
|
||||
})
|
||||
.unwrap_or_default();
|
||||
let guardian_sync_elastic_budget = cfg.features.as_ref()
|
||||
.and_then(|features| features.guardianv2.as_ref())
|
||||
.and_then(|feature| match feature {
|
||||
FeatureToml::Config(guardian) if guardian.sync_elastic_budgeting == Some(true) => Some(guardian),
|
||||
FeatureToml::Config(_) | FeatureToml::Enabled(_) => None,
|
||||
})
|
||||
.map(|guardian| {
|
||||
let sections = guardian.sync_elastic_sections.as_ref().filter(|sections| !sections.is_empty())
|
||||
let resolve_elastic_budget = |named_sections: Option<&BTreeMap<String, codex_features::GuardianElasticSectionConfigToml>>, prefix: &str| {
|
||||
let sections = named_sections.filter(|sections| !sections.is_empty())
|
||||
.ok_or_else(|| std::io::Error::new(std::io::ErrorKind::InvalidData,
|
||||
"sync_elastic_sections is required when sync_elastic_budgeting is enabled"))?;
|
||||
format!("{prefix}_elastic_sections is required when {prefix}_elastic_budgeting is enabled")))?;
|
||||
let mut policy = codex_guardian_context::ElasticBudgetConfig::default();
|
||||
for (name, limits) in sections {
|
||||
let section = codex_guardian_context::ElasticSection::deserialize(name.as_str().into_deserializer())
|
||||
@@ -4304,12 +4298,22 @@ impl Config {
|
||||
}
|
||||
if policy.sections.insert(section, section_limits).is_some() {
|
||||
return Err(std::io::Error::new(std::io::ErrorKind::InvalidData,
|
||||
format!("duplicate sync_elastic_sections section: {name}")));
|
||||
format!("duplicate {prefix}_elastic_sections section: {name}")));
|
||||
}
|
||||
}
|
||||
policy.validate().map_err(|error| std::io::Error::new(std::io::ErrorKind::InvalidData, error))?;
|
||||
Ok::<_, std::io::Error>(policy)
|
||||
}).transpose()?;
|
||||
};
|
||||
let guardian = cfg.features.as_ref()
|
||||
.and_then(|features| features.guardianv2.as_ref())
|
||||
.and_then(|feature| match feature {
|
||||
FeatureToml::Config(guardian) => Some(guardian),
|
||||
FeatureToml::Enabled(_) => None,
|
||||
});
|
||||
let guardian_sync_elastic_budget = guardian
|
||||
.filter(|guardian| guardian.sync_elastic_budgeting == Some(true))
|
||||
.map(|guardian| resolve_elastic_budget(guardian.sync_elastic_sections.as_ref(), "sync"))
|
||||
.transpose()?;
|
||||
let guardian_conversation_history_prompt = cfg.auto_review.as_ref().and_then(|auto_review| {
|
||||
normalize_guardian_policy_config(
|
||||
auto_review.experimental_conversation_history_prompt.as_deref(),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//! Marks bounded assistant evidence used to interpret user replies in Guardian reviews.
|
||||
//! Marks assistant evidence used to interpret user replies in Guardian reviews.
|
||||
//! Assistant text remains conversational context and never grants authorization.
|
||||
|
||||
use codex_history::RetainedUserMessage;
|
||||
@@ -39,8 +39,8 @@ pub fn render_retained_assistant_context(message: &RetainedUserMessage) -> Optio
|
||||
render_original_assistant_context(message)
|
||||
}
|
||||
|
||||
/// Preserves the host fragment boundary while deferring sync size admission.
|
||||
pub(crate) fn render_original_assistant_context(message: &RetainedUserMessage) -> Option<String> {
|
||||
/// Preserves the host fragment boundary while deferring request size admission.
|
||||
pub fn render_original_assistant_context(message: &RetainedUserMessage) -> Option<String> {
|
||||
if !message.complete {
|
||||
return None;
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ pub(crate) use current_time_reminder::CurrentTimeUnavailable;
|
||||
pub(crate) use developer_instructions::DeveloperInstructions;
|
||||
pub(crate) use environments_instructions::EnvironmentsInstructions;
|
||||
pub(crate) use guardian_approved_action::GuardianApprovedAction;
|
||||
pub(crate) use guardian_assistant_context::render_original_assistant_context;
|
||||
pub use guardian_assistant_context::render_original_assistant_context;
|
||||
pub use guardian_assistant_context::render_retained_assistant_context;
|
||||
pub(crate) use guardian_conversation_history::GuardianConversationHistory;
|
||||
pub(crate) use guardian_followup_review_reminder::GuardianFollowupReviewReminder;
|
||||
|
||||
Reference in New Issue
Block a user