Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 17 additions & 17 deletions codex-rs/core/src/tools/handlers/multi_agents_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ use crate::state::TaskKind;
use crate::tasks::SessionTask;
use crate::tasks::SessionTaskContext;
use crate::tools::context::ToolOutput;
use crate::tools::handlers::multi_agents_v2::AssignTaskHandler as AssignTaskHandlerV2;
use crate::tools::handlers::multi_agents_v2::CloseAgentHandler as CloseAgentHandlerV2;
use crate::tools::handlers::multi_agents_v2::FollowupTaskHandler as FollowupTaskHandlerV2;
use crate::tools::handlers::multi_agents_v2::ListAgentsHandler as ListAgentsHandlerV2;
use crate::tools::handlers::multi_agents_v2::SendMessageHandler as SendMessageHandlerV2;
use crate::tools::handlers::multi_agents_v2::SpawnAgentHandler as SpawnAgentHandlerV2;
Expand Down Expand Up @@ -710,7 +710,7 @@ async fn multi_agent_v2_send_message_accepts_root_target_from_child() {
}

#[tokio::test]
async fn multi_agent_v2_assign_task_rejects_root_target_from_child() {
async fn multi_agent_v2_followup_task_rejects_root_target_from_child() {
let (mut session, mut turn) = make_session_and_context().await;
let manager = thread_manager();
let root = manager
Expand Down Expand Up @@ -758,19 +758,19 @@ async fn multi_agent_v2_assign_task_rejects_root_target_from_child() {
agent_role: None,
});

let err = AssignTaskHandlerV2
let err = FollowupTaskHandlerV2
.handle(invocation(
Arc::new(session),
Arc::new(turn),
"assign_task",
"followup_task",
function_payload(json!({
"target": "/root",
"message": "run this",
"interrupt": true
})),
))
.await
.expect_err("assign_task should reject the root target");
.expect_err("followup_task should reject the root target");

assert_eq!(
err,
Expand Down Expand Up @@ -1161,7 +1161,7 @@ async fn multi_agent_v2_send_message_rejects_interrupt_parameter() {
}

#[tokio::test]
async fn multi_agent_v2_assign_task_interrupts_busy_child_without_losing_message() {
async fn multi_agent_v2_followup_task_interrupts_busy_child_without_losing_message() {
let (mut session, mut turn) = make_session_and_context().await;
let manager = thread_manager();
let root = manager
Expand Down Expand Up @@ -1213,19 +1213,19 @@ async fn multi_agent_v2_assign_task_interrupts_busy_child_without_losing_message
)
.await;

AssignTaskHandlerV2
FollowupTaskHandlerV2
.handle(invocation(
session,
turn,
"assign_task",
"followup_task",
function_payload(json!({
"target": agent_id.to_string(),
"message": "continue",
"interrupt": true
})),
))
.await
.expect("interrupting v2 assign_task should succeed");
.expect("interrupting v2 followup_task should succeed");

let ops = manager.captured_ops();
let ops_for_agent: Vec<&Op> = ops
Expand Down Expand Up @@ -1281,7 +1281,7 @@ async fn multi_agent_v2_assign_task_interrupts_busy_child_without_losing_message
}
})
.await
.expect("interrupting v2 assign_task should preserve the redirected message");
.expect("interrupting v2 followup_task should preserve the redirected message");

let _ = thread
.submit(Op::Shutdown {})
Expand All @@ -1290,7 +1290,7 @@ async fn multi_agent_v2_assign_task_interrupts_busy_child_without_losing_message
}

#[tokio::test]
async fn multi_agent_v2_assign_task_completion_notifies_parent_on_every_turn() {
async fn multi_agent_v2_followup_task_completion_notifies_parent_on_every_turn() {
let (mut session, mut turn) = make_session_and_context().await;
let manager = thread_manager();
let root = manager
Expand Down Expand Up @@ -1342,18 +1342,18 @@ async fn multi_agent_v2_assign_task_completion_notifies_parent_on_every_turn() {
)
.await;

AssignTaskHandlerV2
FollowupTaskHandlerV2
.handle(invocation(
session,
turn,
"assign_task",
"followup_task",
function_payload(json!({
"target": agent_id.to_string(),
"message": "continue",
})),
))
.await
.expect("assign_task should succeed");
.expect("followup_task should succeed");

let second_turn = thread.codex.session.new_default_turn().await;
thread
Expand Down Expand Up @@ -1419,7 +1419,7 @@ async fn multi_agent_v2_assign_task_completion_notifies_parent_on_every_turn() {
}

#[tokio::test]
async fn multi_agent_v2_assign_task_rejects_legacy_items_field() {
async fn multi_agent_v2_followup_task_rejects_legacy_items_field() {
let (mut session, mut turn) = make_session_and_context().await;
let manager = thread_manager();
let root = manager
Expand Down Expand Up @@ -1455,14 +1455,14 @@ async fn multi_agent_v2_assign_task_rejects_legacy_items_field() {
let invocation = invocation(
session,
turn,
"assign_task",
"followup_task",
function_payload(json!({
"target": agent_id.to_string(),
"items": [{"type": "text", "text": "continue"}],
})),
);

let Err(err) = AssignTaskHandlerV2.handle(invocation).await else {
let Err(err) = FollowupTaskHandlerV2.handle(invocation).await else {
panic!("legacy items field should be rejected in v2");
};
let FunctionCallError::RespondToModel(message) = err else {
Expand Down
4 changes: 2 additions & 2 deletions codex-rs/core/src/tools/handlers/multi_agents_v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,15 @@ use serde::Deserialize;
use serde::Serialize;
use serde_json::Value as JsonValue;

pub(crate) use assign_task::Handler as AssignTaskHandler;
pub(crate) use close_agent::Handler as CloseAgentHandler;
pub(crate) use followup_task::Handler as FollowupTaskHandler;
pub(crate) use list_agents::Handler as ListAgentsHandler;
pub(crate) use send_message::Handler as SendMessageHandler;
pub(crate) use spawn::Handler as SpawnAgentHandler;
pub(crate) use wait::Handler as WaitAgentHandler;

mod assign_task;
mod close_agent;
mod followup_task;
mod list_agents;
mod message_tool;
mod send_message;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::message_tool::AssignTaskArgs;
use super::message_tool::FollowupTaskArgs;
use super::message_tool::MessageDeliveryMode;
use super::message_tool::MessageToolResult;
use super::message_tool::handle_message_string_tool;
Expand All @@ -20,7 +20,7 @@ impl ToolHandler for Handler {

async fn handle(&self, invocation: ToolInvocation) -> Result<Self::Output, FunctionCallError> {
let arguments = function_arguments(invocation.payload.clone())?;
let args: AssignTaskArgs = parse_arguments(&arguments)?;
let args: FollowupTaskArgs = parse_arguments(&arguments)?;
handle_message_string_tool(
invocation,
MessageDeliveryMode::TriggerTurn,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Shared argument parsing and dispatch for the v2 text-only agent messaging tools.
//!
//! `send_message` and `assign_task` share the same submission path and differ only in whether the
//! `send_message` and `followup_task` share the same submission path and differ only in whether the
//! resulting `InterAgentCommunication` should wake the target immediately.

use super::*;
Expand Down Expand Up @@ -38,8 +38,8 @@ pub(crate) struct SendMessageArgs {

#[derive(Debug, Deserialize)]
#[serde(deny_unknown_fields)]
/// Input for the MultiAgentV2 `assign_task` tool.
pub(crate) struct AssignTaskArgs {
/// Input for the MultiAgentV2 `followup_task` tool.
pub(crate) struct FollowupTaskArgs {
pub(crate) target: String,
pub(crate) message: String,
#[serde(default)]
Expand Down Expand Up @@ -79,7 +79,7 @@ fn message_content(message: String) -> Result<String, FunctionCallError> {
Ok(message)
}

/// Handles the shared MultiAgentV2 plain-text message flow for both `send_message` and `assign_task`.
/// Handles the shared MultiAgentV2 plain-text message flow for both `send_message` and `followup_task`.
pub(crate) async fn handle_message_string_tool(
invocation: ToolInvocation,
mode: MessageDeliveryMode,
Expand Down
8 changes: 4 additions & 4 deletions codex-rs/core/src/tools/spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ pub(crate) fn build_specs_with_discoverable_tools(
use crate::tools::handlers::multi_agents::SendInputHandler;
use crate::tools::handlers::multi_agents::SpawnAgentHandler;
use crate::tools::handlers::multi_agents::WaitAgentHandler;
use crate::tools::handlers::multi_agents_v2::AssignTaskHandler as AssignTaskHandlerV2;
use crate::tools::handlers::multi_agents_v2::CloseAgentHandler as CloseAgentHandlerV2;
use crate::tools::handlers::multi_agents_v2::FollowupTaskHandler as FollowupTaskHandlerV2;
use crate::tools::handlers::multi_agents_v2::ListAgentsHandler as ListAgentsHandlerV2;
use crate::tools::handlers::multi_agents_v2::SendMessageHandler as SendMessageHandlerV2;
use crate::tools::handlers::multi_agents_v2::SpawnAgentHandler as SpawnAgentHandlerV2;
Expand Down Expand Up @@ -136,9 +136,6 @@ pub(crate) fn build_specs_with_discoverable_tools(
ToolHandlerKind::ApplyPatch => {
builder.register_handler(handler.name, apply_patch_handler.clone());
}
ToolHandlerKind::AssignTaskV2 => {
builder.register_handler(handler.name, Arc::new(AssignTaskHandlerV2));
}
ToolHandlerKind::CloseAgentV1 => {
builder.register_handler(handler.name, Arc::new(CloseAgentHandler));
}
Expand All @@ -154,6 +151,9 @@ pub(crate) fn build_specs_with_discoverable_tools(
ToolHandlerKind::DynamicTool => {
builder.register_handler(handler.name, dynamic_tool_handler.clone());
}
ToolHandlerKind::FollowupTaskV2 => {
builder.register_handler(handler.name, Arc::new(FollowupTaskHandlerV2));
}
ToolHandlerKind::JsRepl => {
builder.register_handler(handler.name, js_repl_handler.clone());
}
Expand Down
4 changes: 2 additions & 2 deletions codex-rs/tools/src/agent_tool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ pub fn create_send_message_tool() -> ToolSpec {
})
}

pub fn create_assign_task_tool() -> ToolSpec {
pub fn create_followup_task_tool() -> ToolSpec {
let properties = BTreeMap::from([
(
"target".to_string(),
Expand Down Expand Up @@ -178,7 +178,7 @@ pub fn create_assign_task_tool() -> ToolSpec {
]);

ToolSpec::Function(ResponsesApiTool {
name: "assign_task".to_string(),
name: "followup_task".to_string(),
description: "Add a message to an existing non-root agent and trigger a turn in the target. Use interrupt=true to redirect work immediately. In MultiAgentV2, this tool currently supports text content only."
.to_string(),
strict: false,
Expand Down
10 changes: 5 additions & 5 deletions codex-rs/tools/src/agent_tool_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,22 +127,22 @@ fn send_message_tool_requires_message_and_uses_submission_output() {
}

#[test]
fn assign_task_tool_requires_message_and_uses_submission_output() {
fn followup_task_tool_requires_message_and_uses_submission_output() {
let ToolSpec::Function(ResponsesApiTool {
parameters,
output_schema,
..
}) = create_assign_task_tool()
}) = create_followup_task_tool()
else {
panic!("assign_task should be a function tool");
panic!("followup_task should be a function tool");
};
let JsonSchema::Object {
properties,
required,
..
} = parameters
else {
panic!("assign_task should use object params");
panic!("followup_task should use object params");
};
assert!(properties.contains_key("target"));
assert!(properties.contains_key("message"));
Expand All @@ -153,7 +153,7 @@ fn assign_task_tool_requires_message_and_uses_submission_output() {
Some(vec!["target".to_string(), "message".to_string()])
);
assert_eq!(
output_schema.expect("assign_task output schema")["required"],
output_schema.expect("followup_task output schema")["required"],
json!(["submission_id"])
);
}
Expand Down
2 changes: 1 addition & 1 deletion codex-rs/tools/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ pub use agent_job_tool::create_report_agent_job_result_tool;
pub use agent_job_tool::create_spawn_agents_on_csv_tool;
pub use agent_tool::SpawnAgentToolOptions;
pub use agent_tool::WaitAgentTimeoutOptions;
pub use agent_tool::create_assign_task_tool;
pub use agent_tool::create_close_agent_tool_v1;
pub use agent_tool::create_close_agent_tool_v2;
pub use agent_tool::create_followup_task_tool;
pub use agent_tool::create_list_agents_tool;
pub use agent_tool::create_resume_agent_tool;
pub use agent_tool::create_send_input_tool_v1;
Expand Down
6 changes: 3 additions & 3 deletions codex-rs/tools/src/tool_registry_plan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ use crate::collect_tool_search_app_infos;
use crate::collect_tool_suggest_entries;
use crate::create_apply_patch_freeform_tool;
use crate::create_apply_patch_json_tool;
use crate::create_assign_task_tool;
use crate::create_close_agent_tool_v1;
use crate::create_close_agent_tool_v2;
use crate::create_code_mode_tool;
use crate::create_exec_command_tool;
use crate::create_followup_task_tool;
use crate::create_image_generation_tool;
use crate::create_js_repl_reset_tool;
use crate::create_js_repl_tool;
Expand Down Expand Up @@ -358,7 +358,7 @@ pub fn build_tool_registry_plan(
config.code_mode_enabled,
);
plan.push_spec(
create_assign_task_tool(),
create_followup_task_tool(),
/*supports_parallel_tool_calls*/ false,
config.code_mode_enabled,
);
Expand All @@ -379,7 +379,7 @@ pub fn build_tool_registry_plan(
);
plan.register_handler("spawn_agent", ToolHandlerKind::SpawnAgentV2);
plan.register_handler("send_message", ToolHandlerKind::SendMessageV2);
plan.register_handler("assign_task", ToolHandlerKind::AssignTaskV2);
plan.register_handler("followup_task", ToolHandlerKind::FollowupTaskV2);
plan.register_handler("wait_agent", ToolHandlerKind::WaitAgentV2);
plan.register_handler("close_agent", ToolHandlerKind::CloseAgentV2);
plan.register_handler("list_agents", ToolHandlerKind::ListAgentsV2);
Expand Down
10 changes: 5 additions & 5 deletions codex-rs/tools/src/tool_registry_plan_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ fn test_build_specs_multi_agent_v2_uses_task_names_and_hides_resume() {
&[
"spawn_agent",
"send_message",
"assign_task",
"followup_task",
"wait_agent",
"close_agent",
"list_agents",
Expand Down Expand Up @@ -269,17 +269,17 @@ fn test_build_specs_multi_agent_v2_uses_task_names_and_hides_resume() {
Some(&vec!["target".to_string(), "message".to_string()])
);

let assign_task = find_tool(&tools, "assign_task");
let ToolSpec::Function(ResponsesApiTool { parameters, .. }) = &assign_task.spec else {
panic!("assign_task should be a function tool");
let followup_task = find_tool(&tools, "followup_task");
let ToolSpec::Function(ResponsesApiTool { parameters, .. }) = &followup_task.spec else {
panic!("followup_task should be a function tool");
};
let JsonSchema::Object {
properties,
required,
..
} = parameters
else {
panic!("assign_task should use object params");
panic!("followup_task should use object params");
};
assert!(properties.contains_key("target"));
assert!(properties.contains_key("message"));
Expand Down
2 changes: 1 addition & 1 deletion codex-rs/tools/src/tool_registry_plan_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ use std::collections::HashMap;
pub enum ToolHandlerKind {
AgentJobs,
ApplyPatch,
AssignTaskV2,
CloseAgentV1,
CloseAgentV2,
CodeModeExecute,
CodeModeWait,
DynamicTool,
FollowupTaskV2,
JsRepl,
JsReplReset,
ListAgentsV2,
Expand Down
Loading