Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
- 新增 66 个 @reserved 标注 (已有 22 个) - 覆盖: agent/butler/classroom/hand/mcp/pipeline/skill/trigger/viking/zclaw 等模块 - MCP 命令增加 @connected 注释说明前端接入路径 - @reserved 总数: 89 (含 identity_init)
254 lines
7.8 KiB
Rust
254 lines
7.8 KiB
Rust
//! Trigger commands: CRUD + execute
|
|
//!
|
|
//! Triggers are registered in the Kernel's TriggerManager.
|
|
|
|
use serde::{Deserialize, Serialize};
|
|
use serde_json;
|
|
use tauri::State;
|
|
|
|
use super::{validate_id, KernelState};
|
|
|
|
// ============================================================
|
|
// Trigger Commands
|
|
// ============================================================
|
|
|
|
/// Trigger configuration for creation/update
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct TriggerConfigRequest {
|
|
pub id: String,
|
|
pub name: String,
|
|
pub hand_id: String,
|
|
pub trigger_type: TriggerTypeRequest,
|
|
#[serde(default = "default_trigger_enabled")]
|
|
pub enabled: bool,
|
|
#[serde(default)]
|
|
pub description: Option<String>,
|
|
#[serde(default)]
|
|
pub tags: Vec<String>,
|
|
}
|
|
|
|
fn default_trigger_enabled() -> bool { true }
|
|
|
|
/// Trigger type for API
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
#[serde(tag = "type", rename_all = "snake_case")]
|
|
pub enum TriggerTypeRequest {
|
|
Schedule { cron: String },
|
|
Event { pattern: String },
|
|
Webhook { path: String, secret: Option<String> },
|
|
MessagePattern { pattern: String },
|
|
FileSystem { path: String, events: Vec<String> },
|
|
Manual,
|
|
}
|
|
|
|
/// Trigger response
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct TriggerResponse {
|
|
pub id: String,
|
|
pub name: String,
|
|
pub hand_id: String,
|
|
pub trigger_type: TriggerTypeRequest,
|
|
pub enabled: bool,
|
|
pub created_at: String,
|
|
pub modified_at: String,
|
|
pub description: Option<String>,
|
|
pub tags: Vec<String>,
|
|
}
|
|
|
|
impl From<zclaw_kernel::trigger_manager::TriggerEntry> for TriggerResponse {
|
|
fn from(entry: zclaw_kernel::trigger_manager::TriggerEntry) -> Self {
|
|
let trigger_type = match entry.config.trigger_type {
|
|
zclaw_hands::TriggerType::Schedule { cron } => {
|
|
TriggerTypeRequest::Schedule { cron }
|
|
}
|
|
zclaw_hands::TriggerType::Event { pattern } => {
|
|
TriggerTypeRequest::Event { pattern }
|
|
}
|
|
zclaw_hands::TriggerType::Webhook { path, secret } => {
|
|
TriggerTypeRequest::Webhook { path, secret }
|
|
}
|
|
zclaw_hands::TriggerType::MessagePattern { pattern } => {
|
|
TriggerTypeRequest::MessagePattern { pattern }
|
|
}
|
|
zclaw_hands::TriggerType::FileSystem { path, events } => {
|
|
TriggerTypeRequest::FileSystem {
|
|
path,
|
|
events: events.iter().map(|e| format!("{:?}", e).to_lowercase()).collect(),
|
|
}
|
|
}
|
|
zclaw_hands::TriggerType::Manual => TriggerTypeRequest::Manual,
|
|
};
|
|
|
|
Self {
|
|
id: entry.config.id,
|
|
name: entry.config.name,
|
|
hand_id: entry.config.hand_id,
|
|
trigger_type,
|
|
enabled: entry.config.enabled,
|
|
created_at: entry.created_at.to_rfc3339(),
|
|
modified_at: entry.modified_at.to_rfc3339(),
|
|
description: entry.description,
|
|
tags: entry.tags,
|
|
}
|
|
}
|
|
}
|
|
|
|
/// List all triggers
|
|
// @reserved: trigger management
|
|
// @connected
|
|
#[tauri::command]
|
|
pub async fn trigger_list(
|
|
state: State<'_, KernelState>,
|
|
) -> Result<Vec<TriggerResponse>, String> {
|
|
let kernel_lock = state.lock().await;
|
|
let kernel = kernel_lock.as_ref()
|
|
.ok_or_else(|| "Kernel not initialized".to_string())?;
|
|
|
|
let triggers = kernel.list_triggers().await;
|
|
Ok(triggers.into_iter().map(TriggerResponse::from).collect())
|
|
}
|
|
|
|
/// Get a specific trigger
|
|
// @reserved: trigger management
|
|
// @connected
|
|
#[tauri::command]
|
|
pub async fn trigger_get(
|
|
state: State<'_, KernelState>,
|
|
id: String,
|
|
) -> Result<Option<TriggerResponse>, String> {
|
|
// Validate trigger ID
|
|
let id = validate_id(&id, "trigger_id")?;
|
|
|
|
let kernel_lock = state.lock().await;
|
|
let kernel = kernel_lock.as_ref()
|
|
.ok_or_else(|| "Kernel not initialized".to_string())?;
|
|
|
|
Ok(kernel.get_trigger(&id).await.map(TriggerResponse::from))
|
|
}
|
|
|
|
/// Create a new trigger
|
|
// @reserved: trigger management
|
|
// @connected
|
|
#[tauri::command]
|
|
pub async fn trigger_create(
|
|
state: State<'_, KernelState>,
|
|
request: TriggerConfigRequest,
|
|
) -> Result<TriggerResponse, String> {
|
|
let kernel_lock = state.lock().await;
|
|
let kernel = kernel_lock.as_ref()
|
|
.ok_or_else(|| "Kernel not initialized".to_string())?;
|
|
|
|
// Convert request to config
|
|
let trigger_type = match request.trigger_type {
|
|
TriggerTypeRequest::Schedule { cron } => {
|
|
zclaw_hands::TriggerType::Schedule { cron }
|
|
}
|
|
TriggerTypeRequest::Event { pattern } => {
|
|
zclaw_hands::TriggerType::Event { pattern }
|
|
}
|
|
TriggerTypeRequest::Webhook { path, secret } => {
|
|
zclaw_hands::TriggerType::Webhook { path, secret }
|
|
}
|
|
TriggerTypeRequest::MessagePattern { pattern } => {
|
|
zclaw_hands::TriggerType::MessagePattern { pattern }
|
|
}
|
|
TriggerTypeRequest::FileSystem { path, events } => {
|
|
zclaw_hands::TriggerType::FileSystem {
|
|
path,
|
|
events: events.iter().filter_map(|e| match e.as_str() {
|
|
"created" => Some(zclaw_hands::FileEvent::Created),
|
|
"modified" => Some(zclaw_hands::FileEvent::Modified),
|
|
"deleted" => Some(zclaw_hands::FileEvent::Deleted),
|
|
"any" => Some(zclaw_hands::FileEvent::Any),
|
|
_ => None,
|
|
}).collect(),
|
|
}
|
|
}
|
|
TriggerTypeRequest::Manual => zclaw_hands::TriggerType::Manual,
|
|
};
|
|
|
|
let config = zclaw_hands::TriggerConfig {
|
|
id: request.id,
|
|
name: request.name,
|
|
hand_id: request.hand_id,
|
|
trigger_type,
|
|
enabled: request.enabled,
|
|
max_executions_per_hour: 10,
|
|
};
|
|
|
|
let entry = kernel.create_trigger(config).await
|
|
.map_err(|e| format!("Failed to create trigger: {}", e))?;
|
|
|
|
Ok(TriggerResponse::from(entry))
|
|
}
|
|
|
|
/// Update a trigger
|
|
// @reserved: trigger management
|
|
// @connected
|
|
#[tauri::command]
|
|
pub async fn trigger_update(
|
|
state: State<'_, KernelState>,
|
|
id: String,
|
|
name: Option<String>,
|
|
enabled: Option<bool>,
|
|
hand_id: Option<String>,
|
|
) -> Result<TriggerResponse, String> {
|
|
let kernel_lock = state.lock().await;
|
|
let kernel = kernel_lock.as_ref()
|
|
.ok_or_else(|| "Kernel not initialized".to_string())?;
|
|
|
|
let update = zclaw_kernel::trigger_manager::TriggerUpdateRequest {
|
|
name,
|
|
enabled,
|
|
hand_id,
|
|
trigger_type: None,
|
|
};
|
|
|
|
let entry = kernel.update_trigger(&id, update).await
|
|
.map_err(|e| format!("Failed to update trigger: {}", e))?;
|
|
|
|
Ok(TriggerResponse::from(entry))
|
|
}
|
|
|
|
/// Delete a trigger
|
|
// @connected
|
|
#[tauri::command]
|
|
pub async fn trigger_delete(
|
|
state: State<'_, KernelState>,
|
|
id: String,
|
|
) -> Result<(), String> {
|
|
// Validate trigger ID
|
|
let id = validate_id(&id, "trigger_id")?;
|
|
|
|
let kernel_lock = state.lock().await;
|
|
let kernel = kernel_lock.as_ref()
|
|
.ok_or_else(|| "Kernel not initialized".to_string())?;
|
|
|
|
kernel.delete_trigger(&id).await
|
|
.map_err(|e| format!("Failed to delete trigger: {}", e))
|
|
}
|
|
|
|
/// Execute a trigger manually
|
|
// @reserved: trigger management
|
|
// @connected
|
|
#[tauri::command]
|
|
pub async fn trigger_execute(
|
|
state: State<'_, KernelState>,
|
|
id: String,
|
|
input: serde_json::Value,
|
|
) -> Result<serde_json::Value, String> {
|
|
// Validate trigger ID
|
|
let id = validate_id(&id, "trigger_id")?;
|
|
|
|
let kernel_lock = state.lock().await;
|
|
let kernel = kernel_lock.as_ref()
|
|
.ok_or_else(|| "Kernel not initialized".to_string())?;
|
|
|
|
let result = kernel.execute_trigger(&id, input).await
|
|
.map_err(|e| format!("Failed to execute trigger: {}", e))?;
|
|
|
|
Ok(serde_json::to_value(result).unwrap_or(serde_json::json!({})))
|
|
}
|