mirror of
https://github.com/openai/codex.git
synced 2026-10-25 18:28:38 +00:00
codex: use item done for realtime transcript done
This commit is contained in:
@@ -1136,6 +1136,35 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_realtime_v2_item_done_output_text_event() {
|
||||
let payload = json!({
|
||||
"type": "conversation.item.done",
|
||||
"item": {
|
||||
"id": "item_output_1",
|
||||
"type": "message",
|
||||
"role": "assistant",
|
||||
"content": [
|
||||
{"type": "output_text", "text": "hello"},
|
||||
{"type": "output_text", "text": " world"}
|
||||
]
|
||||
}
|
||||
})
|
||||
.to_string();
|
||||
|
||||
assert_eq!(
|
||||
parse_realtime_event(payload.as_str(), RealtimeEventParser::RealtimeV2),
|
||||
Some(RealtimeEvent::OutputTranscriptDone(
|
||||
RealtimeTranscriptDone {
|
||||
text: "hello world".to_string(),
|
||||
item_id: Some("item_output_1".to_string()),
|
||||
output_index: None,
|
||||
content_index: None,
|
||||
}
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn complete_transcript_entry_replaces_current_part_only() {
|
||||
let mut state = ActiveTranscriptState::default();
|
||||
|
||||
@@ -10,6 +10,7 @@ use codex_protocol::protocol::RealtimeInputAudioSpeechStarted;
|
||||
use codex_protocol::protocol::RealtimeResponseCancelled;
|
||||
use codex_protocol::protocol::RealtimeResponseCreated;
|
||||
use codex_protocol::protocol::RealtimeResponseDone;
|
||||
use codex_protocol::protocol::RealtimeTranscriptDone;
|
||||
use serde_json::Map as JsonMap;
|
||||
use serde_json::Value;
|
||||
use tracing::debug;
|
||||
@@ -128,12 +129,48 @@ fn parse_conversation_item_done_event(parsed: &Value) -> Option<RealtimeEvent> {
|
||||
return Some(handoff);
|
||||
}
|
||||
|
||||
if let Some(transcript_done) = parse_item_done_transcript(item) {
|
||||
return Some(transcript_done);
|
||||
}
|
||||
|
||||
item.get("id")
|
||||
.and_then(Value::as_str)
|
||||
.map(str::to_string)
|
||||
.map(|item_id| RealtimeEvent::ConversationItemDone { item_id })
|
||||
}
|
||||
|
||||
fn parse_item_done_transcript(item: &JsonMap<String, Value>) -> Option<RealtimeEvent> {
|
||||
let role = item.get("role").and_then(Value::as_str)?;
|
||||
let text = item
|
||||
.get("content")
|
||||
.and_then(Value::as_array)?
|
||||
.iter()
|
||||
.filter_map(item_content_text)
|
||||
.collect::<String>();
|
||||
if text.is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let done = RealtimeTranscriptDone {
|
||||
text,
|
||||
item_id: item.get("id").and_then(Value::as_str).map(str::to_string),
|
||||
output_index: None,
|
||||
content_index: None,
|
||||
};
|
||||
match role {
|
||||
"user" => Some(RealtimeEvent::InputTranscriptDone(done)),
|
||||
"assistant" => Some(RealtimeEvent::OutputTranscriptDone(done)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn item_content_text(content: &Value) -> Option<&str> {
|
||||
content
|
||||
.get("text")
|
||||
.or_else(|| content.get("transcript"))
|
||||
.and_then(Value::as_str)
|
||||
}
|
||||
|
||||
fn parse_handoff_requested_event(item: &JsonMap<String, Value>) -> Option<RealtimeEvent> {
|
||||
let item_type = item.get("type").and_then(Value::as_str);
|
||||
let item_name = item.get("name").and_then(Value::as_str);
|
||||
|
||||
Reference in New Issue
Block a user