use super::openai_compat::{OpenAiCompatAdapter, OpenAiCompatConfig};
use crate::inference::adapter::InferenceAdapter;
use crate::inference::configurator::ResolvedProvider;
use crate::inference::error::InferenceError;
use crate::inference::registry::ProviderId;
pub const ATLASCLOUD_BASE_URL: &str = "https://api.atlascloud.ai/v1";
pub fn build(
resolved: &ResolvedProvider,
base_url: &str,
) -> Result<Box<dyn InferenceAdapter>, InferenceError> {
let key = resolved
.key()
.ok_or(InferenceError::MissingCredential {
provider: ProviderId::AtlasCloud,
})?
.clone();
let config = OpenAiCompatConfig {
name: ProviderId::AtlasCloud.as_str().to_string(),
base_url: base_url.to_string(),
api_key: key,
extra_headers: Vec::new(),
capabilities: *resolved.capabilities(),
};
Ok(Box::new(OpenAiCompatAdapter::new(config)?))
}
pub fn factory(resolved: &ResolvedProvider) -> Result<Box<dyn InferenceAdapter>, InferenceError> {
build(resolved, ATLASCLOUD_BASE_URL)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::inference::types::{ChatMessage, ChatRequest, SecretString};
const ATLASCLOUD_MODEL: &str = "openai/gpt-5.6-sol";
fn resolved(key: &str) -> ResolvedProvider {
ResolvedProvider::new(
ProviderId::AtlasCloud,
"atlascloud/openai/gpt-5.6-sol".to_string(),
Some(SecretString::new(key)),
)
}
#[test]
fn factory_builds_named_adapter() {
let adapter = build(&resolved("ac_test_key"), ATLASCLOUD_BASE_URL).expect("built");
assert_eq!(adapter.name(), "atlascloud");
assert!(!adapter.wants_detailed_usage());
assert!(adapter.supports_native_tools());
assert_eq!(adapter.capabilities().id, ProviderId::AtlasCloud);
}
#[test]
fn missing_key_errors() {
let resolved = ResolvedProvider::new(
ProviderId::AtlasCloud,
"atlascloud/openai/gpt-5.6-sol".to_string(),
None,
);
let Err(err) = build(&resolved, ATLASCLOUD_BASE_URL) else {
panic!("expected MissingCredential");
};
assert!(matches!(
err,
InferenceError::MissingCredential {
provider: ProviderId::AtlasCloud
}
));
}
#[tokio::test]
#[ignore = "requires ATLASCLOUD_API_KEY; skipped in CI"]
async fn live_atlascloud_call() {
let Ok(key) = std::env::var("ATLASCLOUD_API_KEY") else {
eprintln!("ATLASCLOUD_API_KEY not set — skipping live test");
return;
};
if key.trim().is_empty() {
eprintln!("ATLASCLOUD_API_KEY is empty — skipping live test");
return;
}
let resolved = ResolvedProvider::new(
ProviderId::AtlasCloud,
ATLASCLOUD_MODEL.to_string(),
Some(SecretString::new(key)),
);
let adapter = build(&resolved, ATLASCLOUD_BASE_URL).expect("build adapter");
let mut req = ChatRequest::new(
ATLASCLOUD_MODEL,
vec![
ChatMessage::system("You are a concise assistant."),
ChatMessage::user("Reply with exactly the word: pong"),
],
);
req.temperature = Some(0.0);
req.max_tokens = Some(16);
let resp = adapter.chat(&req).await.expect("live chat");
let text = resp.first_text().expect("assistant text");
assert!(!text.is_empty(), "assistant text was empty");
assert!(
resp.usage().prompt_tokens > 0,
"prompt_tokens should be > 0"
);
eprintln!(
"live atlascloud ok — text: {text:?}, usage: {:?}",
resp.usage()
);
}
}