use std::fmt;
use thiserror::Error;
#[derive(Error, Debug, Clone)]
pub enum SkillError {
#[error("Skill validation failed: {0}")]
Validation(String),
#[error("Skill execution failed: {0}")]
Execution(String),
#[error("IO error: {0}")]
Io(String),
#[error("Serialization error: {0}")]
Serialization(String),
#[error("Skill not found: {0}")]
NotFound(String),
#[error("Skill already exists: {0}")]
AlreadyExists(String),
#[error("Invalid skill metadata: {0}")]
InvalidMetadata(String),
#[error("Skill version conflict: {0}")]
VersionConflict(String),
#[error("Configuration error: {0}")]
Configuration(String),
}
pub type Result<T> = std::result::Result<T, SkillError>;
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct SkillOutput {
pub success: bool,
pub data: serde_json::Value,
#[serde(skip_serializing_if = "Option::is_none")]
pub error: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata: Option<serde_json::Value>,
}
impl SkillOutput {
pub fn ok(data: impl Into<serde_json::Value>) -> Self {
SkillOutput {
success: true,
data: data.into(),
error: None,
metadata: None,
}
}
pub fn err(error: impl Into<String>) -> Self {
SkillOutput {
success: false,
data: serde_json::Value::Null,
error: Some(error.into()),
metadata: None,
}
}
pub fn with_metadata(mut self, metadata: serde_json::Value) -> Self {
self.metadata = Some(metadata);
self
}
}
impl fmt::Display for SkillOutput {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.success {
write!(f, "Success: {}", self.data)
} else {
write!(
f,
"Error: {}",
self.error.as_deref().unwrap_or("Unknown error")
)
}
}
}
pub type SkillResult = Result<SkillOutput>;