Preserve client metadata through queued submissions (#59826)

## Why

Queued inputs previously stored and dispatched without the submitting client's Responses API metadata, losing attribution such as `client_type` when the queued turn started.

## What changed

- Accept `responsesapiClientMetadata` when adding or updating queued submissions and expose it on returned queue items.
- Persist metadata with the input and forward it when starting a selected item or dispatching an idle queue, including after restoration.
- Preserve existing metadata when an update omits it or supplies an empty map; replace it when a non-empty map is supplied.
- Keep stored inputs readable by older queue workers and update generated protocol artifacts.

## Testing

Extend queue service and app-server tests to cover metadata round trips, preservation and replacement on edits, compatibility with older readers, and forwarding during selected, idle, and restored dispatch.

GitOrigin-RevId: 508043b1d3d0298c9af2be8e05b6999de46596a1
This commit is contained in:
Eddie Chen
2026-11-06 05:10:44 +00:00
committed by copyberry
parent 5fab289359
commit a037e65ead
13 changed files with 254 additions and 46 deletions
@@ -939,6 +939,8 @@ pub struct QueuedSubmission {
pub id: String,
pub input: Vec<UserInput>,
pub client_user_message_id: String,
/// Metadata retained with this input, including across reconnect and restoration.
pub responsesapi_client_metadata: Option<HashMap<String, String>>,
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
@@ -948,6 +950,9 @@ pub struct ThreadQueueAddParams {
pub thread_id: String,
pub input: Vec<UserInput>,
pub client_user_message_id: String,
/// ResponsesAPI metadata captured from the client submitting this input.
#[ts(optional = nullable)]
pub responsesapi_client_metadata: Option<HashMap<String, String>>,
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
@@ -986,6 +991,9 @@ pub struct ThreadQueueUpdateParams {
pub thread_id: String,
pub queued_submission_id: String,
pub input: Vec<UserInput>,
/// Non-empty metadata replaces the input's metadata; omission or an empty map preserves it.
#[ts(optional = nullable)]
pub responsesapi_client_metadata: Option<HashMap<String, String>>,
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]