//! 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` 而是 `Arc`:支持多 session 共享 use std::sync::Arc; use std::time::Duration; use crate::agent::summary::SummaryConfig; use crate::llm::LlmProvider; use crate::llm::compact::CompactConfig; 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, /// 上下文压缩配置(None 表示不启用自动压缩),默认 None。 pub compact_config: Option, /// 摘要自动生成配置(`None` = 不启用)。 /// 设置后 `AgentSession` 每轮 OnTurnEnd 之后进行水位 + 防抖检查,触发时调 LLM /// 生成摘要并写入 `FocusedConfig.summary_override` 与 `SessionMemory["conversation_summary"]`。 pub summary_config: Option, } impl Default for AgentConfig { fn default() -> Self { Self { max_turns: 50, max_tool_turns: 10, session_ttl: None, compact_config: None, summary_config: None, } } } /// Agent Runtime 依赖注入容器。 /// /// 通过 `AgentBuilder::build()` 构造;构造完成后内部为只读视图。 /// `Arc` 共享,多个 `AgentSession` 可共用同一个 bundle。 #[derive(Clone)] pub struct RuntimeBundle { /// LLM 后端(强引用,多 session 共享)。 pub provider: Arc, /// 工具注册表(强引用,多 session 共享)。 pub tool_registry: Arc, /// 钩子执行器(强引用,多 session 共享)。 pub hook_executor: Arc, /// 持久化记忆后端(弱引用 —— 不传也能跑)。 pub memory_store: Option>, /// 记忆检索器(弱引用 —— 不传也能跑)。 /// 传入时可在 `submit_turn` 内部将检索能力作为工具暴露给 LLM。 pub retriever: Option>, /// SessionMemory 后端(选填)。 /// 传入时 `SessionMemory` 使用该后端(支持跨进程共享); /// 不传时 `AgentSession` 内部自动创建 `InMemoryStore` 作为进程级隔离的后端。 pub session_memory_backend: Option>, /// 运行时配置。 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", &"") .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( "has_session_memory_backend", &self.session_memory_backend.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, tool_registry: Arc, hook_executor: Arc, memory_store: Option>, retriever: Option>, session_memory_backend: Option>, config: AgentConfig, ) -> Self { Self { provider, tool_registry, hook_executor, memory_store, retriever, session_memory_backend, config, } } }