当前发布版本:0.2.1。
pi-local-memory 使用 Obsidian Markdown 作为跨会话记忆真源,提供按需检索、人工 /remember 写入,以及一个受服务器端策略约束的自动记忆工具。包不会修改全局 AGENTS.md、settings.json 或其它包。
项目主页:https://github.com/lood31/pi-local-memory
当前版本尚未发布到 npmjs.com。如需安装不依赖开发源码路径的全局包,请在包含该包 package.json 的目录中打包,再从 tarball 安装:
npm pack
npm install --global ./pi-local-memory-0.2.1.tgz将 Pi 的现有 packages 数组追加 npm 包名(不要写本机源码路径):
"npm:pi-local-memory"然后在 Pi 中执行 /reload。发布 tarball 只包含运行时 index.ts、src/、skills/、README.md、LICENSE 和 package.json,并内置运行时依赖 jiti@2.7.0;不包含测试、会话、vault、pending、metrics 或其它运行时数据。
调试时可以临时让 packages 指向本地 checkout 目录,这会直接加载工作树;发布安装和日常使用不要依赖源码目录,应使用上面的 npm:pi-local-memory。
确认 Obsidian vault 名称为 learning 且桌面端运行,以启用官方 CLI 主路径。也可以用 PI_MEMORY_ROOT,或 pi-local-memory.json 中的 { "root": "..." } 覆盖记忆根目录;默认根目录为:
D:/Obsidian仓库/learning/记忆库
| 命令 | 作用 |
|---|---|
/remember |
交互式新增记忆:类型、范围、标题、Markdown 正文、查重、置信度;最后必须确认写入 |
/memory-correct <id/路径/标题> |
编辑正文;保留 id、created、scope,刷新 updated |
/memory-forget <id/路径/标题> |
将文件移入 archive/ 并置 status: superseded,不硬删除 |
/memory-promote |
防御式读取当前 branch 的 OM reflections,逐条人工编辑、确认并晋升 |
/memory-status |
查看根目录、四个分区计数、解析警告和最近更新 |
/memory-index-sessions [current|all|rebuild] |
管理只读分支感知会话索引;all/rebuild 需 TUI 预览确认 |
/memory-knowledge-sources |
在 TUI 中预览并确认知识库 allowlist 修改 |
| `/memory-learning status | run |
这八个命令仍只在 TUI 中工作;all/rebuild、allowlist 修改、learning run/setup/pause/resume/rollback 和其它写入操作都会在实际执行前展示预览等待确认,非 TUI 模式安全拒绝。
包只注册一个 LLM 工具:memory。它是一个紧凑的 action 工具,支持:
propose/remember:提交一个preference、fact、decision、procedure或environment候选;list_pending:列出当前项目可见的待确认候选;resolve:对一个待确认 id 执行approve或reject,批准时可提供revision正文;undo/forget:按一个精确 active id 归档记忆。core 合集还必须给出精确 section 标题,避免一次删除整个合集。
工具输出和存储都有边界:标题最多 200 字符、正文最多 4,000 字符、来源最多 500 字符,待确认列表最多展示 10 条摘要。工具不调用模型,也不启动后台任务。
这些规则在工具执行代码中检查,而不是只写在 prompt 中:
- 只接受上述五种明确类型和
global/ 当前项目范围;其它类型、越权项目范围或超长数据直接拒绝。 - 凭据、密码、secret、API/access/refresh token、cookie、Bearer/JWT、私钥,以及敏感身份、财务、医疗、精确位置、第三方私密内容永不写入 active 或 pending。拒绝发生在触碰存储之前,也不会把候选正文写入审计文件。
- 只有
high置信度且有非空 provenance 的安全候选,才可能静默激活:普通类型必须由user_statement、user_decision或user_preference明确支撑;environment必须是local_environment。inference、uncertain、缺 provenance 或低/中置信度进入 pending。 - 同范围、同类型、同标题的不同正文视为冲突,进入 pending,即使置信度很高;完全重复是 no-op。批准是唯一把 pending 候选变为 active 的确认边界。
undo/forget只接受精确 id,使用归档而非硬删除,并在 pending store 的 metadata-onlyoperations.jsonl中留下有界审计记录。
待确认状态是临时 JSON 文件,默认位于 ~/.pi/agent/pi-local-memory/pending(可用 PI_MEMORY_PENDING_ROOT 指定),明确位于 Obsidian 记忆树之外。因此 Obsidian CLI、rg 和 filesystem retrieval 都看不到它。记录含 provenance、project id/scope、创建时间和过期时间,7 天后自动清理,跨 session/restart 保留。批准或拒绝都必须通过 memory 工具的 resolve action;批准前候选不是记忆。
扩展不再通过 before_agent_start 逐轮修改 system prompt。session_start 和 pending 数量变化只在 TUI 显示不含候选正文的数量状态;不会自动展示或确认候选。
learning 配置默认关闭。只有显式执行 /memory-learning setup on 后,扩展才会在 agent_start/turn_start 建立内存 run state,并在 tool_call/tool_result 中保留工具操作枚举、顺序、isError、write/edit 和 exact-verification 标志;args、output 和正文不会写入 run state、queue 或 metrics。agent_settled 只从 current branch 生成一次 metadata-only episode/candidate。
安全边界固定为至少 5 个 recent episodes、每项目每 24 小时最多一个 candidate、maintainer 通常一次模型调用且最多重试一次(总计不超过 2 次),不启动 subprocess。失败项留在 queue;输入或 shutdown 会 Abort 并释放 lease。Experience Wiki 只由 maintainer/proposer 写入,普通 context 不注入 Wiki 内容。metrics 只记录枚举、计数和 usage,并以 1 MiB 文件轮转。
pause 会保留已有队列但停止新的 run;review 仅展示 queue metadata;rollback <candidate-id> 只移除指定的 queue candidate,不删除原始会话。learning 关闭时不建立 learning 文件、不记录 metrics、也不调用模型。
memory-recall skill(SKILL.md)是按需加载的召回策略,统一路由到只读脚本。以下命令在该 skill 上下文中执行:Pi 会以已安装 SKILL.md 所在目录为基准解析 scripts/...,不依赖 Pi 项目的当前工作目录,也不依赖开发 checkout 的绝对路径。
node scripts/session-recall.mjs search '之前的决定'
node scripts/session-recall.mjs show '<opaque-anchor>'
node scripts/session-recall.mjs status
node scripts/knowledge-recall.mjs search '之前的决定'会话脚本不接受路径或 SQL 参数,知识脚本只读取配置 allowlist;所有输出最多 12 KiB。搜索只读,pending store 不在召回范围内,记忆内容按不可信数据处理。
记忆库/
core/USER.md # preference/global 合集
core/ENVIRONMENT.md # environment/global 合集
projects/<project-id>/ # project scope 下的 facts/decisions/procedures 等
inbox/ # 其它 global 记忆
archive/ # forget 后的历史,不参加默认检索
~/.pi/agent/pi-local-memory/
pending/<pending-id>.json # 临时待确认状态,不是记忆树
operations.jsonl # 不含候选正文的有界审计元数据
src/config.ts 会自动创建 core/、projects/、inbox/、archive/。项目 id 是 git 根(失败时 cwd)的规范化路径 SHA-256 前 16 位。
普通笔记使用扁平 YAML frontmatter:
| 字段 | 说明 |
|---|---|
id |
mem_ + 16 位小写 hex;core 合集为 core:user / core:env |
type |
preference、fact、decision、procedure、environment |
scope |
global 或 project:<project-id> |
status |
active、superseded、invalid |
confidence |
low、medium、high |
created / updated |
ISO-8601 时间 |
source |
manual、automatic-safe-memory、session:<file> 或 promote:<om-id> |
supersedes |
decision 历史 id 列表 |
review_after |
ISO-8601 或空字符串 |
tags |
字符串数组 |
pi-observational-memory 负责会话内观察与 reflection 压缩;本包只在用户执行 /memory-promote 时防御式读取当前 branch 中 customType === "om.reflections.recorded" 的数据,并由用户选择、编辑和确认后写成跨会话 Markdown。OM 缺失、版本变化或 reflection 结构损坏都会优雅降级为提示,不会阻止 pi 启动。
Gate C 与日常记忆路径严格分开。生成 Skill 只写入本包自己的 generated-skills root,绝不写入或覆盖项目 skills/、.pi/skills/、~/.pi/agent/skills/ 等用户 Skill 树;请求的目标路径若不是 generated root 内的精确 SKILL.md 会被拒绝。
resources_discover 只返回当前 project/provider/model 的 generated Skill 目录:最多 5 条 active 加 1 条有验证配置的 trial。global Skill 只有已经在 TUI 明确批准的 active 才可发现,最多 3 条;global draft/trial、rejected、rolled_back 和其它项目/模型的 Skill 永不暴露。Skill 正文按 Pi 的 progressive disclosure 按需读取,description 每条最多 180 字符;普通任务不会注入 Agent 经验 Wiki、session 片段、knowledge 片段或 pending 正文。
project Skill 先进入 trial。学习已启用时,扩展在内存 receipt 中只保留枚举、布尔值和顺序:模型必须先读取生成的精确 SKILL.md,之后才计入 write/edit,且最后一次 mutation 之后必须由用户配置的 exact validation command 成功验证。验证命令不由模型生成、扩展不在后台执行项目命令。满足顺序后,agent_settled 只做 project canary 的 metadata 状态迁移为 active,不会调用 reload;下次 /reload 或新 session 才重新发现 active Skill。没有验证配置、读取普通文件、验证在 mutation 前、再次 mutation 或验证失败都不能 promotion。
global draft 只通过 /memory-learning review 的 TUI 展示。review 会显示完整 SKILL.md diff,用户可以批准、编辑后批准、拒绝或稍后处理;编辑内容会重新做格式、敏感内容和验证检查。批准成功后才 await ctx.reload(),headless/RPC 或没有确认能力时 fail closed。模型 lineage(provider/model)变化会暂停新的 Skill promotion、提示 /reload,不会假装动态刷新 resources。
拒绝、失败和 rollback 不硬删除 generated artifact:状态、历史、impact/diff 和安全 reason 会保留,敏感输出只保留 hash/reason。rollback 也只针对精确 generated Skill id,并保留失败影响记录;它不会触碰用户 Skill 或原始 session。
learning 默认关闭;关闭时不创建 queue、Wiki、metrics 或 generated Skill root,也不调用模型。启用后仍遵守至少 5 个 episode、每项目 24 小时最多一个 candidate、每批通常 1 次且绝对不超过 2 次模型调用、queue 上限 100 和 30 天 TTL。Experience Wiki 只供受控 maintainer/proposer 使用,不供普通 task agent 读取。scanner 是保守的敏感内容拦截,不是完整 DLP;原始 session 和 provider 请求可能仍包含用户敏感内容,不能宣传为端到端本地。
npm test
node --experimental-strip-types --input-type=module -e "await import('./index.ts'); await import('./src/generated-skills.ts'); await import('./src/skill-canary.ts'); await import('./src/skill-validation.ts'); await import('./src/skill-trial.ts')"发布门固定为:恰好 1 个 registerTool(现有 memory)、8 个 slash commands、只有 1 个 recall Skill、memory tool 定义不超过 1,983 字符、每个 Skill description 不超过 180 字符;普通 before_agent_start 不写入 Wiki/session/knowledge/pending。npm test 会运行所有独立和集成 fixtures。
真实 Pi TUI 的 /reload 交互、真实 provider/model completion、实际 cloud 成本与真实项目 canary 结果属于 [UNVERIFIED],本 README 不伪造通过结果;请在用户确认成本后单独执行 smoke test。
MIT