refactor(crates): kernel/generation module split + DeerFlow optimizations + middleware + dead code cleanup

- Split zclaw-kernel/kernel.rs (1486 lines) into 9 domain modules
- Split zclaw-kernel/generation.rs (1080 lines) into 3 modules
- Add DeerFlow-inspired middleware: DanglingTool, SubagentLimit, ToolError, ToolOutputGuard
- Add PromptBuilder for structured system prompt assembly
- Add FactStore (zclaw-memory) for persistent fact extraction
- Add task builtin tool for agent task management
- Driver improvements: Anthropic/OpenAI extended thinking, Gemini safety settings
- Replace let _ = with proper log::warn! across SaaS handlers
- Remove unused dependency (url) from zclaw-hands
This commit is contained in:
iven
2026-04-03 00:28:03 +08:00
parent 0a04b260a4
commit 52bdafa633
55 changed files with 4130 additions and 1959 deletions

View File

@@ -0,0 +1,209 @@
//! Hand execution and run tracking
use std::sync::Arc;
use zclaw_types::{Result, HandRun, HandRunId, HandRunStatus, HandRunFilter, TriggerSource};
use zclaw_hands::{HandContext, HandResult};
use super::Kernel;
impl Kernel {
/// Get the hands registry
pub fn hands(&self) -> &Arc<zclaw_hands::HandRegistry> {
&self.hands
}
/// List all registered hands
pub async fn list_hands(&self) -> Vec<zclaw_hands::HandConfig> {
self.hands.list().await
}
/// Execute a hand with the given input, tracking the run
pub async fn execute_hand(
&self,
hand_id: &str,
input: serde_json::Value,
) -> Result<(HandResult, HandRunId)> {
let run_id = HandRunId::new();
let now = chrono::Utc::now().to_rfc3339();
// Create the initial HandRun record
let mut run = HandRun {
id: run_id,
hand_name: hand_id.to_string(),
trigger_source: TriggerSource::Manual,
params: input.clone(),
status: HandRunStatus::Pending,
result: None,
error: None,
duration_ms: None,
created_at: now.clone(),
started_at: None,
completed_at: None,
};
self.memory.save_hand_run(&run).await?;
// Transition to Running
run.status = HandRunStatus::Running;
run.started_at = Some(chrono::Utc::now().to_rfc3339());
self.memory.update_hand_run(&run).await?;
// Register cancellation flag
let cancel_flag = Arc::new(std::sync::atomic::AtomicBool::new(false));
self.running_hand_runs.insert(run_id, cancel_flag.clone());
// Execute the hand
let context = HandContext::default();
let start = std::time::Instant::now();
let hand_result = self.hands.execute(hand_id, &context, input).await;
let duration = start.elapsed();
// Check if cancelled during execution
if cancel_flag.load(std::sync::atomic::Ordering::Relaxed) {
let mut run_update = run.clone();
run_update.status = HandRunStatus::Cancelled;
run_update.completed_at = Some(chrono::Utc::now().to_rfc3339());
run_update.duration_ms = Some(duration.as_millis() as u64);
self.memory.update_hand_run(&run_update).await?;
self.running_hand_runs.remove(&run_id);
return Err(zclaw_types::ZclawError::Internal("Hand execution cancelled".to_string()));
}
// Remove from running map
self.running_hand_runs.remove(&run_id);
// Update HandRun with result
let completed_at = chrono::Utc::now().to_rfc3339();
match &hand_result {
Ok(res) => {
run.status = HandRunStatus::Completed;
run.result = Some(res.output.clone());
run.error = res.error.clone();
}
Err(e) => {
run.status = HandRunStatus::Failed;
run.error = Some(e.to_string());
}
}
run.duration_ms = Some(duration.as_millis() as u64);
run.completed_at = Some(completed_at);
self.memory.update_hand_run(&run).await?;
hand_result.map(|res| (res, run_id))
}
/// Execute a hand with a specific trigger source (for scheduled/event triggers)
pub async fn execute_hand_with_source(
&self,
hand_id: &str,
input: serde_json::Value,
trigger_source: TriggerSource,
) -> Result<(HandResult, HandRunId)> {
let run_id = HandRunId::new();
let now = chrono::Utc::now().to_rfc3339();
let mut run = HandRun {
id: run_id,
hand_name: hand_id.to_string(),
trigger_source,
params: input.clone(),
status: HandRunStatus::Pending,
result: None,
error: None,
duration_ms: None,
created_at: now,
started_at: None,
completed_at: None,
};
self.memory.save_hand_run(&run).await?;
run.status = HandRunStatus::Running;
run.started_at = Some(chrono::Utc::now().to_rfc3339());
self.memory.update_hand_run(&run).await?;
let cancel_flag = Arc::new(std::sync::atomic::AtomicBool::new(false));
self.running_hand_runs.insert(run_id, cancel_flag.clone());
let context = HandContext::default();
let start = std::time::Instant::now();
let hand_result = self.hands.execute(hand_id, &context, input).await;
let duration = start.elapsed();
// Check if cancelled during execution
if cancel_flag.load(std::sync::atomic::Ordering::Relaxed) {
run.status = HandRunStatus::Cancelled;
run.completed_at = Some(chrono::Utc::now().to_rfc3339());
run.duration_ms = Some(duration.as_millis() as u64);
self.memory.update_hand_run(&run).await?;
self.running_hand_runs.remove(&run_id);
return Err(zclaw_types::ZclawError::Internal("Hand execution cancelled".to_string()));
}
self.running_hand_runs.remove(&run_id);
let completed_at = chrono::Utc::now().to_rfc3339();
match &hand_result {
Ok(res) => {
run.status = HandRunStatus::Completed;
run.result = Some(res.output.clone());
run.error = res.error.clone();
}
Err(e) => {
run.status = HandRunStatus::Failed;
run.error = Some(e.to_string());
}
}
run.duration_ms = Some(duration.as_millis() as u64);
run.completed_at = Some(completed_at);
self.memory.update_hand_run(&run).await?;
hand_result.map(|res| (res, run_id))
}
// ============================================================
// Hand Run Tracking
// ============================================================
/// Get a hand run by ID
pub async fn get_hand_run(&self, id: &HandRunId) -> Result<Option<HandRun>> {
self.memory.get_hand_run(id).await
}
/// List hand runs with filter
pub async fn list_hand_runs(&self, filter: &HandRunFilter) -> Result<Vec<HandRun>> {
self.memory.list_hand_runs(filter).await
}
/// Count hand runs matching filter
pub async fn count_hand_runs(&self, filter: &HandRunFilter) -> Result<u32> {
self.memory.count_hand_runs(filter).await
}
/// Cancel a running hand execution
pub async fn cancel_hand_run(&self, id: &HandRunId) -> Result<()> {
if let Some((_, flag)) = self.running_hand_runs.remove(id) {
flag.store(true, std::sync::atomic::Ordering::Relaxed);
// Note: the actual status update happens in execute_hand_with_source
// when it detects the cancel flag
Ok(())
} else {
// Not currently running — check if exists at all
let run = self.memory.get_hand_run(id).await?;
match run {
Some(r) if r.status == HandRunStatus::Pending => {
let mut updated = r;
updated.status = HandRunStatus::Cancelled;
updated.completed_at = Some(chrono::Utc::now().to_rfc3339());
self.memory.update_hand_run(&updated).await?;
Ok(())
}
Some(r) => Err(zclaw_types::ZclawError::InvalidInput(
format!("Cannot cancel hand run {} with status {}", id, r.status)
)),
None => Err(zclaw_types::ZclawError::NotFound(
format!("Hand run {} not found", id)
)),
}
}
}
}