mirror of
https://github.com/openai/codex.git
synced 2026-09-20 12:47:38 +00:00
## Summary Adds a second realtime v2 function tool, `remain_silent`, so the realtime model has an explicit non-speaking action when the collaboration mode or latest context says it should not answer aloud. This is stacked on #18597. ## Design - Advertise `remain_silent` alongside `background_agent` in realtime v2 conversational sessions. - Parse `remain_silent` function calls into a typed `RealtimeEvent::NoopRequested` event. - Have core answer that function call with an empty `function_call_output` and deliberately avoid `response.create`, so no follow-up realtime response is requested. - Keep the event hidden from app-server/TUI surfaces; it is operational plumbing, not user-visible conversation content.
94 lines
3.9 KiB
Rust
94 lines
3.9 KiB
Rust
use crate::endpoint::realtime_websocket::methods_v1::conversation_handoff_append_message as v1_conversation_handoff_append_message;
|
|
use crate::endpoint::realtime_websocket::methods_v1::conversation_item_create_message as v1_conversation_item_create_message;
|
|
use crate::endpoint::realtime_websocket::methods_v1::session_update_session as v1_session_update_session;
|
|
use crate::endpoint::realtime_websocket::methods_v1::websocket_intent as v1_websocket_intent;
|
|
use crate::endpoint::realtime_websocket::methods_v2::conversation_function_call_output_message as v2_conversation_function_call_output_message;
|
|
use crate::endpoint::realtime_websocket::methods_v2::conversation_item_create_message as v2_conversation_item_create_message;
|
|
use crate::endpoint::realtime_websocket::methods_v2::session_update_session as v2_session_update_session;
|
|
use crate::endpoint::realtime_websocket::methods_v2::websocket_intent as v2_websocket_intent;
|
|
use crate::endpoint::realtime_websocket::protocol::RealtimeEventParser;
|
|
use crate::endpoint::realtime_websocket::protocol::RealtimeOutboundMessage;
|
|
use crate::endpoint::realtime_websocket::protocol::RealtimeOutputModality;
|
|
use crate::endpoint::realtime_websocket::protocol::RealtimeSessionConfig;
|
|
use crate::endpoint::realtime_websocket::protocol::RealtimeSessionMode;
|
|
use crate::endpoint::realtime_websocket::protocol::RealtimeVoice;
|
|
use crate::endpoint::realtime_websocket::protocol::SessionUpdateSession;
|
|
use serde_json::Result as JsonResult;
|
|
use serde_json::Value;
|
|
use serde_json::to_value;
|
|
|
|
pub(super) const REALTIME_AUDIO_SAMPLE_RATE: u32 = 24_000;
|
|
const AGENT_FINAL_MESSAGE_PREFIX: &str = "\"Agent Final Message\":\n\n";
|
|
|
|
pub(super) fn normalized_session_mode(
|
|
event_parser: RealtimeEventParser,
|
|
session_mode: RealtimeSessionMode,
|
|
) -> RealtimeSessionMode {
|
|
match event_parser {
|
|
RealtimeEventParser::V1 => RealtimeSessionMode::Conversational,
|
|
RealtimeEventParser::RealtimeV2 => session_mode,
|
|
}
|
|
}
|
|
|
|
pub(super) fn conversation_item_create_message(
|
|
event_parser: RealtimeEventParser,
|
|
text: String,
|
|
) -> RealtimeOutboundMessage {
|
|
match event_parser {
|
|
RealtimeEventParser::V1 => v1_conversation_item_create_message(text),
|
|
RealtimeEventParser::RealtimeV2 => v2_conversation_item_create_message(text),
|
|
}
|
|
}
|
|
|
|
pub(super) fn conversation_function_call_output_message(
|
|
event_parser: RealtimeEventParser,
|
|
call_id: String,
|
|
output_text: String,
|
|
) -> RealtimeOutboundMessage {
|
|
match event_parser {
|
|
RealtimeEventParser::V1 => v1_conversation_handoff_append_message(
|
|
call_id,
|
|
format!("{AGENT_FINAL_MESSAGE_PREFIX}{output_text}"),
|
|
),
|
|
RealtimeEventParser::RealtimeV2 => {
|
|
v2_conversation_function_call_output_message(call_id, output_text)
|
|
}
|
|
}
|
|
}
|
|
|
|
pub(super) fn session_update_session(
|
|
event_parser: RealtimeEventParser,
|
|
instructions: String,
|
|
session_mode: RealtimeSessionMode,
|
|
output_modality: RealtimeOutputModality,
|
|
voice: RealtimeVoice,
|
|
) -> SessionUpdateSession {
|
|
let session_mode = normalized_session_mode(event_parser, session_mode);
|
|
match event_parser {
|
|
RealtimeEventParser::V1 => v1_session_update_session(instructions, voice),
|
|
RealtimeEventParser::RealtimeV2 => {
|
|
v2_session_update_session(instructions, session_mode, output_modality, voice)
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn session_update_session_json(config: RealtimeSessionConfig) -> JsonResult<Value> {
|
|
let mut session = session_update_session(
|
|
config.event_parser,
|
|
config.instructions,
|
|
config.session_mode,
|
|
config.output_modality,
|
|
config.voice,
|
|
);
|
|
session.id = config.session_id;
|
|
session.model = config.model;
|
|
to_value(session)
|
|
}
|
|
|
|
pub(super) fn websocket_intent(event_parser: RealtimeEventParser) -> Option<&'static str> {
|
|
match event_parser {
|
|
RealtimeEventParser::V1 => v1_websocket_intent(),
|
|
RealtimeEventParser::RealtimeV2 => v2_websocket_intent(),
|
|
}
|
|
}
|