feat(phase4): complete zclaw-skills, zclaw-hands, zclaw-channels, zclaw-protocols 模块实现
This commit is contained in:
147
crates/zclaw-skills/src/skill.rs
Normal file
147
crates/zclaw-skills/src/skill.rs
Normal file
@@ -0,0 +1,147 @@
|
||||
//! Skill definition and types
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value;
|
||||
use zclaw_types::{SkillId, Result};
|
||||
|
||||
/// Skill manifest definition
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct SkillManifest {
|
||||
/// Unique skill identifier
|
||||
pub id: SkillId,
|
||||
/// Human-readable name
|
||||
pub name: String,
|
||||
/// Skill description
|
||||
pub description: String,
|
||||
/// Skill version
|
||||
pub version: String,
|
||||
/// Skill author
|
||||
#[serde(default)]
|
||||
pub author: Option<String>,
|
||||
/// Execution mode
|
||||
pub mode: SkillMode,
|
||||
/// Required capabilities
|
||||
#[serde(default)]
|
||||
pub capabilities: Vec<String>,
|
||||
/// Input schema (JSON Schema)
|
||||
#[serde(default)]
|
||||
pub input_schema: Option<Value>,
|
||||
/// Output schema (JSON Schema)
|
||||
#[serde(default)]
|
||||
pub output_schema: Option<Value>,
|
||||
/// Tags for categorization
|
||||
#[serde(default)]
|
||||
pub tags: Vec<String>,
|
||||
/// Whether the skill is enabled
|
||||
#[serde(default = "default_enabled")]
|
||||
pub enabled: bool,
|
||||
}
|
||||
|
||||
fn default_enabled() -> bool { true }
|
||||
|
||||
/// Skill execution mode
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum SkillMode {
|
||||
/// Prompt-only skill (no code execution)
|
||||
PromptOnly,
|
||||
/// Python script execution
|
||||
Python,
|
||||
/// Shell command execution
|
||||
Shell,
|
||||
/// WebAssembly execution
|
||||
Wasm,
|
||||
/// Native Rust execution
|
||||
Native,
|
||||
}
|
||||
|
||||
/// Skill execution context
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct SkillContext {
|
||||
/// Agent ID executing the skill
|
||||
pub agent_id: String,
|
||||
/// Session ID for the execution
|
||||
pub session_id: String,
|
||||
/// Working directory for execution
|
||||
pub working_dir: Option<std::path::PathBuf>,
|
||||
/// Environment variables
|
||||
pub env: std::collections::HashMap<String, String>,
|
||||
/// Timeout in seconds
|
||||
pub timeout_secs: u64,
|
||||
/// Whether to allow network access
|
||||
pub network_allowed: bool,
|
||||
/// Whether to allow file system access
|
||||
pub file_access_allowed: bool,
|
||||
}
|
||||
|
||||
impl Default for SkillContext {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
agent_id: String::new(),
|
||||
session_id: String::new(),
|
||||
working_dir: None,
|
||||
env: std::collections::HashMap::new(),
|
||||
timeout_secs: 60,
|
||||
network_allowed: false,
|
||||
file_access_allowed: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Skill execution result
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct SkillResult {
|
||||
/// Whether execution succeeded
|
||||
pub success: bool,
|
||||
/// Output data
|
||||
pub output: Value,
|
||||
/// Error message if failed
|
||||
#[serde(default)]
|
||||
pub error: Option<String>,
|
||||
/// Execution duration in milliseconds
|
||||
#[serde(default)]
|
||||
pub duration_ms: Option<u64>,
|
||||
/// Token usage if LLM was #[serde(default)]
|
||||
pub tokens_used: Option<u32>,
|
||||
}
|
||||
|
||||
impl SkillResult {
|
||||
pub fn success(output: Value) -> Self {
|
||||
Self {
|
||||
success: true,
|
||||
output,
|
||||
error: None,
|
||||
duration_ms: None,
|
||||
tokens_used: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn error(message: impl Into<String>) -> Self {
|
||||
Self {
|
||||
success: false,
|
||||
output: Value::Null,
|
||||
error: Some(message.into()),
|
||||
duration_ms: None,
|
||||
tokens_used: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Skill definition with execution logic
|
||||
#[async_trait::async_trait]
|
||||
pub trait Skill: Send + Sync {
|
||||
/// Get the skill manifest
|
||||
fn manifest(&self) -> &SkillManifest;
|
||||
|
||||
/// Execute the skill with given input
|
||||
async fn execute(&self, context: &SkillContext, input: Value) -> Result<SkillResult>;
|
||||
|
||||
/// Validate input against schema
|
||||
fn validate_input(&self, input: &Value) -> Result<()> {
|
||||
// Basic validation - can be overridden
|
||||
if input.is_null() {
|
||||
return Err(zclaw_types::ZclawError::InvalidInput("Input cannot be null".into()));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user