mirror of
https://github.com/openai/codex.git
synced 2026-11-13 14:46:14 +00:00
feat(core): emit canonical hook prompt items (#31630)
## Description This PR moves hook prompts onto the canonical `TurnItem` lifecycle in core. Stop hooks now record their `ResponseItem` through the existing lifecycle path, which emits `ItemStarted` and `ItemCompleted`. App-server consumes those events directly instead of deriving a hook prompt from `RawResponseItem`. ## Why Hook prompts were the only `ThreadItem` app-server synthesized from `RawResponseItem`. This brings them in line with other core-owned turn items while preserving legacy rollout replay. ## What changed - Route stop-hook prompts through `record_response_item_and_emit_turn_item`. - Materialize canonical hook prompts in `ThreadHistoryBuilder`. - Remove `RawResponseItem` to `ThreadItem` synthesis while preserving legacy rollout replay. - Add focused coverage for lifecycle emission and canonical and legacy history materialization.
This commit is contained in:
1 parent
bdaad6820c
commit
ba5dd1fd3a
6 files changed
+77
-117
No files matched your search
@@ -600,6 +600,7 @@ impl ThreadHistoryBuilder {
|
||||
let should_upsert = match item {
|
||||
codex_protocol::items::TurnItem::Plan(plan) => !plan.text.is_empty(),
|
||||
codex_protocol::items::TurnItem::Sleep(_)
|
||||
| codex_protocol::items::TurnItem::HookPrompt(_)
|
||||
| codex_protocol::items::TurnItem::CommandExecution(_)
|
||||
| codex_protocol::items::TurnItem::DynamicToolCall(_)
|
||||
| codex_protocol::items::TurnItem::CollabAgentToolCall(_)
|
||||
@@ -608,7 +609,6 @@ impl ThreadHistoryBuilder {
|
||||
| codex_protocol::items::TurnItem::EnteredReviewMode(_)
|
||||
| codex_protocol::items::TurnItem::ExitedReviewMode(_) => true,
|
||||
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(_)
|
||||
@@ -4027,6 +4027,37 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn canonical_hook_prompt_completion_updates_turn_history() {
|
||||
let hook_prompt = CoreTurnItem::HookPrompt(codex_protocol::items::HookPromptItem {
|
||||
id: "hook-prompt-1".into(),
|
||||
fragments: vec![CoreHookPromptFragment::from_single_hook(
|
||||
"Retry with tests.",
|
||||
"hook-run-1",
|
||||
)],
|
||||
});
|
||||
let expected_item = ThreadItem::from(hook_prompt.clone());
|
||||
let mut builder = ThreadHistoryBuilder::new();
|
||||
builder.handle_event(&EventMsg::TurnStarted(TurnStartedEvent {
|
||||
turn_id: "turn-a".into(),
|
||||
trace_id: None,
|
||||
started_at: None,
|
||||
model_context_window: None,
|
||||
collaboration_mode_kind: Default::default(),
|
||||
}));
|
||||
builder.handle_event(&EventMsg::ItemCompleted(ItemCompletedEvent {
|
||||
thread_id: ThreadId::new(),
|
||||
turn_id: "turn-a".into(),
|
||||
item: hook_prompt,
|
||||
completed_at_ms: 0,
|
||||
}));
|
||||
|
||||
assert_eq!(
|
||||
builder.active_turn_snapshot().expect("active turn").items,
|
||||
vec![expected_item]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ignores_plain_user_response_items_in_rollout_replay() {
|
||||
let items = vec![
|
||||
|
||||
Reference in new issue
Block a user