agentmemory filesystem-watcher 接入指南:把目录变更变成可检索的持久化记忆
2026/9/10 12:18:04 网站建设 项目流程

agentmemory filesystem-watcher 接入指南:把目录变更变成可检索的持久化记忆

【免费下载链接】agentmemory#1 Persistent memory for AI coding agents based on real-world benchmarks项目地址: https://gitcode.com/GitHub_Trending/age/agentmemory

导读:agentmemory是面向 AI 编码 Agent 的持久化记忆服务(详见仓库根目录 README.md)。而 integrations/filesystem-watcher/README.md 描述的@agentmemory/fs-watcher,则是它的一个文件系统数据源连接器:它以常驻进程的方式监控一个或多个目录,每当文件发生写入或删除,就把变更作为一条post_tool_use观测(observation)推送给正在运行的 agentmemory 服务器。读完本文,你将掌握它的安装方式、CLI 与环境变量用法、全部配置项与默认值、事件载荷结构,以及底层脱敏、去抖与容错实现,从而把“编辑文件”这一高频行为自动沉淀为 Agent 可检索的记忆。

一、背景:为什么需要文件系统连接器

agentmemory 的核心能力是把 Agent 工作过程中的信号(hook 事件、对话、工具调用等)沉淀为可检索的观测。但这类观测通常来自 Agent 运行时本身(如 Claude Code、Codex、Cursor 的钩子)。而现实中的很多重要信息——笔记、文档、配置、代码草稿——是直接在编辑器中修改的,并不会经过 Agent 的工具调用链路。

@agentmemory/fs-watcher正是为填补这一空白而设计的单向数据源连接器(属于仓库中>npm install -g @agentmemory/fs-watcher

安装后即获得agentmemory-fs-watcher命令(bin字段指向 bin.mjs)。

2.3 不安装直接运行

npx @agentmemory/fs-watcher ~/work/my-repo

npx会临时拉取并执行该包,适合快速试用。参数含义与全局安装完全一致:后续 CLI 参数即为要监控的目录列表。

三、用法与参数优先级

3.1 用 CLI 参数指定监控目录

# CLI args win over env. —— CLI 参数优先于环境变量 agentmemory-fs-watcher ~/work/my-repo ~/notes

可以同时监控多个根目录,空格分隔即可。从 bin.mjs 的源码可以看到解析逻辑:

const roots = cliArgs.length > 0 ? cliArgs : envCfg.roots;

只要 CLI 传入了任意目录,环境变量AGENTMEMORY_FS_WATCH_DIRS就会被忽略,这正是文档中 "CLI args win over env" 的源码依据。

3.2 用环境变量配置

# 一次性设置 export AGENTMEMORY_FS_WATCH_DIRS=~/work/my-repo,~/notes export AGENTMEMORY_URL=http://localhost:3111 export AGENTMEMORY_SECRET=... # 仅当服务器要求认证时 agentmemory-fs-watcher

此时不传任何 CLI 参数,进程会从环境读取配置。若既不传 CLI 参数、也未设置AGENTMEMORY_FS_WATCH_DIRS,bin.mjs 会向 stderr 输出用法提示并以退出码 2 结束。

3.3 完整配置项一览

以下参数表完整继承自 integrations/filesystem-watcher/README.md:

变量默认值含义
AGENTMEMORY_FS_WATCH_DIRS逗号分隔的待监控目录列表
AGENTMEMORY_FS_WATCH_IGNORE逗号分隔的正则模式,匹配相对路径则忽略
AGENTMEMORY_FS_WATCH_ALLOW_BINARY0设为1时把二进制文件也纳入预览读取
AGENTMEMORY_URLhttp://localhost:3111agentmemory 服务器地址
AGENTMEMORY_SECRETBearer Token;当服务器设置了AGENTMEMORY_SECRET时必须提供
AGENTMEMORY_PROJECT可选,附加到每条观测的项目标签
AGENTMEMORY_SESSION_ID可选,观测归属的会话 id

结合 watcher.mjs 中的configFromEnv,可以补充两点实现细节:

  • AGENTMEMORY_PROJECT_NAME是规范覆盖项:代码注释与 test/project-scope-parity.test.ts 的测试均说明,AGENTMEMORY_PROJECT_NAME优先级更高,AGENTMEMORY_PROJECT仅作为向后兼容的别名保留;且两者都会先trim(),纯空白视为未设置。
  • AGENTMEMORY_FS_WATCH_IGNORE是逐条编译为正则的:每个逗号分隔的片段都会new RegExp(s),因此可以直接写foo$^bar这类锚定表达式(测试中configFromEnv用例对此有断言)。

四、事件语义:一次文件变化 = 一条观测

4.1 观测类型与载荷结构

监控根目录内每次文件变化都会成为一条post_tool_use观测,其data.changeKind为:

  • file_change:文件被写入/修改;
  • file_delete:文件被删除。

观测载荷的完整形态见 watcher.mjs 的flush方法,其 JSON 结构如下:

{ "hookType": "post_tool_use", "sessionId": "fs-watcher-<ts>-<rand>", "project": "<仓库名或目录名>", "cwd": "<根目录绝对路径>", "timestamp": "2026-09-10T01:06:57.000Z", "data": { "source": "filesystem-watcher", "changeKind": "file_change", "files": ["notes.md"], "content": "notes.md (13 bytes)\n\nhello world\n", "rootDir": "/abs/path/to/root", "absPath": "/abs/path/to/root/notes.md", "size": 13, "truncated": false } }

这一结构完全符合 agentmemory 的HookPayload契约。在 src/types.ts 中,HookPayload要求hookTypesessionIdprojectcwdtimestamp五个必填字符串字段,watcher 发送的每条消息都完整携带。

4.2 服务端如何消费这条观测

理解载荷之后,值得看一下它进入服务器后的处理链路,这能让"文件变更如何变成可检索记忆"变得具体:

  1. HTTP 入口:src/triggers/api.ts 中api::observe注册在POST /agentmemory/observe,会先校验hookType/sessionId/project/cwd/timestamp五个必填字段,再转发给mem::observe(缺失任一字段返回 400)。若服务器配置了AGENTMEMORY_SECRET,该路由还受middleware::api-auth中间件保护(src/triggers/api.ts)。
  2. 观测入库:src/functions/observe.ts 中的mem::observe把载荷包装成RawObservation(见 src/types.ts)。由于hookType属于post_tool_use,其origin.channel被标记为tool,同时尝试从data中提取toolNametoolInputtoolOutput
  3. 会话自动创建:一个值得注意的细节是,若sessionId对应的会话尚不存在,只要载荷携带了合法的projectcwd,服务端会自动创建会话记录(src/functions/observe.ts 中else if分支)。这正是 watcher 文档强调"session id 和 project 是 observe 端点必需项"的原因——有了它们,即使 watcher 没有先调用/session/start,记忆也能正确归入会话。
  4. 压缩与索引:默认走零 LLM 消耗的合成压缩(buildSyntheticCompression),随后写入 BM25 搜索索引与向量索引(src/functions/observe.ts),使文件内容片段可被后续recall/搜索命中。

4.3 session id 与 project 的自动推导

observe 端点要求会话与项目信息,watcher 的处理策略是"能自动则自动":

  • session id:未显式设置AGENTMEMORY_SESSION_ID时,生成形如fs-watcher-<时间戳36进制>-<3字节随机hex>按进程会话 id(watcher.mjs 构造函数)。也就是说,一次常驻运行对应一个会话。
  • project:默认取第一个根目录的目录名;但若该目录位于 Git 仓库内,则优先使用仓库顶层目录名。这是因为 watcher.mjs 的deriveProjectName与 hooks 的resolveProject保持相同解析顺序(先git rev-parse --show-toplevel取顶层名,失败再退回目录名),从而让监控子目录时记忆仍按仓库名归类。
  • 多根目录的按根归属:构造器中还维护了projectByRootMap——多根场景下每条事件会打上产生该事件的根目录所对应的 project,而不是统一用第一个根的项目;仅当显式配置了AGENTMEMORY_PROJECT时才对所有根统一覆盖。

五、预览内容与脱敏机制

5.1 预览规则

  • 文本文件会读取前 4 KBMAX_PREVIEW_BYTES = 4096)作为data.content,使得后续检索可以通过子串匹配命中;更大的文件会置data.truncated: true
  • 二进制文件默认不读取,只产生一条不含内容的路径观测;设置AGENTMEMORY_FS_WATCH_ALLOW_BINARY=1可覆盖此行为。
  • 可读文本扩展名内置了一套白名单(见 watcher.mjs 的TEXT_EXTENSIONS):涵盖.ts/.tsx/.js/.jsx/.mjs/.cjs.py/.rb/.go/.rs/.java/.kt/.swift.c/.cc/.cpp/.h/.hpp.md/.mdx/.txt/.rst.json/.yaml/.yml/.toml/.ini/.env.html/.css/.scss/.vue/.svelte.sh/.bash/.zsh/.fish.sql/.graphql/.proto等;此外.env及其变体(.env.*)也被强制视为文本。
  • 未知扩展名的文件只记录路径,不带内容。

content的拼装格式(formatContent)为:相对路径 (字节数[, truncated])\n\n<预览内容>;删除事件则简化为deleted: 相对路径

5.2 敏感信息脱敏(源码级细节)

这是该连接器最有价值的防护设计,watcher.mjs 中有一整套redactSensitivePreview脱敏管线,且每条规则都有对应的测试覆盖(见 test/fs-watcher.test.ts):

  • 敏感键值对:匹配KEY=value/KEY: value(含引号与export前缀)形式的赋值,若键名(去除符号后小写)命中apikey/accesstoken/accesskey/authorization/bearer/clientsecret/password/passwd/privatekey/pwd/secret/token之一,则值替换为[REDACTED]。注意:.env中的OPENAI_API_KEY会被脱敏,而PUBLIC_FLAG这类非敏感键保持原样(测试断言PUBLIC_FLAG=enabled仍可见)。
  • Bearer Token:对Bearer <token>形式的明文令牌(至少 8 个可见字符)统一脱敏。
  • PEM 私钥块-----BEGIN ... PRIVATE KEY----------END ... PRIVATE KEY-----之间的全部内容折叠为[REDACTED],但保留 BEGIN/END 标记;同一行内内联的 PEM(如 JSON 单行值)也能被正确识别,服务账号 JSON 中的private_key即属此类场景。
  • JWT:长度 >= 100 的三段式eyJ...JWT 字符串整体替换为[REDACTED];而较短的、或非三段式 base64 形态的词语不会被误伤(测试用例专门验证了这一点)。

5.3 去抖(Debounce)

编辑器保存文件往往会在短时间内产生多次写事件。watcher 对每个路径做了500 msDEBOUNCE_MS)的去抖:schedule会先取消该路径未决的定时器再重新计时,因此"编辑器连续保存"最终合并为一条观测(测试debounces rapid writes to a single observation断言连续 4 次写入后命中观测数不超过 2)。

六、默认忽略规则与自定义扩展

文档明确列出的默认忽略清单如下,无需任何配置即可生效:

.git/node_modules/dist/build/.next/.turbo/coverage/.DS_Store*.log*.lock

对应到 watcher.mjs 的DEFAULT_IGNORE,它们是编译好的正则数组,例如/(?:^|\/)node_modules(?:\/|$)/匹配路径中任意层级的node_modules目录,/\.log$/匹配所有.log后缀文件。isIgnored会在两个环节生效:事件回调中立即跳过(不入队),以及flush落库前的二次校验。

需要扩展时,通过AGENTMEMORY_FS_WATCH_IGNORE传入逗号分隔的正则表达式(作用于相对路径),例如:

export AGENTMEMORY_FS_WATCH_IGNORE='tmp/,^\.cache/,\.swp$'

七、运行机制、容错与运维建议

7.1 底层机制

  • 基于 Node 内置fs.watch{ recursive: true, persistent: true }(watcher.mjs 的start),macOS、Linux、Windows 10+ 原生可用,无任何原生依赖
  • 事件回调会把相对路径统一为/分隔后再做忽略判断与入队,保证跨平台一致。
  • 观察到的文件变化会先确认目标仍是文件(statSyncisFile()),已被删除则走file_delete分支——这正是删除事件能被识别的方式。
  • 对外发送使用全局fetch提交到${AGENTMEMORY_URL}/agentmemory/observe,带 5 秒超时;失败只记录warn日志,不影响进程继续监控

7.2 容错设计

  • 单个根目录 attach 失败(权限、平台差异等)时,watcher 会记录错误并继续监控其余根目录
  • 对根目录会先做显式statSync校验(存在性 + 是否为目录)。test/fs-watcher.test.ts 中有一条重要回归测试:在 Linux + Node 24+ 上,fs.watch对不存在路径不再同步抛错,若不自行校验,缺失目录会被静默当作"已监控";而现在的实现会直接抛错(could not watch any of the configured roots)。
  • 所有根目录都失败,进程抛错退出,并给出 Node 版本相关的升级提示(Node >=19.1.0/ 建议 Node 20 LTS)。
  • stop()会关闭全部 watcher 句柄并清空未决定时器,保证优雅退出。

7.3 常驻与进程管理

watcher 进程必须保持运行才能持续捕获变化,文档明确建议用进程管理器托管:

Use a process manager(launchdsystemdpm2)to supervise it.

例如 systemd 服务的ExecStart指向agentmemory-fs-watcher并带上目标目录即可。由于 bin.mjs 已对SIGINT/SIGTERM注册了优雅关闭(调用watcher.stop()后退出),无论前台 Ctrl-C 还是进程管理器发信号,都能干净收尾。

八、测试验证与仓库对照

本连接器的行为在 test/fs-watcher.test.ts 中有系统性的集成测试覆盖(通过 mockfetch捕获请求断言),可作为理解其行为的权威参考:

测试场景验证点
写入文件发出post_tool_use观测,URL 为/agentmemory/observechangeKind=file_changecontent含文件内容
删除文件changeKind=file_delete
无效根目录could not watch any of the configured roots
根目录是文件拒绝监控
默认忽略node_modules/ignored.js不产生观测
Bearer 认证配置 secret 后请求头携带Authorization: Bearer shhh
.env脱敏OPENAI_API_KEY=[REDACTED]PUBLIC_FLAG=enabled保留
JSON 敏感键"api_key": [REDACTED],公开键保留
明文 BearerAuthorization: Bearer [REDACTED]
PEM 多行/内联私钥内容折叠为[REDACTED],保留 BEGIN/END 标记
JWT 脱敏长 JWT 被替换,短 base64 词不受影响
去抖连续写入合并为少量观测

九、典型应用场景小结

  • 笔记与文档记忆化:把~/notes纳入监控,随手写的想法、调研结论会自动进入 agentmemory,后续会话可通过检索召回。
  • 配置与草稿追踪:监控.env.yaml.md等变更,让 Agent 知道项目配置与文档"何时、在哪、改了什么"。
  • 代码仓库的增量观察:监控仓库根目录,配合AGENTMEMORY_FS_WATCH_IGNORE排除构建产物,为 Agent 补充基于文件系统信号的工作上下文。

最后再强调两点边界:一是该连接器单向——只写入观测、从不读取记忆库,想给 Agent 注入记忆需依赖 agentmemory 的 recall/检索能力;二是它把文件系统信号作为post_tool_use类观测入库,与钩子事件同构,因此能无缝复用压缩、索引、会话归并等全部下游能力。

【免费下载链接】agentmemory#1 Persistent memory for AI coding agents based on real-world benchmarks项目地址: https://gitcode.com/GitHub_Trending/age/agentmemory

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询