use std::sync::Arc;
use awaken_ext_observability::trace_store::TraceStoreError;
use awaken_server_contract::contract::config_store::ConfigStore;
use awaken_server_contract::contract::executor::LlmExecutor;
use awaken_server_contract::contract::storage::StorageError;
use awaken_server_contract::registry_spec::{AgentSpec, ModelSpec, ProviderSpec};
use crate::app::EvalRoutesState;
use crate::error::ApiError;
use crate::services::config_runtime::build_genai_provider_executor_with_broker;
pub(crate) fn eval_config_store(state: &EvalRoutesState) -> Arc<dyn ConfigStore> {
state.config.config_store.clone()
}
pub(crate) async fn resolve_live_executor(
state: &EvalRoutesState,
model_id: &str,
) -> Result<ResolvedLiveExecutor, ApiError> {
let store = eval_config_store(state);
let model_value = store
.get("models", model_id)
.await
.map_err(map_storage_error)?
.ok_or_else(|| {
ApiError::NotFound(format!(
"model not found: models/{model_id} (register via /v1/config/models)"
))
})?;
let model_record =
awaken_server_contract::config_record::ConfigRecord::<ModelSpec>::from_value(model_value)
.map_err(|err| ApiError::Internal(format!("decoding model spec: {err}")))?;
let spec = model_record.spec;
let provider_value = store
.get("providers", &spec.provider_id)
.await
.map_err(map_storage_error)?
.ok_or_else(|| {
ApiError::NotFound(format!(
"provider not found: providers/{} (referenced by model {model_id})",
spec.provider_id
))
})?;
let provider_record =
awaken_server_contract::config_record::ConfigRecord::<ProviderSpec>::from_value(
provider_value,
)
.map_err(|err| ApiError::Internal(format!("decoding provider: {err}")))?;
let provider = provider_record.spec;
let executor =
build_genai_provider_executor_with_broker(&provider, state.run.credential_broker.clone())
.map_err(|err| ApiError::Internal(format!("building provider executor: {err}")))?;
Ok(ResolvedLiveExecutor {
upstream_model: spec.upstream_model.clone(),
spec,
executor,
})
}
pub(crate) struct ResolvedLiveExecutor {
pub executor: Arc<dyn LlmExecutor>,
pub upstream_model: String,
pub spec: ModelSpec,
}
pub(crate) async fn resolve_agent_spec(
state: &EvalRoutesState,
agent_id: &str,
) -> Result<AgentSpec, ApiError> {
let store = eval_config_store(state);
let raw = store
.get("agents", agent_id)
.await
.map_err(map_storage_error)?
.ok_or_else(|| {
ApiError::NotFound(format!(
"agent not found: agents/{agent_id} (register via /v1/config/agents)"
))
})?;
let record = awaken_server_contract::config_record::ConfigRecord::<AgentSpec>::from_value(raw)
.map_err(|err| ApiError::Internal(format!("decoding agent: {err}")))?;
Ok(record.spec)
}
pub(crate) fn map_storage_error(err: StorageError) -> ApiError {
match err {
StorageError::NotFound(msg) => ApiError::NotFound(msg),
StorageError::AlreadyExists(msg) => ApiError::Conflict(msg),
StorageError::VersionConflict { expected, actual } => ApiError::Conflict(format!(
"revision conflict: expected {expected}, actual {actual}"
)),
StorageError::Validation(msg) => ApiError::BadRequest(msg),
err => ApiError::Internal(err.to_string()),
}
}
pub(crate) fn map_trace_store_error(err: TraceStoreError) -> ApiError {
match err {
TraceStoreError::NotFound { run_id } => {
ApiError::NotFound(format!("trace not found: {run_id}"))
}
TraceStoreError::InvalidRunId(id) => ApiError::BadRequest(format!("invalid run id: {id}")),
err => ApiError::Internal(err.to_string()),
}
}