From d2a63fcdd79da5706e33050907dfbf5e8885ed63 Mon Sep 17 00:00:00 2001 From: pru-oai Date: Mon, 15 Jun 2026 17:35:42 -0700 Subject: [PATCH] [app-server] add image generation title --- codex-rs/analytics/src/analytics_client_tests.rs | 1 + .../schema/json/ServerNotification.json | 7 +++++++ .../schema/json/codex_app_server_protocol.schemas.json | 7 +++++++ .../schema/json/codex_app_server_protocol.v2.schemas.json | 7 +++++++ .../schema/json/v2/ItemCompletedNotification.json | 7 +++++++ .../schema/json/v2/ItemStartedNotification.json | 7 +++++++ .../schema/json/v2/ReviewStartResponse.json | 7 +++++++ .../schema/json/v2/ThreadForkResponse.json | 7 +++++++ .../schema/json/v2/ThreadListResponse.json | 7 +++++++ .../schema/json/v2/ThreadMetadataUpdateResponse.json | 7 +++++++ .../schema/json/v2/ThreadReadResponse.json | 7 +++++++ .../schema/json/v2/ThreadResumeResponse.json | 7 +++++++ .../schema/json/v2/ThreadRollbackResponse.json | 7 +++++++ .../schema/json/v2/ThreadStartResponse.json | 7 +++++++ .../schema/json/v2/ThreadStartedNotification.json | 7 +++++++ .../schema/json/v2/ThreadUnarchiveResponse.json | 7 +++++++ .../schema/json/v2/TurnCompletedNotification.json | 7 +++++++ .../schema/json/v2/TurnStartResponse.json | 7 +++++++ .../schema/json/v2/TurnStartedNotification.json | 7 +++++++ .../app-server-protocol/schema/typescript/v2/ThreadItem.ts | 6 +++++- .../app-server-protocol/src/protocol/thread_history.rs | 3 +++ codex-rs/app-server-protocol/src/protocol/v2/item.rs | 3 +++ codex-rs/app-server/README.md | 1 + .../src/request_processors/thread_resume_redaction.rs | 1 + codex-rs/app-server/tests/suite/v2/imagegen_extension.rs | 1 + codex-rs/tui/src/chatwidget/tests/helpers.rs | 1 + 26 files changed, 142 insertions(+), 1 deletion(-) diff --git a/codex-rs/analytics/src/analytics_client_tests.rs b/codex-rs/analytics/src/analytics_client_tests.rs index 7c634ce370..ba2907796c 100644 --- a/codex-rs/analytics/src/analytics_client_tests.rs +++ b/codex-rs/analytics/src/analytics_client_tests.rs @@ -3957,6 +3957,7 @@ async fn turn_event_counts_completed_tool_items() { ThreadItem::ImageGeneration { id: "image-1".to_string(), status: "completed".to_string(), + title: None, revised_prompt: None, result: "ok".to_string(), saved_path: None, diff --git a/codex-rs/app-server-protocol/schema/json/ServerNotification.json b/codex-rs/app-server-protocol/schema/json/ServerNotification.json index 2c87ad5cde..0b911b420c 100644 --- a/codex-rs/app-server-protocol/schema/json/ServerNotification.json +++ b/codex-rs/app-server-protocol/schema/json/ServerNotification.json @@ -4364,6 +4364,13 @@ "status": { "type": "string" }, + "title": { + "description": "Short display title for the generated image, when available.", + "type": [ + "string", + "null" + ] + }, "type": { "enum": [ "imageGeneration" diff --git a/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json b/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json index 46c3f07206..2c63561ef7 100644 --- a/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json +++ b/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json @@ -17686,6 +17686,13 @@ "status": { "type": "string" }, + "title": { + "description": "Short display title for the generated image, when available.", + "type": [ + "string", + "null" + ] + }, "type": { "enum": [ "imageGeneration" diff --git a/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json b/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json index e95d4c98a8..e854c6c035 100644 --- a/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json +++ b/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json @@ -15494,6 +15494,13 @@ "status": { "type": "string" }, + "title": { + "description": "Short display title for the generated image, when available.", + "type": [ + "string", + "null" + ] + }, "type": { "enum": [ "imageGeneration" diff --git a/codex-rs/app-server-protocol/schema/json/v2/ItemCompletedNotification.json b/codex-rs/app-server-protocol/schema/json/v2/ItemCompletedNotification.json index 162f3aa3d9..eff9ae001e 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/ItemCompletedNotification.json +++ b/codex-rs/app-server-protocol/schema/json/v2/ItemCompletedNotification.json @@ -1114,6 +1114,13 @@ "status": { "type": "string" }, + "title": { + "description": "Short display title for the generated image, when available.", + "type": [ + "string", + "null" + ] + }, "type": { "enum": [ "imageGeneration" diff --git a/codex-rs/app-server-protocol/schema/json/v2/ItemStartedNotification.json b/codex-rs/app-server-protocol/schema/json/v2/ItemStartedNotification.json index af3b1ddd1b..ccf82a8a7e 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/ItemStartedNotification.json +++ b/codex-rs/app-server-protocol/schema/json/v2/ItemStartedNotification.json @@ -1114,6 +1114,13 @@ "status": { "type": "string" }, + "title": { + "description": "Short display title for the generated image, when available.", + "type": [ + "string", + "null" + ] + }, "type": { "enum": [ "imageGeneration" diff --git a/codex-rs/app-server-protocol/schema/json/v2/ReviewStartResponse.json b/codex-rs/app-server-protocol/schema/json/v2/ReviewStartResponse.json index 8918f6cae4..cec473a5e2 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/ReviewStartResponse.json +++ b/codex-rs/app-server-protocol/schema/json/v2/ReviewStartResponse.json @@ -1258,6 +1258,13 @@ "status": { "type": "string" }, + "title": { + "description": "Short display title for the generated image, when available.", + "type": [ + "string", + "null" + ] + }, "type": { "enum": [ "imageGeneration" diff --git a/codex-rs/app-server-protocol/schema/json/v2/ThreadForkResponse.json b/codex-rs/app-server-protocol/schema/json/v2/ThreadForkResponse.json index fa1277b0ef..f684fc66f5 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/ThreadForkResponse.json +++ b/codex-rs/app-server-protocol/schema/json/v2/ThreadForkResponse.json @@ -1742,6 +1742,13 @@ "status": { "type": "string" }, + "title": { + "description": "Short display title for the generated image, when available.", + "type": [ + "string", + "null" + ] + }, "type": { "enum": [ "imageGeneration" diff --git a/codex-rs/app-server-protocol/schema/json/v2/ThreadListResponse.json b/codex-rs/app-server-protocol/schema/json/v2/ThreadListResponse.json index 1b53d4ca2e..7fc1df1018 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/ThreadListResponse.json +++ b/codex-rs/app-server-protocol/schema/json/v2/ThreadListResponse.json @@ -1557,6 +1557,13 @@ "status": { "type": "string" }, + "title": { + "description": "Short display title for the generated image, when available.", + "type": [ + "string", + "null" + ] + }, "type": { "enum": [ "imageGeneration" diff --git a/codex-rs/app-server-protocol/schema/json/v2/ThreadMetadataUpdateResponse.json b/codex-rs/app-server-protocol/schema/json/v2/ThreadMetadataUpdateResponse.json index c98fa1f2a5..f3c361214c 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/ThreadMetadataUpdateResponse.json +++ b/codex-rs/app-server-protocol/schema/json/v2/ThreadMetadataUpdateResponse.json @@ -1557,6 +1557,13 @@ "status": { "type": "string" }, + "title": { + "description": "Short display title for the generated image, when available.", + "type": [ + "string", + "null" + ] + }, "type": { "enum": [ "imageGeneration" diff --git a/codex-rs/app-server-protocol/schema/json/v2/ThreadReadResponse.json b/codex-rs/app-server-protocol/schema/json/v2/ThreadReadResponse.json index 345d84d794..2c2786f3a3 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/ThreadReadResponse.json +++ b/codex-rs/app-server-protocol/schema/json/v2/ThreadReadResponse.json @@ -1557,6 +1557,13 @@ "status": { "type": "string" }, + "title": { + "description": "Short display title for the generated image, when available.", + "type": [ + "string", + "null" + ] + }, "type": { "enum": [ "imageGeneration" diff --git a/codex-rs/app-server-protocol/schema/json/v2/ThreadResumeResponse.json b/codex-rs/app-server-protocol/schema/json/v2/ThreadResumeResponse.json index 98ef79517b..12fd42a10e 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/ThreadResumeResponse.json +++ b/codex-rs/app-server-protocol/schema/json/v2/ThreadResumeResponse.json @@ -1742,6 +1742,13 @@ "status": { "type": "string" }, + "title": { + "description": "Short display title for the generated image, when available.", + "type": [ + "string", + "null" + ] + }, "type": { "enum": [ "imageGeneration" diff --git a/codex-rs/app-server-protocol/schema/json/v2/ThreadRollbackResponse.json b/codex-rs/app-server-protocol/schema/json/v2/ThreadRollbackResponse.json index f63dfe6ffb..c581007973 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/ThreadRollbackResponse.json +++ b/codex-rs/app-server-protocol/schema/json/v2/ThreadRollbackResponse.json @@ -1557,6 +1557,13 @@ "status": { "type": "string" }, + "title": { + "description": "Short display title for the generated image, when available.", + "type": [ + "string", + "null" + ] + }, "type": { "enum": [ "imageGeneration" diff --git a/codex-rs/app-server-protocol/schema/json/v2/ThreadStartResponse.json b/codex-rs/app-server-protocol/schema/json/v2/ThreadStartResponse.json index 052023361a..6c87545e1b 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/ThreadStartResponse.json +++ b/codex-rs/app-server-protocol/schema/json/v2/ThreadStartResponse.json @@ -1742,6 +1742,13 @@ "status": { "type": "string" }, + "title": { + "description": "Short display title for the generated image, when available.", + "type": [ + "string", + "null" + ] + }, "type": { "enum": [ "imageGeneration" diff --git a/codex-rs/app-server-protocol/schema/json/v2/ThreadStartedNotification.json b/codex-rs/app-server-protocol/schema/json/v2/ThreadStartedNotification.json index cdeda64b7c..f07139aba5 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/ThreadStartedNotification.json +++ b/codex-rs/app-server-protocol/schema/json/v2/ThreadStartedNotification.json @@ -1557,6 +1557,13 @@ "status": { "type": "string" }, + "title": { + "description": "Short display title for the generated image, when available.", + "type": [ + "string", + "null" + ] + }, "type": { "enum": [ "imageGeneration" diff --git a/codex-rs/app-server-protocol/schema/json/v2/ThreadUnarchiveResponse.json b/codex-rs/app-server-protocol/schema/json/v2/ThreadUnarchiveResponse.json index 2a7281fcbb..b9b7002150 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/ThreadUnarchiveResponse.json +++ b/codex-rs/app-server-protocol/schema/json/v2/ThreadUnarchiveResponse.json @@ -1557,6 +1557,13 @@ "status": { "type": "string" }, + "title": { + "description": "Short display title for the generated image, when available.", + "type": [ + "string", + "null" + ] + }, "type": { "enum": [ "imageGeneration" diff --git a/codex-rs/app-server-protocol/schema/json/v2/TurnCompletedNotification.json b/codex-rs/app-server-protocol/schema/json/v2/TurnCompletedNotification.json index 3cc329c9e5..e4ebcc660d 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/TurnCompletedNotification.json +++ b/codex-rs/app-server-protocol/schema/json/v2/TurnCompletedNotification.json @@ -1258,6 +1258,13 @@ "status": { "type": "string" }, + "title": { + "description": "Short display title for the generated image, when available.", + "type": [ + "string", + "null" + ] + }, "type": { "enum": [ "imageGeneration" diff --git a/codex-rs/app-server-protocol/schema/json/v2/TurnStartResponse.json b/codex-rs/app-server-protocol/schema/json/v2/TurnStartResponse.json index 7dbea8af53..1d36ba56df 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/TurnStartResponse.json +++ b/codex-rs/app-server-protocol/schema/json/v2/TurnStartResponse.json @@ -1258,6 +1258,13 @@ "status": { "type": "string" }, + "title": { + "description": "Short display title for the generated image, when available.", + "type": [ + "string", + "null" + ] + }, "type": { "enum": [ "imageGeneration" diff --git a/codex-rs/app-server-protocol/schema/json/v2/TurnStartedNotification.json b/codex-rs/app-server-protocol/schema/json/v2/TurnStartedNotification.json index 362e789ea8..fe6bf3b115 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/TurnStartedNotification.json +++ b/codex-rs/app-server-protocol/schema/json/v2/TurnStartedNotification.json @@ -1258,6 +1258,13 @@ "status": { "type": "string" }, + "title": { + "description": "Short display title for the generated image, when available.", + "type": [ + "string", + "null" + ] + }, "type": { "enum": [ "imageGeneration" diff --git a/codex-rs/app-server-protocol/schema/typescript/v2/ThreadItem.ts b/codex-rs/app-server-protocol/schema/typescript/v2/ThreadItem.ts index 8d74ae8de2..ba172abe07 100644 --- a/codex-rs/app-server-protocol/schema/typescript/v2/ThreadItem.ts +++ b/codex-rs/app-server-protocol/schema/typescript/v2/ThreadItem.ts @@ -99,4 +99,8 @@ reasoningEffort: ReasoningEffort | null, /** * Last known status of the target agents, when available. */ -agentsStates: { [key in string]?: CollabAgentState }, } | { "type": "subAgentActivity", id: string, kind: SubAgentActivityKind, agentThreadId: string, agentPath: string, } | { "type": "webSearch", id: string, query: string, action: WebSearchAction | null, } | { "type": "imageView", id: string, path: AbsolutePathBuf, } | { "type": "imageGeneration", id: string, status: string, revisedPrompt: string | null, result: string, savedPath?: AbsolutePathBuf, } | { "type": "enteredReviewMode", id: string, review: string, } | { "type": "exitedReviewMode", id: string, review: string, } | { "type": "contextCompaction", id: string, }; +agentsStates: { [key in string]?: CollabAgentState }, } | { "type": "subAgentActivity", id: string, kind: SubAgentActivityKind, agentThreadId: string, agentPath: string, } | { "type": "webSearch", id: string, query: string, action: WebSearchAction | null, } | { "type": "imageView", id: string, path: AbsolutePathBuf, } | { "type": "imageGeneration", id: string, status: string, +/** + * Short display title for the generated image, when available. + */ +title: string | null, revisedPrompt: string | null, result: string, savedPath?: AbsolutePathBuf, } | { "type": "enteredReviewMode", id: string, review: string, } | { "type": "exitedReviewMode", id: string, review: string, } | { "type": "contextCompaction", id: string, }; diff --git a/codex-rs/app-server-protocol/src/protocol/thread_history.rs b/codex-rs/app-server-protocol/src/protocol/thread_history.rs index e19a19e1e3..f6d0e5f180 100644 --- a/codex-rs/app-server-protocol/src/protocol/thread_history.rs +++ b/codex-rs/app-server-protocol/src/protocol/thread_history.rs @@ -602,6 +602,7 @@ impl ThreadHistoryBuilder { let item = ThreadItem::ImageGeneration { id: payload.call_id.clone(), status: String::new(), + title: None, revised_prompt: None, result: String::new(), saved_path: None, @@ -613,6 +614,7 @@ impl ThreadHistoryBuilder { let item = ThreadItem::ImageGeneration { id: payload.call_id.clone(), status: payload.status.clone(), + title: None, revised_prompt: payload.revised_prompt.clone(), result: payload.result.clone(), saved_path: payload.saved_path.clone(), @@ -1622,6 +1624,7 @@ mod tests { ThreadItem::ImageGeneration { id: "ig_123".into(), status: "completed".into(), + title: None, revised_prompt: Some("final prompt".into()), result: "Zm9v".into(), saved_path: Some(test_path_buf("/tmp/ig_123.png").abs()), diff --git a/codex-rs/app-server-protocol/src/protocol/v2/item.rs b/codex-rs/app-server-protocol/src/protocol/v2/item.rs index f556890a96..2ce61f3aa6 100644 --- a/codex-rs/app-server-protocol/src/protocol/v2/item.rs +++ b/codex-rs/app-server-protocol/src/protocol/v2/item.rs @@ -358,6 +358,8 @@ pub enum ThreadItem { ImageGeneration { id: String, status: String, + /// Short display title for the generated image, when available. + title: Option, revised_prompt: Option, result: String, #[serde(default, skip_serializing_if = "Option::is_none")] @@ -837,6 +839,7 @@ impl From for ThreadItem { CoreTurnItem::ImageGeneration(image) => ThreadItem::ImageGeneration { id: image.id, status: image.status, + title: None, revised_prompt: image.revised_prompt, result: image.result, saved_path: image.saved_path, diff --git a/codex-rs/app-server/README.md b/codex-rs/app-server/README.md index b6b1048d22..a41b78d3b1 100644 --- a/codex-rs/app-server/README.md +++ b/codex-rs/app-server/README.md @@ -1354,6 +1354,7 @@ Today both notifications carry an empty `items` array even when item events were - `collabToolCall` — `{id, tool, status, senderThreadId, receiverThreadId?, newThreadId?, prompt?, agentStatus?}` describing collab tool calls (`spawn_agent`, `send_input`, `resume_agent`, `wait`, `close_agent`); `status` is `inProgress`, `completed`, or `failed`. - `webSearch` — `{id, query, action?}` for a web search request issued by the agent; `action` mirrors the Responses API web_search action payload (`search`, `open_page`, `find_in_page`) and may be omitted until completion. - `imageView` — `{id, path}` emitted when the agent invokes the image viewer tool. +- `imageGeneration` — `{id, status, title, revisedPrompt, result, savedPath?}` emitted when the agent generates an image; `title` is a short display title when available, while `revisedPrompt` contains the full prompt used for generation. - `enteredReviewMode` — `{id, review}` sent when the reviewer starts; `review` is a short user-facing label such as `"current changes"` or the requested target description. - `exitedReviewMode` — `{id, review}` emitted when the reviewer finishes; `review` is the full plain-text review (usually, overall notes plus bullet point findings). - `contextCompaction` — `{id}` emitted when codex compacts the conversation history. This can happen automatically. diff --git a/codex-rs/app-server/src/request_processors/thread_resume_redaction.rs b/codex-rs/app-server/src/request_processors/thread_resume_redaction.rs index e970a88a9f..2b14add857 100644 --- a/codex-rs/app-server/src/request_processors/thread_resume_redaction.rs +++ b/codex-rs/app-server/src/request_processors/thread_resume_redaction.rs @@ -94,6 +94,7 @@ mod tests { ThreadItem::ImageGeneration { id: "ig-1".to_string(), status: "completed".to_string(), + title: None, revised_prompt: Some("revised".to_string()), result: "base64-result".to_string(), saved_path: Some(test_path_buf("/tmp/ig-1.png").abs()), diff --git a/codex-rs/app-server/tests/suite/v2/imagegen_extension.rs b/codex-rs/app-server/tests/suite/v2/imagegen_extension.rs index 5c18aa8a4e..bd2466d1e4 100644 --- a/codex-rs/app-server/tests/suite/v2/imagegen_extension.rs +++ b/codex-rs/app-server/tests/suite/v2/imagegen_extension.rs @@ -200,6 +200,7 @@ async fn standalone_image_generation_failure_emits_terminal_item() -> Result<()> ThreadItem::ImageGeneration { id: call_id.to_string(), status: "failed".to_string(), + title: None, revised_prompt: Some("paint a blue whale".to_string()), result: String::new(), saved_path: None, diff --git a/codex-rs/tui/src/chatwidget/tests/helpers.rs b/codex-rs/tui/src/chatwidget/tests/helpers.rs index dc32e8c7ba..43a8e91882 100644 --- a/codex-rs/tui/src/chatwidget/tests/helpers.rs +++ b/codex-rs/tui/src/chatwidget/tests/helpers.rs @@ -710,6 +710,7 @@ pub(super) fn handle_image_generation_end( item: AppServerThreadItem::ImageGeneration { id: call_id.into(), status: status.into(), + title: None, revised_prompt, result: String::new(), saved_path,