feat(phase4): complete zclaw-skills, zclaw-hands, zclaw-channels, zclaw-protocols 模块实现
This commit is contained in:
156
crates/zclaw-hands/src/hand.rs
Normal file
156
crates/zclaw-hands/src/hand.rs
Normal file
@@ -0,0 +1,156 @@
|
||||
//! Hand definition and types
|
||||
|
||||
use async_trait::async_trait;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value;
|
||||
use zclaw_types::{Result, AgentId};
|
||||
|
||||
/// Hand configuration
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct HandConfig {
|
||||
/// Unique hand identifier
|
||||
pub id: String,
|
||||
/// Human-readable name
|
||||
pub name: String,
|
||||
/// Hand description
|
||||
pub description: String,
|
||||
/// Whether this hand needs approval before execution
|
||||
#[serde(default)]
|
||||
pub needs_approval: bool,
|
||||
/// Required dependencies
|
||||
#[serde(default)]
|
||||
pub dependencies: Vec<String>,
|
||||
/// Input schema
|
||||
#[serde(default)]
|
||||
pub input_schema: Option<Value>,
|
||||
/// Tags for categorization
|
||||
#[serde(default)]
|
||||
pub tags: Vec<String>,
|
||||
/// Whether the hand is enabled
|
||||
#[serde(default = "default_enabled")]
|
||||
pub enabled: bool,
|
||||
}
|
||||
|
||||
fn default_enabled() -> bool { true }
|
||||
|
||||
/// Hand execution context
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct HandContext {
|
||||
/// Agent ID executing the hand
|
||||
pub agent_id: AgentId,
|
||||
/// Working directory
|
||||
pub working_dir: Option<std::path::PathBuf>,
|
||||
/// Environment variables
|
||||
pub env: std::collections::HashMap<String, String>,
|
||||
/// Timeout in seconds
|
||||
pub timeout_secs: u64,
|
||||
/// Callback URL for async results
|
||||
pub callback_url: Option<String>,
|
||||
}
|
||||
|
||||
impl Default for HandContext {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
agent_id: AgentId::new(),
|
||||
working_dir: None,
|
||||
env: std::collections::HashMap::new(),
|
||||
timeout_secs: 300,
|
||||
callback_url: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Hand execution result
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct HandResult {
|
||||
/// 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>,
|
||||
/// Status message
|
||||
#[serde(default)]
|
||||
pub status: String,
|
||||
}
|
||||
|
||||
impl HandResult {
|
||||
pub fn success(output: Value) -> Self {
|
||||
Self {
|
||||
success: true,
|
||||
output,
|
||||
error: None,
|
||||
duration_ms: None,
|
||||
status: "completed".to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn error(message: impl Into<String>) -> Self {
|
||||
Self {
|
||||
success: false,
|
||||
output: Value::Null,
|
||||
error: Some(message.into()),
|
||||
duration_ms: None,
|
||||
status: "failed".to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pending(status: impl Into<String>) -> Self {
|
||||
Self {
|
||||
success: true,
|
||||
output: Value::Null,
|
||||
error: None,
|
||||
duration_ms: None,
|
||||
status: status.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Hand execution status
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum HandStatus {
|
||||
Idle,
|
||||
Running,
|
||||
PendingApproval,
|
||||
Completed,
|
||||
Failed,
|
||||
}
|
||||
|
||||
/// Hand trait - autonomous capability
|
||||
#[async_trait]
|
||||
pub trait Hand: Send + Sync {
|
||||
/// Get the hand configuration
|
||||
fn config(&self) -> &HandConfig;
|
||||
|
||||
/// Execute the hand
|
||||
async fn execute(&self, context: &HandContext, input: Value) -> Result<HandResult>;
|
||||
|
||||
/// Check if the hand needs approval
|
||||
fn needs_approval(&self) -> bool {
|
||||
self.config().needs_approval
|
||||
}
|
||||
|
||||
/// Check dependencies
|
||||
fn check_dependencies(&self) -> Result<Vec<String>> {
|
||||
let missing: Vec<String> = self.config().dependencies.iter()
|
||||
.filter(|dep| !self.is_dependency_available(dep))
|
||||
.cloned()
|
||||
.collect();
|
||||
Ok(missing)
|
||||
}
|
||||
|
||||
/// Check if a specific dependency is available
|
||||
fn is_dependency_available(&self, _dep: &str) -> bool {
|
||||
true // Default implementation
|
||||
}
|
||||
|
||||
/// Get current status
|
||||
fn status(&self) -> HandStatus {
|
||||
HandStatus::Idle
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user