mirror of
https://github.com/openai/codex.git
synced 2026-10-18 17:18:52 +00:00
Centralize persistent mode enablement checks (#48611)
## What changed Add `Features::persistent_mode_enabled` and use it for persistent instructions and current-time reminder defaults. Enablement still requires `ReasoningEffort::Persistent`. Change `PersistentModeState::new` to accept an explicit enablement boolean, separating instruction rendering from reasoning-effort selection. ## Testing Update persistent-context tests to use boolean enablement while preserving coverage for instruction replacement, removal, deduplication, and retained history without a snapshot. GitOrigin-RevId: f412b90d783438d1526956a56c11b9e66385ee0e
This commit is contained in:
committed by
copyberry
parent
9db8162d65
commit
814de47b69
@@ -6,7 +6,6 @@ use super::WorldStateHash;
|
||||
use super::WorldStateSection;
|
||||
use crate::context::ContextualUserFragment;
|
||||
use codex_protocol::models::ContentItemKind;
|
||||
use codex_protocol::openai_models::ReasoningEffort;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
||||
@@ -49,11 +48,11 @@ pub(crate) struct PersistentModeSnapshot {
|
||||
|
||||
impl PersistentModeState {
|
||||
pub(crate) fn new(
|
||||
reasoning_effort: Option<&ReasoningEffort>,
|
||||
enabled: bool,
|
||||
instructions_template: &str,
|
||||
send_user_message_async_available: bool,
|
||||
) -> Self {
|
||||
let instructions = if reasoning_effort == Some(&ReasoningEffort::Persistent) {
|
||||
let instructions = if enabled {
|
||||
instructions_template.trim().replace(
|
||||
"{{ approval_request_channel }}",
|
||||
if send_user_message_async_available {
|
||||
|
||||
@@ -1,35 +1,29 @@
|
||||
//! Covers effort selection and persistent-context transitions.
|
||||
//! Covers persistent-context transitions independently of effort selection.
|
||||
|
||||
use super::*;
|
||||
use crate::context::world_state::WorldState;
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
#[test]
|
||||
fn persistent_instructions_follow_effort_and_catalog_updates_without_duplicates() {
|
||||
fn persistent_instructions_follow_mode_and_catalog_updates_without_duplicates() {
|
||||
let mut history = Vec::new();
|
||||
let mut previous = None;
|
||||
let persistent = Some(ReasoningEffort::Persistent);
|
||||
let medium = Some(ReasoningEffort::Medium);
|
||||
let replacement = format!("{REPLACEMENT_NOTICE}\n\nupdated instructions");
|
||||
|
||||
for (effort, instructions, expected) in [
|
||||
(None, "", None),
|
||||
(persistent.clone(), "instructions", Some("instructions")),
|
||||
(persistent.clone(), "instructions", None),
|
||||
(
|
||||
persistent.clone(),
|
||||
"updated instructions",
|
||||
Some(replacement.as_str()),
|
||||
),
|
||||
(persistent.clone(), "", Some(REMOVAL_NOTICE)),
|
||||
(persistent.clone(), "", None),
|
||||
(persistent, "instructions", Some("instructions")),
|
||||
(medium.clone(), "", Some(REMOVAL_NOTICE)),
|
||||
(medium, "", None),
|
||||
for (enabled, instructions, expected) in [
|
||||
(false, "", None),
|
||||
(true, "instructions", Some("instructions")),
|
||||
(true, "instructions", None),
|
||||
(true, "updated instructions", Some(replacement.as_str())),
|
||||
(true, "", Some(REMOVAL_NOTICE)),
|
||||
(true, "", None),
|
||||
(true, "instructions", Some("instructions")),
|
||||
(false, "", Some(REMOVAL_NOTICE)),
|
||||
(false, "", None),
|
||||
] {
|
||||
let mut world_state = WorldState::default();
|
||||
world_state.add_section(PersistentModeState::new(
|
||||
effort.as_ref(),
|
||||
enabled,
|
||||
instructions,
|
||||
/*send_user_message_async_available*/ false,
|
||||
));
|
||||
@@ -59,16 +53,16 @@ fn retained_persistent_instructions_are_replaced_or_retired_without_a_snapshot()
|
||||
let retained = ContextualUserFragment::into(PersistentModeState {
|
||||
instructions: "previous instructions".to_string(),
|
||||
});
|
||||
for (effort, expected) in [
|
||||
for (enabled, expected) in [
|
||||
(
|
||||
ReasoningEffort::Persistent,
|
||||
true,
|
||||
format!("{REPLACEMENT_NOTICE}\n\ncurrent instructions"),
|
||||
),
|
||||
(ReasoningEffort::Medium, REMOVAL_NOTICE.to_string()),
|
||||
(false, REMOVAL_NOTICE.to_string()),
|
||||
] {
|
||||
let mut world_state = WorldState::default();
|
||||
world_state.add_section(PersistentModeState::new(
|
||||
Some(&effort),
|
||||
enabled,
|
||||
"current instructions",
|
||||
/*send_user_message_async_available*/ false,
|
||||
));
|
||||
|
||||
@@ -25,7 +25,6 @@ use codex_protocol::config_types::ShellEnvironmentPolicy;
|
||||
use codex_protocol::models::AdditionalPermissionProfile;
|
||||
use codex_protocol::openai_models::MODEL_SPECIALTY_CYBER;
|
||||
use codex_protocol::openai_models::ModelInfo;
|
||||
use codex_protocol::openai_models::ReasoningEffort;
|
||||
use codex_protocol::permissions::RawFileSystemSandboxPolicy;
|
||||
use codex_protocol::protocol::EnvironmentConfig;
|
||||
use codex_protocol::protocol::EnvironmentConfigState;
|
||||
@@ -955,7 +954,10 @@ impl Session {
|
||||
use_model_token_budget_defaults,
|
||||
model_info,
|
||||
);
|
||||
if step_settings.reasoning_effort() == Some(&ReasoningEffort::Persistent) {
|
||||
if per_turn_config
|
||||
.features
|
||||
.persistent_mode_enabled(step_settings.reasoning_effort())
|
||||
{
|
||||
super::time_reminder::apply_persistent_defaults(&mut per_turn_config);
|
||||
}
|
||||
per_turn_config.service_tier = step_settings.service_tier.clone();
|
||||
|
||||
@@ -218,7 +218,9 @@ impl Session {
|
||||
.iter()
|
||||
.any(|tool| tool == "send_user_message_async");
|
||||
world_state.add_section(PersistentModeState::new(
|
||||
step_context.settings.effective_reasoning_effort().as_ref(),
|
||||
turn_context.config.features.persistent_mode_enabled(
|
||||
step_context.settings.effective_reasoning_effort().as_ref(),
|
||||
),
|
||||
model_messages.persistent_instructions(),
|
||||
send_user_message_async_available,
|
||||
));
|
||||
|
||||
@@ -39,6 +39,7 @@ use codex_protocol::items::TurnItem;
|
||||
use codex_protocol::models::ImageReference;
|
||||
use codex_protocol::models::ResponseItem;
|
||||
use codex_protocol::openai_models::CodeModeToolMessages;
|
||||
use codex_protocol::openai_models::ReasoningEffort;
|
||||
use codex_protocol::openai_models::ToolMessage;
|
||||
use codex_protocol::openai_models::ToolMode;
|
||||
use codex_protocol::protocol::EnvironmentConfigState;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
//! This crate defines the feature registry plus the logic used to resolve an
|
||||
//! effective feature set from config-like inputs.
|
||||
|
||||
use codex_protocol::openai_models::ReasoningEffort;
|
||||
use codex_protocol::protocol::Event;
|
||||
use codex_protocol::protocol::EventMsg;
|
||||
use codex_protocol::protocol::WarningEvent;
|
||||
@@ -513,6 +514,11 @@ impl Features {
|
||||
self.enabled.contains(&f)
|
||||
}
|
||||
|
||||
/// Returns whether persistent execution is enabled for the selected effort.
|
||||
pub fn persistent_mode_enabled(&self, reasoning_effort: Option<&ReasoningEffort>) -> bool {
|
||||
reasoning_effort == Some(&ReasoningEffort::Persistent)
|
||||
}
|
||||
|
||||
pub fn apps_enabled_for_auth(&self, has_chatgpt_auth: bool) -> bool {
|
||||
self.enabled(Feature::Apps) && has_chatgpt_auth
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user