package main import ( "fmt" "git.yeij.top/AskaEth/Cyrene_v2/internal/logger" "git.yeij.top/AskaEth/Cyrene_v2/internal/runtime/memory" ) // 本文件把记忆整理(DevDocs/design/23-记忆整理与去重 §4)接进组合根。 // // 三件事只在这里定: // - **形态**:低峰定期后台任务(memory.TidyService 的心跳),不是会话内派 // subagent。它在 main.go 与 backthink 并列启动、在 close 里先于关库停止; // - **依赖面**:只给它记忆存储与 embedder —— 服务侧拿不到任何会话/历史读数, // 因此 design §4.1「绝不碰主会话上下文」是结构性成立的,而不是靠自觉; // - **审计**:接到网关的 AuditEvent(design §8 的 memory.tidy.*),出口在调用 // 时才解析 a.gw —— 网关比本服务晚组装(wireFrontend),与 onToolAudit // 同一手法。未就绪时只记日志,绝不假装写过审计。 // // 刻意**不做**的两件事(design §4.1 F、§3 非目标): // - 不把 sess-memorytidy 加进 flowPub 的图源白名单(默认关:整理是系统任务, // 不是主人的会话); // - 不给它任何写记忆的路径(第一版只产候选,"立即整理"入口是 // TidyService.RunOnce)。 func (a *app) wireMemoryTidy() error { svc, err := memory.NewTidyService(memory.TidyConfigFromConfig(a.cfg.MemoryTidy), memory.TidyDeps{ Store: a.memStore, Embedder: a.embedder, Audit: a.auditMemoryTidy, Log: logger.WithSource(a.log, "memory/tidy"), }) if err != nil { return fmt.Errorf("memory tidy: %w", err) } a.memoryTidy = svc return nil } // auditMemoryTidy 把一轮整理的计数写进网关审计链。它**只带计数**,绝不带 // 任何记忆正文(design §8 的 who/what/when/result 口径)。 func (a *app) auditMemoryTidy(who, what, result string) { if a.gw != nil { a.gw.AuditEvent(who, what, result) return } logger.WithSource(a.log, "memory/tidy").Info( "memory tidy audit dropped: gateway not ready", "who", who, "what", what, "result", result) }