use std::collections::HashMap;
use std::pin::Pin;
use async_trait::async_trait;
use bytes::Bytes;
use futures::stream::Stream;
use modkit_macros::domain_model;
use modkit_security::SecurityContext;
use super::error::DomainError;
pub type FileStream =
Pin<Box<dyn Stream<Item = Result<Bytes, Box<dyn std::error::Error + Send + Sync>>> + Send>>;
pub(crate) mod metric_labels;
pub(crate) mod metrics;
pub(crate) use metrics::MiniChatMetricsPort;
#[domain_model]
#[derive(Debug, thiserror::Error)]
pub enum FileStorageError {
#[error("provider rejected request: {message}")]
Rejected { code: String, message: String },
#[error("provider unavailable: {message}")]
Unavailable { message: String },
#[error("configuration error: {message}")]
Configuration { message: String },
#[error("invalid provider response: {message}")]
InvalidResponse { message: String },
}
impl From<FileStorageError> for DomainError {
fn from(e: FileStorageError) -> Self {
match e {
FileStorageError::Rejected { code, message } => DomainError::ProviderError {
code,
sanitized_message: message,
},
FileStorageError::Unavailable { message } => DomainError::ProviderError {
code: "provider_unavailable".to_owned(),
sanitized_message: message,
},
FileStorageError::Configuration { message } => DomainError::ProviderError {
code: "configuration_error".to_owned(),
sanitized_message: message,
},
FileStorageError::InvalidResponse { message } => DomainError::ProviderError {
code: "response_parse_error".to_owned(),
sanitized_message: message,
},
}
}
}
#[domain_model]
pub struct UploadFileParams {
pub filename: String,
pub content_type: String,
pub file_stream: FileStream,
pub purpose: String,
}
#[domain_model]
pub struct AddFileToVectorStoreParams {
pub vector_store_id: String,
pub provider_file_id: String,
pub attributes: HashMap<String, String>,
}
#[async_trait]
pub trait FileStorageProvider: Send + Sync {
async fn upload_file(
&self,
ctx: SecurityContext,
provider_id: &str,
params: UploadFileParams,
) -> Result<(String, u64), FileStorageError>;
async fn delete_file(
&self,
ctx: SecurityContext,
provider_id: &str,
provider_file_id: &str,
) -> Result<(), FileStorageError>;
}
#[async_trait]
pub trait VectorStoreProvider: Send + Sync {
async fn create_vector_store(
&self,
ctx: SecurityContext,
provider_id: &str,
) -> Result<String, FileStorageError>;
async fn add_file_to_vector_store(
&self,
ctx: SecurityContext,
provider_id: &str,
params: AddFileToVectorStoreParams,
) -> Result<(), FileStorageError>;
async fn delete_vector_store(
&self,
ctx: SecurityContext,
provider_id: &str,
vector_store_id: &str,
) -> Result<(), FileStorageError>;
}