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,120 @@
use std::fmt::Write;
use crate::driver::ToolDefinition;
/// Runtime context that determines which prompt sections are included.
pub struct PromptContext {
/// Base system prompt from AgentConfig
pub base_prompt: Option<String>,
/// Custom agent personality (SOUL.md equivalent)
pub soul: Option<String>,
/// Whether thinking/extended reasoning is enabled
pub thinking_enabled: bool,
/// Whether plan mode is active
pub plan_mode: bool,
/// Tool definitions available for dynamic injection
pub tool_definitions: Vec<ToolDefinition>,
/// Agent name for personalization
pub agent_name: Option<String>,
}
/// A single section in the assembled prompt.
pub struct PromptSection {
pub name: &'static str,
pub template: String,
pub priority: u32,
}
/// Builds structured system prompts from conditional sections.
pub struct PromptBuilder {
sections: Vec<PromptSection>,
}
impl PromptBuilder {
pub fn new() -> Self {
Self {
sections: Vec::new(),
}
}
/// Add a section unconditionally.
pub fn add_section(
mut self,
name: &'static str,
template: impl Into<String>,
priority: u32,
) -> Self {
self.sections.push(PromptSection {
name,
template: template.into(),
priority,
});
self
}
/// Assemble the final system prompt based on runtime context.
pub fn build(&self, ctx: &PromptContext) -> String {
let mut sections: Vec<&PromptSection> = self.sections.iter().collect();
sections.sort_by_key(|s| s.priority);
let mut result = String::with_capacity(4096);
// Base prompt (always included)
if let Some(ref base) = ctx.base_prompt {
result.push_str(base);
} else {
result.push_str("You are a helpful AI assistant.");
}
// Soul/personality section
if let Some(ref soul) = ctx.soul {
result.push_str("\n\n## Agent Personality\n\n");
result.push_str(soul);
}
// Agent name personalization
if let Some(ref name) = ctx.agent_name {
let _ = write!(result, "\n\nYou are known as \"{name}\". Respond in character.");
}
// Dynamic tool descriptions
if !ctx.tool_definitions.is_empty() {
result.push_str("\n\n## Available Tools\n\n");
for tool in &ctx.tool_definitions {
let _ = writeln!(result, "- **{}**: {}", tool.name, tool.description);
}
}
// Thinking style guidance
if ctx.thinking_enabled {
result.push_str("\n\n## Reasoning Mode\n\n");
result.push_str(
"Extended reasoning is enabled. Think step-by-step before responding. \
Show your reasoning process, then provide the final answer.",
);
}
// Plan mode instructions
if ctx.plan_mode {
result.push_str("\n\n## Plan Mode\n\n");
result.push_str(
"You are in plan mode. Before executing any actions, create a detailed plan. \
Present the plan to the user for approval before proceeding.",
);
}
// Additional registered sections
for section in sections {
result.push_str("\n\n");
result.push_str(&section.template);
}
result
}
}
impl Default for PromptBuilder {
fn default() -> Self {
Self::new()
}
}

View File

@@ -0,0 +1,9 @@
//! Dynamic prompt assembly module.
//!
//! Inspired by DeerFlow's conditional section-based prompt composition.
//! The `PromptBuilder` assembles a structured system prompt from multiple
//! conditional sections before the middleware chain further modifies it.
mod builder;
pub use builder::{PromptBuilder, PromptContext, PromptSection};