#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct ToolDefinition {
pub name: String,
pub description: String,
pub input_schema_json: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub output_schema_json: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub capabilities: Option<Vec<String>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub agentic_worker_metadata: Option<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub secret_requirements: Vec<greentic_types::secrets::SecretRequirement>,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct PromptFragment {
pub section: String,
pub content_markdown: String,
pub priority: u32,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct KnowledgeEntrySummary {
pub id: String,
pub title: String,
pub category: String,
pub tags: Vec<String>,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct KnowledgeEntry {
pub id: String,
pub title: String,
pub category: String,
pub tags: Vec<String>,
pub content_json: String,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum Severity {
Error,
Warning,
Info,
Hint,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct Diagnostic {
pub severity: Severity,
pub code: String,
pub message: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub path: Option<String>,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct TargetSummary {
pub id: String,
pub display_name: String,
pub description: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub icon_path: Option<String>,
pub supports_rollback: bool,
}
#[derive(Debug, Clone)]
pub struct DeployRequest {
pub target_id: String,
pub artifact_bytes: Vec<u8>,
pub credentials_json: String,
pub config_json: String,
pub deployment_name: String,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "kebab-case")]
pub enum DeployStatus {
Pending,
Provisioning,
Configuring,
Starting,
Running,
Failed,
RolledBack,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct DeployJob {
pub id: String,
pub status: DeployStatus,
pub message: String,
pub endpoints: Vec<String>,
}
#[derive(Debug, Clone, thiserror::Error)]
pub enum DeployExtensionError {
#[error("invalid input: {0}")]
InvalidInput(String),
#[error("missing capability: {0}")]
MissingCapability(String),
#[error("permission denied: {0}")]
PermissionDenied(String),
#[error("not found: {0}")]
NotFound(String),
#[error("schema invalid: {0}")]
SchemaInvalid(String),
#[error("internal: {0}")]
Internal(String),
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct ValidateResult {
pub valid: bool,
pub diagnostics: Vec<Diagnostic>,
}
#[derive(Debug, Clone, Default)]
pub struct BundleSession {
pub flows_json: String,
pub contents_json: String,
pub assets: Vec<(String, Vec<u8>)>,
pub capabilities_used: Vec<String>,
}
#[derive(Debug, Clone)]
pub struct BundleArtifact {
pub filename: String,
pub bytes: Vec<u8>,
pub sha256: String,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "kebab-case")]
pub enum TargetKind {
AdaptiveCard,
SlackBlockKit,
TeamsCard,
PlainText,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct RoleSpec {
pub name: String,
pub description: String,
pub json_schema: String,
pub target: TargetKind,
pub schema_version: u32,
pub context_aware: bool,
}
#[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize)]
pub struct CompileContext {
pub flow_entries_json: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub flow_id: Option<String>,
pub locale: String,
}
#[derive(Debug, Clone, thiserror::Error, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "kebab-case", tag = "kind", content = "message")]
pub enum HostExtensionError {
#[error("invalid input: {0}")]
InvalidInput(String),
#[error("missing capability: {0}")]
MissingCapability(String),
#[error("permission denied: {0}")]
PermissionDenied(String),
#[error("not found: {0}")]
NotFound(String),
#[error("schema invalid: {0}")]
SchemaInvalid(String),
#[error("internal: {0}")]
Internal(String),
}
impl HostExtensionError {
#[must_use]
pub fn code(&self) -> &'static str {
match self {
Self::InvalidInput(_) => "invalid-input",
Self::MissingCapability(_) => "missing-capability",
Self::PermissionDenied(_) => "permission-denied",
Self::NotFound(_) => "not-found",
Self::SchemaInvalid(_) => "schema-invalid",
Self::Internal(_) => "internal",
}
}
}
#[derive(Debug, Clone, thiserror::Error)]
pub enum RoleError {
#[error("unknown role: {0}")]
UnknownRole(String),
#[error("invalid input: {0:?}")]
InvalidInput(Vec<Diagnostic>),
#[error("compile failed: {0}")]
CompileFailed(String),
#[error("target not supported: {0:?}")]
TargetNotSupported(TargetKind),
#[error("schema version not supported: {0}")]
VersionNotSupported(u32),
#[error("host: {0}")]
Host(#[from] HostExtensionError),
}
#[cfg(test)]
mod host_extension_error_tests {
#[test]
fn host_extension_error_codes_are_stable_kebab() {
use super::HostExtensionError as E;
let cases = [
(E::InvalidInput("x".into()), "invalid-input"),
(E::MissingCapability("x".into()), "missing-capability"),
(E::PermissionDenied("x".into()), "permission-denied"),
(E::NotFound("x".into()), "not-found"),
(E::SchemaInvalid("x".into()), "schema-invalid"),
(E::Internal("x".into()), "internal"),
];
for (e, code) in cases {
assert_eq!(e.code(), code);
}
}
}
#[cfg(test)]
mod target_summary_tests {
use super::*;
#[test]
fn target_summary_serializes_and_deserializes() {
let t = TargetSummary {
id: "aws-ecs-fargate-local".into(),
display_name: "AWS ECS Fargate (local creds)".into(),
description: "Deploy to AWS ECS Fargate using ambient credentials.".into(),
icon_path: Some("icons/aws.svg".into()),
supports_rollback: true,
};
let json = serde_json::to_string(&t).unwrap();
let back: TargetSummary = serde_json::from_str(&json).unwrap();
assert_eq!(back.id, t.id);
assert!(back.supports_rollback);
}
}