feat(agent): 实现 ContextSlot fork/merge
- 新增 MergeStrategy 枚举(#[non_exhaustive],为 Phase 16 Summarize 预留) - 新增 ContextSlot::fork() 从父 slot 派生独立子 slot(Full / Focused 策略) - 新增 ContextSlot::merge() 将子 slot 消息合入父 slot(Append / Replace 策略) - 防御性检查:禁止 self-merge、跨 session merge、合并到 Readonly slot - 重构 AgentSession::derive_slot 复用 fork() 消除重复代码 - 新增 9 个内联测试覆盖 fork/merge happy path 与 error path - agent.rs 追加 MergeStrategy re-export(agcore::agent::MergeStrategy 路径可用)
This commit is contained in:
+7
-33
@@ -16,8 +16,11 @@ use futures_core::Stream;
|
||||
|
||||
use crate::agent::agent::Agent;
|
||||
use crate::agent::context::{
|
||||
ContextSlot, DeriveStrategy, SlotConfig, SlotMode, SlotSource,
|
||||
ContextSlot, DeriveStrategy, SlotConfig, SlotMode,
|
||||
};
|
||||
// SlotSource 仅在 `mod tests` 中使用(通过 `use super::*;` 引入),lib 主体保留以避免测试 import 变更。
|
||||
#[allow(unused_imports)]
|
||||
use crate::agent::context::SlotSource;
|
||||
use crate::agent::error::AgentError;
|
||||
use crate::agent::runtime::RuntimeBundle;
|
||||
use crate::agent::session_memory::SessionMemory;
|
||||
@@ -224,38 +227,9 @@ impl AgentSession {
|
||||
.slots
|
||||
.get(parent_id)
|
||||
.ok_or_else(|| AgentError::SlotNotFound(parent_id.to_string()))?;
|
||||
|
||||
let parent_messages = parent.messages.clone();
|
||||
let (messages, focused_cfg) = match &strategy {
|
||||
DeriveStrategy::Full => (parent_messages, None),
|
||||
DeriveStrategy::Focused(cfg) => {
|
||||
let filtered = ContextSlot::filter_focused(&parent_messages, cfg);
|
||||
(filtered, Some(cfg.clone()))
|
||||
}
|
||||
};
|
||||
|
||||
let mode = match focused_cfg {
|
||||
Some(cfg) => SlotMode::Focused(cfg),
|
||||
None => SlotMode::Full,
|
||||
};
|
||||
|
||||
let slot = ContextSlot::new(
|
||||
&self.session_id,
|
||||
&slot_id,
|
||||
SlotConfig {
|
||||
mode,
|
||||
source: SlotSource::Derived {
|
||||
parent_id: parent_id.to_string(),
|
||||
strategy,
|
||||
},
|
||||
budget: Default::default(),
|
||||
compact: true,
|
||||
},
|
||||
);
|
||||
let mut slot = slot;
|
||||
slot.messages = messages;
|
||||
slot.save(&*self.resolve_store()).await?;
|
||||
self.slots.insert(slot_id, slot);
|
||||
let child = parent.fork(slot_id.clone(), strategy);
|
||||
child.save(&*self.resolve_store()).await?;
|
||||
self.slots.insert(slot_id, child);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user