@jishen/agentic-memory
v0.1.2
Published
Codex-style markdown memory plugin for agentic/opencode — 14 LLM tools, auto-capture pipeline, inbox review, secret scanning
Maintainers
Readme
agentic-memory
Codex 风格的 Markdown 记忆插件,用于 agentic(基于 opencode)。LLM 主导,引擎兜底——模型自己决定何时保存、搜索、删除记忆。
引擎提供:Markdown 存储 + 关键词搜索(CJK) + 自动去重 + TTL 清理 + 审核队列 + 密钥扫描
LLM 决定:何时记、记什么、何时搜、搜什么、何时删不自动注入记忆到上下文——模型用 memory_search 按需搜索。
竞品对比
| | Claude Code | Codex CLI | agentic-memory | |------|:--:|:--:|:--:| | 存储 | Markdown | Markdown | Markdown + YAML | | 检索 | 启动注入 | grep | 关键词+时效(CJK支持) | | 自动注入 | 是 | 否 | 否(可配置) | | 去重 | LLM 自判 | 双模型 | Jaccard 自动 | | 清理 | LLM 自删 | 30天删 | TTL归档(pinned保护) | | 摘要 | 无 | 双模型 pipeline | API/启发式 → 审核队列 | | 密钥防护 | 无 | 无 | 7 种模式扫描 |
架构
src/
├── index.ts ← 插件入口,5 hooks + 14 tools 注册
├── tools.ts ← LLM 工具定义(Zod 校验)
├── storage/ ← 数据层
│ ├── memory-file.ts ← CRUD + 索引 + inbox
│ ├── search.ts ← 关键词+时效(CJK分词)
│ ├── frontmatter.ts ← YAML 解析/序列化
│ ├── paths.ts ← 路径 + slugify + git root
│ ├── lock.ts ← mkdir 跨进程锁
│ ├── explorer.ts ← Codex-style 安全路径浏览(预留)
│ └── utf8.ts ← UTF-8 截断
└── services/ ← 业务层
├── config.ts ← 配置解析 + 环境变量
├── capture.ts ← 事件捕捉 + 内存缓冲
├── summarizer.ts ← API/启发式 consolidation
├── dedup.ts ← Jaccard 去重
├── auto.ts ← autoSearch 上下文构建
├── cleanup.ts ← TTL 归档 + processed 清理
└── secrets.ts ← 密钥扫描安装
// ~/.config/agentic/agentic.jsonc
{ "plugin": ["/path/to/agentic-memory/packages/agentic-memory/src/index.ts"] }前置条件:agentic 源码中禁用内置 memory(一行注释):
// engines/agentic/code/packages/opencode/src/session/instruction.ts
// const memory = yield* projectMemory() // ← 已注释14 个 LLM 工具
核心 CRUD
| 工具 | 触发条件 | 参数 |
|------|------|------|
| memory_save | 创建 NEW 记忆 | name, content, type, description?, title?, tags?, pinned?, ttlDays? |
| memory_update | 追加到 EXISTING 记忆 | 同上 |
| memory_read | 按路径精确读 | path, lineOffset?, maxLines?, maxBytes? |
| memory_note | 用户显式指令 | slug, note |
| memory_list | 枚举所有记忆 | path?, cursor?, maxResults? |
| memory_forget | 删除记忆 | name |
搜索与导航
| 工具 | 说明 |
|------|------|
| memory_search | 关键词搜索(ranked) / Codex-style 精确子串搜索(queries/matchMode/path/cursor) |
| memory_index | 启动时快速浏览 MEMORY.md |
| memory_reindex | 从 topic 文件重建 MEMORY.md |
审核队列
| 工具 | 说明 |
|------|------|
| memory_inbox_list | 列待审核候选 |
| memory_inbox_approve | 批准 → 正式记忆 |
| memory_inbox_reject | 拒绝 → 删除 |
自动管道
| 工具 | 说明 |
|------|------|
| memory_capture_status | pending 队列状态 |
| memory_consolidate | 手动触发摘要合并 |
选择指南(内置在工具描述中)
新话题 → memory_save
已有话题追加 → memory_update
用户命令 → memory_note
需要精确行号 → memory_read
快速浏览 → memory_index
完整列表 → memory_list已跨 6 个 LLM 模型(DeepSeek V4 Pro/Flash, Kimi k2.7-code, GLM-5.2, Qwen3.7+, Gemini 2.5-Flash)验证工具选择正确率 100%。
5 个 Hooks
| Hook | 触发时机 | 行为 |
|------|------|------|
| chat.message | 用户输入 | extractText → isWorthCapturing → scanForSecrets → 内存缓冲 → scheduleConsolidation |
| tool.execute.after | memory_* 调用后 | 重置 sessionSearchIndex 缓存 |
| experimental.text.complete | AI 回复文本 | 同上 capture 流程 |
| experimental.chat.system.transform | 每轮开始时 | searchCache + autoSearch 注入 + inbox 提醒 + 记忆纪律 |
| experimental.session.compacting | 上下文压缩前 | Hermes-style memory flush 提醒 |
| dispose | 插件卸载 | flushEventBuffer + 清理缓存 |
自动捕捉流水线
chat.message → extractText → isWorthCapturing(噪音过滤)
→ scanForSecrets(密钥拦截)
→ 内存缓冲(Map<string, string[]>)
↓ scheduleConsolidation(setTimeout(0), 互斥锁)
→ readPendingBatch(落盘到 pending/*.jsonl)
↓
callOpenAiCompatible / heuristicDraft
↓
addToInbox → inbox/*.md(候选待审核)
↓
approveInbox → saveMemory → .agentic/memory/topic.md
↓
rebuildIndex → MEMORY.md每层职责不可省略,但可按需关闭 (autoCapture: false / summarizer: "none")。容量限制:capture 200 条/session,inbox 100 条。
配置
// ~/.config/agentic/agentic.jsonc plugin options
{
"memory": {
"autoCapture": true, // 自动捕捉用户对话
"autoSearch": false, // 每轮自动注入记忆(默认关闭,LLM主导)
"summarizer": "agent", // "agent" | "api" | "none"
"consolidation": "llm", // "llm" | "heuristic"
"summarizerApi": { // API模式配置
"baseUrl": "https://api.deepseek.com/v1",
"model": "deepseek-v4-flash",
"apiKey": "sk-xxx"
}
}
}环境变量:AGENTIC_MEMORY_SUMMARIZER_BASE_URL, AGENTIC_MEMORY_SUMMARIZER_MODEL, AGENTIC_MEMORY_SUMMARIZER_API_KEY, AGENTIC_MEMORY_SUMMARIZER_TIMEOUT_MS
默认配置:autoCapture: true, autoSearch: false, summarizer: "agent", captureMaxBytes: 8000, captureMinChars: 40
存储格式
.agentic/memory/
├── MEMORY.md ← 自动维护的索引文件
├── topic-name.md ← 话题文件
├── pending/ ← 捕捉队列(JSONL)
│ └── processed/ ← 已处理(14天自动清理)
├── inbox/ ← 审核候选
└── .archive/ ← TTL 过期归档话题文件格式:
---
name: auth-debug
description: OAuth2 token refresh bug fix
type: project
title: Auth 调试记录
tags: auth, oauth
createdAt: 2026-07-04T00:00:00.000Z
updatedAt: 2026-07-04T00:00:00.000Z
pinned: true
ttlDays: 365
---
Body content in Markdown.插入/拔出
两个系统共享 .agentic/memory/ 目录和格式,切换不丢数据:
使用插件: agentic.jsonc 加插件路径 + instruction.ts 注释掉 2 行
切回内置: agentic.jsonc 删插件行 + instruction.ts 取消注释 2 行
两者不能同时启用(会导致重复 memory 上下文注入)。
安全与可靠性
| 机制 | 实现 |
|------|------|
| 原子写入 | temp + rename,崩溃安全 |
| 并发锁 | mkdir 原子互斥,max 100 retries |
| 路径安全 | 拒绝 ..、隐藏目录、symlink、inbox/pending/.archive |
| 密钥防护 | 7 种模式(OpenAI/GitHub/AWS/JWT/Bearer/PrivateKey/SecretAssignment),写入前拦截 |
| 数据完整性 | name slug 校验、Jaccard 去重、索引自动维护 |
| API 降级 | API 失败自动 fallback 到 heuristic |
搜索算法
关键词匹配 + 时效评分,支持中文(CJK bigram/trigram):
得分 = 匹配词数/搜索词数 + max(0, 1-天数/30)×0.2
结果过滤:得分 < 0.1 不返回
时效警告:≥1天记忆标注「N days old」
正文截断:maxBytesPerResult 超限追加 [truncated] 标记O(n) 全量扫描,1000+ 记忆时规划倒排索引优化(当前不影响使用)。
TTL 策略
| type | 默认 | 可覆盖 |
|------|:--:|:--:|
| project | 180 天 | ttlDays 字段 |
| feedback | 365 天 | ttlDays 字段 |
| reference | 365 天 | ttlDays 字段 |
| user | 不归档 | ttlDays 字段 |
| 任意 pinned: true | 永不归档 | — |
测试
cd packages/agentic-memory
bun run tests/run.ts # 60 passed, 0 failed跨模型 E2E 验证:DeepSeek V4 Pro/Flash、Kimi k2.7-code、GLM-5.2、Qwen3.7+、Gemini 2.5-Flash
路线图
- [x] Markdown 存储 + YAML frontmatter
- [x] 关键词搜索 + CJK 分词
- [x] 自动去重(Jaccard)
- [x] MEMORY.md 索引自动维护
- [x] TTL 归档(pinned 保护)
- [x] 14 个 LLM 工具
- [x] 审核队列(inbox)
- [x] 自动捕捉流水线
- [x] 密钥扫描
- [x] 原子写入 + 文件锁
- [x] 6 模型跨验证
- [ ] npm 发布
- [ ] 倒排索引优化(1000+ 记忆时)
- [ ] hook 层测试覆盖
