mirror of
https://github.com/openai/codex.git
synced 2026-10-29 16:09:06 +00:00
## Summary Codex is repurposing `session` to mean a thread group, so the realtime provider session id should no longer use `session_id` / `sessionId` in Codex-facing protocol payloads. This PR renames that provider-specific field to `realtime_session_id` / `realtimeSessionId` and intentionally breaks clients that still send the old field names. ## What Changed - Renamed realtime provider session fields in `ConversationStartParams`, `RealtimeConversationStartedEvent`, and `RealtimeEvent::SessionUpdated`. - Renamed app-server v2 realtime request and notification fields to `realtimeSessionId`. - Removed legacy serde aliases for `session_id` / `sessionId`; clients must send the new names. - Propagated the rename through core realtime startup, app-server adapters, codex-api websocket handling, and TUI realtime state. - Regenerated app-server protocol schema/TypeScript outputs and updated app-server README examples. - Kept upstream Realtime API concepts unchanged: provider `session.id` parsing and `x-session-id` headers still use the upstream wire names. ## Testing - CI is running on the latest pushed commit. - Earlier local verification on this PR: - `cargo test -p codex-protocol` - `CODEX_SKIP_VENDORED_BWRAP=1 cargo test -p codex-core realtime_conversation` - `cargo test -p codex-app-server-protocol` - `CODEX_SKIP_VENDORED_BWRAP=1 cargo test -p codex-app-server realtime_conversation` - attempted `CODEX_SKIP_VENDORED_BWRAP=1 cargo test -p codex-tui` (local linker bus error while linking the test binary) --------- Co-authored-by: Codex <noreply@openai.com>
84 lines
2.5 KiB
Rust
84 lines
2.5 KiB
Rust
use codex_protocol::protocol::RealtimeEvent;
|
|
use codex_protocol::protocol::RealtimeTranscriptDelta;
|
|
use codex_protocol::protocol::RealtimeTranscriptDone;
|
|
use serde_json::Value;
|
|
use tracing::debug;
|
|
|
|
pub(super) fn parse_realtime_payload(payload: &str, parser_name: &str) -> Option<(Value, String)> {
|
|
let parsed: Value = match serde_json::from_str(payload) {
|
|
Ok(message) => message,
|
|
Err(err) => {
|
|
debug!("failed to parse {parser_name} event: {err}, data: {payload}");
|
|
return None;
|
|
}
|
|
};
|
|
|
|
let message_type = match parsed.get("type").and_then(Value::as_str) {
|
|
Some(message_type) => message_type.to_string(),
|
|
None => {
|
|
debug!("received {parser_name} event without type field: {payload}");
|
|
return None;
|
|
}
|
|
};
|
|
|
|
Some((parsed, message_type))
|
|
}
|
|
|
|
pub(super) fn parse_session_updated_event(parsed: &Value) -> Option<RealtimeEvent> {
|
|
let session_id = parsed
|
|
.get("session")
|
|
.and_then(Value::as_object)
|
|
.and_then(|session| session.get("id"))
|
|
.and_then(Value::as_str)
|
|
.map(str::to_string)?;
|
|
let instructions = parsed
|
|
.get("session")
|
|
.and_then(Value::as_object)
|
|
.and_then(|session| session.get("instructions"))
|
|
.and_then(Value::as_str)
|
|
.map(str::to_string);
|
|
Some(RealtimeEvent::SessionUpdated {
|
|
realtime_session_id: session_id,
|
|
instructions,
|
|
})
|
|
}
|
|
|
|
pub(super) fn parse_transcript_delta_event(
|
|
parsed: &Value,
|
|
field: &str,
|
|
) -> Option<RealtimeTranscriptDelta> {
|
|
parsed
|
|
.get(field)
|
|
.and_then(Value::as_str)
|
|
.map(str::to_string)
|
|
.map(|delta| RealtimeTranscriptDelta { delta })
|
|
}
|
|
|
|
pub(super) fn parse_transcript_done_event(
|
|
parsed: &Value,
|
|
field: &str,
|
|
) -> Option<RealtimeTranscriptDone> {
|
|
parsed
|
|
.get(field)
|
|
.and_then(Value::as_str)
|
|
.map(str::to_string)
|
|
.map(|text| RealtimeTranscriptDone { text })
|
|
}
|
|
|
|
pub(super) fn parse_error_event(parsed: &Value) -> Option<RealtimeEvent> {
|
|
parsed
|
|
.get("message")
|
|
.and_then(Value::as_str)
|
|
.map(str::to_string)
|
|
.or_else(|| {
|
|
parsed
|
|
.get("error")
|
|
.and_then(Value::as_object)
|
|
.and_then(|error| error.get("message"))
|
|
.and_then(Value::as_str)
|
|
.map(str::to_string)
|
|
})
|
|
.or_else(|| parsed.get("error").map(ToString::to_string))
|
|
.map(RealtimeEvent::Error)
|
|
}
|