use std::sync::Arc;
use omp_llm_catalog::discovery::{Discovery, DiscoveryHttp};
pub(crate) fn register(http: Arc<dyn DiscoveryHttp>) -> Discovery {
Discovery::new(http)
.with(&omp_llm_openai::discovery::DISCOVERY)
.with(&omp_llm_google::discovery::DISCOVERY)
.with(&omp_llm_cursor::discovery::DISCOVERY)
.with(&omp_llm_devin::discovery::DISCOVERY)
.with(&omp_llm_gitlab::discovery::DISCOVERY)
.with(&omp_llm_fm::discovery::DISCOVERY)
.with(&omp_llm_ollama::discovery::DISCOVERY)
.with(&omp_llm_bedrock::discovery::DISCOVERY)
}
#[cfg(test)]
mod tests {
use async_trait::async_trait;
use bytes::Bytes;
use http::{Method, Request, Version};
use omp_llm_catalog::{
codex::{CODEX_CLIENT_VERSION, CODEX_ORIGINATOR},
discovery::{Account, Error, HttpResponse, SealedBody},
provider::{BUILTIN_PROVIDERS_TOML, DiscoveryKind, ProviderEntry, load_providers},
};
use omp_llm_egress::auth_inject::AwsSigV4Context;
use parking_lot::Mutex;
use super::*;
struct NeverCalled;
#[async_trait]
impl DiscoveryHttp for NeverCalled {
async fn execute(
&self,
_provider: &ProviderEntry,
_account: &Account,
_request: Request<Bytes>,
) -> Result<HttpResponse, Error> {
unreachable!("registration coverage never dispatches")
}
}
#[test]
fn every_specialized_provider_row_has_a_registered_protocol() {
let providers = load_providers(BUILTIN_PROVIDERS_TOML).expect("built-in providers");
let discovery = register(Arc::new(NeverCalled));
let mut covered = 0usize;
for provider in providers.values().filter(|provider| {
provider
.discovery
.as_ref()
.is_some_and(|spec| spec.kind == DiscoveryKind::Specialized)
}) {
assert!(
discovery.serves(provider.transport),
"provider {} declares specialized discovery but no protocol is registered for \
transport {:?}",
provider.id,
provider.transport
);
covered += 1;
}
assert!(covered >= 10, "expected every shipped specialized row to be covered, saw {covered}");
}
#[derive(Debug)]
struct Seen {
method: Method,
uri: String,
version: Version,
headers: Vec<(String, String)>,
body: Bytes,
sealed: bool,
aws: Option<AwsSigV4Context>,
}
impl Seen {
fn header(&self, name: &str) -> Option<&str> {
self
.headers
.iter()
.find(|(key, _)| key == name)
.map(|(_, value)| value.as_str())
}
}
struct Recorder {
status: u16,
body: &'static str,
seen: Mutex<Vec<Seen>>,
}
impl Recorder {
fn new(status: u16, body: &'static str) -> Arc<Self> {
Arc::new(Self { status, body, seen: Mutex::new(Vec::new()) })
}
}
#[async_trait]
impl DiscoveryHttp for Recorder {
async fn execute(
&self,
_provider: &ProviderEntry,
_account: &Account,
request: Request<Bytes>,
) -> Result<HttpResponse, Error> {
self.seen.lock().push(Seen {
method: request.method().clone(),
uri: request.uri().to_string(),
version: request.version(),
headers: request
.headers()
.iter()
.map(|(name, value)| {
(name.as_str().to_owned(), value.to_str().unwrap_or_default().to_owned())
})
.collect(),
sealed: request.extensions().get::<SealedBody>().is_some(),
aws: request.extensions().get::<AwsSigV4Context>().cloned(),
body: request.into_body(),
});
Ok(HttpResponse::new(self.status, Bytes::from_static(self.body.as_bytes())))
}
}
fn entry(id: &str) -> ProviderEntry {
load_providers(BUILTIN_PROVIDERS_TOML)
.expect("built-in providers")
.get(id)
.unwrap_or_else(|| panic!("{id} must exist in providers.toml"))
.clone()
}
async fn drive(id: &str, account: &Account, http: Arc<Recorder>) -> Vec<Seen> {
let _ = register(http.clone()).discover(&entry(id), account).await;
std::mem::take(&mut *http.seen.lock())
}
fn account() -> Account {
Account::new("7", "fixture")
}
#[tokio::test]
async fn cursor_posts_protobuf_over_http2() {
let sent = drive("cursor", &account(), Recorder::new(500, "")).await;
let [request] = sent.as_slice() else {
panic!("Cursor discovery makes exactly one call, saw {}", sent.len());
};
assert_eq!(request.method, Method::POST);
assert_eq!(request.uri, "https://api2.cursor.sh/agent.v1.AgentService/GetUsableModels");
assert_eq!(request.version, Version::HTTP_2);
assert_eq!(request.header("content-type"), Some("application/proto"));
assert_eq!(request.header("te"), Some("trailers"));
assert_eq!(request.header("x-cursor-client-type"), Some("cli"));
assert!(!request.sealed);
assert_eq!(request.body, omp_llm_cursor::model_discovery_request());
}
#[tokio::test]
async fn codex_falls_back_to_the_bare_models_endpoint() {
let sent = drive("openai-codex", &account(), Recorder::new(404, "")).await;
let uris: Vec<&str> = sent.iter().map(|request| request.uri.as_str()).collect();
assert_eq!(uris.len(), 2, "both Codex endpoints are attempted: {uris:?}");
assert!(uris[0].contains("/codex/models?client_version="), "{uris:?}");
assert!(
uris[1].contains("/models?client_version=") && !uris[1].contains("/codex/"),
"{uris:?}"
);
assert_eq!(sent[0].header("originator"), Some(CODEX_ORIGINATOR));
assert_eq!(sent[0].header("version"), Some(CODEX_CLIENT_VERSION));
}
#[tokio::test]
async fn devin_defers_its_body_to_the_credential_boundary() {
let sent = drive("devin", &account(), Recorder::new(500, "")).await;
let [request] = sent.as_slice() else {
panic!("Devin discovery makes exactly one call, saw {}", sent.len());
};
assert_eq!(request.method, Method::POST);
assert_eq!(
request.uri,
"https://server.codeium.com/exa.api_server_pb.ApiServerService/GetCliModelConfigs"
);
assert!(request.sealed, "Devin embeds its credential in the body");
assert!(request.body.is_empty(), "the protocol must not attempt to build the sealed body");
}
#[tokio::test]
async fn cloud_code_assist_walks_its_fallback_endpoints() {
let sent = drive("google-antigravity", &account(), Recorder::new(503, "")).await;
let uris: Vec<&str> = sent.iter().map(|request| request.uri.as_str()).collect();
assert_eq!(
uris,
[
"https://daily-cloudcode-pa.googleapis.com/v1internal:fetchAvailableModels",
"https://daily-cloudcode-pa.sandbox.googleapis.com/v1internal:fetchAvailableModels",
],
"the fallback_base_urls column must be walked in order"
);
assert_eq!(sent[0].body.as_ref(), b"{}");
}
#[tokio::test]
async fn ollama_cloud_lists_native_tags() {
let http = Recorder::new(200, r#"{"models":[{"name":"kimi-k2:1t","model":"kimi-k2:1t"}]}"#);
let cards = register(http.clone())
.discover(&entry("ollama-cloud"), &account())
.await
.expect("canned tags payload");
let sent = std::mem::take(&mut *http.seen.lock());
assert_eq!(sent[0].method, Method::GET);
assert_eq!(sent[0].uri, "https://ollama.com/api/tags");
assert_eq!(cards.len(), 1);
assert_eq!(cards[0].id.as_str(), "ollama-cloud/kimi-k2:1t");
}
#[tokio::test]
async fn gitlab_duo_queries_the_account_namespace_first() {
let http = Recorder::new(
200,
r#"{"data":{"aiChatAvailableModels":{
"defaultModel":{"name":"Sonnet","ref":"claude_sonnet_4_6_vertex"},
"selectableModels":[],"pinnedModel":null}}}"#,
);
let account = Account::new("7", "fixture").with_scope(Some("42".into()), None);
let cards = register(http.clone())
.discover(&entry("gitlab-duo-agent"), &account)
.await
.expect("canned GraphQL payload");
let sent = std::mem::take(&mut *http.seen.lock());
assert_eq!(sent.len(), 1, "a scoped account skips the group crawl: {sent:?}");
assert_eq!(sent[0].method, Method::POST);
assert_eq!(sent[0].uri, "https://gitlab.com/api/graphql");
let body = String::from_utf8_lossy(&sent[0].body);
assert!(body.contains("gid://gitlab/Group/42"), "numeric namespaces are wrapped: {body}");
assert_eq!(cards.len(), 1);
assert_eq!(cards[0].model.as_str(), "claude_sonnet_4_6_vertex");
}
#[tokio::test]
async fn bedrock_lists_from_the_control_plane_with_signing_context() {
let http = Recorder::new(
200,
r#"{"modelSummaries":[{"modelId":"anthropic.claude-3-5-sonnet-20241022-v2:0",
"modelName":"Claude 3.5 Sonnet v2","providerName":"Anthropic",
"inputModalities":["TEXT","IMAGE"],"outputModalities":["TEXT"],
"responseStreamingSupported":true,
"inferenceTypesSupported":["ON_DEMAND"],
"modelLifecycle":{"status":"ACTIVE"}}]}"#,
);
let account = Account::new("7", "aws").with_region(Some("eu-central-1".into()));
let cards = register(http.clone())
.discover(&entry("amazon-bedrock"), &account)
.await
.expect("canned ListFoundationModels payload");
let sent = std::mem::take(&mut *http.seen.lock());
let [request] = sent.as_slice() else {
panic!("ListFoundationModels is a single unpaginated call, saw {}", sent.len());
};
assert_eq!(request.method, Method::GET);
assert_eq!(request.uri, "https://bedrock.eu-central-1.amazonaws.com/foundation-models");
let aws = request
.aws
.as_ref()
.expect("SigV4 context must reach the broker");
assert_eq!(aws.service, "bedrock");
assert_eq!(aws.region, "eu-central-1");
assert_eq!(cards.len(), 1);
assert_eq!(cards[0].id.as_str(), "amazon-bedrock/anthropic.claude-3-5-sonnet-20241022-v2:0");
}
}