pub mod cognitive_output_audio;
pub mod cognitive_output_text;
pub mod peer_input_audio;
pub mod peer_input_text;
pub mod speech_to_text;
pub mod storage;
pub mod sync;
pub mod types;
pub mod llm;
use async_trait::async_trait;
use crate::cognitive_output_audio::types::CognitiveOutputAudio;
use crate::peer_input_audio::types::PeerInputAudio;
use crate::speech_to_text::types::{
InputVoiceAudio, SpeakerSegment, SpeechDetected, SpeechTranscript,
};
use crate::sync::{broadcast, mpsc, watch};
use crate::types::CognitiveOutputSpeech;
#[async_trait]
pub trait AudioInputPlugin: Plugin + Send + Sync {
async fn start(&self, tx: mpsc::Sender<PeerInputAudio>) -> Result<(), String>;
}
#[async_trait]
pub trait AudioOutputPlugin: Plugin + Send + Sync {
async fn start(&self, rx: mpsc::Receiver<CognitiveOutputAudio>) -> Result<(), String>;
}
#[async_trait]
pub trait STTPlugin: Plugin + Send + Sync {
async fn start(
&self,
audio_rx: mpsc::Receiver<InputVoiceAudio>,
transcript_tx: mpsc::Sender<SpeechTranscript>,
speech_detected: SpeechDetected,
) -> Result<(), String>;
}
#[async_trait]
pub trait TTSPlugin: Plugin + Send + Sync {
async fn start(
&self,
speech_rx: broadcast::Receiver<CognitiveOutputSpeech>,
audio_tx: mpsc::Sender<CognitiveOutputAudio>,
) -> Result<(), String>;
}
#[async_trait]
pub trait DiarizationPlugin: Plugin + Send + Sync {
async fn start(
&self,
audio_rx: broadcast::Receiver<InputVoiceAudio>,
segment_tx: mpsc::Sender<SpeakerSegment>,
) -> Result<(), String>;
fn heuristic(&self) -> Option<crate::speech_to_text::types::SpeakerHeuristicCallback> {
None
}
}
#[async_trait]
pub trait ChatPlugin: Plugin + Send + Sync {
fn channel_context_schema() -> schemars::Schema
where
Self: Sized,
{
schemars::schema_for!(())
}
async fn start(
&self,
peer_input_text_tx: mpsc::Sender<crate::peer_input_text::types::PeerInputText>,
cognitive_output_text_rx: mpsc::Receiver<
crate::cognitive_output_text::types::CognitiveOutputText,
>,
cognitive_state_rx: broadcast::Receiver<crate::types::CognitiveStateUpdate>,
add_document_tx: Option<mpsc::Sender<crate::types::AddDocumentRequest>>,
) -> Result<(), String>;
}
#[async_trait]
pub trait GuiPlugin: Plugin + Send + Sync {
async fn start(
&self,
registries: std::sync::Arc<crate::types::ContextRegistries>,
error_rx: std::sync::mpsc::Receiver<String>,
) -> Result<(), String>;
}
#[async_trait]
pub trait DocumentsPlugin: Plugin + Send + Sync {
async fn start(
&self,
add_document_rx: mpsc::Receiver<crate::types::AddDocumentRequest>,
) -> Result<(), String>;
}
#[async_trait]
pub trait RetrospectiveConsolidationPlugin: Plugin + Send + Sync {
async fn start(
&self,
not_clear_memory_rx: watch::Receiver<crate::types::NotClearInteractionMemory>,
resolve_not_clear_tx: mpsc::Sender<crate::types::Timestamp>,
) -> Result<(), String>;
}
pub trait PluginRegistry {
fn register_gui<P: GuiPlugin>(&mut self, plugin: std::sync::Arc<P>);
fn register_audio_input<P: AudioInputPlugin>(&mut self, plugin: std::sync::Arc<P>);
fn register_audio_output<P: AudioOutputPlugin>(&mut self, plugin: std::sync::Arc<P>);
fn register_stt<P: STTPlugin>(&mut self, plugin: std::sync::Arc<P>);
fn register_tts<P: TTSPlugin>(&mut self, plugin: std::sync::Arc<P>);
fn register_diarization<P: DiarizationPlugin>(&mut self, plugin: std::sync::Arc<P>);
fn register_chat<P: ChatPlugin>(&mut self, plugin: std::sync::Arc<P>);
fn register_documents<P: DocumentsPlugin>(&mut self, plugin: std::sync::Arc<P>);
fn register_interaction_observer<P: InteractionObserver>(&mut self, plugin: std::sync::Arc<P>);
fn register_rollout_controller<P: RolloutController>(&mut self, plugin: std::sync::Arc<P>);
fn register_retrospective_consolidation<P: RetrospectiveConsolidationPlugin>(
&mut self,
plugin: std::sync::Arc<P>,
);
fn register_camera<P: CameraPlugin>(&mut self, plugin: std::sync::Arc<P>);
fn register_context_provider<P: crate::types::ContextProvider>(
&mut self,
provider: std::sync::Arc<P>,
);
fn register_command<C: crate::types::Command>(&mut self, command: C);
fn register_tool<T: crate::types::Tool>(&mut self, tool: T);
fn register_call<P: CallPlugin>(
&mut self,
plugin: std::sync::Arc<P>,
capability: Option<&'static str>,
);
fn register_recorder<P: AudioRecorderPlugin>(&mut self, plugin: std::sync::Arc<P>);
}
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct EmptyPluginConfig {}
#[async_trait]
pub trait Plugin: Send + Sync + 'static {
const CAPABILITY: Option<&'static str> = None;
async fn create(context: crate::types::PluginContext) -> Result<Self, String>
where
Self: Sized;
fn register<R: PluginRegistry + ?Sized>(self: std::sync::Arc<Self>, registry: &mut R)
where
Self: Sized;
}
#[async_trait]
pub trait CallPlugin: Plugin + Send + Sync {
async fn start(
&self,
peer_input_text_rx: sync::broadcast::Receiver<crate::peer_input_text::types::PeerInputText>,
cognitive_output_text_tx: sync::mpsc::Sender<
crate::cognitive_output_text::types::CognitiveOutputText,
>,
last_voice_time_rx: sync::watch::Receiver<std::time::Instant>,
ai_speaking_rx: sync::watch::Receiver<bool>,
call_active_tx: sync::watch::Sender<bool>,
) -> Result<(), String>;
}
#[async_trait]
pub trait AudioRecorderPlugin: Plugin + Send + Sync {
async fn start(
&self,
call_active_rx: watch::Receiver<bool>,
input_voice_audio_rx: broadcast::Receiver<InputVoiceAudio>,
) -> Result<(), String>;
}
#[async_trait]
pub trait CameraPlugin: Plugin + Send + Sync {
async fn start(
&self,
video_tx: crate::sync::watch::Sender<crate::types::CameraInputFrame>,
) -> Result<(), String>;
}
#[async_trait]
pub trait RolloutController: Plugin + Send + Sync {
async fn start(&self, rollout_tx: watch::Sender<crate::types::Timestamp>)
-> Result<(), String>;
}
#[async_trait]
pub trait InteractionObserver: Plugin + Send + Sync {
async fn start(
&self,
interaction_rx: mpsc::Receiver<crate::types::ObservedInteraction>,
) -> Result<(), String>;
}