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
接通"写了没接"的定时功能断链: - NlScheduleParser has_schedule_intent/parse_nl_schedule 接入 agent_chat_stream - 新增 _reminder 系统 Hand 作为定时触发器桥接 - TriggerManager hand_id 验证对 _ 前缀系统 Hand 放行 - 聊天消息含定时意图时自动拦截,创建触发器并返回确认消息 验证:cargo check 0 error, 49 tests passed, Tauri MCP "每天早上9点提醒我查房" → cron 0 9 * * * 确认正确显示
78 lines
2.2 KiB
Rust
78 lines
2.2 KiB
Rust
//! Reminder Hand - Internal hand for scheduled reminders
|
|
//!
|
|
//! This is a system hand (id `_reminder`) used by the schedule interception
|
|
//! layer in `agent_chat_stream`. When the NlScheduleParser detects a schedule
|
|
//! intent in chat, it creates a trigger targeting this hand. The SchedulerService
|
|
//! fires the trigger at the scheduled time.
|
|
|
|
use async_trait::async_trait;
|
|
use serde_json::Value;
|
|
use zclaw_types::Result;
|
|
|
|
use crate::{Hand, HandConfig, HandContext, HandResult, HandStatus};
|
|
|
|
/// Internal reminder hand for scheduled tasks
|
|
pub struct ReminderHand {
|
|
config: HandConfig,
|
|
}
|
|
|
|
impl ReminderHand {
|
|
/// Create a new reminder hand
|
|
pub fn new() -> Self {
|
|
Self {
|
|
config: HandConfig {
|
|
id: "_reminder".to_string(),
|
|
name: "定时提醒".to_string(),
|
|
description: "Internal hand for scheduled reminders".to_string(),
|
|
needs_approval: false,
|
|
dependencies: vec![],
|
|
input_schema: None,
|
|
tags: vec!["system".to_string()],
|
|
enabled: true,
|
|
max_concurrent: 0,
|
|
timeout_secs: 0,
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
#[async_trait]
|
|
impl Hand for ReminderHand {
|
|
fn config(&self) -> &HandConfig {
|
|
&self.config
|
|
}
|
|
|
|
async fn execute(&self, _context: &HandContext, input: Value) -> Result<HandResult> {
|
|
let task_desc = input
|
|
.get("task_description")
|
|
.and_then(|v| v.as_str())
|
|
.unwrap_or("定时提醒");
|
|
|
|
let cron = input
|
|
.get("cron")
|
|
.and_then(|v| v.as_str())
|
|
.unwrap_or("");
|
|
|
|
let fired_at = input
|
|
.get("fired_at")
|
|
.and_then(|v| v.as_str())
|
|
.unwrap_or("unknown time");
|
|
|
|
tracing::info!(
|
|
"[ReminderHand] Fired at {} — task: {}, cron: {}",
|
|
fired_at, task_desc, cron
|
|
);
|
|
|
|
Ok(HandResult::success(serde_json::json!({
|
|
"task": task_desc,
|
|
"cron": cron,
|
|
"fired_at": fired_at,
|
|
"status": "reminded",
|
|
})))
|
|
}
|
|
|
|
fn status(&self) -> HandStatus {
|
|
HandStatus::Idle
|
|
}
|
|
}
|