feat(gateway): add Codex Live and OpenAI Realtime

Implement preflighted Live/Realtime WebSocket transports, protocol-aware authentication, usage auditing, UI filtering, and legacy Codex permission migration.
This commit is contained in:
ZheFox
2026-08-21 04:27:34 +08:00
parent fe38dcd294
commit 2c89202001
105 changed files with 7553 additions and 947 deletions
@@ -65,6 +65,45 @@ fn parse_users_me_usage_offset(query: Option<&str>) -> Result<usize, String> {
}
}
#[derive(Clone, Debug, Default, PartialEq, Eq)]
struct UsersMeUsageRecordFilter {
statuses: Option<Vec<String>>,
is_stream: Option<bool>,
is_websocket: Option<bool>,
error_only: bool,
}
fn parse_users_me_usage_record_filter(query: Option<&str>) -> UsersMeUsageRecordFilter {
let Some(status) = query_param_value(query, "status")
.map(|value| value.trim().to_ascii_lowercase())
.filter(|value| !value.is_empty())
else {
return UsersMeUsageRecordFilter::default();
};
let mut filter = UsersMeUsageRecordFilter::default();
match status.as_str() {
"stream" => {
filter.is_stream = Some(true);
filter.is_websocket = Some(false);
}
"standard" => {
filter.is_stream = Some(false);
filter.is_websocket = Some(false);
}
"websocket" | "ws" => filter.is_websocket = Some(true),
"error" | "failed" => filter.error_only = true,
"active" => {
filter.statuses = Some(vec!["pending".to_string(), "streaming".to_string()]);
}
"pending" | "streaming" | "completed" | "cancelled" => {
filter.statuses = Some(vec![status]);
}
_ => {}
}
filter
}
fn parse_users_me_usage_hours(query: Option<&str>) -> Result<u32, String> {
match query_param_value(query, "hours") {
Some(value) => parse_bounded_u32("hours", &value, 1, 720),
@@ -480,6 +519,11 @@ fn build_users_me_usage_record_payload(
"first_byte_time_ms": item.first_byte_time_ms,
"is_stream": item.is_stream,
"is_websocket": item.is_websocket(),
"websocket_transport": item.websocket_transport(),
"usage_available": item.usage_available(),
"usage_pricing_available": item.usage_pricing_available(),
"input_audio_tokens": item.realtime_input_audio_tokens(),
"output_audio_tokens": item.realtime_output_audio_tokens(),
"upstream_is_stream": upstream_is_stream,
"client_requested_stream": client_is_stream,
"client_is_stream": client_is_stream,
@@ -564,6 +608,11 @@ fn build_users_me_usage_active_payload(item: &StoredRequestUsageAudit) -> serde_
"endpoint_api_format": item.endpoint_api_format,
"is_stream": item.is_stream,
"is_websocket": item.is_websocket(),
"websocket_transport": item.websocket_transport(),
"usage_available": item.usage_available(),
"usage_pricing_available": item.usage_pricing_available(),
"input_audio_tokens": item.realtime_input_audio_tokens(),
"output_audio_tokens": item.realtime_output_audio_tokens(),
"upstream_is_stream": upstream_is_stream,
"client_requested_stream": client_is_stream,
"client_is_stream": client_is_stream,
@@ -947,6 +996,7 @@ pub(super) async fn handle_users_me_usage_get(
Ok(value) => value,
Err(detail) => return admin_stats_bad_request_response(detail),
};
let record_filter = parse_users_me_usage_record_filter(query);
// When no time range is specified, default to 7 days to avoid full-table scans.
let effective_time_range = time_range.or_else(|| {
@@ -1087,10 +1137,11 @@ pub(super) async fn handle_users_me_usage_get(
api_format: None,
client_family: None,
exclude_unknown_model_or_provider: false,
statuses: None,
statuses: record_filter.statuses.clone(),
exclude_status_codes: Vec::new(),
is_stream: None,
error_only: false,
is_stream: record_filter.is_stream,
is_websocket: record_filter.is_websocket,
error_only: record_filter.error_only,
keywords,
matched_user_ids_by_keyword: Vec::new(),
auth_user_reader_available: false,
@@ -1143,10 +1194,11 @@ pub(super) async fn handle_users_me_usage_get(
api_format: None,
client_family: None,
exclude_unknown_model_or_provider: false,
statuses: None,
statuses: record_filter.statuses.clone(),
exclude_status_codes: Vec::new(),
is_stream: None,
error_only: false,
is_stream: record_filter.is_stream,
is_websocket: record_filter.is_websocket,
error_only: record_filter.error_only,
limit: None,
offset: None,
newest_first: true,
@@ -1172,10 +1224,11 @@ pub(super) async fn handle_users_me_usage_get(
api_format: None,
client_family: None,
exclude_unknown_model_or_provider: false,
statuses: None,
statuses: record_filter.statuses.clone(),
exclude_status_codes: Vec::new(),
is_stream: None,
error_only: false,
is_stream: record_filter.is_stream,
is_websocket: record_filter.is_websocket,
error_only: record_filter.error_only,
limit: Some(limit),
offset: Some(offset),
newest_first: true,
@@ -1314,6 +1367,7 @@ pub(super) async fn handle_users_me_usage_active_get(
statuses: Some(vec!["pending".to_string(), "streaming".to_string()]),
exclude_status_codes: Vec::new(),
is_stream: None,
is_websocket: None,
error_only: false,
limit: Some(50),
offset: None,
@@ -1568,10 +1622,34 @@ mod tests {
use super::{
build_users_me_usage_active_payload, build_users_me_usage_record_payload,
users_me_usage_client_is_stream, users_me_usage_is_failed,
users_me_usage_terminal_candidate_state_override, users_me_usage_upstream_is_stream,
parse_users_me_usage_record_filter, users_me_usage_client_is_stream,
users_me_usage_is_failed, users_me_usage_terminal_candidate_state_override,
users_me_usage_upstream_is_stream,
};
#[test]
fn users_me_usage_transport_statuses_are_disjoint_server_side_filters() {
for status in ["websocket", "ws", "WS"] {
let filter = parse_users_me_usage_record_filter(Some(
format!("limit=20&status={status}").as_str(),
));
assert_eq!(filter.is_websocket, Some(true));
assert_eq!(filter.is_stream, None);
assert_eq!(filter.statuses, None);
assert!(!filter.error_only);
}
for (status, expected_stream) in [("stream", true), ("standard", false)] {
let filter = parse_users_me_usage_record_filter(Some(
format!("limit=20&status={status}").as_str(),
));
assert_eq!(filter.is_stream, Some(expected_stream));
assert_eq!(filter.is_websocket, Some(false));
assert_eq!(filter.statuses, None);
assert!(!filter.error_only);
}
}
fn sample_usage(status: &str) -> StoredRequestUsageAudit {
StoredRequestUsageAudit::new(
"usage-1".to_string(),
@@ -1731,6 +1809,12 @@ mod tests {
request_metadata: Some(json!({
"websocket_mode": true,
"websocket_transport": "responses",
"usage_available": false,
"usage_pricing_available": false,
"realtime_session": {
"input_audio_tokens": 7,
"output_audio_tokens": 3,
},
})),
..sample_usage("completed")
};
@@ -1740,6 +1824,16 @@ mod tests {
assert_eq!(record["is_websocket"], true);
assert_eq!(active["is_websocket"], true);
assert_eq!(record["websocket_transport"], "responses");
assert_eq!(active["websocket_transport"], "responses");
assert_eq!(record["usage_available"], false);
assert_eq!(active["usage_available"], false);
assert_eq!(record["usage_pricing_available"], false);
assert_eq!(active["usage_pricing_available"], false);
assert_eq!(record["input_audio_tokens"], 7);
assert_eq!(active["input_audio_tokens"], 7);
assert_eq!(record["output_audio_tokens"], 3);
assert_eq!(active["output_audio_tokens"], 3);
}
#[test]