test(kernel,growth): Phase 1 缝测试安全网 — 3条核心链路 19 测试全部通过
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

对话链路: 4 缝测试 (Tauri→Kernel / Kernel→LLM / LLM→UI / 流式生命周期)
Hands链路: 3 缝测试 (工具路由 / 执行回调 / 通用工具)
记忆链路: 3 缝测试 (FTS5存储 / 模式检索 / 去重)
冒烟测试: 3 Rust + 8 TypeScript 全量 PASS
- Kernel::boot_with_driver() 测试辅助方法
- 全量 cargo test 0 回归

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
iven
2026-04-21 21:36:46 +08:00
parent 317b8254e4
commit 591af5802c
8 changed files with 907 additions and 0 deletions

View File

@@ -178,6 +178,84 @@ impl Kernel {
})
}
/// Boot the kernel with a pre-configured driver (for testing).
///
/// Skips `config.create_driver()` and uses the provided driver directly.
/// Uses an in-memory SQLite database to avoid filesystem side effects.
pub async fn boot_with_driver(
config: KernelConfig,
driver: Arc<dyn LlmDriver>,
) -> Result<Self> {
let memory = Arc::new(MemoryStore::new("sqlite::memory:").await?);
let registry = AgentRegistry::new();
let capabilities = CapabilityManager::new();
let events = EventBus::new();
let skills = Arc::new(SkillRegistry::new());
if let Some(ref skills_dir) = config.skills_dir {
if skills_dir.exists() {
skills.add_skill_dir(skills_dir.clone()).await?;
}
}
let hands = Arc::new(HandRegistry::new());
let quiz_model = config.model().to_string();
let quiz_generator = Arc::new(LlmQuizGenerator::new(driver.clone(), quiz_model));
hands.register(Arc::new(BrowserHand::new())).await;
hands.register(Arc::new(QuizHand::with_generator(quiz_generator))).await;
hands.register(Arc::new(ResearcherHand::new())).await;
hands.register(Arc::new(CollectorHand::new())).await;
hands.register(Arc::new(ClipHand::new())).await;
hands.register(Arc::new(TwitterHand::new())).await;
hands.register(Arc::new(ReminderHand::new())).await;
hands.register(Arc::new(DailyReportHand::new())).await;
let hand_configs = hands.list().await;
let skill_executor = Arc::new(KernelSkillExecutor::new(skills.clone(), driver.clone()));
let hand_executor = Arc::new(KernelHandExecutor::new(hands.clone()));
let llm_completer: Arc<dyn zclaw_skills::LlmCompleter> =
Arc::new(adapters::LlmDriverAdapter {
driver: driver.clone(),
max_tokens: config.max_tokens(),
temperature: config.temperature(),
});
let trigger_manager = crate::trigger_manager::TriggerManager::new(hands.clone());
let viking = Arc::new(zclaw_runtime::VikingAdapter::in_memory());
let a2a_router = {
let kernel_agent_id = AgentId::new();
Arc::new(A2aRouter::new(kernel_agent_id))
};
Ok(Self {
config,
registry,
capabilities,
events,
memory,
driver,
llm_completer,
skills,
skill_executor,
hand_executor,
hands,
hand_configs,
trigger_manager,
pending_approvals: Arc::new(Mutex::new(Vec::new())),
running_hand_runs: Arc::new(dashmap::DashMap::new()),
viking,
growth: std::sync::Mutex::new(None),
extraction_driver: None,
embedding_client: None,
mcp_adapters: Arc::new(std::sync::RwLock::new(Vec::new())),
industry_keywords: Arc::new(tokio::sync::RwLock::new(Vec::new())),
a2a_router,
a2a_inboxes: Arc::new(dashmap::DashMap::new()),
})
}
/// Create a tool registry with built-in tools + Hand tools + MCP tools.
/// When `subagent_enabled` is false, TaskTool is excluded to prevent
/// the LLM from attempting sub-agent delegation in non-Ultra modes.