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 mode;
|
||||||
pub mod model;
|
pub mod model;
|
||||||
pub mod oauth;
|
pub mod oauth;
|
||||||
|
pub mod provider;
|
||||||
pub mod providers;
|
pub mod providers;
|
||||||
pub mod router;
|
pub mod router;
|
||||||
pub mod sandbox;
|
pub mod sandbox;
|
||||||
@@ -50,6 +51,7 @@ pub use mcp::{
|
|||||||
};
|
};
|
||||||
pub use mode::*;
|
pub use mode::*;
|
||||||
pub use model::*;
|
pub use model::*;
|
||||||
|
pub use provider::*;
|
||||||
pub use providers::*;
|
pub use providers::*;
|
||||||
pub use router::*;
|
pub use router::*;
|
||||||
pub use sandbox::*;
|
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