mirror of
https://github.com/openai/codex.git
synced 2026-10-18 17:18:52 +00:00
Honor Guardian runtime settings from model defaults (#39738)
## What changed - Add `max_tool_call_lag`, `reuse_parent_compaction`, and transcript `include_images` to the Guardian model configuration. - Inherit these settings from model defaults while preserving explicit local overrides. - Enable image capture for Node REPL review evidence when transcript images are included. ## Testing - Cover inheritance and local override precedence for the new settings. - Verify that enabling transcript images initializes review-evidence capture. GitOrigin-RevId: 7c1965c2ec00a78a0436fa916b630be0004dbb51
This commit is contained in:
@@ -75,6 +75,9 @@ impl GuardianV2Config {
|
||||
.review_threshold_basis_points
|
||||
.map(|basis_points| f64::from(basis_points) / 10_000.0)
|
||||
});
|
||||
configured.max_tool_call_lag = configured
|
||||
.max_tool_call_lag
|
||||
.or(model_defaults.max_tool_call_lag);
|
||||
configured.reasoning_effort = configured
|
||||
.reasoning_effort
|
||||
.or_else(|| model_defaults.reasoning_effort.clone());
|
||||
@@ -84,6 +87,9 @@ impl GuardianV2Config {
|
||||
configured.max_classifier_instruction_tokens = configured
|
||||
.max_classifier_instruction_tokens
|
||||
.or(model_defaults.max_classifier_instruction_tokens);
|
||||
configured.reuse_parent_compaction = configured
|
||||
.reuse_parent_compaction
|
||||
.or(model_defaults.reuse_parent_compaction);
|
||||
configured.max_parent_compaction_tokens = configured
|
||||
.max_parent_compaction_tokens
|
||||
.or(model_defaults.max_parent_compaction_tokens);
|
||||
@@ -109,6 +115,9 @@ impl GuardianV2Config {
|
||||
.collect::<Result<Vec<_>, _>>()?,
|
||||
);
|
||||
}
|
||||
transcript.include_images = transcript
|
||||
.include_images
|
||||
.or(model_transcript.include_images);
|
||||
transcript.max_message_entry_tokens = transcript
|
||||
.max_message_entry_tokens
|
||||
.or(model_transcript.max_message_entry_tokens);
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
use codex_features::GuardianV2ConfigToml;
|
||||
use codex_features::GuardianV2ReviewScopeConfigToml;
|
||||
use codex_features::GuardianV2TranscriptConfigToml;
|
||||
use codex_protocol::openai_models::GuardianV2ModelConfig;
|
||||
use codex_protocol::openai_models::GuardianV2TranscriptModelConfig;
|
||||
use codex_protocol::openai_models::ReasoningEffort;
|
||||
use codex_protocol::protocol::TruncationPolicy;
|
||||
use pretty_assertions::assert_eq;
|
||||
@@ -145,3 +147,49 @@ fn model_prompt_and_explicit_threshold_precedence_are_preserved() {
|
||||
0.5,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn model_runtime_settings_preserve_local_overrides() {
|
||||
let defaults = GuardianV2ModelConfig {
|
||||
max_tool_call_lag: Some(1),
|
||||
reuse_parent_compaction: Some(false),
|
||||
transcript: Some(GuardianV2TranscriptModelConfig {
|
||||
include_images: Some(true),
|
||||
..Default::default()
|
||||
}),
|
||||
..Default::default()
|
||||
};
|
||||
let inherited = GuardianV2Config::from_overrides(GuardianV2ConfigToml::default())
|
||||
.unwrap()
|
||||
.with_model_defaults(Some(&defaults))
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
(
|
||||
inherited.max_tool_call_lag,
|
||||
inherited.reuse_parent_compaction,
|
||||
inherited.transcript.include_images,
|
||||
),
|
||||
(1, false, true)
|
||||
);
|
||||
|
||||
let overridden = GuardianV2Config::from_overrides(GuardianV2ConfigToml {
|
||||
max_tool_call_lag: Some(4),
|
||||
reuse_parent_compaction: Some(true),
|
||||
transcript: Some(GuardianV2TranscriptConfigToml {
|
||||
include_images: Some(false),
|
||||
..Default::default()
|
||||
}),
|
||||
..Default::default()
|
||||
})
|
||||
.unwrap()
|
||||
.with_model_defaults(Some(&defaults))
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
(
|
||||
overridden.max_tool_call_lag,
|
||||
overridden.reuse_parent_compaction,
|
||||
overridden.transcript.include_images,
|
||||
),
|
||||
(4, true, false)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -461,6 +461,12 @@ impl GuardianV2Extension {
|
||||
return;
|
||||
}
|
||||
};
|
||||
if guardian_config.transcript.include_images {
|
||||
input
|
||||
.thread_store
|
||||
.get_or_init(NodeReplReviewEvidence::default)
|
||||
.enable_image_capture();
|
||||
}
|
||||
input.thread_store.insert(guardian_config.clone());
|
||||
let tool_call_index = score_progress
|
||||
.latest_tool_call
|
||||
|
||||
@@ -7,6 +7,7 @@ use std::time::SystemTime;
|
||||
|
||||
use anyhow::Result;
|
||||
use codex_core::config::Config;
|
||||
use codex_core::context::NodeReplReviewEvidence;
|
||||
use codex_extension_api::ConversationHistorySnapshot;
|
||||
use codex_extension_api::ExtensionData;
|
||||
use codex_extension_api::ExtensionMetrics;
|
||||
@@ -1231,15 +1232,18 @@ async fn contributor_uses_model_defaults_and_preserves_local_overrides() -> Resu
|
||||
let model_defaults = GuardianV2ModelConfig {
|
||||
classifier_instructions: Some("Use the experimental model-owned prompt.".to_owned()),
|
||||
review_threshold_basis_points: Some(6_000),
|
||||
max_tool_call_lag: Some(2),
|
||||
reasoning_effort: Some(ReasoningEffort::Minimal),
|
||||
transcript: Some(GuardianV2TranscriptModelConfig {
|
||||
sources: Some(vec!["reasoning".to_owned()]),
|
||||
include_images: Some(true),
|
||||
max_message_entry_tokens: Some(128),
|
||||
max_message_transcript_tokens: Some(256),
|
||||
..Default::default()
|
||||
}),
|
||||
max_action_tokens: Some(128),
|
||||
max_classifier_instruction_tokens: Some(256),
|
||||
reuse_parent_compaction: Some(false),
|
||||
max_parent_compaction_tokens: Some(384),
|
||||
};
|
||||
let conversation_history = vec![
|
||||
@@ -1312,13 +1316,19 @@ async fn contributor_uses_model_defaults_and_preserves_local_overrides() -> Resu
|
||||
|
||||
let session_store = ExtensionData::new("session-1");
|
||||
let thread_store = test.codex.thread_extension_data();
|
||||
let guardian_config = thread_store
|
||||
.get::<crate::async_scorer::config::GuardianV2Config>()
|
||||
.expect("Guardian v2 configuration should be installed");
|
||||
assert_eq!(
|
||||
thread_store
|
||||
.get::<crate::async_scorer::config::GuardianV2Config>()
|
||||
.expect("Guardian v2 configuration should be installed")
|
||||
.max_parent_compaction_tokens,
|
||||
384
|
||||
(
|
||||
guardian_config.max_tool_call_lag,
|
||||
guardian_config.reuse_parent_compaction,
|
||||
guardian_config.max_parent_compaction_tokens,
|
||||
guardian_config.transcript.include_images,
|
||||
),
|
||||
(2, false, 384, true)
|
||||
);
|
||||
assert!(thread_store.get::<NodeReplReviewEvidence>().is_some());
|
||||
tokio::time::timeout(Duration::from_secs(5), async {
|
||||
while thread_store.get::<SecurityRiskScore>().is_none() {
|
||||
tokio::task::yield_now().await;
|
||||
|
||||
@@ -13,6 +13,8 @@ pub struct GuardianV2ModelConfig {
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub review_threshold_basis_points: Option<u16>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub max_tool_call_lag: Option<usize>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub reasoning_effort: Option<ReasoningEffort>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub transcript: Option<GuardianV2TranscriptModelConfig>,
|
||||
@@ -21,6 +23,8 @@ pub struct GuardianV2ModelConfig {
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub max_classifier_instruction_tokens: Option<usize>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub reuse_parent_compaction: Option<bool>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub max_parent_compaction_tokens: Option<usize>,
|
||||
}
|
||||
|
||||
@@ -30,6 +34,8 @@ pub struct GuardianV2TranscriptModelConfig {
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub sources: Option<Vec<String>>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub include_images: Option<bool>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub max_message_entry_tokens: Option<usize>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub max_tool_entry_tokens: Option<usize>,
|
||||
|
||||
Reference in New Issue
Block a user