mirror of
https://github.com/openai/codex.git
synced 2026-09-04 15:08:45 +00:00
Preserve selected roots in bounded agent forks
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
use super::residency::is_v2_resident_session_source;
|
||||
use super::*;
|
||||
use codex_extension_api::ExtensionDataInit;
|
||||
|
||||
const AGENT_NAMES: &str = include_str!("../agent_names.txt");
|
||||
|
||||
@@ -433,6 +434,16 @@ impl AgentControl {
|
||||
))
|
||||
})?;
|
||||
|
||||
let selected_capability_roots = parent_history
|
||||
.items
|
||||
.iter()
|
||||
.find_map(|item| {
|
||||
let RolloutItem::SessionMeta(meta_line) = item else {
|
||||
return None;
|
||||
};
|
||||
Some(meta_line.meta.selected_capability_roots.clone())
|
||||
})
|
||||
.unwrap_or_default();
|
||||
let mut forked_rollout_items = parent_history.items;
|
||||
if let SpawnAgentForkMode::LastNTurns(last_n_turns) = fork_mode {
|
||||
forked_rollout_items =
|
||||
@@ -504,6 +515,8 @@ impl AgentControl {
|
||||
{
|
||||
forked_rollout_items.push(RolloutItem::ResponseItem(subagent_usage_hint_message));
|
||||
}
|
||||
let mut thread_extension_init = ExtensionDataInit::new();
|
||||
thread_extension_init.insert(selected_capability_roots);
|
||||
|
||||
state
|
||||
.fork_thread_with_source(
|
||||
@@ -517,6 +530,7 @@ impl AgentControl {
|
||||
inherited_environments,
|
||||
inherited_exec_policy,
|
||||
options.environments.clone(),
|
||||
thread_extension_init,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@ use codex_features::Feature;
|
||||
use codex_login::AuthManager;
|
||||
use codex_login::CodexAuth;
|
||||
use codex_protocol::AgentPath;
|
||||
use codex_protocol::capabilities::CapabilityRootLocation;
|
||||
use codex_protocol::capabilities::SelectedCapabilityRoot;
|
||||
use codex_protocol::config_types::ModeKind;
|
||||
use codex_protocol::models::ContentItem;
|
||||
use codex_protocol::models::MessagePhase;
|
||||
@@ -38,6 +40,7 @@ use codex_thread_store::InMemoryThreadStore;
|
||||
use codex_thread_store::LocalThreadStore;
|
||||
use codex_thread_store::LocalThreadStoreConfig;
|
||||
use codex_thread_store::ThreadStore;
|
||||
use codex_utils_path_uri::PathUri;
|
||||
use pretty_assertions::assert_eq;
|
||||
use tempfile::TempDir;
|
||||
use tokio::time::Duration;
|
||||
@@ -1446,7 +1449,33 @@ async fn spawn_agent_fork_last_n_turns_keeps_only_recent_turns() {
|
||||
#[tokio::test]
|
||||
async fn spawn_agent_fork_last_n_turns_drops_parent_startup_prefix_when_under_limit() {
|
||||
let harness = AgentControlHarness::new().await;
|
||||
let (parent_thread_id, parent_thread) = harness.start_thread().await;
|
||||
let selected_capability_roots = vec![SelectedCapabilityRoot {
|
||||
id: "demo@1".to_string(),
|
||||
location: CapabilityRootLocation::Environment {
|
||||
environment_id: "build".to_string(),
|
||||
path: PathUri::parse("file:///plugins/demo").expect("plugin root URI"),
|
||||
},
|
||||
}];
|
||||
let mut thread_extension_init = ExtensionDataInit::new();
|
||||
thread_extension_init.insert(selected_capability_roots.clone());
|
||||
let parent = harness
|
||||
.manager
|
||||
.start_thread_with_options(StartThreadOptions {
|
||||
config: harness.config.clone(),
|
||||
initial_history: InitialHistory::New,
|
||||
session_source: None,
|
||||
thread_source: None,
|
||||
dynamic_tools: Vec::new(),
|
||||
metrics_service_name: None,
|
||||
parent_trace: None,
|
||||
environments: Vec::new(),
|
||||
thread_extension_init,
|
||||
supports_openai_form_elicitation: false,
|
||||
})
|
||||
.await
|
||||
.expect("start parent thread");
|
||||
let parent_thread_id = parent.thread_id;
|
||||
let parent_thread = parent.thread;
|
||||
let startup_turn_context = parent_thread.codex.session.new_default_turn().await;
|
||||
parent_thread
|
||||
.codex
|
||||
@@ -1525,6 +1554,14 @@ async fn spawn_agent_fork_last_n_turns_drops_parent_startup_prefix_when_under_li
|
||||
!history_contains_text(history.raw_items(), "parent startup developer context"),
|
||||
"bounded fork should drop parent startup context even when fewer turns exist than requested"
|
||||
);
|
||||
assert_eq!(
|
||||
&child_thread
|
||||
.codex
|
||||
.session
|
||||
.services
|
||||
.selected_capability_roots,
|
||||
&selected_capability_roots
|
||||
);
|
||||
assert!(
|
||||
child_thread
|
||||
.codex
|
||||
|
||||
@@ -1402,6 +1402,7 @@ impl ThreadManagerState {
|
||||
inherited_environments: Option<TurnEnvironmentSnapshot>,
|
||||
inherited_exec_policy: Option<Arc<crate::exec_policy::ExecPolicyManager>>,
|
||||
environments: Option<Vec<TurnEnvironmentSelection>>,
|
||||
thread_extension_init: ExtensionDataInit,
|
||||
) -> CodexResult<NewThread> {
|
||||
let environments = environments.unwrap_or_else(|| {
|
||||
default_thread_environment_selections(self.environment_manager.as_ref(), &config.cwd)
|
||||
@@ -1421,7 +1422,7 @@ impl ThreadManagerState {
|
||||
inherited_exec_policy,
|
||||
/*parent_trace*/ None,
|
||||
environments,
|
||||
/*thread_extension_init*/ ExtensionDataInit::default(),
|
||||
thread_extension_init,
|
||||
/*supports_openai_form_elicitation*/ false,
|
||||
/*user_shell_override*/ None,
|
||||
))
|
||||
|
||||
Reference in New Issue
Block a user