Skip to main content

systemprompt_traits/
file_upload.rs

1use async_trait::async_trait;
2use std::sync::Arc;
3use systemprompt_identifiers::{ContextId, FileId, SessionId, TraceId, UserId};
4
5pub type FileUploadResult<T> = Result<T, FileUploadProviderError>;
6
7#[derive(Debug, thiserror::Error)]
8#[non_exhaustive]
9pub enum FileUploadProviderError {
10    #[error("Upload disabled")]
11    Disabled,
12
13    #[error("Validation failed: {0}")]
14    ValidationFailed(String),
15
16    #[error("Storage error: {0}")]
17    StorageError(String),
18
19    #[error("Internal error: {0}")]
20    Internal(String),
21}
22
23impl From<anyhow::Error> for FileUploadProviderError {
24    fn from(err: anyhow::Error) -> Self {
25        Self::Internal(err.to_string())
26    }
27}
28
29#[derive(Debug, Clone)]
30pub struct FileUploadInput {
31    pub mime_type: String,
32    pub bytes_base64: String,
33    pub name: Option<String>,
34    pub context_id: ContextId,
35    pub user_id: Option<UserId>,
36    pub session_id: Option<SessionId>,
37    pub trace_id: Option<TraceId>,
38}
39
40impl FileUploadInput {
41    #[must_use]
42    pub fn new(
43        mime_type: impl Into<String>,
44        bytes_base64: impl Into<String>,
45        context_id: ContextId,
46    ) -> Self {
47        Self {
48            mime_type: mime_type.into(),
49            bytes_base64: bytes_base64.into(),
50            name: None,
51            context_id,
52            user_id: None,
53            session_id: None,
54            trace_id: None,
55        }
56    }
57
58    #[must_use]
59    pub fn with_name(mut self, name: impl Into<String>) -> Self {
60        self.name = Some(name.into());
61        self
62    }
63
64    #[must_use]
65    pub fn with_user_id(mut self, user_id: UserId) -> Self {
66        self.user_id = Some(user_id);
67        self
68    }
69
70    #[must_use]
71    pub fn with_session_id(mut self, session_id: SessionId) -> Self {
72        self.session_id = Some(session_id);
73        self
74    }
75
76    #[must_use]
77    pub fn with_trace_id(mut self, trace_id: TraceId) -> Self {
78        self.trace_id = Some(trace_id);
79        self
80    }
81}
82
83#[derive(Debug, Clone)]
84pub struct UploadedFileInfo {
85    pub file_id: FileId,
86    pub public_url: String,
87    pub size_bytes: Option<i64>,
88}
89
90#[async_trait]
91pub trait FileUploadProvider: Send + Sync {
92    fn is_enabled(&self) -> bool;
93
94    async fn upload_file(&self, input: FileUploadInput) -> FileUploadResult<UploadedFileInfo>;
95}
96
97pub type DynFileUploadProvider = Arc<dyn FileUploadProvider>;