use std::sync::{Arc, Mutex};
use serial_test::serial;
use trusty_common::credentials::MemoryKeyStore;
use trusty_common::credentials::test_sandbox::CredentialSandbox;
use trusty_common::inference::InferenceAdapter;
use trusty_common::inference::registry::{ProviderId, capabilities};
use trusty_common::inference::test_support::ScriptedAdapter;
use super::{
DEFAULT_MANAGER_MODEL, FALLBACK_MODEL_ENV, InferenceUnavailable, Inner, MANAGER_MODEL_ENV,
ManagerInference, Source, resolve_manager_model,
};
fn credential_sandbox() -> CredentialSandbox {
let mut sandbox = CredentialSandbox::enter();
sandbox.remove(MANAGER_MODEL_ENV);
sandbox.remove(FALLBACK_MODEL_ENV);
sandbox
}
fn credentialed_over(store: MemoryKeyStore, model: &str) -> ManagerInference {
let mut configurator = trusty_common::inference::Configurator::new();
trusty_common::inference::register_default_factories(&mut configurator);
ManagerInference {
inner: Mutex::new(Inner {
model: model.to_string(),
source: Source::Credentialed {
configurator,
store: Box::new(store),
},
}),
}
}
#[test]
#[serial]
fn resolve_reports_no_provider_when_unconfigured() {
let _sandbox = credential_sandbox();
let seam = credentialed_over(MemoryKeyStore::new(), "openai/gpt-4o-mini");
let Err(err) = seam.resolve() else {
panic!("empty store must not resolve a provider");
};
assert!(matches!(err, InferenceUnavailable::NoProvider));
}
#[test]
fn resolve_returns_injected_adapter() {
let caps = capabilities(ProviderId::OpenRouter);
let scripted: Arc<dyn InferenceAdapter> = Arc::new(ScriptedAdapter::echo("scripted", caps));
let seam = ManagerInference::with_adapter(scripted, "test/model");
let (model, adapter) = seam.resolve().expect("fixed adapter resolves");
assert_eq!(model, "test/model");
assert_eq!(adapter.name(), "scripted");
}
#[test]
#[serial]
fn set_adapter_overrides_credentialed_source() {
let _sandbox = credential_sandbox();
let seam = credentialed_over(MemoryKeyStore::new(), "openai/gpt-4o-mini");
assert!(seam.resolve().is_err(), "starts unconfigured");
let caps = capabilities(ProviderId::OpenRouter);
let scripted: Arc<dyn InferenceAdapter> = Arc::new(ScriptedAdapter::echo("scripted", caps));
seam.set_adapter(scripted, "swapped/model");
let (model, adapter) = seam.resolve().expect("resolves after swap");
assert_eq!(model, "swapped/model");
assert_eq!(adapter.name(), "scripted");
}
#[test]
#[serial]
fn manager_model_env_precedence() {
let mut sandbox = credential_sandbox();
assert_eq!(resolve_manager_model(), DEFAULT_MANAGER_MODEL);
sandbox.set(FALLBACK_MODEL_ENV, "fleet/model");
assert_eq!(resolve_manager_model(), "fleet/model");
sandbox.set(MANAGER_MODEL_ENV, "manager/model");
assert_eq!(resolve_manager_model(), "manager/model");
}