1use alloc::{collections::BTreeMap, string::String, vec::Vec};
4
5use crate::{AllowList, NetworkPolicy};
6
7#[cfg(feature = "schemars")]
8use schemars::JsonSchema;
9#[cfg(feature = "serde")]
10use serde::{Deserialize, Serialize};
11
12#[non_exhaustive]
14#[derive(Clone, Debug, Default, PartialEq, Eq)]
15#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
16#[cfg_attr(feature = "schemars", derive(JsonSchema))]
17pub struct Capabilities {
18 #[cfg_attr(
20 feature = "serde",
21 serde(default, skip_serializing_if = "Option::is_none")
22 )]
23 pub http: Option<HttpCaps>,
24 #[cfg_attr(
26 feature = "serde",
27 serde(default, skip_serializing_if = "Option::is_none")
28 )]
29 pub secrets: Option<SecretsCaps>,
30 #[cfg_attr(
32 feature = "serde",
33 serde(default, skip_serializing_if = "Option::is_none")
34 )]
35 pub kv: Option<KvCaps>,
36 #[cfg_attr(
38 feature = "serde",
39 serde(default, skip_serializing_if = "Option::is_none")
40 )]
41 pub fs: Option<FsCaps>,
42 #[cfg_attr(
44 feature = "serde",
45 serde(default, skip_serializing_if = "Option::is_none")
46 )]
47 pub net: Option<NetCaps>,
48 #[cfg_attr(
50 feature = "serde",
51 serde(default, skip_serializing_if = "Option::is_none")
52 )]
53 pub tools: Option<ToolsCaps>,
54}
55
56impl Capabilities {
57 pub fn new() -> Self {
59 Self::default()
60 }
61
62 pub fn is_empty(&self) -> bool {
64 self.http.is_none()
65 && self.secrets.is_none()
66 && self.kv.is_none()
67 && self.fs.is_none()
68 && self.net.is_none()
69 && self.tools.is_none()
70 }
71}
72
73#[non_exhaustive]
75#[derive(Clone, Debug, Default, PartialEq, Eq)]
76#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
77#[cfg_attr(feature = "schemars", derive(JsonSchema))]
78pub struct HttpCaps {
79 #[cfg_attr(
81 feature = "serde",
82 serde(default, skip_serializing_if = "Option::is_none")
83 )]
84 pub allow_list: Option<AllowList>,
85 #[cfg_attr(
87 feature = "serde",
88 serde(default, skip_serializing_if = "Option::is_none")
89 )]
90 pub max_body_bytes: Option<u64>,
91}
92
93impl HttpCaps {
94 pub fn new() -> Self {
96 Self::default()
97 }
98}
99
100#[non_exhaustive]
102#[derive(Clone, Debug, Default, PartialEq, Eq)]
103#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
104#[cfg_attr(feature = "schemars", derive(JsonSchema))]
105pub struct SecretsCaps {
106 #[cfg_attr(
108 feature = "serde",
109 serde(default, skip_serializing_if = "Vec::is_empty")
110 )]
111 pub required: Vec<String>,
112}
113
114impl SecretsCaps {
115 pub fn new() -> Self {
117 Self::default()
118 }
119}
120
121#[non_exhaustive]
123#[derive(Clone, Debug, Default, PartialEq, Eq)]
124#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
125#[cfg_attr(feature = "schemars", derive(JsonSchema))]
126pub struct KvCaps {
127 #[cfg_attr(
129 feature = "serde",
130 serde(default, skip_serializing_if = "Vec::is_empty")
131 )]
132 pub namespaces: Vec<String>,
133}
134
135impl KvCaps {
136 pub fn new() -> Self {
138 Self::default()
139 }
140}
141
142#[non_exhaustive]
144#[derive(Clone, Debug, PartialEq, Eq)]
145#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
146#[cfg_attr(feature = "schemars", derive(JsonSchema))]
147pub struct FsCaps {
148 #[cfg_attr(
150 feature = "serde",
151 serde(default, skip_serializing_if = "Vec::is_empty")
152 )]
153 pub paths: Vec<String>,
154 #[cfg_attr(feature = "serde", serde(default = "FsCaps::default_read_only"))]
156 pub read_only: bool,
157}
158
159impl Default for FsCaps {
160 fn default() -> Self {
161 Self {
162 paths: Vec::new(),
163 read_only: true,
164 }
165 }
166}
167
168impl FsCaps {
169 const fn default_read_only() -> bool {
170 true
171 }
172
173 pub fn new() -> Self {
175 Self::default()
176 }
177}
178
179#[non_exhaustive]
181#[derive(Clone, Debug, Default, PartialEq, Eq)]
182#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
183#[cfg_attr(feature = "schemars", derive(JsonSchema))]
184pub struct NetCaps {
185 #[cfg_attr(
187 feature = "serde",
188 serde(default, skip_serializing_if = "Option::is_none")
189 )]
190 pub policy: Option<NetworkPolicy>,
191}
192
193impl NetCaps {
194 pub fn new() -> Self {
196 Self::default()
197 }
198}
199
200#[non_exhaustive]
202#[derive(Clone, Debug, Default, PartialEq, Eq)]
203#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
204#[cfg_attr(feature = "schemars", derive(JsonSchema))]
205pub struct ToolsCaps {
206 #[cfg_attr(
208 feature = "serde",
209 serde(default, skip_serializing_if = "Vec::is_empty")
210 )]
211 pub allowed: Vec<String>,
212}
213
214impl ToolsCaps {
215 pub fn new() -> Self {
217 Self::default()
218 }
219}
220
221#[non_exhaustive]
223#[derive(Clone, Debug, PartialEq, Eq)]
224#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
225#[cfg_attr(feature = "schemars", derive(JsonSchema))]
226pub struct Limits {
227 pub memory_mb: u32,
229 pub wall_time_ms: u64,
231 #[cfg_attr(
233 feature = "serde",
234 serde(default, skip_serializing_if = "Option::is_none")
235 )]
236 pub fuel: Option<u64>,
237 #[cfg_attr(
239 feature = "serde",
240 serde(default, skip_serializing_if = "Option::is_none")
241 )]
242 pub files: Option<u32>,
243}
244
245impl Limits {
246 pub fn new(memory_mb: u32, wall_time_ms: u64) -> Self {
248 Self {
249 memory_mb,
250 wall_time_ms,
251 fuel: None,
252 files: None,
253 }
254 }
255}
256
257impl Default for Limits {
258 fn default() -> Self {
259 Self::new(0, 0)
260 }
261}
262
263#[non_exhaustive]
265#[derive(Clone, Debug, PartialEq, Eq)]
266#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
267#[cfg_attr(feature = "schemars", derive(JsonSchema))]
268pub struct TelemetrySpec {
269 pub span_prefix: String,
271 #[cfg_attr(feature = "serde", serde(default))]
273 pub attributes: BTreeMap<String, String>,
274 pub emit_node_spans: bool,
276}
277
278impl TelemetrySpec {
279 pub fn new(span_prefix: impl Into<String>) -> Self {
281 Self {
282 span_prefix: span_prefix.into(),
283 attributes: BTreeMap::new(),
284 emit_node_spans: false,
285 }
286 }
287}
288
289impl Default for TelemetrySpec {
290 fn default() -> Self {
291 Self::new("greentic")
292 }
293}