mirror of
https://github.com/openai/codex.git
synced 2026-09-15 12:08:01 +00:00
switch to tool call
This commit is contained in:
@@ -1,6 +1,10 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use codex_protocol::ThreadId;
|
||||
use codex_protocol::models::FunctionCallOutputPayload;
|
||||
use codex_protocol::models::ResponseItem;
|
||||
use serde_json::json;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::agent::AgentStatus;
|
||||
use crate::agent::status::is_final;
|
||||
@@ -22,8 +26,10 @@ pub(crate) fn spawn_collab_completion_warning_watcher(
|
||||
)
|
||||
.await
|
||||
{
|
||||
let message = completion_warning_message(agent_id, &status);
|
||||
session.record_model_warning(message, &turn_context).await;
|
||||
let items = synthetic_wait_items(agent_id, status);
|
||||
session
|
||||
.record_conversation_items(&turn_context, &items)
|
||||
.await;
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -59,6 +65,87 @@ async fn wait_for_final_status(session: &Session, agent_id: ThreadId) -> Option<
|
||||
}
|
||||
}
|
||||
|
||||
fn completion_warning_message(agent_id: ThreadId, status: &AgentStatus) -> String {
|
||||
format!("Sub-agent {agent_id} finished with status {status:?}. Keep working.")
|
||||
fn synthetic_wait_items(agent_id: ThreadId, status: AgentStatus) -> Vec<ResponseItem> {
|
||||
tracing::info!("synthetic_wait_items: agent_id: {}, status: {:?}", agent_id, status);
|
||||
let call_id = format!("synthetic-wait-{}", Uuid::new_v4());
|
||||
let agent_id_str = agent_id.to_string();
|
||||
let arguments = json!({
|
||||
"ids": [agent_id_str.clone()],
|
||||
"timeout_ms": 300_000,
|
||||
})
|
||||
.to_string();
|
||||
let output = json!({
|
||||
"status": { agent_id_str: status },
|
||||
"timed_out": false,
|
||||
})
|
||||
.to_string();
|
||||
|
||||
let call = ResponseItem::FunctionCall {
|
||||
id: None,
|
||||
name: "wait".to_string(),
|
||||
arguments,
|
||||
call_id: call_id.clone(),
|
||||
};
|
||||
let output = ResponseItem::FunctionCallOutput {
|
||||
call_id,
|
||||
output: FunctionCallOutputPayload {
|
||||
content: output,
|
||||
..Default::default()
|
||||
},
|
||||
};
|
||||
|
||||
vec![call, output]
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::synthetic_wait_items;
|
||||
use crate::agent::AgentStatus;
|
||||
use codex_protocol::ThreadId;
|
||||
use codex_protocol::models::ResponseItem;
|
||||
use pretty_assertions::assert_eq;
|
||||
use serde_json::Value;
|
||||
|
||||
#[test]
|
||||
fn synthetic_wait_items_look_like_a_real_wait_result() {
|
||||
let agent_id =
|
||||
ThreadId::from_string("00000000-0000-7000-0000-000000000001").expect("valid id");
|
||||
let status = AgentStatus::Completed(Some("done".to_string()));
|
||||
|
||||
let items = synthetic_wait_items(agent_id, status.clone());
|
||||
assert_eq!(items.len(), 2);
|
||||
|
||||
let (call_id, arguments_json) = match &items[0] {
|
||||
ResponseItem::FunctionCall {
|
||||
name,
|
||||
call_id,
|
||||
arguments,
|
||||
..
|
||||
} => {
|
||||
assert_eq!(name, "wait");
|
||||
(call_id.clone(), arguments.clone())
|
||||
}
|
||||
other => panic!("expected function call, got {other:?}"),
|
||||
};
|
||||
|
||||
let args: Value = serde_json::from_str(&arguments_json).expect("arguments should be json");
|
||||
let agent_id_string = agent_id.to_string();
|
||||
assert_eq!(args["ids"][0].as_str(), Some(agent_id_string.as_str()));
|
||||
|
||||
match &items[1] {
|
||||
ResponseItem::FunctionCallOutput {
|
||||
call_id: out_id,
|
||||
output,
|
||||
} => {
|
||||
assert_eq!(out_id, &call_id);
|
||||
let out: Value =
|
||||
serde_json::from_str(&output.content).expect("output should be json");
|
||||
assert_eq!(out["timed_out"].as_bool(), Some(false));
|
||||
let expected_status =
|
||||
serde_json::to_value(status).expect("status should serialize");
|
||||
assert_eq!(out["status"][agent_id_string.as_str()], expected_status);
|
||||
}
|
||||
other => panic!("expected function call output, got {other:?}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user