1pub mod cognitive_output_audio;
2pub mod cognitive_output_text;
3pub mod peer_input_audio;
4pub mod peer_input_text;
5pub mod speech_to_text;
6pub mod storage;
7
8pub mod sync;
10pub mod types;
12
13pub mod llm;
14
15use async_trait::async_trait;
16
17use crate::cognitive_output_audio::types::CognitiveOutputAudio;
18use crate::peer_input_audio::types::PeerInputAudio;
19use crate::speech_to_text::types::{
20 InputVoiceAudio, SpeakerSegment, SpeechDetected, SpeechTranscript,
21};
22use crate::sync::{broadcast, mpsc, watch};
23use crate::types::CognitiveOutputSpeech;
24
25#[async_trait]
26pub trait AudioInputPlugin: Plugin + Send + Sync {
27 async fn start(&self, tx: mpsc::Sender<PeerInputAudio>) -> Result<(), String>;
28}
29
30#[async_trait]
31pub trait AudioOutputPlugin: Plugin + Send + Sync {
32 async fn start(&self, rx: mpsc::Receiver<CognitiveOutputAudio>) -> Result<(), String>;
33}
34
35#[async_trait]
36pub trait STTPlugin: Plugin + Send + Sync {
37 async fn start(
38 &self,
39 audio_rx: mpsc::Receiver<InputVoiceAudio>,
40 transcript_tx: mpsc::Sender<SpeechTranscript>,
41 speech_detected: SpeechDetected,
42 ) -> Result<(), String>;
43}
44
45#[async_trait]
46pub trait TTSPlugin: Plugin + Send + Sync {
47 async fn start(
48 &self,
49 speech_rx: broadcast::Receiver<CognitiveOutputSpeech>,
50 audio_tx: mpsc::Sender<CognitiveOutputAudio>,
51 ) -> Result<(), String>;
52}
53
54#[async_trait]
55pub trait DiarizationPlugin: Plugin + Send + Sync {
56 async fn start(
57 &self,
58 audio_rx: broadcast::Receiver<InputVoiceAudio>,
59 segment_tx: mpsc::Sender<SpeakerSegment>,
60 ) -> Result<(), String>;
61
62 fn heuristic(&self) -> Option<crate::speech_to_text::types::SpeakerHeuristicCallback> {
63 None
64 }
65}
66
67#[async_trait]
68pub trait ChatPlugin: Plugin + Send + Sync {
69 fn channel_context_schema() -> schemars::Schema
70 where
71 Self: Sized,
72 {
73 schemars::schema_for!(())
74 }
75
76 async fn start(
77 &self,
78 peer_input_text_tx: mpsc::Sender<crate::peer_input_text::types::PeerInputText>,
79 cognitive_output_text_rx: mpsc::Receiver<
80 crate::cognitive_output_text::types::CognitiveOutputText,
81 >,
82 cognitive_state_rx: broadcast::Receiver<crate::types::CognitiveStateUpdate>,
83 add_document_tx: Option<mpsc::Sender<crate::types::AddDocumentRequest>>,
84 ) -> Result<(), String>;
85}
86
87#[async_trait]
88pub trait GuiPlugin: Plugin + Send + Sync {
89 async fn start(
90 &self,
91 registries: std::sync::Arc<crate::types::ContextRegistries>,
92 error_rx: std::sync::mpsc::Receiver<String>,
93 ) -> Result<(), String>;
94}
95
96#[async_trait]
97pub trait DocumentsPlugin: Plugin + Send + Sync {
98 async fn start(
99 &self,
100 add_document_rx: mpsc::Receiver<crate::types::AddDocumentRequest>,
101 ) -> Result<(), String>;
102}
103
104#[async_trait]
105pub trait RetrospectiveConsolidationPlugin: Plugin + Send + Sync {
106 async fn start(
107 &self,
108 not_clear_memory_rx: watch::Receiver<crate::types::NotClearInteractionMemory>,
109 resolve_not_clear_tx: mpsc::Sender<crate::types::Timestamp>,
110 ) -> Result<(), String>;
111}
112
113pub trait PluginRegistry {
114 fn register_gui<P: GuiPlugin>(&mut self, plugin: std::sync::Arc<P>);
115 fn register_audio_input<P: AudioInputPlugin>(&mut self, plugin: std::sync::Arc<P>);
116 fn register_audio_output<P: AudioOutputPlugin>(&mut self, plugin: std::sync::Arc<P>);
117 fn register_stt<P: STTPlugin>(&mut self, plugin: std::sync::Arc<P>);
118 fn register_tts<P: TTSPlugin>(&mut self, plugin: std::sync::Arc<P>);
119 fn register_diarization<P: DiarizationPlugin>(&mut self, plugin: std::sync::Arc<P>);
120 fn register_chat<P: ChatPlugin>(&mut self, plugin: std::sync::Arc<P>);
121 fn register_documents<P: DocumentsPlugin>(&mut self, plugin: std::sync::Arc<P>);
122 fn register_interaction_observer<P: InteractionObserver>(&mut self, plugin: std::sync::Arc<P>);
123 fn register_rollout_controller<P: RolloutController>(&mut self, plugin: std::sync::Arc<P>);
124 fn register_retrospective_consolidation<P: RetrospectiveConsolidationPlugin>(
125 &mut self,
126 plugin: std::sync::Arc<P>,
127 );
128 fn register_camera<P: CameraPlugin>(&mut self, plugin: std::sync::Arc<P>);
129 fn register_context_provider<P: crate::types::ContextProvider>(
130 &mut self,
131 provider: std::sync::Arc<P>,
132 );
133 fn register_command<C: crate::types::Command>(&mut self, command: C);
134 fn register_tool<T: crate::types::Tool>(&mut self, tool: T);
135 fn register_call<P: CallPlugin>(
136 &mut self,
137 plugin: std::sync::Arc<P>,
138 capability: Option<&'static str>,
139 );
140 fn register_recorder<P: AudioRecorderPlugin>(&mut self, plugin: std::sync::Arc<P>);
141}
142
143use serde::{Deserialize, Serialize};
144
145#[derive(Debug, Clone, Serialize, Deserialize, Default)]
146pub struct EmptyPluginConfig {}
147
148#[async_trait]
149pub trait Plugin: Send + Sync + 'static {
150 const CAPABILITY: Option<&'static str> = None;
152
153 async fn create(context: crate::types::PluginContext) -> Result<Self, String>
160 where
161 Self: Sized;
162
163 fn register<R: PluginRegistry + ?Sized>(self: std::sync::Arc<Self>, registry: &mut R)
164 where
165 Self: Sized;
166}
167
168#[async_trait]
169pub trait CallPlugin: Plugin + Send + Sync {
170 async fn start(
171 &self,
172 peer_input_text_rx: sync::broadcast::Receiver<crate::peer_input_text::types::PeerInputText>,
173 cognitive_output_text_tx: sync::mpsc::Sender<
174 crate::cognitive_output_text::types::CognitiveOutputText,
175 >,
176 last_voice_time_rx: sync::watch::Receiver<std::time::Instant>,
177 ai_speaking_rx: sync::watch::Receiver<bool>,
178 call_active_tx: sync::watch::Sender<bool>,
179 ) -> Result<(), String>;
180}
181
182#[async_trait]
183pub trait AudioRecorderPlugin: Plugin + Send + Sync {
184 async fn start(
185 &self,
186 call_active_rx: watch::Receiver<bool>,
187 input_voice_audio_rx: broadcast::Receiver<InputVoiceAudio>,
188 ) -> Result<(), String>;
189}
190
191#[async_trait]
192pub trait CameraPlugin: Plugin + Send + Sync {
193 async fn start(
194 &self,
195 video_tx: crate::sync::watch::Sender<crate::types::CameraInputFrame>,
196 ) -> Result<(), String>;
197}
198
199#[async_trait]
200pub trait RolloutController: Plugin + Send + Sync {
201 async fn start(&self, rollout_tx: watch::Sender<crate::types::Timestamp>)
202 -> Result<(), String>;
203}
204
205#[async_trait]
206pub trait InteractionObserver: Plugin + Send + Sync {
207 async fn start(
208 &self,
209 interaction_rx: mpsc::Receiver<crate::types::ObservedInteraction>,
210 ) -> Result<(), String>;
211}