mirror of
https://github.com/openai/codex.git
synced 2026-04-24 14:45:27 +00:00
feat: set policy for phase 2 memory (#11449)
Set the policy of the memory phase 2 worker such that it never ask for approval
This commit is contained in:
@@ -92,6 +92,29 @@ impl<T: Send + Sync> Constrained<T> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn allow_only(only_value: T) -> Self
|
||||
where
|
||||
T: Clone + fmt::Debug + PartialEq + 'static,
|
||||
{
|
||||
let allowed_value = only_value.clone();
|
||||
Self {
|
||||
value: only_value,
|
||||
validator: Arc::new(move |candidate| {
|
||||
if candidate == &allowed_value {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(ConstraintError::InvalidValue {
|
||||
field_name: "<unknown>",
|
||||
candidate: format!("{candidate:?}"),
|
||||
allowed: format!("[{allowed_value:?}]"),
|
||||
requirement_source: RequirementSource::Unknown,
|
||||
})
|
||||
}
|
||||
}),
|
||||
normalizer: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Allow any value of T, using T's Default as the initial value.
|
||||
pub fn allow_any_from_default() -> Self
|
||||
where
|
||||
@@ -176,6 +199,20 @@ mod tests {
|
||||
assert_eq!(constrained.value(), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn constrained_allow_only_rejects_different_values() {
|
||||
let mut constrained = Constrained::allow_only(5);
|
||||
constrained
|
||||
.set(5)
|
||||
.expect("allowed value should be accepted");
|
||||
|
||||
let err = constrained
|
||||
.set(6)
|
||||
.expect_err("different value should be rejected");
|
||||
assert_eq!(err, invalid_value("6", "[5]"));
|
||||
assert_eq!(constrained.value(), 5);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn constrained_normalizer_applies_on_init_and_set() -> anyhow::Result<()> {
|
||||
let mut constrained = Constrained::normalized(-1, |value| value.max(0))?;
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
use crate::codex::Session;
|
||||
use crate::config::Config;
|
||||
use crate::config::Constrained;
|
||||
use crate::memories::memory_root;
|
||||
use codex_protocol::protocol::AskForApproval;
|
||||
use codex_protocol::protocol::SandboxPolicy;
|
||||
use codex_protocol::protocol::SessionSource;
|
||||
use codex_protocol::protocol::SubAgentSource;
|
||||
use codex_protocol::user_input::UserInput;
|
||||
use codex_utils_absolute_path::AbsolutePathBuf;
|
||||
use std::sync::Arc;
|
||||
use tracing::debug;
|
||||
use tracing::info;
|
||||
@@ -64,6 +68,42 @@ pub(super) async fn run_global_memory_consolidation(
|
||||
}
|
||||
};
|
||||
|
||||
let root = memory_root(&config.codex_home);
|
||||
let consolidation_config = {
|
||||
let mut consolidation_config = config.as_ref().clone();
|
||||
consolidation_config.cwd = root.clone();
|
||||
consolidation_config.approval_policy = Constrained::allow_only(AskForApproval::Never);
|
||||
let mut writable_roots = Vec::new();
|
||||
match AbsolutePathBuf::from_absolute_path(consolidation_config.codex_home.clone()) {
|
||||
Ok(codex_home) => writable_roots.push(codex_home),
|
||||
Err(err) => warn!(
|
||||
"memory phase-2 consolidation could not add codex_home writable root {}: {err}",
|
||||
consolidation_config.codex_home.display()
|
||||
),
|
||||
}
|
||||
let consolidation_sandbox_policy = SandboxPolicy::WorkspaceWrite {
|
||||
writable_roots,
|
||||
network_access: false,
|
||||
exclude_tmpdir_env_var: false,
|
||||
exclude_slash_tmp: false,
|
||||
};
|
||||
if let Err(err) = consolidation_config
|
||||
.sandbox_policy
|
||||
.set(consolidation_sandbox_policy)
|
||||
{
|
||||
warn!("memory phase-2 consolidation sandbox policy was rejected by constraints: {err}");
|
||||
let _ = state_db
|
||||
.mark_global_phase2_job_failed(
|
||||
&ownership_token,
|
||||
"consolidation sandbox policy was rejected by constraints",
|
||||
PHASE_TWO_JOB_RETRY_DELAY_SECONDS,
|
||||
)
|
||||
.await;
|
||||
return false;
|
||||
}
|
||||
consolidation_config
|
||||
};
|
||||
|
||||
let latest_memories = match state_db
|
||||
.list_stage1_outputs_for_global(MAX_RAW_MEMORIES_FOR_GLOBAL)
|
||||
.await
|
||||
@@ -81,7 +121,6 @@ pub(super) async fn run_global_memory_consolidation(
|
||||
return false;
|
||||
}
|
||||
};
|
||||
let root = memory_root(&config.codex_home);
|
||||
let completion_watermark = completion_watermark(claimed_watermark, &latest_memories);
|
||||
if let Err(err) = sync_rollout_summaries_from_memories(&root, &latest_memories).await {
|
||||
warn!("failed syncing local memory artifacts for global consolidation: {err}");
|
||||
@@ -119,8 +158,6 @@ pub(super) async fn run_global_memory_consolidation(
|
||||
text: prompt,
|
||||
text_elements: vec![],
|
||||
}];
|
||||
let mut consolidation_config = config.as_ref().clone();
|
||||
consolidation_config.cwd = root.clone();
|
||||
let source = SessionSource::SubAgent(SubAgentSource::Other(
|
||||
MEMORY_CONSOLIDATION_SUBAGENT_LABEL.to_string(),
|
||||
));
|
||||
@@ -173,7 +210,9 @@ mod tests {
|
||||
use crate::memories::rollout_summaries_dir;
|
||||
use chrono::Utc;
|
||||
use codex_protocol::ThreadId;
|
||||
use codex_protocol::protocol::AskForApproval;
|
||||
use codex_protocol::protocol::Op;
|
||||
use codex_protocol::protocol::SandboxPolicy;
|
||||
use codex_protocol::protocol::SessionSource;
|
||||
use codex_state::Phase2JobClaimOutcome;
|
||||
use codex_state::Stage1Output;
|
||||
@@ -336,6 +375,27 @@ mod tests {
|
||||
|
||||
let user_input_ops = harness.user_input_ops_count();
|
||||
assert_eq!(user_input_ops, 1);
|
||||
let thread_ids = harness.manager.list_thread_ids().await;
|
||||
assert_eq!(thread_ids.len(), 1);
|
||||
let subagent = harness
|
||||
.manager
|
||||
.get_thread(thread_ids[0])
|
||||
.await
|
||||
.expect("get consolidation thread");
|
||||
let config_snapshot = subagent.config_snapshot().await;
|
||||
assert_eq!(config_snapshot.approval_policy, AskForApproval::Never);
|
||||
assert_eq!(config_snapshot.cwd, memory_root(&harness.config.codex_home));
|
||||
match config_snapshot.sandbox_policy {
|
||||
SandboxPolicy::WorkspaceWrite { writable_roots, .. } => {
|
||||
assert!(
|
||||
writable_roots
|
||||
.iter()
|
||||
.any(|root| root.as_path() == harness.config.codex_home.as_path()),
|
||||
"consolidation subagent should have codex_home as writable root"
|
||||
);
|
||||
}
|
||||
other => panic!("unexpected sandbox policy: {other:?}"),
|
||||
}
|
||||
|
||||
harness.shutdown_threads().await;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user