mirror of
https://github.com/openai/codex.git
synced 2026-11-05 20:10:33 +00:00
codex: represent disabled multi-agent runtime explicitly
This commit is contained in:
@@ -1288,7 +1288,7 @@ impl Config {
|
||||
} else if self.features.enabled(Feature::Collab) {
|
||||
Some(MultiAgentVersion::V1)
|
||||
} else {
|
||||
None
|
||||
Some(MultiAgentVersion::Disabled)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1310,7 +1310,7 @@ impl Config {
|
||||
.saturating_sub(1),
|
||||
))
|
||||
}
|
||||
None | Some(MultiAgentVersion::V1) => {
|
||||
None | Some(MultiAgentVersion::Disabled | MultiAgentVersion::V1) => {
|
||||
Ok(self.agent_max_threads.or(DEFAULT_AGENT_MAX_THREADS))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ use codex_protocol::protocol::Event;
|
||||
use codex_protocol::protocol::EventMsg;
|
||||
use codex_protocol::protocol::ForkedHistory;
|
||||
use codex_protocol::protocol::InitialHistory;
|
||||
use codex_protocol::protocol::MultiAgentVersion;
|
||||
use codex_protocol::protocol::Op;
|
||||
use codex_protocol::protocol::RolloutItem;
|
||||
use codex_protocol::protocol::SandboxPolicy;
|
||||
@@ -610,7 +611,7 @@ async fn spawn_guardian_review_session(
|
||||
cancel_token.clone(),
|
||||
SubAgentSource::Other(GUARDIAN_REVIEWER_NAME.to_string()),
|
||||
initial_history,
|
||||
/*multi_agent_version*/ None,
|
||||
/*multi_agent_version*/ Some(MultiAgentVersion::Disabled),
|
||||
))
|
||||
.await?;
|
||||
|
||||
|
||||
@@ -128,7 +128,7 @@ pub(super) async fn spawn_review_thread(
|
||||
user_instructions: None,
|
||||
compact_prompt: parent_turn_context.compact_prompt.clone(),
|
||||
collaboration_mode: parent_turn_context.collaboration_mode.clone(),
|
||||
multi_agent_version: None,
|
||||
multi_agent_version: Some(MultiAgentVersion::Disabled),
|
||||
personality: parent_turn_context.personality,
|
||||
approval_policy: parent_turn_context.approval_policy.clone(),
|
||||
permission_profile: parent_turn_context.permission_profile(),
|
||||
|
||||
@@ -12,6 +12,7 @@ use codex_protocol::protocol::Event;
|
||||
use codex_protocol::protocol::EventMsg;
|
||||
use codex_protocol::protocol::ExitedReviewModeEvent;
|
||||
use codex_protocol::protocol::ItemCompletedEvent;
|
||||
use codex_protocol::protocol::MultiAgentVersion;
|
||||
use codex_protocol::protocol::ReviewOutputEvent;
|
||||
use codex_protocol::protocol::SubAgentSource;
|
||||
use tokio_util::sync::CancellationToken;
|
||||
@@ -132,7 +133,7 @@ async fn start_review_conversation(
|
||||
SubAgentSource::Review,
|
||||
/*final_output_json_schema*/ None,
|
||||
/*initial_history*/ None,
|
||||
/*multi_agent_version*/ None,
|
||||
/*multi_agent_version*/ Some(MultiAgentVersion::Disabled),
|
||||
)
|
||||
.await)
|
||||
.ok()
|
||||
|
||||
@@ -113,19 +113,26 @@ async fn build_runner_options(
|
||||
turn: &Arc<TurnContext>,
|
||||
requested_concurrency: Option<usize>,
|
||||
) -> Result<JobRunnerOptions, FunctionCallError> {
|
||||
let session_source = turn.session_source.clone();
|
||||
let child_depth = next_thread_spawn_depth(&session_source);
|
||||
let max_depth = turn.config.agent_max_depth;
|
||||
if exceeds_thread_spawn_depth_limit(child_depth, max_depth) {
|
||||
return Err(FunctionCallError::RespondToModel(
|
||||
"agent depth limit reached; this session cannot spawn more subagents".to_string(),
|
||||
));
|
||||
}
|
||||
let multi_agent_version = turn.multi_agent_version.ok_or_else(|| {
|
||||
FunctionCallError::RespondToModel(
|
||||
"multi-agent version is unresolved; this session cannot spawn workers".to_string(),
|
||||
)
|
||||
})?;
|
||||
if multi_agent_version == MultiAgentVersion::Disabled {
|
||||
return Err(FunctionCallError::RespondToModel(
|
||||
"multi-agent runtime is disabled; this session cannot spawn workers".to_string(),
|
||||
));
|
||||
}
|
||||
let session_source = turn.session_source.clone();
|
||||
let child_depth = next_thread_spawn_depth(&session_source);
|
||||
let max_depth = turn.config.agent_max_depth;
|
||||
if multi_agent_version == MultiAgentVersion::V1
|
||||
&& exceeds_thread_spawn_depth_limit(child_depth, max_depth)
|
||||
{
|
||||
return Err(FunctionCallError::RespondToModel(
|
||||
"agent depth limit reached; this session cannot spawn more subagents".to_string(),
|
||||
));
|
||||
}
|
||||
let agent_max_threads = turn
|
||||
.config
|
||||
.effective_agent_max_threads(Some(multi_agent_version))
|
||||
|
||||
@@ -294,7 +294,7 @@ fn multi_agent_v2_enabled(turn_context: &TurnContext) -> bool {
|
||||
|
||||
fn collab_tools_enabled(turn_context: &TurnContext) -> bool {
|
||||
match turn_context.multi_agent_version {
|
||||
None => false,
|
||||
None | Some(MultiAgentVersion::Disabled) => false,
|
||||
Some(MultiAgentVersion::V1) => !exceeds_thread_spawn_depth_limit(
|
||||
next_thread_spawn_depth(&turn_context.session_source),
|
||||
turn_context.config.agent_max_depth,
|
||||
@@ -312,12 +312,7 @@ fn goal_tools_enabled(turn_context: &TurnContext) -> bool {
|
||||
}
|
||||
|
||||
fn agent_jobs_tools_enabled(turn_context: &TurnContext) -> bool {
|
||||
turn_context.features.get().enabled(Feature::SpawnCsv)
|
||||
&& turn_context.multi_agent_version.is_some()
|
||||
&& !exceeds_thread_spawn_depth_limit(
|
||||
next_thread_spawn_depth(&turn_context.session_source),
|
||||
turn_context.config.agent_max_depth,
|
||||
)
|
||||
turn_context.features.get().enabled(Feature::SpawnCsv) && collab_tools_enabled(turn_context)
|
||||
}
|
||||
|
||||
fn agent_jobs_worker_tools_enabled(turn_context: &TurnContext) -> bool {
|
||||
|
||||
@@ -44,7 +44,10 @@ async fn legacy_resume_seeds_multi_agent_version_for_later_forks() {
|
||||
.build(&server)
|
||||
.await
|
||||
.expect("create legacy source thread");
|
||||
assert_eq!(initial.codex.multi_agent_version(), None);
|
||||
assert_eq!(
|
||||
initial.codex.multi_agent_version(),
|
||||
Some(MultiAgentVersion::Disabled)
|
||||
);
|
||||
initial.codex.ensure_rollout_materialized().await;
|
||||
initial
|
||||
.codex
|
||||
@@ -58,6 +61,11 @@ async fn legacy_resume_seeds_multi_agent_version_for_later_forks() {
|
||||
.shutdown_and_wait()
|
||||
.await
|
||||
.expect("shutdown source thread");
|
||||
remove_multi_agent_version(&rollout_path);
|
||||
assert_eq!(
|
||||
latest_multi_agent_version(&rollout_path, source_thread_id),
|
||||
None
|
||||
);
|
||||
|
||||
let mut resume_builder = test_codex().with_config(|config| {
|
||||
config
|
||||
@@ -385,3 +393,24 @@ fn latest_multi_agent_version(
|
||||
})
|
||||
.flatten()
|
||||
}
|
||||
|
||||
fn remove_multi_agent_version(path: &std::path::Path) {
|
||||
let text = std::fs::read_to_string(path)
|
||||
.unwrap_or_else(|err| panic!("failed to read rollout file {}: {err}", path.display()));
|
||||
let lines = text
|
||||
.lines()
|
||||
.filter(|line| !line.trim().is_empty())
|
||||
.map(|line| {
|
||||
let mut line = serde_json::from_str::<RolloutLine>(line)
|
||||
.unwrap_or_else(|err| panic!("failed to parse rollout line `{line}`: {err}"));
|
||||
if let RolloutItem::SessionMeta(meta_line) = &mut line.item {
|
||||
meta_line.meta.multi_agent_version = None;
|
||||
}
|
||||
serde_json::to_string(&line)
|
||||
.unwrap_or_else(|err| panic!("failed to serialize rollout line: {err}"))
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n");
|
||||
std::fs::write(path, format!("{lines}\n"))
|
||||
.unwrap_or_else(|err| panic!("failed to write rollout file {}: {err}", path.display()));
|
||||
}
|
||||
|
||||
@@ -2752,6 +2752,7 @@ fn multi_agent_version_from_items(
|
||||
#[derive(Serialize, Deserialize, Clone, Copy, Debug, PartialEq, Eq, JsonSchema, TS)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum MultiAgentVersion {
|
||||
Disabled,
|
||||
V1,
|
||||
V2,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user