mirror of
https://github.com/fawney19/Aether.git
synced 2026-10-04 08:27:46 +08:00
refactor(workspace): enforce layered crate boundaries
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
[package]
|
||||
name = "aether-provider-core"
|
||||
version = "0.1.0"
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
repository.workspace = true
|
||||
description = "Pure provider catalog, capability, and health contracts for Aether"
|
||||
|
||||
[dependencies]
|
||||
serde.workspace = true
|
||||
thiserror.workspace = true
|
||||
@@ -0,0 +1,11 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
pub enum ProviderCapability {
|
||||
Chat,
|
||||
Responses,
|
||||
Embeddings,
|
||||
Images,
|
||||
Video,
|
||||
Files,
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{ProviderCapability, ProviderHealth};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct ProviderDescriptor {
|
||||
pub provider_id: String,
|
||||
pub display_name: String,
|
||||
pub capabilities: Vec<ProviderCapability>,
|
||||
pub health: ProviderHealth,
|
||||
}
|
||||
|
||||
impl ProviderDescriptor {
|
||||
pub fn supports(&self, capability: ProviderCapability) -> bool {
|
||||
self.capabilities.contains(&capability)
|
||||
}
|
||||
|
||||
pub fn validate(&self) -> Result<(), ProviderConfigError> {
|
||||
if self.provider_id.trim().is_empty() {
|
||||
return Err(ProviderConfigError::MissingProviderId);
|
||||
}
|
||||
if self.display_name.trim().is_empty() {
|
||||
return Err(ProviderConfigError::MissingDisplayName);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error, PartialEq, Eq)]
|
||||
pub enum ProviderConfigError {
|
||||
#[error("provider id cannot be empty")]
|
||||
MissingProviderId,
|
||||
#[error("provider display name cannot be empty")]
|
||||
MissingDisplayName,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::ProviderDescriptor;
|
||||
use crate::{ProviderCapability, ProviderHealth};
|
||||
|
||||
#[test]
|
||||
fn descriptor_exposes_capability_without_transport_dependencies() {
|
||||
let descriptor = ProviderDescriptor {
|
||||
provider_id: "openai".to_string(),
|
||||
display_name: "OpenAI".to_string(),
|
||||
capabilities: vec![ProviderCapability::Chat],
|
||||
health: ProviderHealth::Healthy,
|
||||
};
|
||||
assert!(descriptor.validate().is_ok());
|
||||
assert!(descriptor.supports(ProviderCapability::Chat));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum ProviderHealth {
|
||||
Unknown,
|
||||
Healthy,
|
||||
Degraded,
|
||||
Unavailable,
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
//! Provider domain contracts independent from transport and persistence.
|
||||
|
||||
mod capability;
|
||||
mod catalog;
|
||||
mod health;
|
||||
mod policy;
|
||||
|
||||
pub use capability::ProviderCapability;
|
||||
pub use catalog::{ProviderConfigError, ProviderDescriptor};
|
||||
pub use health::ProviderHealth;
|
||||
pub use policy::ProviderEligibilityPolicy;
|
||||
@@ -0,0 +1,7 @@
|
||||
use crate::{ProviderCapability, ProviderDescriptor, ProviderHealth};
|
||||
|
||||
pub trait ProviderEligibilityPolicy: Send + Sync {
|
||||
fn is_eligible(&self, provider: &ProviderDescriptor, capability: ProviderCapability) -> bool {
|
||||
provider.health != ProviderHealth::Unavailable && provider.supports(capability)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user