Require prefixes for outbound response item IDs (#32312)

## What changed

- Add a `ResponseItemId` type that generates item-specific prefixes with UUIDv7 suffixes and use it across response items.
- Keep deserialization permissive for legacy histories, but omit empty or unprefixed item IDs from HTTP and WebSocket requests.
- Export the new type in the generated TypeScript protocol schema.

## Testing

- Cover prefixed ID generation, legacy deserialization, prefix recognition, and outbound request filtering.

GitOrigin-RevId: 0209fe430c826d0ae88bc4648652c4ebf390c4a4
This commit is contained in:
pakrym-oai
2026-07-11 02:24:09 +00:00
committed by copyberry
parent 08ba14b03d
commit c9d52de5ca
38 changed files with 430 additions and 160 deletions

View File

@@ -892,6 +892,7 @@ fn serialize_websocket_request(request: &ResponsesWsRequest) -> Result<String, A
mod tests {
use super::*;
use crate::common::ResponseCreateWsRequest;
use codex_protocol::ResponseItemId;
use codex_protocol::models::ContentItem;
use codex_protocol::models::ResponseItem;
use pretty_assertions::assert_eq;
@@ -905,7 +906,7 @@ mod tests {
instructions: "Use the available tools.".to_string(),
previous_response_id: Some("resp-1".to_string()),
input: vec![ResponseItem::Message {
id: Some("msg-1".to_string()),
id: Some(ResponseItemId::with_suffix("msg", "1")),
role: "user".to_string(),
content: vec![ContentItem::InputText {
text: "hello".to_string(),

View File

@@ -70,6 +70,7 @@ mod tests {
use codex_client::Response;
use codex_client::StreamResponse;
use codex_client::TransportError;
use codex_protocol::ResponseItemId;
use codex_protocol::models::ContentItem;
use codex_protocol::models::ResponseItem;
use http::StatusCode;
@@ -150,7 +151,7 @@ mod tests {
model: "gpt-test".to_string(),
reasoning: None,
input: Some(SearchInput::Items(vec![ResponseItem::Message {
id: Some("msg_search".to_string()),
id: Some(ResponseItemId::with_suffix("msg", "search")),
role: "user".to_string(),
content: vec![
ContentItem::InputText {

View File

@@ -19,6 +19,7 @@ use codex_client::RequestBody;
use codex_client::Response;
use codex_client::StreamResponse;
use codex_client::TransportError;
use codex_protocol::ResponseItemId;
use codex_protocol::models::ContentItem;
use codex_protocol::models::ResponseItem;
use codex_protocol::protocol::SessionSource;
@@ -309,7 +310,7 @@ async fn responses_client_stream_request_preserves_item_ids() -> Result<()> {
model: "gpt-test".into(),
instructions: "Say hi".into(),
input: vec![ResponseItem::Message {
id: Some("msg_1".into()),
id: Some(ResponseItemId::with_suffix("msg", "1")),
role: "user".into(),
content: vec![ContentItem::InputText { text: "hi".into() }],
phase: None,
@@ -516,7 +517,7 @@ async fn azure_store_sends_ids_and_headers() -> Result<()> {
model: "gpt-test".into(),
instructions: "Say hi".into(),
input: vec![ResponseItem::Message {
id: Some("msg_1".into()),
id: Some(ResponseItemId::with_suffix("msg", "1")),
role: "user".into(),
content: vec![ContentItem::InputText { text: "hi".into() }],
phase: None,