feat: DeerFlow 2.0 core capabilities — Phase 1.0 + 1.1
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
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
Phase 1.0 — Butler Mode UI: - Hide "自动化" and "技能市场" entries from sidebar navigation - Remove AutomationPanel and SkillMarket view rendering from App.tsx - Simplify MainViewType to only 'chat' - Main interface is now: chat + conversation list + detail panel only Phase 1.1 — Mode Differentiation: - Add subagent_enabled field to ChatModeConfig (Rust), StreamChatRequest (Tauri), gateway-client, kernel-client, saas-relay-client, and streamStore - TaskTool is now only registered when subagent_enabled=true (Ultra mode) - System prompt includes sub-agent delegation instructions only in Ultra mode - Frontend transmits subagent_enabled from ChatMode config through the full stack This connects the 4-tier mode selector (Flash/Thinking/Pro/Ultra) to actual backend behavioral differences — Ultra mode now truly enables sub-agent delegation.
This commit is contained in:
@@ -4,12 +4,13 @@ use tokio::sync::mpsc;
|
||||
use zclaw_types::{AgentId, Result};
|
||||
|
||||
/// Chat mode configuration passed from the frontend.
|
||||
/// Controls thinking, reasoning, and plan mode behavior.
|
||||
/// Controls thinking, reasoning, plan mode, and sub-agent behavior.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ChatModeConfig {
|
||||
pub thinking_enabled: Option<bool>,
|
||||
pub reasoning_effort: Option<String>,
|
||||
pub plan_mode: Option<bool>,
|
||||
pub subagent_enabled: Option<bool>,
|
||||
}
|
||||
|
||||
use zclaw_runtime::{AgentLoop, tool::builtin::PathValidator};
|
||||
@@ -45,7 +46,8 @@ impl Kernel {
|
||||
let model = self.config.model().to_string();
|
||||
|
||||
// Create agent loop with model configuration
|
||||
let tools = self.create_tool_registry();
|
||||
let subagent_enabled = chat_mode.as_ref().and_then(|m| m.subagent_enabled).unwrap_or(false);
|
||||
let tools = self.create_tool_registry(subagent_enabled);
|
||||
let mut loop_runner = AgentLoop::new(
|
||||
*agent_id,
|
||||
self.driver.clone(),
|
||||
@@ -92,7 +94,10 @@ impl Kernel {
|
||||
}
|
||||
|
||||
// Build system prompt with skill information injected
|
||||
let system_prompt = self.build_system_prompt_with_skills(agent_config.system_prompt.as_ref()).await;
|
||||
let system_prompt = self.build_system_prompt_with_skills(
|
||||
agent_config.system_prompt.as_ref(),
|
||||
subagent_enabled,
|
||||
).await;
|
||||
let loop_runner = loop_runner.with_system_prompt(&system_prompt);
|
||||
|
||||
// Run the loop
|
||||
@@ -147,7 +152,8 @@ impl Kernel {
|
||||
let model = self.config.model().to_string();
|
||||
|
||||
// Create agent loop with model configuration
|
||||
let tools = self.create_tool_registry();
|
||||
let subagent_enabled = chat_mode.as_ref().and_then(|m| m.subagent_enabled).unwrap_or(false);
|
||||
let tools = self.create_tool_registry(subagent_enabled);
|
||||
let mut loop_runner = AgentLoop::new(
|
||||
*agent_id,
|
||||
self.driver.clone(),
|
||||
@@ -197,7 +203,10 @@ impl Kernel {
|
||||
// Use external prompt if provided, otherwise build default
|
||||
let system_prompt = match system_prompt_override {
|
||||
Some(prompt) => prompt,
|
||||
None => self.build_system_prompt_with_skills(agent_config.system_prompt.as_ref()).await,
|
||||
None => self.build_system_prompt_with_skills(
|
||||
agent_config.system_prompt.as_ref(),
|
||||
subagent_enabled,
|
||||
).await,
|
||||
};
|
||||
let loop_runner = loop_runner.with_system_prompt(&system_prompt);
|
||||
|
||||
@@ -206,8 +215,13 @@ impl Kernel {
|
||||
loop_runner.run_streaming(session_id, message).await
|
||||
}
|
||||
|
||||
/// Build a system prompt with skill information injected
|
||||
pub(super) async fn build_system_prompt_with_skills(&self, base_prompt: Option<&String>) -> String {
|
||||
/// Build a system prompt with skill information injected.
|
||||
/// When `subagent_enabled` is true, adds sub-agent delegation instructions.
|
||||
pub(super) async fn build_system_prompt_with_skills(
|
||||
&self,
|
||||
base_prompt: Option<&String>,
|
||||
subagent_enabled: bool,
|
||||
) -> String {
|
||||
// Get skill list asynchronously
|
||||
let skills = self.skills.list().await;
|
||||
|
||||
@@ -215,7 +229,8 @@ impl Kernel {
|
||||
.map(|p| p.clone())
|
||||
.unwrap_or_else(|| "You are a helpful AI assistant.".to_string());
|
||||
|
||||
// Inject skill information with categories
|
||||
// Inject skill metadata only (progressive loading pattern from DeerFlow).
|
||||
// Full skill content is loaded on-demand via `load_skill_content` tool.
|
||||
if !skills.is_empty() {
|
||||
prompt.push_str("\n\n## Available Skills\n\n");
|
||||
prompt.push_str("You have access to specialized skills. Analyze user intent and autonomously call `execute_skill` with the appropriate skill_id.\n\n");
|
||||
@@ -245,6 +260,21 @@ impl Kernel {
|
||||
prompt.push_str("User: \"分析腾讯财报\" → Intent: Financial analysis → Call: execute_skill(\"finance-tracker\", {...})\n");
|
||||
}
|
||||
|
||||
// Sub-agent delegation instructions (Ultra mode only)
|
||||
if subagent_enabled {
|
||||
prompt.push_str("\n\n## Sub-Agent Delegation\n\n");
|
||||
prompt.push_str("You can delegate complex sub-tasks to sub-agents using the `task` tool. This enables parallel execution of independent work.\n\n");
|
||||
prompt.push_str("### When to use sub-agents:\n");
|
||||
prompt.push_str("- Complex tasks that can be decomposed into independent parallel sub-tasks\n");
|
||||
prompt.push_str("- Research tasks requiring multiple independent searches\n");
|
||||
prompt.push_str("- Tasks requiring different expertise areas simultaneously\n\n");
|
||||
prompt.push_str("### Guidelines:\n");
|
||||
prompt.push_str("- Break complex work into clear, self-contained sub-tasks\n");
|
||||
prompt.push_str("- Each sub-task should have a clear objective and expected output\n");
|
||||
prompt.push_str("- Synthesize sub-agent results into a coherent final response\n");
|
||||
prompt.push_str("- Maximum 3 concurrent sub-agents — batch if more are needed\n");
|
||||
}
|
||||
|
||||
prompt
|
||||
}
|
||||
|
||||
|
||||
@@ -162,18 +162,22 @@ impl Kernel {
|
||||
})
|
||||
}
|
||||
|
||||
/// Create a tool registry with built-in tools
|
||||
pub(crate) fn create_tool_registry(&self) -> ToolRegistry {
|
||||
/// Create a tool registry with built-in tools.
|
||||
/// When `subagent_enabled` is false, TaskTool is excluded to prevent
|
||||
/// the LLM from attempting sub-agent delegation in non-Ultra modes.
|
||||
pub(crate) fn create_tool_registry(&self, subagent_enabled: bool) -> ToolRegistry {
|
||||
let mut tools = ToolRegistry::new();
|
||||
zclaw_runtime::tool::builtin::register_builtin_tools(&mut tools);
|
||||
|
||||
// Register TaskTool with driver and memory for sub-agent delegation
|
||||
let task_tool = zclaw_runtime::tool::builtin::TaskTool::new(
|
||||
self.driver.clone(),
|
||||
self.memory.clone(),
|
||||
self.config.model(),
|
||||
);
|
||||
tools.register(Box::new(task_tool));
|
||||
// Register TaskTool only when sub-agent mode is enabled (Ultra mode)
|
||||
if subagent_enabled {
|
||||
let task_tool = zclaw_runtime::tool::builtin::TaskTool::new(
|
||||
self.driver.clone(),
|
||||
self.memory.clone(),
|
||||
self.config.model(),
|
||||
);
|
||||
tools.register(Box::new(task_tool));
|
||||
}
|
||||
|
||||
tools
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user