Cap legacy notify input-messages in turn-complete payloads
Summary
Legacy notify turn-complete payloads can become very large because Codex serializes input-messages into the final argv JSON. In local source inspection, the values appear to be collected from the prompt history used for the sampling request, not just the current user turn.
This makes hook execution fragile for long sessions/prompts:
- consumers receive a very large argv JSON payload before they can decide whether they need it;
- on Windows, this can exceed command-line/process invocation limits (related: #18309);
- on Linux/macOS, consumers that parse the argv JSON can pay avoidable CPU/memory costs.
Evidence from source inspection
In codex-rs/core/src/session/turn.rs, sampling_request_input_messages is built from sampling_request_input, which comes from prompt history:
let sampling_request_input: Vec<ResponseItem> = {
sess.clone_history()
.await
.for_prompt(&turn_context.model_info.input_modalities)
};
let sampling_request_input_messages = sampling_request_input
.iter()
.filter_map(|item| match parse_turn_item(item) {
Some(TurnItem::UserMessage(user_message)) => Some(user_message),
_ => None,
})
.map(|user_message| user_message.message())
.collect::<Vec<String>>();
That vector is later passed to the legacy notify payload:
HookEventAfterAgent {
input_messages: sampling_request_input_messages,
last_assistant_message: last_agent_message.clone(),
}
codex-rs/hooks/src/legacy_notify.rs then serializes it into argv JSON:
input_messages: event.input_messages.clone(),
last_assistant_message: event.last_assistant_message.clone(),
Expected behavior
Legacy notify should avoid putting unbounded prompt history into argv.
Possible approaches:
- send only current-turn user input in
input-messages; - or cap
input-messages/last-assistant-messagewith explicit flags such as: input-messages-truncated: trueinput-message-count: <n>last-assistant-message-truncated: true- or keep full data in transcript and pass
transcript_path/ metadata in notify payload.
Related downstream impact
The oh-my-codex project hit the same class of problem in long sessions and added defensive bounded intake for hook consumers:
- https://github.com/Yeachan-Heo/oh-my-codex/issues/2614
- https://github.com/Yeachan-Heo/oh-my-codex/pull/2615
That consumer-side guard is useful, but the producer-side payload should still be compact/capped so notify hooks are reliable across platforms.