feat(agent): 实现 Agent Runtime 核心胶水层 (Phase 4a)
- 添加 Agent trait、AgentSession、RuntimeBundle、AgentBuilder - 添加 Plan/Step/StepStatus 任务规划数据结构 - 添加 AgentError 统一错误类型(聚合 LlmError/ToolError/MemoryError) - 实现 submit_turn 单轮对话流程(含 hook 触发与 cost 累计) - 扩展 LlmCycle 支持 Arc<dyn LlmProvider> - 扩展 HookEvent 添加 OnTurnStart/OnTurnEnd - 更新 roadmap 状态
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
//! Runtime Bundle —— 显式依赖注入容器(OpenHarness 风格)。
|
||||
//!
|
||||
//! 集中持有 Agent 运行所需的全部运行时依赖:`LlmProvider` / `ToolRegistry` / `HookExecutor` /
|
||||
//! `MemoryStore`(弱引用)/ `MemoryRetriever`(弱引用) / `AgentConfig`。
|
||||
//!
|
||||
//! **设计意图**(参见 `docs/7-agent-runtime.md` §3.2.2):
|
||||
//!
|
||||
//! - 所有运行时依赖显式打包,便于跨 `AgentSession` 共享、便于测试注入 mock
|
||||
//! - `memory_store` / `retriever` 为 `Option`:上层应用不传也能跑(无记忆模式)
|
||||
//! - 构造时若 `retriever` 为 `Some`,自动注册 `"retrieve"` tool(v0.1 占位——
|
||||
//! Phase 4a 不在 `submit_turn` 中真正调用;Phase 4a 任务范围仅"装配可注册",
|
||||
//! 真正的 `RetrieveTool` 实现留待 v0.2 接入)
|
||||
//! - 不持有 `Box<dyn LlmProvider>` 而是 `Arc<dyn LlmProvider>`:支持多 session 共享
|
||||
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
use crate::llm::compact::CompactConfig;
|
||||
use crate::llm::provider::LlmProvider;
|
||||
use crate::llm::hooks::HookExecutor;
|
||||
use crate::memory::retriever::MemoryRetriever;
|
||||
use crate::memory::store::MemoryStore;
|
||||
use crate::tools::ToolRegistry;
|
||||
|
||||
/// Agent 运行配置。
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct AgentConfig {
|
||||
/// 单次会话最大 turn 数(含工具循环内部 turn),默认 50。
|
||||
pub max_turns: u32,
|
||||
/// 单次会话最大工具循环轮次(与 LlmCycle 的 `max_tool_turns` 对齐),默认 10。
|
||||
pub max_tool_turns: u32,
|
||||
/// 会话 TTL(None 表示无过期),默认 None。
|
||||
pub session_ttl: Option<Duration>,
|
||||
/// 上下文压缩配置(None 表示不启用自动压缩),默认 None。
|
||||
pub compact_config: Option<CompactConfig>,
|
||||
}
|
||||
|
||||
impl Default for AgentConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
max_turns: 50,
|
||||
max_tool_turns: 10,
|
||||
session_ttl: None,
|
||||
compact_config: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Agent Runtime 依赖注入容器。
|
||||
///
|
||||
/// 通过 `AgentBuilder::build()` 构造;构造完成后内部为只读视图。
|
||||
/// `Arc` 共享,多个 `AgentSession` 可共用同一个 bundle。
|
||||
#[derive(Clone)]
|
||||
pub struct RuntimeBundle {
|
||||
/// LLM 后端(强引用,多 session 共享)。
|
||||
pub provider: Arc<dyn LlmProvider>,
|
||||
|
||||
/// 工具注册表(强引用,多 session 共享)。
|
||||
pub tool_registry: Arc<ToolRegistry>,
|
||||
|
||||
/// 钩子执行器(强引用,多 session 共享)。
|
||||
pub hook_executor: Arc<HookExecutor>,
|
||||
|
||||
/// 持久化记忆后端(弱引用 —— 不传也能跑)。
|
||||
pub memory_store: Option<Arc<dyn MemoryStore>>,
|
||||
|
||||
/// 记忆检索器(弱引用 —— 不传也能跑)。
|
||||
/// 传入时可在 `submit_turn` 内部将检索能力作为工具暴露给 LLM。
|
||||
pub retriever: Option<Arc<MemoryRetriever>>,
|
||||
|
||||
/// 运行时配置。
|
||||
pub config: AgentConfig,
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for RuntimeBundle {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("RuntimeBundle")
|
||||
.field("provider_type", &"<dyn LlmProvider>")
|
||||
.field("tool_names", &self.tool_registry.list_tools())
|
||||
.field("has_memory_store", &self.memory_store.is_some())
|
||||
.field("has_retriever", &self.retriever.is_some())
|
||||
.field("config", &self.config)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl RuntimeBundle {
|
||||
/// 构造一个 `RuntimeBundle`。
|
||||
///
|
||||
/// **Phase 4a 行为**:`retriever` 存在时仅占位记录,不真正注入工具
|
||||
/// (v0.1 不在 `submit_turn` 中启用检索;Phase 4c 之后再决定是否注册成 tool)。
|
||||
/// 真正的工具注入留待 v0.2 接入 `RetrieveTool` 实现。
|
||||
pub fn new(
|
||||
provider: Arc<dyn LlmProvider>,
|
||||
tool_registry: Arc<ToolRegistry>,
|
||||
hook_executor: Arc<HookExecutor>,
|
||||
memory_store: Option<Arc<dyn MemoryStore>>,
|
||||
retriever: Option<Arc<MemoryRetriever>>,
|
||||
config: AgentConfig,
|
||||
) -> Self {
|
||||
Self {
|
||||
provider,
|
||||
tool_registry,
|
||||
hook_executor,
|
||||
memory_store,
|
||||
retriever,
|
||||
config,
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user