1use crate::client::LlmClient;
26use crate::error::Error;
27
28pub async fn embed(client: &dyn LlmClient, text: &str) -> Result<Vec<f32>, Error> {
36 client.embed(text).await
37}
38
39#[cfg(test)]
40mod tests {
41 use super::*;
42 use async_trait::async_trait;
43
44 use crate::client::{CompletionRequest, TokenStream};
45
46 struct OkClient;
47
48 #[async_trait]
49 impl LlmClient for OkClient {
50 fn default_model(&self) -> &str {
51 "test"
52 }
53
54 async fn complete(&self, _: CompletionRequest) -> Result<String, Error> {
55 Err(Error::Unsupported)
56 }
57
58 async fn complete_stream(&self, _: CompletionRequest) -> Result<TokenStream, Error> {
59 Err(Error::Unsupported)
60 }
61
62 async fn embed(&self, _: &str) -> Result<Vec<f32>, Error> {
63 Ok(vec![0.1, 0.2, 0.3])
64 }
65 }
66
67 struct UnsupportedClient;
68
69 #[async_trait]
70 impl LlmClient for UnsupportedClient {
71 fn default_model(&self) -> &str {
72 "test"
73 }
74
75 async fn complete(&self, _: CompletionRequest) -> Result<String, Error> {
76 Err(Error::Unsupported)
77 }
78
79 async fn complete_stream(&self, _: CompletionRequest) -> Result<TokenStream, Error> {
80 Err(Error::Unsupported)
81 }
82
83 async fn embed(&self, _: &str) -> Result<Vec<f32>, Error> {
84 Err(Error::Unsupported)
85 }
86 }
87
88 #[tokio::test]
89 async fn embed_delegates_to_client() {
90 let client = OkClient;
91 let result = embed(&client, "hello").await.unwrap();
92 assert_eq!(result, vec![0.1f32, 0.2, 0.3]);
93 }
94
95 #[tokio::test]
96 async fn embed_propagates_unsupported() {
97 let client = UnsupportedClient;
98 let result = embed(&client, "hello").await;
99 assert!(
100 matches!(result, Err(Error::Unsupported)),
101 "expected Err(Error::Unsupported), got: {result:?}"
102 );
103 }
104}