mirror of
https://github.com/openai/codex.git
synced 2026-10-27 08:01:52 +00:00
Support standalone tool outputs in turn/start (#41002)
## What changed - Add an optional `toolOutput` to `turn/start` for starting or steering a turn with a named function-call output instead of user input. - Emit standalone outputs as `functionCallOutput` thread items, persist them in durable history, and include them in resumed threads. - Validate that tool outputs have a name, are not combined with nonempty `input`, satisfy the text-size limit, and use supported image URLs. ## Testing - Cover standalone tool-output notifications, model input, and resumed history in both legacy and paginated history modes. - Cover the text-size limit for structured tool output. GitOrigin-RevId: a1eeec7b9b7de67b1a1c5e829a54552b85ec118b
This commit is contained in:
@@ -192,7 +192,10 @@ fn activity_summary(item: &ThreadItem) -> Option<String> {
|
||||
ThreadItem::EnteredReviewMode { .. } => return Some("Entered review mode".to_string()),
|
||||
ThreadItem::ExitedReviewMode { .. } => return Some("Exited review mode".to_string()),
|
||||
ThreadItem::ContextCompaction { .. } => return Some("Compacted context".to_string()),
|
||||
ThreadItem::UserMessage { .. } | ThreadItem::HookPrompt { .. } | ThreadItem::Sleep(_) => {
|
||||
ThreadItem::UserMessage { .. }
|
||||
| ThreadItem::HookPrompt { .. }
|
||||
| ThreadItem::FunctionCallOutput { .. }
|
||||
| ThreadItem::Sleep(_) => {
|
||||
return None;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1208,6 +1208,7 @@ impl AppServerSession {
|
||||
turn_trigger: None,
|
||||
client_user_message_id: None,
|
||||
input: items,
|
||||
tool_output: None,
|
||||
responsesapi_client_metadata: None,
|
||||
additional_context: None,
|
||||
environments: None,
|
||||
|
||||
@@ -218,7 +218,7 @@ impl ChatWidget {
|
||||
ThreadItem::ContextCompaction { .. } => {
|
||||
self.add_info_message("Context compacted".to_string(), /*hint*/ None);
|
||||
}
|
||||
ThreadItem::HookPrompt { .. } => {}
|
||||
ThreadItem::HookPrompt { .. } | ThreadItem::FunctionCallOutput { .. } => {}
|
||||
ThreadItem::CollabAgentToolCall {
|
||||
id,
|
||||
tool,
|
||||
|
||||
@@ -1061,6 +1061,7 @@ async fn execute_inner(
|
||||
"name": "webSearch", "status": null
|
||||
})),
|
||||
ThreadItem::UserMessage { .. }
|
||||
| ThreadItem::FunctionCallOutput { .. }
|
||||
| ThreadItem::HookPrompt { .. }
|
||||
| ThreadItem::AgentMessage { .. }
|
||||
| ThreadItem::Plan { .. }
|
||||
@@ -1316,6 +1317,23 @@ fn turn_summary(turn: &Turn, include_outputs: bool, output_chars: usize) -> Valu
|
||||
ThreadItem::HookPrompt { id, fragments } => json!({
|
||||
"type": "hookPrompt", "id": id, "fragmentCount": fragments.len()
|
||||
}),
|
||||
ThreadItem::FunctionCallOutput {
|
||||
id,
|
||||
name,
|
||||
namespace,
|
||||
output,
|
||||
} => {
|
||||
let mut item = json!({
|
||||
"type": "functionCallOutput", "id": id, "name": name, "namespace": namespace
|
||||
});
|
||||
if include_outputs {
|
||||
item["output"] = output_summary(
|
||||
output.to_text().as_deref().unwrap_or("[non-text output]"),
|
||||
output_chars,
|
||||
);
|
||||
}
|
||||
item
|
||||
}
|
||||
ThreadItem::AgentMessage { id, text, phase, .. } => json!({
|
||||
"type": "agentMessage", "id": id, "text": truncate(text, DEFAULT_OUTPUT_CHARS), "phase": phase
|
||||
}),
|
||||
|
||||
@@ -281,6 +281,7 @@ fn fallback_transcript_cell(item: &ThreadItem) -> Option<PlainHistoryCell> {
|
||||
}
|
||||
ThreadItem::UserMessage { .. }
|
||||
| ThreadItem::AgentMessage { .. }
|
||||
| ThreadItem::FunctionCallOutput { .. }
|
||||
| ThreadItem::Plan { .. }
|
||||
| ThreadItem::Reasoning { .. }
|
||||
| ThreadItem::Sleep(_) => return None,
|
||||
|
||||
Reference in New Issue
Block a user