fleetforge_runtime/gateway/
mod.rs1pub mod anthropic;
4pub mod openai;
5pub mod speech;
6
7use std::sync::Arc;
8
9use async_trait::async_trait;
10use serde_json::Value;
11
12use self::speech::{NoopStt, NoopTts, SpeechToText, TextToSpeech};
13use fleetforge_prompt::{ChatMessage, ChatRole, ModelResponse, ModelUsage, ToolSpec};
14use fleetforge_telemetry::context::TraceContext;
15use fleetforge_trust::Trust;
16
17#[async_trait]
19pub trait LanguageModel: Send + Sync {
20 async fn chat(
21 &self,
22 messages: &[ChatMessage],
23 tools: Option<&[ToolSpec]>,
24 response_schema: Option<&Value>,
25 strict: bool,
26 params: &Value,
27 trace: &TraceContext,
28 ) -> anyhow::Result<ModelResponse>;
29
30 async fn complete(
31 &self,
32 prompt: &str,
33 params: &Value,
34 trace: &TraceContext,
35 ) -> anyhow::Result<String> {
36 let messages = [ChatMessage {
37 role: ChatRole::User,
38 content: Value::String(prompt.to_owned()),
39 name: None,
40 tool_call_id: None,
41 metadata: None,
42 trust: Some(Trust::Untrusted),
43 trust_origin: None,
44 }];
45 let response = self
46 .chat(&messages, None, None, false, params, trace)
47 .await?;
48 Ok(response
49 .messages
50 .last()
51 .and_then(|m| m.content.as_str().map(str::to_owned))
52 .unwrap_or_default())
53 }
54}
55
56#[async_trait]
58pub trait ToolAdapter: Send + Sync {
59 async fn invoke(&self, name: &str, payload: &Value) -> anyhow::Result<Value>;
60}
61
62#[derive(Debug, Clone, Copy, PartialEq, Eq)]
64pub enum GatewayKind {
65 LanguageModel,
66 Tool,
67}
68
69#[derive(Clone)]
71pub struct GatewayRegistry {
72 pub language_model: Option<Arc<dyn LanguageModel>>,
73 pub tool: Option<Arc<dyn ToolAdapter>>,
74 pub stt: Arc<dyn SpeechToText>,
75 pub tts: Arc<dyn TextToSpeech>,
76}
77
78impl GatewayRegistry {
79 pub fn with_defaults() -> Self {
81 Self {
82 language_model: None,
83 tool: None,
84 stt: Arc::new(NoopStt),
85 tts: Arc::new(NoopTts),
86 }
87 }
88
89 pub fn with_language_model(mut self, model: Arc<dyn LanguageModel>) -> Self {
90 self.language_model = Some(model);
91 self
92 }
93
94 pub fn with_tool(mut self, tool: Arc<dyn ToolAdapter>) -> Self {
95 self.tool = Some(tool);
96 self
97 }
98
99 pub fn with_stt<T>(mut self, adapter: T) -> Self
100 where
101 T: SpeechToText + 'static,
102 {
103 self.stt = Arc::new(adapter);
104 self
105 }
106
107 pub fn with_tts<T>(mut self, adapter: T) -> Self
108 where
109 T: TextToSpeech + 'static,
110 {
111 self.tts = Arc::new(adapter);
112 self
113 }
114}
115
116impl Default for GatewayRegistry {
117 fn default() -> Self {
118 Self::with_defaults()
119 }
120}