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:
@@ -60,34 +60,39 @@ impl AgentMiddleware for MemoryMiddleware {
|
||||
fn priority(&self) -> i32 { 150 }
|
||||
|
||||
async fn before_completion(&self, ctx: &mut MiddlewareContext) -> Result<MiddlewareDecision> {
|
||||
// Skip memory injection for very short queries.
|
||||
// Short queries (e.g., "1+6", "hi", "好") don't benefit from memory context.
|
||||
// Worse, the retriever's scope-based fallback may return high-importance but
|
||||
// irrelevant old memories, causing the model to think about past conversations
|
||||
// instead of answering the current question.
|
||||
// Use char count (not byte count) so CJK queries are handled correctly:
|
||||
// a single Chinese char is 3 UTF-8 bytes but 1 meaningful character.
|
||||
let query = ctx.user_input.trim();
|
||||
if query.chars().count() < 2 {
|
||||
tracing::debug!(
|
||||
"[MemoryMiddleware] Skipping enhancement for short query ({:?}): no memory context needed",
|
||||
query
|
||||
);
|
||||
return Ok(MiddlewareDecision::Continue);
|
||||
}
|
||||
tracing::debug!(
|
||||
"[MemoryMiddleware] before_completion for query: {:?}",
|
||||
ctx.user_input.chars().take(50).collect::<String>()
|
||||
);
|
||||
|
||||
match self.growth.enhance_prompt(
|
||||
&ctx.agent_id,
|
||||
&ctx.system_prompt,
|
||||
&ctx.user_input,
|
||||
).await {
|
||||
// Retrieve relevant memories and inject into system prompt.
|
||||
// The SqliteStorage retriever now uses FTS5-only matching — if FTS5 finds
|
||||
// no relevant results, no memories are returned (no scope-based fallback).
|
||||
// This prevents irrelevant high-importance memories from leaking into
|
||||
// unrelated conversations.
|
||||
let base = &ctx.system_prompt;
|
||||
match self.growth.enhance_prompt(&ctx.agent_id, base, &ctx.user_input).await {
|
||||
Ok(enhanced) => {
|
||||
ctx.system_prompt = enhanced;
|
||||
if enhanced != *base {
|
||||
tracing::info!(
|
||||
"[MemoryMiddleware] Injected memories into system prompt for agent {}",
|
||||
ctx.agent_id
|
||||
);
|
||||
ctx.system_prompt = enhanced;
|
||||
} else {
|
||||
tracing::debug!(
|
||||
"[MemoryMiddleware] No relevant memories found for query: {:?}",
|
||||
ctx.user_input.chars().take(50).collect::<String>()
|
||||
);
|
||||
}
|
||||
Ok(MiddlewareDecision::Continue)
|
||||
}
|
||||
Err(e) => {
|
||||
// Non-fatal: memory retrieval failure should not block the loop
|
||||
tracing::warn!("[MemoryMiddleware] Prompt enhancement failed: {}", e);
|
||||
// Non-fatal: retrieval failure should not block the conversation
|
||||
tracing::warn!(
|
||||
"[MemoryMiddleware] Memory retrieval failed (non-fatal): {}",
|
||||
e
|
||||
);
|
||||
Ok(MiddlewareDecision::Continue)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user