fix(memory): 把插件的 NoMemory 声明落到事件上

声明链此前断在最后一步:
  InjectOptions.NoMemory / ChannelDef.NoMemory
    → payload["no_memory"] → stageCtx.NoMemory   ✅ 已合成
    → ContextEvent.NoMemory                      ❌ 从未赋值

后果:QQ 那句取件样板("来自「X」的私聊消息(message_id=…) 先用
qq_get_message 取正文…")每轮都进计算层(向量化/关键词/蒸馏),
而它是指令不是内容 —— 真实对话内容在记忆里被它挤薄。

按字段**既有契约**处置(context.go 的注释写明):只影响计算层,
归档照常。理由是同一条注释里的 2026-10-22 教训 —— coldcontext_query
的 Consume 已从 L2 删除原文,回填事件必须能落回 L2,否则三层全无。

判据:nomemory_flag_test.go
(NoMemory 事件 textForVector 为空但 Input/Response 保留;普通事件不受影响)
This commit is contained in:
JianFeeeee
2026-10-27 15:40:43 +08:00
parent 14daf5b584
commit 20cf138d3b
3 changed files with 83 additions and 0 deletions

View File

@ -410,6 +410,15 @@ func (c *RelevanceContext) Save() error {
// (另一处 InsertByTimestamp 同样处理)。所以明文拦截放在这里,
// 而不是在每个调用点 —— 逐个补必漏(实测踩到:只拦了 f.Msgs,
// 而 f.CleanInput / f.ToolResults / f.Response 都是独立副本)。
// snapshotEvents 返回当前事件的浅拷贝(判据/诊断用;调用方不得修改元素)。
func (c *RelevanceContext) snapshotEvents() []*ContextEvent {
c.mu.Lock()
defer c.mu.Unlock()
out := make([]*ContextEvent, len(c.events))
copy(out, c.events)
return out
}
func (c *RelevanceContext) Append(evt ContextEvent) {
c.mu.Lock()
defer c.mu.Unlock()