mirror of
https://github.com/openai/codex.git
synced 2026-11-06 20:20:34 +00:00
Merge branch 'nicholasclark/tool-call-task-headers-_meta' into nicholasclark/app-server-inprocess-parent-request-headers
This commit is contained in:
@@ -18,6 +18,7 @@ use crate::protocol::v2::TurnError;
|
||||
use crate::protocol::v2::TurnStatus;
|
||||
use crate::protocol::v2::UserInput;
|
||||
use crate::protocol::v2::WebSearchAction;
|
||||
use codex_protocol::items::parse_hook_prompt_message;
|
||||
use codex_protocol::models::MessagePhase;
|
||||
use codex_protocol::protocol::AgentReasoningEvent;
|
||||
use codex_protocol::protocol::AgentReasoningRawContentEvent;
|
||||
@@ -184,12 +185,37 @@ impl ThreadHistoryBuilder {
|
||||
match item {
|
||||
RolloutItem::EventMsg(event) => self.handle_event(event),
|
||||
RolloutItem::Compacted(payload) => self.handle_compacted(payload),
|
||||
RolloutItem::TurnContext(_)
|
||||
| RolloutItem::SessionMeta(_)
|
||||
| RolloutItem::ResponseItem(_) => {}
|
||||
RolloutItem::ResponseItem(item) => self.handle_response_item(item),
|
||||
RolloutItem::TurnContext(_) | RolloutItem::SessionMeta(_) => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_response_item(&mut self, item: &codex_protocol::models::ResponseItem) {
|
||||
let codex_protocol::models::ResponseItem::Message {
|
||||
role, content, id, ..
|
||||
} = item
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
if role != "user" {
|
||||
return;
|
||||
}
|
||||
|
||||
let Some(hook_prompt) = parse_hook_prompt_message(id.as_ref(), content) else {
|
||||
return;
|
||||
};
|
||||
|
||||
self.ensure_turn().items.push(ThreadItem::HookPrompt {
|
||||
id: hook_prompt.id,
|
||||
fragments: hook_prompt
|
||||
.fragments
|
||||
.into_iter()
|
||||
.map(crate::protocol::v2::HookPromptFragment::from)
|
||||
.collect(),
|
||||
});
|
||||
}
|
||||
|
||||
fn handle_user_message(&mut self, payload: &UserMessageEvent) {
|
||||
// User messages should stay in explicitly opened turns. For backward
|
||||
// compatibility with older streams that did not open turns explicitly,
|
||||
@@ -281,6 +307,7 @@ impl ThreadHistoryBuilder {
|
||||
);
|
||||
}
|
||||
codex_protocol::items::TurnItem::UserMessage(_)
|
||||
| codex_protocol::items::TurnItem::HookPrompt(_)
|
||||
| codex_protocol::items::TurnItem::AgentMessage(_)
|
||||
| codex_protocol::items::TurnItem::Reasoning(_)
|
||||
| codex_protocol::items::TurnItem::WebSearch(_)
|
||||
@@ -301,6 +328,7 @@ impl ThreadHistoryBuilder {
|
||||
);
|
||||
}
|
||||
codex_protocol::items::TurnItem::UserMessage(_)
|
||||
| codex_protocol::items::TurnItem::HookPrompt(_)
|
||||
| codex_protocol::items::TurnItem::AgentMessage(_)
|
||||
| codex_protocol::items::TurnItem::Reasoning(_)
|
||||
| codex_protocol::items::TurnItem::WebSearch(_)
|
||||
@@ -1149,8 +1177,10 @@ mod tests {
|
||||
use crate::protocol::v2::CommandExecutionSource;
|
||||
use codex_protocol::ThreadId;
|
||||
use codex_protocol::dynamic_tools::DynamicToolCallOutputContentItem as CoreDynamicToolCallOutputContentItem;
|
||||
use codex_protocol::items::HookPromptFragment as CoreHookPromptFragment;
|
||||
use codex_protocol::items::TurnItem as CoreTurnItem;
|
||||
use codex_protocol::items::UserMessageItem as CoreUserMessageItem;
|
||||
use codex_protocol::items::build_hook_prompt_message;
|
||||
use codex_protocol::models::MessagePhase as CoreMessagePhase;
|
||||
use codex_protocol::models::WebSearchAction as CoreWebSearchAction;
|
||||
use codex_protocol::parse_command::ParsedCommand;
|
||||
@@ -2645,4 +2675,80 @@ mod tests {
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rebuilds_hook_prompt_items_from_rollout_response_items() {
|
||||
let hook_prompt = build_hook_prompt_message(&[
|
||||
CoreHookPromptFragment::from_single_hook("Retry with tests.", "hook-run-1"),
|
||||
CoreHookPromptFragment::from_single_hook("Then summarize cleanly.", "hook-run-2"),
|
||||
])
|
||||
.expect("hook prompt message");
|
||||
let items = vec![
|
||||
RolloutItem::EventMsg(EventMsg::TurnStarted(TurnStartedEvent {
|
||||
turn_id: "turn-a".into(),
|
||||
model_context_window: None,
|
||||
collaboration_mode_kind: Default::default(),
|
||||
})),
|
||||
RolloutItem::EventMsg(EventMsg::UserMessage(UserMessageEvent {
|
||||
message: "hello".into(),
|
||||
images: None,
|
||||
text_elements: Vec::new(),
|
||||
local_images: Vec::new(),
|
||||
})),
|
||||
RolloutItem::ResponseItem(hook_prompt),
|
||||
RolloutItem::EventMsg(EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: "turn-a".into(),
|
||||
last_agent_message: None,
|
||||
})),
|
||||
];
|
||||
|
||||
let turns = build_turns_from_rollout_items(&items);
|
||||
|
||||
assert_eq!(turns.len(), 1);
|
||||
assert_eq!(turns[0].items.len(), 2);
|
||||
assert_eq!(
|
||||
turns[0].items[1],
|
||||
ThreadItem::HookPrompt {
|
||||
id: turns[0].items[1].id().to_string(),
|
||||
fragments: vec![
|
||||
crate::protocol::v2::HookPromptFragment {
|
||||
text: "Retry with tests.".into(),
|
||||
hook_run_id: "hook-run-1".into(),
|
||||
},
|
||||
crate::protocol::v2::HookPromptFragment {
|
||||
text: "Then summarize cleanly.".into(),
|
||||
hook_run_id: "hook-run-2".into(),
|
||||
},
|
||||
],
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ignores_plain_user_response_items_in_rollout_replay() {
|
||||
let items = vec![
|
||||
RolloutItem::EventMsg(EventMsg::TurnStarted(TurnStartedEvent {
|
||||
turn_id: "turn-a".into(),
|
||||
model_context_window: None,
|
||||
collaboration_mode_kind: Default::default(),
|
||||
})),
|
||||
RolloutItem::ResponseItem(codex_protocol::models::ResponseItem::Message {
|
||||
id: Some("msg-1".into()),
|
||||
role: "user".into(),
|
||||
content: vec![codex_protocol::models::ContentItem::InputText {
|
||||
text: "plain text".into(),
|
||||
}],
|
||||
end_turn: None,
|
||||
phase: None,
|
||||
}),
|
||||
RolloutItem::EventMsg(EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: "turn-a".into(),
|
||||
last_agent_message: None,
|
||||
})),
|
||||
];
|
||||
|
||||
let turns = build_turns_from_rollout_items(&items);
|
||||
assert_eq!(turns.len(), 1);
|
||||
assert!(turns[0].items.is_empty());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4130,6 +4130,12 @@ pub enum ThreadItem {
|
||||
UserMessage { id: String, content: Vec<UserInput> },
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(rename_all = "camelCase")]
|
||||
HookPrompt {
|
||||
id: String,
|
||||
fragments: Vec<HookPromptFragment>,
|
||||
},
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(rename_all = "camelCase")]
|
||||
AgentMessage {
|
||||
id: String,
|
||||
text: String,
|
||||
@@ -4263,10 +4269,19 @@ pub enum ThreadItem {
|
||||
ContextCompaction { id: String },
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(rename_all = "camelCase", export_to = "v2/")]
|
||||
pub struct HookPromptFragment {
|
||||
pub text: String,
|
||||
pub hook_run_id: String,
|
||||
}
|
||||
|
||||
impl ThreadItem {
|
||||
pub fn id(&self) -> &str {
|
||||
match self {
|
||||
ThreadItem::UserMessage { id, .. }
|
||||
| ThreadItem::HookPrompt { id, .. }
|
||||
| ThreadItem::AgentMessage { id, .. }
|
||||
| ThreadItem::Plan { id, .. }
|
||||
| ThreadItem::Reasoning { id, .. }
|
||||
@@ -4376,6 +4391,14 @@ impl From<CoreTurnItem> for ThreadItem {
|
||||
id: user.id,
|
||||
content: user.content.into_iter().map(UserInput::from).collect(),
|
||||
},
|
||||
CoreTurnItem::HookPrompt(hook_prompt) => ThreadItem::HookPrompt {
|
||||
id: hook_prompt.id,
|
||||
fragments: hook_prompt
|
||||
.fragments
|
||||
.into_iter()
|
||||
.map(HookPromptFragment::from)
|
||||
.collect(),
|
||||
},
|
||||
CoreTurnItem::AgentMessage(agent) => {
|
||||
let text = agent
|
||||
.content
|
||||
@@ -4418,6 +4441,15 @@ impl From<CoreTurnItem> for ThreadItem {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<codex_protocol::items::HookPromptFragment> for HookPromptFragment {
|
||||
fn from(value: codex_protocol::items::HookPromptFragment) -> Self {
|
||||
Self {
|
||||
text: value.text,
|
||||
hook_run_id: value.hook_run_id,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export_to = "v2/")]
|
||||
|
||||
Reference in New Issue
Block a user