Add realtime transcript notification in v2

Emit a typed realtime handoff transcript notification and wire the app-server TUI to handle it.

Co-authored-by: Codex <noreply@openai.com>
This commit is contained in:
Ahmed Ibrahim
2026-03-20 12:58:03 -07:00
parent a941d8439d
commit 4125a6a05f
15 changed files with 408 additions and 45 deletions

View File

@@ -21,6 +21,8 @@ use codex_app_server_protocol::ThreadRealtimeStartResponse;
use codex_app_server_protocol::ThreadRealtimeStartedNotification;
use codex_app_server_protocol::ThreadRealtimeStopParams;
use codex_app_server_protocol::ThreadRealtimeStopResponse;
use codex_app_server_protocol::ThreadRealtimeTranscriptAddedNotification;
use codex_app_server_protocol::ThreadRealtimeTranscriptEntry;
use codex_app_server_protocol::ThreadStartParams;
use codex_app_server_protocol::ThreadStartResponse;
use codex_features::FEATURES;
@@ -66,6 +68,20 @@ async fn realtime_conversation_streams_v2_notifications() -> Result<()> {
"content": [{ "type": "text", "text": "hi" }]
}
}),
json!({
"type": "conversation.input_transcript.delta",
"delta": "delegate now"
}),
json!({
"type": "conversation.output_transcript.delta",
"delta": "working"
}),
json!({
"type": "conversation.handoff.requested",
"handoff_id": "handoff_1",
"item_id": "item_2",
"input_transcript": "delegate now"
}),
json!({
"type": "error",
"message": "upstream boom"
@@ -180,6 +196,28 @@ async fn realtime_conversation_streams_v2_notifications() -> Result<()> {
assert_eq!(item_added.thread_id, output_audio.thread_id);
assert_eq!(item_added.item["type"], json!("message"));
let transcript_added = read_notification::<ThreadRealtimeTranscriptAddedNotification>(
&mut mcp,
"thread/realtime/transcriptAdded",
)
.await?;
assert_eq!(transcript_added.thread_id, output_audio.thread_id);
assert_eq!(transcript_added.handoff_id, "handoff_1");
assert_eq!(transcript_added.item_id, "item_2");
assert_eq!(
transcript_added.transcript,
vec![
ThreadRealtimeTranscriptEntry {
role: "user".to_string(),
text: "delegate now".to_string(),
},
ThreadRealtimeTranscriptEntry {
role: "assistant".to_string(),
text: "working".to_string(),
},
]
);
let realtime_error =
read_notification::<ThreadRealtimeErrorNotification>(&mut mcp, "thread/realtime/error")
.await?;