feat(provider): add unified provider abstraction layer with ModelProvider trait and shared types
This commit is contained in:
@@ -18,6 +18,7 @@ pub mod mcp;
|
||||
pub mod mode;
|
||||
pub mod model;
|
||||
pub mod oauth;
|
||||
pub mod provider;
|
||||
pub mod providers;
|
||||
pub mod router;
|
||||
pub mod sandbox;
|
||||
@@ -50,6 +51,7 @@ pub use mcp::{
|
||||
};
|
||||
pub use mode::*;
|
||||
pub use model::*;
|
||||
pub use provider::*;
|
||||
pub use providers::*;
|
||||
pub use router::*;
|
||||
pub use sandbox::*;
|
||||
|
||||
34
crates/owlen-core/src/provider/mod.rs
Normal file
34
crates/owlen-core/src/provider/mod.rs
Normal file
@@ -0,0 +1,34 @@
|
||||
//! Unified provider abstraction layer.
|
||||
//!
|
||||
//! This module defines the async [`ModelProvider`] trait that all model
|
||||
//! backends implement, together with a small suite of shared data structures
|
||||
//! used for model discovery and streaming generation.
|
||||
|
||||
mod types;
|
||||
|
||||
use std::pin::Pin;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use futures::Stream;
|
||||
|
||||
pub use self::types::*;
|
||||
|
||||
use crate::Result;
|
||||
|
||||
/// Convenience alias for the stream type yielded by [`ModelProvider::generate_stream`].
|
||||
pub type GenerateStream = Pin<Box<dyn Stream<Item = Result<GenerateChunk>> + Send + 'static>>;
|
||||
|
||||
#[async_trait]
|
||||
pub trait ModelProvider: Send + Sync {
|
||||
/// Returns descriptive metadata about the provider.
|
||||
fn metadata(&self) -> &ProviderMetadata;
|
||||
|
||||
/// Check the current health state for the provider.
|
||||
async fn health_check(&self) -> Result<ProviderStatus>;
|
||||
|
||||
/// List all models available through the provider.
|
||||
async fn list_models(&self) -> Result<Vec<ModelInfo>>;
|
||||
|
||||
/// Acquire a streaming response for a generation request.
|
||||
async fn generate_stream(&self, request: GenerateRequest) -> Result<GenerateStream>;
|
||||
}
|
||||
124
crates/owlen-core/src/provider/types.rs
Normal file
124
crates/owlen-core/src/provider/types.rs
Normal file
@@ -0,0 +1,124 @@
|
||||
//! Shared types used by the unified provider abstraction layer.
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value;
|
||||
|
||||
/// Categorises providers so the UI can distinguish between local and hosted
|
||||
/// backends.
|
||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub enum ProviderType {
|
||||
Local,
|
||||
Cloud,
|
||||
}
|
||||
|
||||
/// Represents the current availability state for a provider.
|
||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub enum ProviderStatus {
|
||||
Available,
|
||||
Unavailable,
|
||||
RequiresSetup,
|
||||
}
|
||||
|
||||
/// Describes core metadata for a provider implementation.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub struct ProviderMetadata {
|
||||
pub id: String,
|
||||
pub name: String,
|
||||
pub provider_type: ProviderType,
|
||||
pub requires_auth: bool,
|
||||
#[serde(default)]
|
||||
pub metadata: HashMap<String, Value>,
|
||||
}
|
||||
|
||||
impl ProviderMetadata {
|
||||
/// Construct a new metadata instance for a provider.
|
||||
pub fn new(
|
||||
id: impl Into<String>,
|
||||
name: impl Into<String>,
|
||||
provider_type: ProviderType,
|
||||
requires_auth: bool,
|
||||
) -> Self {
|
||||
Self {
|
||||
id: id.into(),
|
||||
name: name.into(),
|
||||
provider_type,
|
||||
requires_auth,
|
||||
metadata: HashMap::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Information about a model that can be displayed to users.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
||||
pub struct ModelInfo {
|
||||
pub name: String,
|
||||
#[serde(default)]
|
||||
pub size_bytes: Option<u64>,
|
||||
#[serde(default)]
|
||||
pub capabilities: Vec<String>,
|
||||
#[serde(default)]
|
||||
pub description: Option<String>,
|
||||
pub provider: ProviderMetadata,
|
||||
#[serde(default)]
|
||||
pub metadata: HashMap<String, Value>,
|
||||
}
|
||||
|
||||
/// Unified request for streaming text generation across providers.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
||||
pub struct GenerateRequest {
|
||||
pub model: String,
|
||||
#[serde(default)]
|
||||
pub prompt: Option<String>,
|
||||
#[serde(default)]
|
||||
pub context: Vec<String>,
|
||||
#[serde(default)]
|
||||
pub parameters: HashMap<String, Value>,
|
||||
#[serde(default)]
|
||||
pub metadata: HashMap<String, Value>,
|
||||
}
|
||||
|
||||
impl GenerateRequest {
|
||||
/// Helper for building a request from the minimum required fields.
|
||||
pub fn new(model: impl Into<String>) -> Self {
|
||||
Self {
|
||||
model: model.into(),
|
||||
prompt: None,
|
||||
context: Vec::new(),
|
||||
parameters: HashMap::new(),
|
||||
metadata: HashMap::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Streamed chunk of generation output from a model.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
||||
pub struct GenerateChunk {
|
||||
#[serde(default)]
|
||||
pub text: Option<String>,
|
||||
#[serde(default)]
|
||||
pub is_final: bool,
|
||||
#[serde(default)]
|
||||
pub metadata: HashMap<String, Value>,
|
||||
}
|
||||
|
||||
impl GenerateChunk {
|
||||
/// Construct a new chunk with the provided text payload.
|
||||
pub fn from_text(text: impl Into<String>) -> Self {
|
||||
Self {
|
||||
text: Some(text.into()),
|
||||
is_final: false,
|
||||
metadata: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Mark the chunk as the terminal item in a stream.
|
||||
pub fn final_chunk() -> Self {
|
||||
Self {
|
||||
text: None,
|
||||
is_final: true,
|
||||
metadata: HashMap::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user