1#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
3pub struct ToolDefinition {
4 pub name: String,
5 pub description: String,
6 pub input_schema_json: String,
7 #[serde(default, skip_serializing_if = "Option::is_none")]
8 pub output_schema_json: Option<String>,
9 #[serde(default, skip_serializing_if = "Option::is_none")]
12 pub capabilities: Option<Vec<String>>,
13 #[serde(default, skip_serializing_if = "Option::is_none")]
16 pub agentic_worker_metadata: Option<String>,
17 #[serde(default, skip_serializing_if = "Vec::is_empty")]
20 pub secret_requirements: Vec<greentic_types::secrets::SecretRequirement>,
21}
22
23#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
25pub struct PromptFragment {
26 pub section: String,
27 pub content_markdown: String,
28 pub priority: u32,
29}
30
31#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
33pub struct KnowledgeEntrySummary {
34 pub id: String,
35 pub title: String,
36 pub category: String,
37 pub tags: Vec<String>,
38}
39
40#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
42pub struct KnowledgeEntry {
43 pub id: String,
44 pub title: String,
45 pub category: String,
46 pub tags: Vec<String>,
47 pub content_json: String,
48}
49
50#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
52#[serde(rename_all = "lowercase")]
53pub enum Severity {
54 Error,
55 Warning,
56 Info,
57 Hint,
58}
59
60#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
62pub struct Diagnostic {
63 pub severity: Severity,
64 pub code: String,
65 pub message: String,
66 #[serde(default, skip_serializing_if = "Option::is_none")]
67 pub path: Option<String>,
68}
69
70#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
75pub struct TargetSummary {
76 pub id: String,
77 pub display_name: String,
78 pub description: String,
79 #[serde(default, skip_serializing_if = "Option::is_none")]
80 pub icon_path: Option<String>,
81 pub supports_rollback: bool,
82}
83
84#[derive(Debug, Clone)]
90pub struct DeployRequest {
91 pub target_id: String,
92 pub artifact_bytes: Vec<u8>,
93 pub credentials_json: String,
94 pub config_json: String,
95 pub deployment_name: String,
96}
97
98#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
100#[serde(rename_all = "kebab-case")]
101pub enum DeployStatus {
102 Pending,
103 Provisioning,
104 Configuring,
105 Starting,
106 Running,
107 Failed,
108 RolledBack,
109}
110
111#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
113pub struct DeployJob {
114 pub id: String,
115 pub status: DeployStatus,
116 pub message: String,
117 pub endpoints: Vec<String>,
118}
119
120#[derive(Debug, Clone, thiserror::Error)]
131pub enum DeployExtensionError {
132 #[error("invalid input: {0}")]
133 InvalidInput(String),
134 #[error("missing capability: {0}")]
135 MissingCapability(String),
136 #[error("permission denied: {0}")]
137 PermissionDenied(String),
138 #[error("not found: {0}")]
139 NotFound(String),
140 #[error("schema invalid: {0}")]
141 SchemaInvalid(String),
142 #[error("internal: {0}")]
143 Internal(String),
144}
145
146#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
148pub struct ValidateResult {
149 pub valid: bool,
150 pub diagnostics: Vec<Diagnostic>,
151}
152
153#[derive(Debug, Clone, Default)]
161pub struct BundleSession {
162 pub flows_json: String,
163 pub contents_json: String,
164 pub assets: Vec<(String, Vec<u8>)>,
165 pub capabilities_used: Vec<String>,
166}
167
168#[derive(Debug, Clone)]
175pub struct BundleArtifact {
176 pub filename: String,
177 pub bytes: Vec<u8>,
178 pub sha256: String,
179}
180
181#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
187#[serde(rename_all = "kebab-case")]
188pub enum TargetKind {
189 AdaptiveCard,
190 SlackBlockKit,
191 TeamsCard,
192 PlainText,
193}
194
195#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
201pub struct RoleSpec {
202 pub name: String,
203 pub description: String,
204 pub json_schema: String,
205 pub target: TargetKind,
206 pub schema_version: u32,
207 pub context_aware: bool,
208}
209
210#[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize)]
217pub struct CompileContext {
218 pub flow_entries_json: String,
219 #[serde(default, skip_serializing_if = "Option::is_none")]
220 pub flow_id: Option<String>,
221 pub locale: String,
222}
223
224#[derive(Debug, Clone, thiserror::Error, serde::Serialize, serde::Deserialize)]
236#[serde(rename_all = "kebab-case", tag = "kind", content = "message")]
237pub enum HostExtensionError {
238 #[error("invalid input: {0}")]
239 InvalidInput(String),
240 #[error("missing capability: {0}")]
241 MissingCapability(String),
242 #[error("permission denied: {0}")]
243 PermissionDenied(String),
244 #[error("not found: {0}")]
245 NotFound(String),
246 #[error("schema invalid: {0}")]
247 SchemaInvalid(String),
248 #[error("internal: {0}")]
249 Internal(String),
250}
251
252impl HostExtensionError {
253 #[must_use]
257 pub fn code(&self) -> &'static str {
258 match self {
259 Self::InvalidInput(_) => "invalid-input",
260 Self::MissingCapability(_) => "missing-capability",
261 Self::PermissionDenied(_) => "permission-denied",
262 Self::NotFound(_) => "not-found",
263 Self::SchemaInvalid(_) => "schema-invalid",
264 Self::Internal(_) => "internal",
265 }
266 }
267}
268
269#[derive(Debug, Clone, thiserror::Error)]
278pub enum RoleError {
279 #[error("unknown role: {0}")]
280 UnknownRole(String),
281 #[error("invalid input: {0:?}")]
282 InvalidInput(Vec<Diagnostic>),
283 #[error("compile failed: {0}")]
284 CompileFailed(String),
285 #[error("target not supported: {0:?}")]
286 TargetNotSupported(TargetKind),
287 #[error("schema version not supported: {0}")]
288 VersionNotSupported(u32),
289 #[error("host: {0}")]
290 Host(#[from] HostExtensionError),
291}
292
293#[cfg(test)]
294mod host_extension_error_tests {
295 #[test]
296 fn host_extension_error_codes_are_stable_kebab() {
297 use super::HostExtensionError as E;
298 let cases = [
299 (E::InvalidInput("x".into()), "invalid-input"),
300 (E::MissingCapability("x".into()), "missing-capability"),
301 (E::PermissionDenied("x".into()), "permission-denied"),
302 (E::NotFound("x".into()), "not-found"),
303 (E::SchemaInvalid("x".into()), "schema-invalid"),
304 (E::Internal("x".into()), "internal"),
305 ];
306 for (e, code) in cases {
307 assert_eq!(e.code(), code);
308 }
309 }
310}
311
312#[cfg(test)]
313mod target_summary_tests {
314 use super::*;
315
316 #[test]
317 fn target_summary_serializes_and_deserializes() {
318 let t = TargetSummary {
319 id: "aws-ecs-fargate-local".into(),
320 display_name: "AWS ECS Fargate (local creds)".into(),
321 description: "Deploy to AWS ECS Fargate using ambient credentials.".into(),
322 icon_path: Some("icons/aws.svg".into()),
323 supports_rollback: true,
324 };
325 let json = serde_json::to_string(&t).unwrap();
326 let back: TargetSummary = serde_json::from_str(&json).unwrap();
327 assert_eq!(back.id, t.id);
328 assert!(back.supports_rollback);
329 }
330}