ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

cc-haha 内存系统内部机制全解:从系统提示注入到后台自动提取的完整技术剖析

cc-haha 内存系统内部机制全解:从系统提示注入到后台自动提取的完整技术剖析 人工智能AI 应用桌面应用代码智能体MCP Clients【免费下载链接】cc-hahaLocal-first cross-platform desktop workspace for Claude Code / agents: multi-agent, Git worktrees, code diffs, skill marketplace, multi-model, Computer Use, task-aware desktop pets, with WeChat, Feishu, DingTalk, Telegram, WhatsApp and H5 access.项目地址https://gitcode.com/gh_mirrors/cl/cc-haha点击查看免费下载本指南以 cc-haha 仓库Local-first 桌面工作区面向 Claude Code / 多 Agent 场景中的记忆Memory子系统为对象逐层拆解其五大核心模块与若干辅助模块的实现细节路径解析、系统提示注入、自动记忆提取、智能检索与团队记忆同步。读者读完本文后将掌握内存目录的优先级解析与安全校验规则、MEMORY.md 索引的双重截断策略、基于 forked agent 的后台提取机制、Sonnet 相关性选择器的提示词设计以及 TEAMMEM 团队同步的增量上传语义可直接据此调试、扩展或在自己的 Agent 产品中复刻同类设计。总体架构内存系统由 5 个核心模块协同工作源码集中在src/memdir/与src/services/extractMemories/两个目录模块源码位置职责路径解析Path Resolutionsrc/memdir/paths.ts计算记忆存储目录处理覆盖override与安全校验提示构建Prompt Constructionsrc/memdir/memdir.ts将记忆指令注入系统提示记忆扫描Memory Scanningsrc/memdir/memoryScan.ts扫描目录、解析 frontmatter、对条目排序智能检索Intelligent Retrievalsrc/memdir/findRelevantMemories.ts使用 Sonnet 挑选与当前查询相关的记忆自动提取Auto-Extractionsrc/services/extractMemories/后台 forked agent 从对话中提取记忆辅助模块模块源码位置职责AutoDreamsrc/services/autoDream/后台记忆整合梦境详见 AutoDream 文档类型定义src/memdir/memoryTypes.ts四种记忆类型的分类学与提示模板新鲜度Freshnesssrc/memdir/memoryAge.ts计算记忆年龄生成过期警告文件检测src/utils/memoryFileDetection.ts判断某路径是否属于记忆系统Agent 记忆src/tools/AgentTool/agentMemory.ts子代理专属的三级记忆目录团队同步src/services/teamMemorySync/记忆的远端上传/下载路径解析系统核心函数getAutoMemPath()记忆目录的解析优先级从高到低1. CLAUDE_COWORK_MEMORY_PATH_OVERRIDE - Cowork 环境变量完整路径 2. settings.json - autoMemoryDirectory - 用户设置支持 ~/ 展开 3. {memoryBase}/projects/{sanitized-git-root}/memory/ - 默认计算路径关键源码 src/memdir/paths.ts#L223-L235export const getAutoMemPath memoize( (): string { const override getAutoMemPathOverride() ?? getAutoMemPathSetting() if (override) { return override } const projectsDir join(getMemoryBaseDir(), projects) return ( join(projectsDir, sanitizePath(getAutoMemBase()), AUTO_MEM_DIRNAME) sep ).normalize(NFC) }, () getProjectRoot(), // 缓存键 项目根目录 )实现细节值得注意memoize 以项目根目录为缓存键getAutoMemPath被渲染路径的调用方如collapseReadSearchGroups → isAutoManagedMemoryFile在每个 tool-use 消息的每次 Messages 重渲染时触发每次 miss 都会引发getSettingsForSource × 4 → parseSettingsFilerealpathSync readFileSync因此必须缓存。以项目根为键既保证了测试中 mock 变更能重新计算又利用了生产环境下 env / settings / config 目录的会话稳定性src/memdir/paths.ts#L216-L222。默认路径基于规范化 Git 根而非当前目录getAutoMemBase()使用findCanonicalGitRoot(getProjectRoot())同一仓库的所有 worktree 共享同一个自动记忆目录避免一个仓库多个 worktree 各建一份记忆src/memdir/paths.ts#L203-L205。~展开仅对 settings.json 生效环境变量覆盖路径由 Cowork/SDK 程序化设置恒为绝对路径不做展开同时~、~/、~/.、~/..这类平凡剩余会被显式拒绝——它们会展开到$HOME或其父目录与/、C:\属于同一类危险src/memdir/paths.ts#L116-L135。路径安全校验validateMemoryPath()会拒绝以下危险路径src/memdir/paths.ts#L109-L150被拒绝的路径原因../foo相对路径依赖 CWD/或/a根路径或过短路径C:\Windows 盘符根\\server\shareUNC 网络路径含\0空字节可在系统调用中被截断返回的路径保证恰好一个尾随分隔符normalized sep并做NFC规范化。安全限制项目级.claude/settings.json不允许设置autoMemoryDirectory。原因在源码注释中讲得很清楚恶意仓库可以设置autoMemoryDirectory: ~/.ssh从而借助 filesystem 写入 carve-out当isAutoMemPath()命中且hasAutoMemPathOverride()为 false 时触发静默获得对敏感目录的写权限src/memdir/paths.ts#L168-L178。这与hasSkipDangerousModePermissionPrompt()等采用同一防护模式。settings.json 覆盖路径只从policySettings、flagSettings、localSettings、userSettings四个受信来源读取。启用条件isAutoMemoryEnabled()的检查链src/memdir/paths.ts#L30-L55CLAUDE_CODE_DISABLE_AUTO_MEMORY1 - 禁用1/true 关闭0/false 显式开启 CLAUDE_CODE_SIMPLE (--bare) - 禁用 远程模式且未设 REMOTE_MEMORY_DIR - 禁用 settings.json autoMemoryEnabled - 遵循设置支持项目级 opt-out 默认 - 启用其中--bare分支值得注意注释指出 prompts.ts 已通过 SIMPLE 早退在系统提示中删除了记忆段这里的开关是为了同时关停另一半功能——turn-end 提取 fork、autoDream、/remember、/dream、团队同步src/memdir/paths.ts#L38-L42。系统提示注入入口loadMemoryPrompt()这是内存系统与系统提示之间的接口启动时调用一次通过systemPromptSection缓存。分发逻辑src/memdir/memdir.ts#L419-L506loadMemoryPrompt() |-- KAIROS 模式? - buildAssistantDailyLogPrompt() [日志追加模式] |-- TEAMMEM 开启? - buildCombinedMemoryPrompt() [个人 团队双目录] |-- 正常模式 - buildMemoryLines() [单一目录] |-- 禁用 - 返回 null并上报 tengu_memdir_disabled 遥测两个模式的细节KAIROS助手日常日志模式助手会话近似永久模型不再维护 MEMORY.md 实时索引而是以追加方式写入按日期命名的日志文件autoMemPath/logs/YYYY/MM/YYYY-MM-DD.md提示词用YYYY/MM模式串描述路径而非内联当天字面路径——因为该提示被systemPromptSection(memory, ...)缓存且不会因日期变更而失效模型靠尾部 date_change 附件推导当前日期以在跨午夜时保留提示缓存前缀src/memdir/memdir.ts#L327-L370、src/memdir/paths.ts#L246-L251。TEAMMEM 模式团队记忆必须是自动记忆的子目录getTeamMemPath()定义为join(getAutoMemPath(), team)因此不存在仅团队分支递归 mkdir 团队目录时会把自动目录一并创建出来src/memdir/memdir.ts#L448-L473。buildMemoryLines()构建的提示结构# auto memory You have a persistent file-based memory system located at {memoryDir}... ## Types of memory - 四种类型的定义与示例 ## What NOT to save - 排除规则 ## How to save memories - 两步保存流程 ## When to access memories - 何时查阅 ## Before recommending - 引用前先验证 ## Memory and other forms - 与 Plan/Task 的区分 ## MEMORY.md - 索引内容或 currently empty提示中所有引导文本都来自 src/memdir/memoryTypes.ts 的具名导出。有几处设计直接反映了评测eval驱动的迭代结果Before recommending from memory 标题优于 Trusting what you recall源码注释记录了 H1 实验——在决策点给出动作提示的标题3/3 通过胜过抽象标题0/3正文完全相同只有标题不同src/memdir/memoryTypes.ts#L240-L256。记忆漂移警告MEMORY_DRIFT_CAVEAT要求模型把记忆当作某个时间点的观察回答前先读当前文件/资源验证记忆与现状冲突时信任现状并更新或删除过期记忆src/memdir/memoryTypes.ts#L201-L202。忽略记忆指令的显式处理当用户说ignore或not use记忆时模型应视 MEMORY.md 为空不得引用、对比或提及记忆内容——这是针对把 ignore 理解为 acknowledge-then-override这一失败模式的显式反模式说明src/memdir/memoryTypes.ts#L216-L222。What NOT to save 的显式保存门即使用户明确要求保存排除规则依然生效若用户要求保存 PR 列表/活动摘要应追问其中令人惊讶或非常规的部分src/memdir/memoryTypes.ts#L183-L195。四种记忆类型的 frontmatter 模板MEMORY_FRONTMATTER_EXAMPLEsrc/memdir/memoryTypes.ts#L261-L271--- name: {{memory name}} description: {{one-line description — 用于判断未来对话中的相关性请具体}} type: {{user, feedback, project, reference}} --- {{memory content — feedback/project 类型建议按规则/事实然后 **Why:** 和 **How to apply:** 行组织}}MEMORY.md 截断策略truncateEntrypointContent()施加双重限制src/memdir/memdir.ts#L57-L103// 先按行数截断 if (lineCount 200) - 截断到 200 行 // 再按字节数截断兜住超长行 if (bytes 25,000) - 在最后一个换行符处截断 // 追加警告 WARNING: MEMORY.md is {reason}. Only part of it was loaded.MAX_ENTRYPOINT_LINES 200MAX_ENTRYPOINT_BYTES 25_000约 200 行 × 125 字符/行的 p97 分位p100 实测出现过 200 行以内达到 197KB 的极端情况因此字节上限针对的是行数上限漏网的长行索引。字节截断发生在最后一个换行符处避免从行中间切断。警告文本区分触发原因仅超字节时给出格式化大小对比index entries are too long并建议索引条目控制在 ~200 字符以内的一行、把细节挪进主题文件。目录自动创建ensureMemoryDirExists()在加载提示时保证目录存在src/memdir/memdir.ts#L129-L147使用FsOperations.mkdir递归创建一条调用搞定整条父链~/.claude/projects/slug/memory/内部吞掉EEXIST天然幂等真正的权限错误EACCES/EPERM/EROFS只记录到 debug 日志、不抛出——提示构建照常继续真实错误由后续 Write 工具浮现FileWriteTool 会自行 mkdir 父目录。配合DIR_EXISTS_GUIDANCE常量This directory already exists — write to it directly with the Write tool (do not run mkdir or check for its existence)提示明确告诉模型目录已存在避免模型浪费回合执行ls或mkdirsrc/memdir/memdir.ts#L116-L119。自动记忆提取触发时机当模型产出最终响应无工具调用时在handleStopHooks中触发。关键源码src/services/extractMemories/extractMemories.ts。触发入口executeExtractMemories()通过extractor由initExtractMemories()创建的闭包执行fire-and-forget 调用与 prompt suggestion/coaching 并列于 stop hookssrc/services/extractMemories/extractMemories.ts#L598-L603。状态全部闭包作用域化lastMemoryMessageUuid游标、inProgress、turnsSinceLastExtraction、pendingContext测试在beforeEach中调用initExtractMemories()获取全新闭包src/services/extractMemories/extractMemories.ts#L296-L326。完整提取流程1. 模型完成响应无 tool_use | 2. 调用 executeExtractMemories() | 3. 守卫检查 - 是主代理吗子代理不提取context.toolUseContext.agentId 存在则直接返回 - 特性门控开启tengu_passport_quail - 自动记忆开启isAutoMemoryEnabled - 非远程模式getIsRemoteMode - 无并行提取进行中 | 4. 频率控制 turnsSinceLastExtraction if tengu_bramble_lintel - 跳过默认 1即每轮都允许 | 5. 互斥检查 主代理自己写入了记忆- 跳过推进游标 | 6. 扫描现有记忆目录scanMemoryFiles 生成清单formatMemoryManifest | 7. 构建提取提示buildExtractAutoOnlyPrompt / buildExtractCombinedPrompt | 8. 运行 forked agentrunForkedAgent - 共享父会话的提示缓存 - 最多 5 轮 - 受限工具权限 | 9. 提取已写入的文件路径 推进游标到最后一条消息 | 10. 通知用户Memory updated in ...几个实现要点扫描放在频率闸门之后被跳过的轮次不必支付scanMemoryFiles的开销src/services/extractMemories/extractMemories.ts#L395-L400。游标仅在成功运行后推进如果 forked agent 出错游标原地不动这些消息会在下次提取中被重新考虑src/services/extractMemories/extractMemories.ts#L428-L435。提取完成度可预期注释指出行为良好的提取通常 2–4 轮完成读→写5 轮硬上限防止验证兔子洞烧掉 tokensrc/services/extractMemories/extractMemories.ts#L424-L426。drainPendingExtraction()print.ts 在响应刷出后、gracefulShutdownSync之前调用带 60 秒软超时等待在途提取含 trailing 合并运行完成避免 5 秒关闭保险丝把 forked agent 杀掉src/services/extractMemories/extractMemories.ts#L579-L614。Forked Agent自动提取使用runForkedAgent——主会话的完美分叉共享提示缓存createCacheSafeParams(context)复用父会话的缓存参数避免重复的 API 缓存创建成本fork 的工具列表必须与主会话一致否则破坏提示缓存共享工具是缓存键的一部分REPL 工具因此被显式放行src/services/extractMemories/extractMemories.ts#L171-L182。隔离执行不影响主会话的消息历史。受限工具仅允许 Read、Grep、Glob、只读 Bash 以及记忆目录内的 Edit/Write。不记录转录skipTranscript: true——避免与主线程产生竞态src/services/extractMemories/extractMemories.ts#L420-L423。工具权限createAutoMemCanUseTool允许Read、Grep、Glob无限制 允许Bash仅只读命令ls、find、grep、cat、stat、wc、head、tail 等 允许Edit/Write仅限自动记忆目录内路径 拒绝MCP、Agent、非只读 Bash、其他写操作实现上是返回一个CanUseToolFnBash 必须通过BashTool.isReadOnly对解析后的输入做校验否则给出明确拒绝理由Edit/Write 必须带file_path且通过isAutoMemPath()检查路径经normalize防..穿越。该函数同时被 extractMemories 与 autoDream 共享src/services/extractMemories/extractMemories.ts#L171-L222。互斥机制主代理与提取代理互斥src/services/extractMemories/extractMemories.ts#L121-L148function hasMemoryWritesSince(messages, sinceUuid): boolean { // 扫描 sinceUuid 之后的所有 assistant 消息 // 若任何 Edit/Write tool_use 指向自动记忆目录 // - 返回 true跳过提取推进游标 }这防止重复保存主代理已写入记忆时后台提取被跳过并把游标推进到最后一条消息使下次提取只考虑主代理写入之后的新增内容。主代理提示中携带完整保存指令因此这种冗余提取本就不必要。合并机制若上一次提取仍在运行新上下文被暂存pendingContext后到者覆盖先到者——只有最新消息最多的一次有意义旧提取完成后立即启动一次尾随提取tail extraction尾随提取只处理两次调用之间新增的消息——它以刚推进过的游标为基准计算newMessageCountsrc/services/extractMemories/extractMemories.ts#L506-L522。智能记忆检索工作方式每次用户发送查询时触发findRelevantMemories()src/memdir/findRelevantMemories.ts1. scanMemoryFiles(memoryDir) - 递归读取所有 .md 文件排除 MEMORY.md - 解析 frontmatter前 30 行 - 按修改时间降序排序 - 最多 200 个文件 | 2. 过滤先前已展示过的记忆alreadySurfaced | 3. 格式化清单formatMemoryManifest - [type] filename (ISO timestamp): description | 4. Sonnet 模型选择sideQuery - 系统提示You are a memory selector... - 用户消息Query Available memories Recently used tools - 输出JSON { selected_memories: string[] } - 最多 5 个选择 | 5. 返回选中的记忆作为 { path, mtimeMs }设计细节alreadySurfaced过滤在 Sonnet 调用之前让选择器把 5 个名额花在新鲜候选项上而不是反复挑选调用方即将丢弃的旧文件src/memdir/findRelevantMemories.ts#L46-L48。sideQuery使用getDefaultSonnetModel()max_tokens: 256输出约束为 JSON Schemaselected_memories: string[]返回的文件名会与合法文件名集合比对防止模型幻觉出不存在的文件src/memdir/findRelevantMemories.ts#L97-L140。recentTools上下文抑制噪音当 Claude Code 正在使用某工具如mcp__X__spawn时再浮现该工具的使用参考文档是噪音——对话中已含可用用法但工具的warnings/gotchas/known issues记忆仍应选中因为正在使用恰恰是它们最该出现的时候src/memdir/findRelevantMemories.ts#L87-L95。MEMORY_SHAPE_TELEMETRY特性门开启时记录召回形状logMemoryRecallShape即使空选择也会上报——选择率需要分母跑过但没选与从没跑过要能区分src/memdir/findRelevantMemories.ts#L64-L72。Sonnet 选择器提示You are selecting memories that will be useful to Claude Code as it processes a users query. You will be given the users query and a list of available memory files with their filenames and descriptions. Return a list of filenames for the memories that will clearly be useful to Claude Code as it processes the users query (up to 5). Only include memories that you are certain will be helpful based on their name and description. - If you are unsure if a memory will be useful, do not include it. Be selective and discerning. - If there are no memories that would clearly be useful, feel free to return an empty list. - If a list of recently-used tools is provided, do not select memories that are usage reference or API documentation for those tools (Claude Code is already exercising them). DO still select memories containing warnings, gotchas, or known issues about those tools — active use is exactly when those matter.新鲜度警告选中的记忆带着新鲜度信息注入上下文。memoryFreshnessText()src/memdir/memoryAge.ts#L33-L42function memoryFreshnessText(mtimeMs: number): string { const d memoryAgeDays(mtimeMs) if (d 1) return // 今天/昨天不加警告 return This memory is ${d} days old. Memories are point-in-time observations, not live state — claims about code behavior or file:line citations may be outdated. Verify against current code before asserting as fact. }memoryAgeDays按天向下取整今天 0、昨天 1、更早 2未来时间戳时钟偏移钳制到 0src/memdir/memoryAge.ts#L6-L8。动机来自用户报告过期的代码状态记忆引用已变更代码的 file:line被当作事实断言——引用让过期声明听起来更有权威而非更弱。另有两个变体memoryAge()输出人类可读的 47 days ago模型不擅长日期算术memoryFreshnessNote()把警告包进system-reminder标签供不加自有包装的调用方如 FileReadTool 输出使用src/memdir/memoryAge.ts#L15-L20、src/memdir/memoryAge.ts#L49-L53。记忆扫描详解scanMemoryFiles()关键设计单遍扫描先读后排序避免双倍 stat 系统调用。readFileInRange内部自行 stat 并返回mtimeMs因此是读-然后-排序而非stat-排序-读。常见场景N ≤ 200下相比单独 stat 一轮减少一半系统调用大 N 时多读几个小文件但仍避免了存活 200 个文件的二次 statsrc/memdir/memoryScan.ts#L24-L33。async function scanMemoryFiles(memoryDir, signal): PromiseMemoryHeader[] { const entries await readdir(memoryDir, { recursive: true }) const mdFiles entries.filter(f f.endsWith(.md) basename(f) ! MEMORY.md) // 并行读取所有文件的 frontmatter前 30 行 const headerResults await Promise.allSettled( mdFiles.map(async (relativePath) { const { content, mtimeMs } await readFileInRange(filePath, 0, 30) const { frontmatter } parseFrontmatter(content) return { filename, filePath, mtimeMs, description, type } }) ) // 过滤成功结果按时间降序排序取前 200 return fulfilled.sort((a, b) b.mtimeMs - a.mtimeMs).slice(0, 200) }该模块从findRelevantMemories.ts中拆出专门供 extractMemories 复用扫描而不引入 sideQuery 与 API client 链曾通过 memdir.ts 形成循环依赖#25372src/memdir/memoryScan.ts#L1-L5。类型解析parseMemoryType()对无效或缺失的type:字段返回undefined——无 type 字段的旧文件继续可用未知类型优雅降级src/memdir/memoryTypes.ts#L28-L31。formatMemoryManifest()生成供 Sonnet 或提取代理消费的清单- [feedback] testing_policy.md (2026-03-15T10:30:00.000Z): Integration tests use real DB - [user] role.md (2026-03-14T08:00:00.000Z): Data scientist, focused on logging - [project] freeze.md (2026-03-10T15:00:00.000Z): Merge freeze starting 3/5实现上逐行[type] filename (ISO 时间戳): description无 description 时省略冒号后的部分src/memdir/memoryScan.ts#L84-L94。Agent 记忆通过 Agent 工具启动的子代理拥有独立的三级记忆系统src/tools/AgentTool/agentMemory.ts作用域路径描述user~/.claude/agent-memory/{agentType}/全局用户级project.claude/agent-memory/{agentType}/项目级提交进版本库local.claude/agent-memory-local/{agentType}/本地级不提交与主记忆的差异无 MEMORY.md 索引步骤skipIndex truebuildMemoryLines因此省略Step 2 — 在 MEMORY.md 添加指针的指令直接写文件即可src/memdir/memdir.ts#L205-L217文件可直接写入无需两步流程每种 agent 类型相互隔离explorer、planner 等各有独立目录——agentType 会先经sanitizeAgentTypeForPath处理把 Windows 上非法且用于插件命名空间的冒号如my-plugin:my-agent替换为连字符src/tools/AgentTool/agentMemory.ts#L20-L23local 作用域在设置CLAUDE_CODE_REMOTE_MEMORY_DIR时改挂载到远端目录下的projects/{sanitized-git-root}/agent-memory-local/src/tools/AgentTool/agentMemory.ts#L29-L44。团队记忆同步当TEAMMEM特性门开启时isTeamMemoryEnabled()要求自动记忆启用否则一律 false——所有团队记忆消费方由此保持一致src/memdir/teamMemPaths.ts#L73-L78目录结构~/.claude/projects/{hash}/memory/ ├── MEMORY.md - 个人记忆索引 ├── user_*.md - 个人记忆 └── team/ - 团队共享目录 ├── MEMORY.md - 团队记忆索引 └── *.md - 团队记忆同步 APIGET /api/claude_code/team_memory?repo{owner/repo} - 拉取 GET /api/claude_code/team_memory?repo{owner/repo}viewhashes - 仅元数据 entryChecksums不带正文 PUT /api/claude_code/team_memory?repo{owner/repo} - 推送upsert 语义 404 尚无数据同步语义Pull服务端内容覆盖本地文件按 key 服务端优先Push仅上传与serverChecksums内容哈希不同的 key增量上传服务端 upsertPUT 中未出现的 key 保留src/services/teamMemorySync/index.ts#L14-L24删除不传播本地删除不会移除远端条目下次 pull 会恢复限制单文件最大 250KBMAX_FILE_SIZE_BYTES 250_000预过滤超大条目以省带宽上传体最大 200KBMAX_PUT_BODY_BYTES 200_000超限分批顺序 PUT——服务端 upsert-merge 语义保证分批安全src/services/teamMemorySync/index.ts#L71-L91重试最多 3 次常规重试 2 次冲突重试可变的SyncStateETag、serverChecksums、serverMaxEntries由调用方创建并贯穿所有调用避免模块级可变状态、利于测试隔离src/services/teamMemorySync/index.ts#L100-L119。团队写入还有一层纵深防御validateTeamMemWritePath()/validateTeamMemKey()除字符串级..检查外还会对最深已存在祖先做realpath解析再比对真实目录——path.resolve()不解析符号链接攻击者若能在 teamDir 内放置指向~/.ssh/authorized_keys的符号链接即可绕过字符串级包含检查PSR M22186悬空符号链接ENOENT 但 lstat 成功与符号链接环ELOOP也会被显式识别为PathTraversalErrorsrc/memdir/teamMemPaths.ts#L96-L171、src/memdir/teamMemPaths.ts#L228-L284。团队 vs 个人路由规则在 src/memdir/memoryTypes.ts 中每种类型声明scope指令类型默认作用域user恒为个人feedback默认个人项目级约定才进团队project偏向团队reference通常团队对应到提示文案TYPES_SECTION_COMBINED中的 feedback 类型明确写道 default to private. Save as team only when the guidance is clearly a project-wide convention that every contributor should follow (e.g., a testing policy, a build invariant)并给出集成测试必须连真实数据库进团队、而用户偏好简洁回复留私人的对照示例src/memdir/memoryTypes.ts#L57-L73。关键常量速查// 索引文件 ENTRYPOINT_NAME MEMORY.md // src/memdir/memdir.ts MAX_ENTRYPOINT_LINES 200 MAX_ENTRYPOINT_BYTES 25_000 // 扫描 MAX_MEMORY_FILES 200 // src/memdir/memoryScan.ts FRONTMATTER_MAX_LINES 30 // 路径 AUTO_MEM_DIRNAME memory // src/memdir/paths.ts // 提取 maxTurns 5 // forked agent 最多 5 轮extractMemories.ts // 检索 最多返回 5 条相关记忆 // findRelevantMemories.ts // 团队同步 // src/services/teamMemorySync/index.ts MAX_FILE_SIZE_BYTES 250_000 // 单文件上限 MAX_PUT_BODY_BYTES 200_000 // 上传体上限分批 MAX_RETRIES 3 / MAX_CONFLICT_RETRIES 2数据流总览┌─────────────────────────────────────────────────────┐ │ 会话启动Session Startup │ │ │ │ loadMemoryPrompt() │ │ - ensureMemoryDirExists() │ │ - buildMemoryLines() MEMORY.md content │ │ - 注入系统提示systemPromptSection 缓存 │ └────────────────────────┬────────────────────────────┘ | ┌─────────────────────────────────────────────────────┐ │ 用户查询User Query │ │ │ │ findRelevantMemories() │ │ - scanMemoryFiles() [扫描 frontmatter] │ │ - Sonnet 选择最多 5 条相关记忆 │ │ - 注入对话上下文 │ │ 新鲜度警告 │ └────────────────────────┬────────────────────────────┘ | ┌─────────────────────────────────────────────────────┐ │ Claude 响应Response │ │ │ │ 模型可直接写入记忆 │ │ 遵循系统提示指引两步流程 │ │ 或未写入 - 触发后台提取 │ └────────────────────────┬────────────────────────────┘ | ┌─────────────────────────────────────────────────────┐ │ 后台自动提取Auto-Extraction │ │ │ │ executeExtractMemories() │ │ - 互斥检查 │ │ 主代理已写入跳过 │ │ - 构建提取提示 记忆清单 │ │ - runForkedAgent() │ │ [共享缓存、受限工具、5 轮上限] │ │ - 写入新记忆文件 更新 MEMORY.md │ │ - 通知用户 │ └────────────────────────┬────────────────────────────┘ | ┌─────────────────────────────────────────────────────┐ │ 后台记忆整合AutoDream可选 │ │ │ │ executeAutoDream() │ │ [每 24h 5 个会话触发] │ │ - 五重闸门检查 │ │ (开关/时间/节流/会话/锁) │ │ - buildConsolidationPrompt() │ │ - runForkedAgent() │ │ [只读 Bash、仅记忆目录写入] │ │ - 四个阶段 │ │ Orient - Gather - Consolidate - Prune │ │ - 合并重复 / 修复过期 / 压缩索引 │ │ - 通知用户Improved N memories │ │ │ │ 详见 autodream.md │ └─────────────────────────────────────────────────────┘延伸阅读记忆整合AutoDream的完整机制见 docs/en/internals/autodream.md记忆的顶层概念与使用指南见 docs/en/internals/memory.md记忆类型提示文案与作用域路由的完整定义在 src/memdir/memoryTypes.ts团队同步的 API 契约与限流实现在 src/services/teamMemorySync/index.ts子代理记忆路径解析在 src/tools/AgentTool/agentMemory.ts。综上cc-haha 的记忆系统是一个提示注入 显式写入 后台兜底 模型选择召回 团队同步的完整闭环路径解析层用三级优先级与多层安全校验守住写入边界提示层用 eval 验证过的措辞约束模型行为提取层用 forked agent 与互斥/合并机制在后台零打扰地补全遗漏检索层则把选什么进上下文交给 Sonnet 并用新鲜度警告对抗记忆漂移。这套设计对任何希望为 Agent 增加持久化记忆能力的实现者都有直接的参考价值。赞分享人工智能AI 应用桌面应用代码智能体MCP Clients【免费下载链接】cc-hahaLocal-first cross-platform desktop workspace for Claude Code / agents: multi-agent, Git worktrees, code diffs, skill marketplace, multi-model, Computer Use, task-aware desktop pets, with WeChat, Feishu, DingTalk, Telegram, WhatsApp and H5 access.项目地址https://gitcode.com/gh_mirrors/cl/cc-haha点击查看免费下载相关推荐cc-haha Skills 系统实现原理Skill 从发现、注入到执行的完整链路剖析cc haha Skills 系统实现原理Skill 从发现、注入到执行的完整链路剖析 Skills 是 cc hahaClaude Code 本地优先工作人工智能AI 应用桌面应用代码智能体MCP Clients深入解析 py-spy 内存读取机制process_vm_readv 系统调用剖析深入解析 py spy 内存读取机制process_vm_readv 系统调用剖析 py spy 是一个革命性的 Python 采样分析器它能够在无需修改代开发工具性能剖析CLIAgent Zero 记忆插件的碎片自动提取机制深入解析 memories_sum 系统提示词Agent Zero 记忆插件的碎片自动提取机制深入解析 memories_sum 系统提示词 memory.memories_sum.sys.md 是 Ag人工智能大模型AI AgentAgent 框架自主智能体多智能体工具调用MCP 服务浏览器控制创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进