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
16 changes: 16 additions & 0 deletions codex-rs/app-server-protocol/schema/json/EventMsg.json
Original file line number Diff line number Diff line change
Expand Up @@ -3015,10 +3015,16 @@
"description": "Identifier for the collab tool call.",
"type": "string"
},
"model": {
"type": "string"
},
"prompt": {
"description": "Initial prompt sent to the agent. Can be empty to prevent CoT leaking at the beginning.",
"type": "string"
},
"reasoning_effort": {
"$ref": "#/definitions/ReasoningEffort"
},
"sender_thread_id": {
"allOf": [
{
Expand All @@ -3037,7 +3043,9 @@
},
"required": [
"call_id",
"model",
"prompt",
"reasoning_effort",
"sender_thread_id",
"type"
],
Expand Down Expand Up @@ -9115,10 +9123,16 @@
"description": "Identifier for the collab tool call.",
"type": "string"
},
"model": {
"type": "string"
},
"prompt": {
"description": "Initial prompt sent to the agent. Can be empty to prevent CoT leaking at the beginning.",
"type": "string"
},
"reasoning_effort": {
"$ref": "#/definitions/ReasoningEffort"
},
"sender_thread_id": {
"allOf": [
{
Expand All @@ -9137,7 +9151,9 @@
},
"required": [
"call_id",
"model",
"prompt",
"reasoning_effort",
"sender_thread_id",
"type"
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4366,10 +4366,16 @@
"description": "Identifier for the collab tool call.",
"type": "string"
},
"model": {
"type": "string"
},
"prompt": {
"description": "Initial prompt sent to the agent. Can be empty to prevent CoT leaking at the beginning.",
"type": "string"
},
"reasoning_effort": {
"$ref": "#/definitions/v2/ReasoningEffort"
},
"sender_thread_id": {
"allOf": [
{
Expand All @@ -4388,7 +4394,9 @@
},
"required": [
"call_id",
"model",
"prompt",
"reasoning_effort",
"sender_thread_id",
"type"
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6176,10 +6176,16 @@
"description": "Identifier for the collab tool call.",
"type": "string"
},
"model": {
"type": "string"
},
"prompt": {
"description": "Initial prompt sent to the agent. Can be empty to prevent CoT leaking at the beginning.",
"type": "string"
},
"reasoning_effort": {
"$ref": "#/definitions/ReasoningEffort"
},
"sender_thread_id": {
"allOf": [
{
Expand All @@ -6198,7 +6204,9 @@
},
"required": [
"call_id",
"model",
"prompt",
"reasoning_effort",
"sender_thread_id",
"type"
],
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!

// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { ReasoningEffort } from "./ReasoningEffort";
import type { ThreadId } from "./ThreadId";

export type CollabAgentSpawnBeginEvent = {
Expand All @@ -16,4 +17,4 @@ sender_thread_id: ThreadId,
* Initial prompt sent to the agent. Can be empty to prevent CoT leaking at the
* beginning.
*/
prompt: string, };
prompt: string, model: string, reasoning_effort: ReasoningEffort, };
2 changes: 2 additions & 0 deletions codex-rs/core/src/tools/handlers/multi_agents.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,8 @@ mod spawn {
call_id: call_id.clone(),
sender_thread_id: session.conversation_id,
prompt: prompt.clone(),
model: args.model.clone().unwrap_or_default(),
reasoning_effort: args.reasoning_effort.unwrap_or_default(),
}
.into(),
)
Expand Down
3 changes: 1 addition & 2 deletions codex-rs/core/src/tools/spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1205,8 +1205,7 @@ fn create_close_agent_tool() -> ToolSpec {

ToolSpec::Function(ResponsesApiTool {
name: "close_agent".to_string(),
description: "Close an agent when it is no longer needed and return its last known status."
.to_string(),
description: "Close an agent when it is no longer needed and return its last known status. Don't keep agents open for too long if they are not needed anymore.".to_string(),
strict: false,
parameters: JsonSchema::Object {
properties,
Expand Down
1 change: 1 addition & 0 deletions codex-rs/exec/src/event_processor_with_human_output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -698,6 +698,7 @@ impl EventProcessor for EventProcessorWithHumanOutput {
call_id,
sender_thread_id: _,
prompt,
..
}) => {
ts_msg!(
self,
Expand Down
3 changes: 3 additions & 0 deletions codex-rs/exec/tests/event_processor_with_json_output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ use codex_protocol::ThreadId;
use codex_protocol::config_types::ModeKind;
use codex_protocol::mcp::CallToolResult;
use codex_protocol::models::WebSearchAction;
use codex_protocol::openai_models::ReasoningEffort as ReasoningEffortConfig;
use codex_protocol::plan_tool::PlanItemArg;
use codex_protocol::plan_tool::StepStatus;
use codex_protocol::plan_tool::UpdatePlanArgs;
Expand Down Expand Up @@ -547,6 +548,8 @@ fn collab_spawn_begin_and_end_emit_item_events() {
call_id: "call-10".to_string(),
sender_thread_id,
prompt: prompt.clone(),
model: "gpt-5".to_string(),
reasoning_effort: ReasoningEffortConfig::default(),
}),
);
let begin_events = ep.collect_thread_events(&begin);
Expand Down
2 changes: 2 additions & 0 deletions codex-rs/protocol/src/protocol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3125,6 +3125,8 @@ pub struct CollabAgentSpawnBeginEvent {
/// Initial prompt sent to the agent. Can be empty to prevent CoT leaking at the
/// beginning.
pub prompt: String,
pub model: String,
pub reasoning_effort: ReasoningEffortConfig,
}

#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq, JsonSchema, TS)]
Expand Down
25 changes: 23 additions & 2 deletions codex-rs/tui/src/chatwidget.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ use codex_protocol::protocol::AgentReasoningRawContentEvent;
use codex_protocol::protocol::ApplyPatchApprovalRequestEvent;
use codex_protocol::protocol::BackgroundEventEvent;
use codex_protocol::protocol::CodexErrorInfo;
use codex_protocol::protocol::CollabAgentSpawnBeginEvent;
use codex_protocol::protocol::CreditsSnapshot;
use codex_protocol::protocol::DeprecationNoticeEvent;
use codex_protocol::protocol::ErrorEvent;
Expand Down Expand Up @@ -579,6 +580,7 @@ pub(crate) struct ChatWidget {
// Latest completed user-visible Codex output that `/copy` should place on the clipboard.
last_copyable_output: Option<String>,
running_commands: HashMap<String, RunningCommand>,
pending_collab_spawn_requests: HashMap<String, multi_agents::SpawnRequestSummary>,
suppressed_exec_calls: HashSet<String>,
skills_all: Vec<ProtocolSkillMetadata>,
skills_initial_state: Option<HashMap<PathBuf, bool>>,
Expand Down Expand Up @@ -3243,6 +3245,7 @@ impl ChatWidget {
plan_stream_controller: None,
last_copyable_output: None,
running_commands: HashMap::new(),
pending_collab_spawn_requests: HashMap::new(),
suppressed_exec_calls: HashSet::new(),
last_unified_wait: None,
unified_exec_wait_streak: None,
Expand Down Expand Up @@ -3427,6 +3430,7 @@ impl ChatWidget {
plan_stream_controller: None,
last_copyable_output: None,
running_commands: HashMap::new(),
pending_collab_spawn_requests: HashMap::new(),
suppressed_exec_calls: HashSet::new(),
last_unified_wait: None,
unified_exec_wait_streak: None,
Expand Down Expand Up @@ -3603,6 +3607,7 @@ impl ChatWidget {
plan_stream_controller: None,
last_copyable_output: None,
running_commands: HashMap::new(),
pending_collab_spawn_requests: HashMap::new(),
suppressed_exec_calls: HashSet::new(),
last_unified_wait: None,
unified_exec_wait_streak: None,
Expand Down Expand Up @@ -4999,8 +5004,24 @@ impl ChatWidget {
}
EventMsg::ExitedReviewMode(review) => self.on_exited_review_mode(review),
EventMsg::ContextCompacted(_) => self.on_agent_message("Context compacted".to_owned()),
EventMsg::CollabAgentSpawnBegin(_) => {}
EventMsg::CollabAgentSpawnEnd(ev) => self.on_collab_event(multi_agents::spawn_end(ev)),
EventMsg::CollabAgentSpawnBegin(CollabAgentSpawnBeginEvent {
call_id,
model,
reasoning_effort,
..
}) => {
self.pending_collab_spawn_requests.insert(
call_id,
multi_agents::SpawnRequestSummary {
model,
reasoning_effort,
},
);
}
EventMsg::CollabAgentSpawnEnd(ev) => {
let spawn_request = self.pending_collab_spawn_requests.remove(&ev.call_id);
self.on_collab_event(multi_agents::spawn_end(ev, spawn_request.as_ref()));
}
EventMsg::CollabAgentInteractionBegin(_) => {}
EventMsg::CollabAgentInteractionEnd(ev) => {
self.on_collab_event(multi_agents::interaction_end(ev))
Expand Down
46 changes: 46 additions & 0 deletions codex-rs/tui/src/chatwidget/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,12 @@ use codex_protocol::protocol::AgentMessageDeltaEvent;
use codex_protocol::protocol::AgentMessageEvent;
use codex_protocol::protocol::AgentReasoningDeltaEvent;
use codex_protocol::protocol::AgentReasoningEvent;
use codex_protocol::protocol::AgentStatus;
use codex_protocol::protocol::ApplyPatchApprovalRequestEvent;
use codex_protocol::protocol::BackgroundEventEvent;
use codex_protocol::protocol::CodexErrorInfo;
use codex_protocol::protocol::CollabAgentSpawnBeginEvent;
use codex_protocol::protocol::CollabAgentSpawnEndEvent;
use codex_protocol::protocol::CreditsSnapshot;
use codex_protocol::protocol::Event;
use codex_protocol::protocol::EventMsg;
Expand Down Expand Up @@ -1838,6 +1841,7 @@ async fn make_chatwidget_manual(
plan_stream_controller: None,
last_copyable_output: None,
running_commands: HashMap::new(),
pending_collab_spawn_requests: HashMap::new(),
suppressed_exec_calls: HashSet::new(),
skills_all: Vec::new(),
skills_initial_state: None,
Expand Down Expand Up @@ -2011,6 +2015,48 @@ fn lines_to_single_string(lines: &[ratatui::text::Line<'static>]) -> String {
s
}

#[tokio::test]
async fn collab_spawn_end_shows_requested_model_and_effort() {
let (mut chat, mut rx, _ops) = make_chatwidget_manual(None).await;
let sender_thread_id = ThreadId::new();
let spawned_thread_id = ThreadId::new();

chat.handle_codex_event(Event {
id: "spawn-begin".into(),
msg: EventMsg::CollabAgentSpawnBegin(CollabAgentSpawnBeginEvent {
call_id: "call-spawn".to_string(),
sender_thread_id,
prompt: "Explore the repo".to_string(),
model: "gpt-5".to_string(),
reasoning_effort: ReasoningEffortConfig::High,
}),
});
chat.handle_codex_event(Event {
id: "spawn-end".into(),
msg: EventMsg::CollabAgentSpawnEnd(CollabAgentSpawnEndEvent {
call_id: "call-spawn".to_string(),
sender_thread_id,
new_thread_id: Some(spawned_thread_id),
new_agent_nickname: Some("Robie".to_string()),
new_agent_role: Some("explorer".to_string()),
prompt: "Explore the repo".to_string(),
status: AgentStatus::PendingInit,
}),
});

let cells = drain_insert_history(&mut rx);
let rendered = cells
.iter()
.map(|lines| lines_to_single_string(lines))
.collect::<Vec<_>>()
.join("\n");

assert!(
rendered.contains("Spawned Robie [explorer] (gpt-5 high)"),
"expected spawn line to include agent metadata and requested model, got {rendered:?}"
);
}

fn status_line_text(chat: &ChatWidget) -> Option<String> {
chat.status_line_text()
}
Expand Down
Loading
Loading