This commit is contained in:
Owen Lin
2026-04-09 16:19:47 -07:00
parent cf91ea808a
commit 0f835a5af4
4 changed files with 31 additions and 150 deletions

View File

@@ -4,7 +4,6 @@ pub(crate) mod mailbox;
mod registry;
pub(crate) mod role;
pub(crate) mod status;
pub(crate) mod subagent_config;
pub(crate) use codex_protocol::protocol::AgentStatus;
pub(crate) use control::AgentControl;
@@ -13,6 +12,3 @@ pub(crate) use mailbox::MailboxReceiver;
pub(crate) use registry::exceeds_thread_spawn_depth_limit;
pub(crate) use registry::next_thread_spawn_depth;
pub(crate) use status::agent_status_from_event;
pub(crate) use subagent_config::SubAgentConfigBuilder;
pub(crate) use subagent_config::SubAgentPromptInheritance;
pub(crate) use subagent_config::SubAgentPromptSelection;

View File

@@ -1,119 +0,0 @@
use anyhow::Context;
use crate::codex::TurnContext;
use crate::config::Config;
#[derive(Debug, Clone, Copy)]
#[allow(dead_code)]
pub(crate) enum SubAgentPromptInheritance {
InheritParent,
None,
Select(SubAgentPromptSelection),
}
#[derive(Debug, Clone, Copy)]
pub(crate) struct SubAgentPromptSelection {
pub(crate) base_instructions: bool,
pub(crate) user_instructions: bool,
pub(crate) project_docs: bool,
pub(crate) developer_instructions: bool,
pub(crate) compact_prompt: bool,
pub(crate) permissions: bool,
pub(crate) apps: bool,
pub(crate) environment_context: bool,
}
pub(crate) struct SubAgentConfigBuilder {
config: Config,
}
impl SubAgentConfigBuilder {
pub(crate) fn from_parent_config(parent_config: &Config) -> Self {
Self {
config: parent_config.clone(),
}
}
pub(crate) fn from_parent_turn(turn: &TurnContext) -> anyhow::Result<Self> {
let base_config = turn.config.clone();
let mut builder = Self::from_parent_config(base_config.as_ref());
builder.config.model = Some(turn.model_info.slug.clone());
builder.config.model_provider = turn.provider.clone();
builder.config.model_reasoning_effort = turn.reasoning_effort;
builder.config.model_reasoning_summary = Some(turn.reasoning_summary);
builder.config.developer_instructions = turn.developer_instructions.clone();
builder.config.compact_prompt = turn.compact_prompt.clone();
Self::apply_turn_runtime_to_config(&mut builder.config, turn)?;
Ok(builder)
}
pub(crate) fn apply_turn_runtime_to_config(
config: &mut Config,
turn: &TurnContext,
) -> anyhow::Result<()> {
config
.permissions
.approval_policy
.set(turn.approval_policy.value())
.context("approval_policy is invalid")?;
config.permissions.shell_environment_policy = turn.shell_environment_policy.clone();
config.codex_linux_sandbox_exe = turn.codex_linux_sandbox_exe.clone();
config.cwd = turn.cwd.clone();
config
.permissions
.sandbox_policy
.set(turn.sandbox_policy.get().clone())
.context("sandbox_policy is invalid")?;
config.permissions.file_system_sandbox_policy = turn.file_system_sandbox_policy.clone();
config.permissions.network_sandbox_policy = turn.network_sandbox_policy;
Ok(())
}
pub(crate) fn prompt_inheritance(mut self, inheritance: SubAgentPromptInheritance) -> Self {
match inheritance {
SubAgentPromptInheritance::InheritParent => {}
SubAgentPromptInheritance::None => {
self.config.base_instructions = None;
self.config.user_instructions = None;
self.config.developer_instructions = None;
self.config.compact_prompt = None;
self.config.project_doc_max_bytes = 0;
self.config.project_doc_fallback_filenames.clear();
self.config.include_permissions_instructions = false;
self.config.include_apps_instructions = false;
self.config.include_environment_context = false;
}
SubAgentPromptInheritance::Select(selection) => {
self.apply_prompt_selection(selection);
}
}
self
}
pub(crate) fn build(self) -> Config {
self.config
}
fn apply_prompt_selection(&mut self, selection: SubAgentPromptSelection) {
if !selection.base_instructions {
self.config.base_instructions = None;
}
if !selection.user_instructions {
self.config.user_instructions = None;
}
if !selection.developer_instructions {
self.config.developer_instructions = None;
}
if !selection.compact_prompt {
self.config.compact_prompt = None;
}
if !selection.project_docs {
self.config.project_doc_max_bytes = 0;
self.config.project_doc_fallback_filenames.clear();
}
self.config.include_permissions_instructions = selection.permissions;
self.config.include_apps_instructions = selection.apps;
self.config.include_environment_context = selection.environment_context;
}
}

View File

@@ -24,9 +24,6 @@ use tokio::sync::Mutex;
use tokio_util::sync::CancellationToken;
use tracing::warn;
use crate::agent::SubAgentConfigBuilder;
use crate::agent::SubAgentPromptInheritance;
use crate::agent::SubAgentPromptSelection;
use crate::codex::Codex;
use crate::codex::Session;
use crate::codex::TurnContext;
@@ -622,11 +619,7 @@ pub(crate) fn build_guardian_review_session_config(
active_model: &str,
reasoning_effort: Option<codex_protocol::openai_models::ReasoningEffort>,
) -> anyhow::Result<Config> {
let mut guardian_config = SubAgentConfigBuilder::from_parent_config(parent_config)
.prompt_inheritance(SubAgentPromptInheritance::Select(
guardian_review_prompt_selection(),
))
.build();
let mut guardian_config = parent_config.clone();
guardian_config.model = Some(active_model.to_string());
guardian_config.model_reasoning_effort = reasoning_effort;
guardian_config.personality = None;
@@ -667,19 +660,6 @@ pub(crate) fn build_guardian_review_session_config(
Ok(guardian_config)
}
const fn guardian_review_prompt_selection() -> SubAgentPromptSelection {
SubAgentPromptSelection {
base_instructions: false,
user_instructions: false,
project_docs: true,
developer_instructions: true,
compact_prompt: false,
permissions: false,
apps: false,
environment_context: true,
}
}
async fn run_before_review_deadline<T>(
deadline: tokio::time::Instant,
external_cancel: Option<&CancellationToken>,

View File

@@ -1,6 +1,4 @@
use crate::agent::AgentStatus;
use crate::agent::SubAgentConfigBuilder;
use crate::agent::SubAgentPromptInheritance;
use crate::codex::Session;
use crate::codex::TurnContext;
use crate::config::Config;
@@ -8,6 +6,7 @@ use crate::function_tool::FunctionCallError;
use crate::tools::context::FunctionToolOutput;
use crate::tools::context::ToolOutput;
use crate::tools::context::ToolPayload;
use anyhow::Context;
use codex_features::Feature;
use codex_models_manager::manager::RefreshStrategy;
use codex_protocol::AgentPath;
@@ -223,11 +222,17 @@ pub(crate) fn build_agent_resume_config(
}
fn build_agent_shared_config(turn: &TurnContext) -> Result<Config, FunctionCallError> {
let builder = SubAgentConfigBuilder::from_parent_turn(turn).map_err(|err| {
let mut config = turn.config.as_ref().clone();
config.model = Some(turn.model_info.slug.clone());
config.model_provider = turn.provider.clone();
config.model_reasoning_effort = turn.reasoning_effort;
config.model_reasoning_summary = Some(turn.reasoning_summary);
config.developer_instructions = turn.developer_instructions.clone();
config.compact_prompt = turn.compact_prompt.clone();
apply_turn_runtime_to_config(&mut config, turn).map_err(|err| {
FunctionCallError::RespondToModel(format!("spawn config is invalid: {err}"))
})?;
let builder = builder.prompt_inheritance(SubAgentPromptInheritance::InheritParent);
Ok(builder.build())
Ok(config)
}
/// Copies runtime-only turn state onto a child config before it is handed to `AgentControl`.
@@ -238,10 +243,29 @@ pub(crate) fn apply_spawn_agent_runtime_overrides(
config: &mut Config,
turn: &TurnContext,
) -> Result<(), FunctionCallError> {
SubAgentConfigBuilder::apply_turn_runtime_to_config(config, turn)
apply_turn_runtime_to_config(config, turn)
.map_err(|err| FunctionCallError::RespondToModel(format!("spawn config is invalid: {err}")))
}
fn apply_turn_runtime_to_config(config: &mut Config, turn: &TurnContext) -> anyhow::Result<()> {
config
.permissions
.approval_policy
.set(turn.approval_policy.value())
.context("approval_policy is invalid")?;
config.permissions.shell_environment_policy = turn.shell_environment_policy.clone();
config.codex_linux_sandbox_exe = turn.codex_linux_sandbox_exe.clone();
config.cwd = turn.cwd.clone();
config
.permissions
.sandbox_policy
.set(turn.sandbox_policy.get().clone())
.context("sandbox_policy is invalid")?;
config.permissions.file_system_sandbox_policy = turn.file_system_sandbox_policy.clone();
config.permissions.network_sandbox_policy = turn.network_sandbox_policy;
Ok(())
}
pub(crate) fn apply_spawn_agent_overrides(config: &mut Config, child_depth: i32) {
if child_depth >= config.agent_max_depth && !config.features.enabled(Feature::MultiAgentV2) {
let _ = config.features.disable(Feature::SpawnCsv);