bamboo_server/tools/
model_catalog.rs1use std::sync::Arc;
6use std::time::Duration;
7
8use async_trait::async_trait;
9
10use bamboo_engine::session_app::child_session::{ModelCatalogPort, ProviderModelList};
11use bamboo_llm::ProviderRegistry;
12
13const PER_PROVIDER_TIMEOUT: Duration = Duration::from_secs(8);
17
18pub struct RegistryModelCatalog {
20 registry: Arc<ProviderRegistry>,
21}
22
23impl RegistryModelCatalog {
24 pub fn new(registry: Arc<ProviderRegistry>) -> Self {
25 Self { registry }
26 }
27}
28
29#[async_trait]
30impl ModelCatalogPort for RegistryModelCatalog {
31 async fn list_models(&self) -> Vec<ProviderModelList> {
32 let mut names = self.registry.provider_names();
33 names.sort();
34
35 let futures = names.into_iter().map(|name| {
37 let provider = self.registry.get(&name);
38 async move {
39 let Some(provider) = provider else {
40 return ProviderModelList {
41 provider: name,
42 models: Vec::new(),
43 error: Some("provider not initialized".to_string()),
44 };
45 };
46 match tokio::time::timeout(PER_PROVIDER_TIMEOUT, provider.list_models()).await {
47 Ok(Ok(mut models)) => {
48 models.sort();
49 ProviderModelList {
50 provider: name,
51 models,
52 error: None,
53 }
54 }
55 Ok(Err(e)) => ProviderModelList {
56 provider: name,
57 models: Vec::new(),
58 error: Some(e.to_string()),
59 },
60 Err(_) => ProviderModelList {
61 provider: name,
62 models: Vec::new(),
63 error: Some(format!(
64 "timed out after {}s",
65 PER_PROVIDER_TIMEOUT.as_secs()
66 )),
67 },
68 }
69 }
70 });
71
72 futures::future::join_all(futures).await
73 }
74
75 fn default_provider(&self) -> String {
76 self.registry.default_provider_name()
77 }
78}