1use std::future::Future;
4
5use bytes::Bytes;
6use serde::Deserialize;
7use serde::Serialize;
8use tokio_util::sync::CancellationToken;
9
10use crate::error::ProviderError;
11use crate::shared::Headers;
12use crate::shared::ProviderId;
13use crate::shared::ProviderMetadata;
14use crate::shared::ProviderOptions;
15use crate::shared::ProviderReference;
16use crate::shared::Warning;
17use crate::shared::base64_bytes;
18
19pub trait Skills: Send + Sync + 'static {
21 fn provider(&self) -> &ProviderId;
23
24 fn upload_skill(
26 &self,
27 options: UploadSkillOptions,
28 ) -> impl Future<Output = Result<UploadSkillResult, ProviderError>> + Send;
29}
30
31#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
33#[serde(tag = "type", rename_all = "lowercase")]
34#[non_exhaustive]
35pub enum SkillFileData {
36 Data {
38 #[serde(with = "base64_bytes")]
40 data: Bytes,
41 },
42 Text {
44 text: String,
46 },
47}
48
49#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
51pub struct SkillFile {
52 pub path: String,
54 pub data: SkillFileData,
56}
57
58#[derive(Debug, Clone)]
60pub struct UploadSkillOptions {
61 pub files: Vec<SkillFile>,
63 pub display_title: Option<String>,
65 pub headers: Headers,
67 pub provider_options: ProviderOptions,
69 pub cancellation: CancellationToken,
71}
72
73impl UploadSkillOptions {
74 #[must_use]
76 pub fn new(files: Vec<SkillFile>) -> Self {
77 Self {
78 files,
79 display_title: None,
80 headers: Headers::new(),
81 provider_options: ProviderOptions::new(),
82 cancellation: CancellationToken::new(),
83 }
84 }
85}
86
87#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
89pub struct UploadSkillResult {
90 pub provider_reference: ProviderReference,
92 #[serde(default, skip_serializing_if = "Option::is_none")]
94 pub display_title: Option<String>,
95 #[serde(default, skip_serializing_if = "Option::is_none")]
97 pub name: Option<String>,
98 #[serde(default, skip_serializing_if = "Option::is_none")]
100 pub description: Option<String>,
101 #[serde(default, skip_serializing_if = "Option::is_none")]
103 pub latest_version: Option<String>,
104 #[serde(default, skip_serializing_if = "Option::is_none")]
106 pub provider_metadata: Option<ProviderMetadata>,
107 #[serde(default)]
109 pub warnings: Vec<Warning>,
110}