feat: emit warning when sub agent is done

This commit is contained in:
jif-oai
2026-01-26 16:55:47 +00:00
parent 48aeb67f7a
commit ec2551ba36
3 changed files with 64 additions and 0 deletions

View File

@@ -0,0 +1,57 @@
use std::sync::Arc;
use codex_protocol::ThreadId;
use crate::agent::AgentStatus;
use crate::agent::status::is_final;
use crate::codex::Session;
use crate::codex::TurnContext;
/// Subscribe to a spawned sub-agent and warn the model once it reaches a final status.
pub(crate) fn spawn_collab_completion_warning_watcher(
session: Arc<Session>,
turn_context: Arc<TurnContext>,
agent_id: ThreadId,
) {
tokio::spawn(async move {
if let Some(status) = wait_for_final_status(session.as_ref(), agent_id).await {
let message = completion_warning_message(agent_id, &status);
session.record_model_warning(message, &turn_context).await;
}
});
}
async fn wait_for_final_status(session: &Session, agent_id: ThreadId) -> Option<AgentStatus> {
let mut status_rx = match session
.services
.agent_control
.subscribe_status(agent_id)
.await
{
Ok(rx) => rx,
Err(_) => {
let status = session.services.agent_control.get_status(agent_id).await;
return is_final(&status).then_some(status);
}
};
let mut status = status_rx.borrow().clone();
if is_final(&status) {
return Some(status);
}
loop {
if status_rx.changed().await.is_err() {
let latest = session.services.agent_control.get_status(agent_id).await;
return is_final(&latest).then_some(latest);
}
status = status_rx.borrow().clone();
if is_final(&status) {
return Some(status);
}
}
}
fn completion_warning_message(agent_id: ThreadId, status: &AgentStatus) -> String {
format!("Sub-agent {agent_id} finished with status {status:?}. Use wait to collect the result.")
}

View File

@@ -1,9 +1,11 @@
mod collab_completion_warning;
pub(crate) mod control;
mod guards;
pub(crate) mod role;
pub(crate) mod status;
pub(crate) use codex_protocol::protocol::AgentStatus;
pub(crate) use collab_completion_warning::spawn_collab_completion_warning_watcher;
pub(crate) use control::AgentControl;
pub(crate) use guards::MAX_THREAD_SPAWN_DEPTH;
pub(crate) use guards::exceeds_thread_spawn_depth_limit;

View File

@@ -168,6 +168,11 @@ mod spawn {
)
.await;
let new_thread_id = result?;
crate::agent::spawn_collab_completion_warning_watcher(
session.clone(),
turn.clone(),
new_thread_id,
);
let content = serde_json::to_string(&SpawnAgentResult {
agent_id: new_thread_id.to_string(),