pub struct RealtimeServiceProcessor<R: RealtimeLlm + RealtimeKickoff> { /* private fields */ }Expand description
Wraps a RealtimeLlm (the existing Gemini client through the trait — never a
rewrite). On first InputAudio (after the stream-start kickoff gate) it lazily
spawns the next_event reader task (the existing reader-task→mpsc bridge made a
processor-internal task, PROCESSOR-DESIGN §6.1) which emits downstream
OutputAudio/transcription/tool-call/Interruption/usage frames and a terminal
End on Closed. It feeds each InputAudio to send_audio; consumes the
brain’s upstream [ToolResult]→send_tool_result and [Reprompt]→update_system.
Trait Implementations§
Source§impl<R: RealtimeLlm + RealtimeKickoff + 'static> FrameProcessor for RealtimeServiceProcessor<R>
impl<R: RealtimeLlm + RealtimeKickoff + 'static> FrameProcessor for RealtimeServiceProcessor<R>
Source§fn stop<'life0, 'async_trait>(
&'life0 mut self,
_reason: StopReason,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn stop<'life0, 'async_trait>(
&'life0 mut self,
_reason: StopReason,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Teardown: abort the model-event reader so it stops reconnecting the realtime
session once the call has ended. Without this the reader (which transparently
reconnects on Gemini’s 1008 aborts) keeps re-opening the session in the
background until the reconnect ceiling — burning provider quota and a
connection for minutes after every call. Aborting drops the reader’s clone of
the session Arc, so the realtime WS closes with the call.
Source§fn name(&self) -> &str
fn name(&self) -> &str
Source§fn start<'life0, 'life1, 'life2, 'async_trait>(
&'life0 mut self,
_setup: &'life1 ProcessorSetup,
_params: &'life2 StartParams,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn start<'life0, 'life1, 'life2, 'async_trait>(
&'life0 mut self,
_setup: &'life1 ProcessorSetup,
_params: &'life2 StartParams,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Frame::Start frame reaches this processor, before
any data frame. Open sockets / spawn provider readers here. Default: no-op.Source§fn process_frame<'life0, 'life1, 'async_trait>(
&'life0 mut self,
env: Envelope,
link: &'life1 Link,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn process_frame<'life0, 'life1, 'async_trait>(
&'life0 mut self,
env: Envelope,
link: &'life1 Link,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
link. Must not block: long work
(a provider round-trip) is driven by an internally-spawned task that feeds
results back as frames. The default impl forwards the frame unchanged in
its direction — so a pure observer/no-op processor is process_frame =
default.Source§fn can_generate_metrics(&self) -> bool
fn can_generate_metrics(&self) -> bool
can_generate_metrics,
:395). Services override to true.