{"_id":"@dannyge/openclaw-memory-inject","_rev":"2-d250eee08871a8a3d3718c5fcad0aa71","name":"@dannyge/openclaw-memory-inject","dist-tags":{"latest":"0.2.0"},"versions":{"0.1.1":{"name":"@dannyge/openclaw-memory-inject","version":"0.1.1","keywords":["openclaw","plugin","memory","session","context","context-injection"],"author":{"name":"dannyge"},"license":"MIT","_id":"@dannyge/openclaw-memory-inject@0.1.1","maintainers":[{"name":"dannyge","email":"gezhenying@gmail.com"}],"homepage":"https://github.com/dannyge/openclaw-memory-inject#readme","bugs":{"url":"https://github.com/dannyge/openclaw-memory-inject/issues","email":"dannyge@users.noreply.github.com"},"dist":{"shasum":"2ec716b5b57c0aa832dcf04d123faa34b0c652d6","tarball":"https://registry.npmjs.org/@dannyge/openclaw-memory-inject/-/openclaw-memory-inject-0.1.1.tgz","fileCount":30,"integrity":"sha512-WE3fj5pFpg+Zl9gasveBeQ/mb8rzJC6yJ/RXHPpKBzUGsawf2vqgcfdm8p+5ctIYuI5d28QbpuzPy3a9wMdKpA==","signatures":[{"sig":"MEQCIA9SMSBjv6BqE5uw+Fmi2rZebQhBPtO3NDcHoC81EgkfAiApHflNLzup37f/5lSp+BBiFO2KdjEYJI9Ilz9f8CBJfw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":91422},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"gitHead":"ee60a63005c41ff8a262f0a823a4f195d6fbdb64","scripts":{"test":"node --test --import tsx test/*.test.ts","build":"tsc -p tsconfig.json","clean":"rm -rf dist *.tsbuildinfo","prepack":"npm run build","typecheck":"tsc --noEmit -p tsconfig.json && tsc --noEmit -p tsconfig.test.json","test:watch":"node --test --import tsx --watch test/*.test.ts","version-check":"node scripts/check-version.mjs","prepublishOnly":"npm run clean && npm run build && npm test"},"_npmUser":{"name":"dannyge","email":"gezhenying@gmail.com"},"openclaw":{"hooks":["./dist/index.js"],"extensions":["./dist/index.js"]},"repository":{"url":"git+https://github.com/dannyge/openclaw-memory-inject.git","type":"git"},"_npmVersion":"10.9.8","description":"OpenClaw plugin: auto-inject recent memory/*.md files into new sessions via before_prompt_build hook.","directories":{},"_nodeVersion":"22.22.3","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.0","typescript":"^5.5.0","@types/node":"^22.0.0"},"_npmOperationalInternal":{"tmp":"tmp/openclaw-memory-inject_0.1.1_1782280722785_0.46629057562559617","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@dannyge/openclaw-memory-inject","version":"0.2.0","description":"OpenClaw plugin: auto-inject recent memory/*.md files into new sessions via before_prompt_build hook.","type":"module","main":"dist/index.js","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"openclaw":{"extensions":["./dist/index.js"],"hooks":["./dist/index.js"]},"scripts":{"build":"tsc -p tsconfig.json","test":"node --test --import tsx test/*.test.ts","test:watch":"node --test --import tsx --watch test/*.test.ts","typecheck":"tsc --noEmit -p tsconfig.json && tsc --noEmit -p tsconfig.test.json","version-check":"node scripts/check-version.mjs","clean":"rm -rf dist *.tsbuildinfo","prepublishOnly":"npm run clean && npm run build && npm test","prepack":"npm run build"},"keywords":["openclaw","plugin","memory","session","context","context-injection"],"author":{"name":"dannyge"},"license":"MIT","homepage":"https://github.com/dannyge/openclaw-memory-inject#readme","repository":{"type":"git","url":"git+https://github.com/dannyge/openclaw-memory-inject.git"},"bugs":{"url":"https://github.com/dannyge/openclaw-memory-inject/issues","email":"dannyge@users.noreply.github.com"},"engines":{"node":">=22.19"},"publishConfig":{"access":"public"},"devDependencies":{"@types/node":"^22.0.0","typescript":"^5.5.0","tsx":"^4.19.0"},"gitHead":"623e2351f1b4669e37eddace4e9a3f786dd7054d","_id":"@dannyge/openclaw-memory-inject@0.2.0","_nodeVersion":"24.16.0","_npmVersion":"11.13.0","dist":{"integrity":"sha512-6UBSGkOkpwu/2dKIAVJNJCQHkMnOZSzzo8i1vbXcM0aS0BNfk6wPZdwCeUOlKmUhRRkHGX4hJghWXkmWte1qGw==","shasum":"8f796d5dfe619a6e8553ccd6ab7fea85fbdb9806","tarball":"https://registry.npmjs.org/@dannyge/openclaw-memory-inject/-/openclaw-memory-inject-0.2.0.tgz","fileCount":30,"unpackedSize":92262,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIFC6xwNRddLcukxsgkJ/tdVAcQnb65JbIjgEBL0t0uO5AiB23BX2WixvjpudW87rUssj34l7JerkT1M6v8bHuGe1Yg=="}]},"_npmUser":{"name":"dannyge","email":"gezhenying@gmail.com"},"directories":{},"maintainers":[{"name":"dannyge","email":"gezhenying@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/openclaw-memory-inject_0.2.0_1782283728134_0.3791644310572926"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-24T05:58:42.626Z","modified":"2026-06-24T06:48:48.407Z","0.1.1":"2026-06-24T05:58:42.935Z","0.2.0":"2026-06-24T06:48:48.297Z"},"bugs":{"url":"https://github.com/dannyge/openclaw-memory-inject/issues","email":"dannyge@users.noreply.github.com"},"author":{"name":"dannyge"},"license":"MIT","homepage":"https://github.com/dannyge/openclaw-memory-inject#readme","keywords":["openclaw","plugin","memory","session","context","context-injection"],"repository":{"type":"git","url":"git+https://github.com/dannyge/openclaw-memory-inject.git"},"description":"OpenClaw plugin: auto-inject recent memory/*.md files into new sessions via before_prompt_build hook.","maintainers":[{"name":"dannyge","email":"gezhenying@gmail.com"}],"readme":"# @dannyge/openclaw-memory-inject\n\n[![CI](https://github.com/dannyge/openclaw-memory-inject/actions/workflows/ci.yml/badge.svg)](https://github.com/dannyge/openclaw-memory-inject/actions/workflows/ci.yml)\n[![npm version](https://img.shields.io/npm/v/@dannyge/openclaw-memory-inject)](https://www.npmjs.com/package/@dannyge/openclaw-memory-inject)\n[![license](https://img.shields.io/npm/l/@dannyge/openclaw-memory-inject)](./LICENSE)\n[![node](https://img.shields.io/node/v/@dannyge/openclaw-memory-inject)](https://www.npmjs.com/package/@dannyge/openclaw-memory-inject)\n\n> **[English](README.md)** | **[中文](README.zh.md)**\n\n新会话自动注入最近的 memory 文件，让 agent 在每次新对话中都能延续上下文。\n\n## 问题背景\n\nOpenClaw 的 `startupContext` 机制只在**裸 `/new` 或 `/reset`**（空消息时）触发。对于 Discord 新开 thread、API 创建 session 等场景，`startupContext` 不会被注入，agent 启动时完全不知道之前发生过什么。\n\n这在多 agent 协作和长期运维中很致命：每次新开一个 thread，agent 就\"失忆\"了，需要反复解释背景信息。\n\n类似的\"memory 在 session 间不连续\"问题在 OpenClaw 社区被多次报告过：\n\n- [#11618](https://github.com/openclaw/openclaw/issues/11618) — \"Hook to inject relevant memory on session start\"（已 close/completed）。这个 issue 最终促使 OpenClaw 在 2026.6 引入 `session_start` + `before_prompt_build` 两个 hook，本插件正是基于这个能力构建的。\n- [#32905](https://github.com/openclaw/openclaw/issues/32905) — \"session-memory hook saves context but never recalls\"（已 close/not_planned）。描述 `session-memory` hook 只能保存、无法在新 session 自动恢复的问题，这正是本插件要直接补上的能力缺口。\n\n## 解决方案\n\n`memory-inject` 通过两个 hook 解决问题：\n\n1. **`session_start`** — 标记\"这是一个新 session，需要注入 memory\"\n2. **`before_prompt_build`** — 在构建 prompt 之前，将最近的 memory 文件内容注入到上下文里\n\n每个 session 至多注入一次。注入时机是 `before_prompt_build`，这意味着 memory 内容会出现在 system prompt 的起始位置，agent 在生成回复之前就能看到。\n\n## 特性\n\n- **多 agent 自动适配** — 通过 `ctx.workspaceDir` 自动定位每个 agent 的 memory 目录，无需为每个 agent 单独配置\n- **fail-open 设计** — 配置错误、文件缺失、磁盘 IO 异常都不会阻塞 agent 正常回复\n- **零运行时依赖** — 纯 Node.js 标准库实现，不引入任何第三方包\n- **token 预算截断** — 可按字符数估算 token，超出预算自动丢弃最旧的文件\n- **mtime 排序** — 按文件修改时间倒序，最新修改的文件优先注入\n- **正则匹配文件名** — 默认匹配 `YYYY-MM-DD.md` 或 `YYYY-MM-DD-<slug>.md`\n- **可配置** — 8 个配置项，覆盖日常和高级场景\n- **MIT 许可证**\n\n## 安装\n\n要求 **Node.js 22.19+**（推荐 Node 24）和 **OpenClaw 2026.6+**（引入\n`session_start` 和 `before_prompt_build` hook 的版本）。不支持 Node 20 —— 它已 EOL，\n且 OpenClaw 本身就要求 22.19+。\n\n### 方式一：从 npm 安装（推荐）\n\n```bash\nopenclaw plugins install @dannyge/openclaw-memory-inject\n```\n\n通过 `openclaw plugins update memory-inject` 更新。\n\n### 方式二：从 GitHub 安装\n\n```bash\nopenclaw plugins install dannyge/openclaw-memory-inject\n```\n\n### 方式三：开发模式（本地链接）\n\n```bash\ngit clone https://github.com/dannyge/openclaw-memory-inject.git\ncd openclaw-memory-inject\nnpm install && npm run build\nopenclaw plugins install --link /path/to/openclaw-memory-inject\n```\n\n安装后需要重启 gateway：\n\n```bash\nopenclaw gateway restart\n```\n\n## 配置\n\n在 `openclaw.plugin.json` 的 `memory-inject` 段中配置。所有配置项都有合理的默认值，不配置即可使用。\n\n| 配置项 | 类型 | 默认值 | 说明 |\n|--------|------|--------|------|\n| `enabled` | boolean | `true` | 总开关。设为 `false` 时插件加载但不执行注入 |\n| `memoryDir` | string | `\"memory\"` | 相对于 agent workspaceDir 的 memory 目录 |\n| `daysToLoad` | number | `2` | 加载最近几天的 memory 文件（1-365） |\n| `maxFiles` | number | `4` | 每个 session 最多注入的文件数（1-100） |\n| `maxTokens` | number | `4000` | token 预算（字符数 / 4 估算），超出时丢弃最旧文件 |\n| `filenamePattern` | string | `\"^\\\\d{4}-\\\\d{2}-\\\\d{2}(-.+)?\\\\.md$\"` | 文件名匹配正则 |\n| `excludeAgents` | string[] | `[]` | 排除的 agent id 列表 |\n| `contextLabel` | string | `\"Recent memory (auto-injected by memory-inject plugin)\"` | 注入内容前的标题行，设为空字符串可省略 |\n\n### 完整 JSON 配置示例\n\n```json\n{\n  \"plugins\": {\n    \"memory-inject\": {\n      \"enabled\": true,\n      \"memoryDir\": \"memory\",\n      \"daysToLoad\": 3,\n      \"maxFiles\": 5,\n      \"maxTokens\": 8000,\n      \"filenamePattern\": \"^\\\\d{4}-\\\\d{2}-\\\\d{2}(-.+)?\\\\.md$\",\n      \"excludeAgents\": [],\n      \"contextLabel\": \"Recent memory (auto-injected by memory-inject plugin)\"\n    }\n  }\n}\n```\n\n## 使用示例\n\n### 基础用法\n\n安装后无需额外配置。插件会自动扫描 `~/.openclaw/agents/<agentId>/workspace/memory/` 下的文件，向每个新 session 注入最近 2 天、最多 4 个、不超过 4000 token 的 memory 内容。\n\nmemory 文件示例：\n\n```\n~/.openclaw/agents/ops/workspace/memory/\n├── 2026-06-23.md          # 今天的\n├── 2026-06-22.md          # 昨天的\n├── 2026-06-21-deploy.md   # 前天的，带 slug\n└── 2026-06-20.md          # 4 天前，超出 daysToLoad 范围，不会被加载\n```\n\n### 进阶配置\n\n**一个 agent 需要更长的上下文**：\n\n```json\n{\n  \"plugins\": {\n    \"memory-inject\": {\n      \"daysToLoad\": 7,\n      \"maxFiles\": 10,\n      \"maxTokens\": 12000\n    }\n  }\n}\n```\n\n**排除敏感 agent**：\n\n```json\n{\n  \"plugins\": {\n    \"memory-inject\": {\n      \"excludeAgents\": [\"finance\", \"hr\"]\n    }\n  }\n}\n```\n\n**自定义 memory 目录**：\n\n```json\n{\n  \"plugins\": {\n    \"memory-inject\": {\n      \"memoryDir\": \"notes\"\n    }\n  }\n}\n```\n\n此时会扫描 `~/.openclaw/agents/<agentId>/workspace/notes/`。\n\n**匹配特定文件名格式**：\n\n```json\n{\n  \"plugins\": {\n    \"memory-inject\": {\n      \"filenamePattern\": \"^(daily|weekly)-\\\\d{4}-\\\\d{2}-\\\\d{2}\\\\.md$\"\n    }\n  }\n}\n```\n\n## memory 文件匹配规则\n\n插件按以下步骤筛选和排序 memory 文件：\n\n1. **扫描目录** — 读取 `~/.openclaw/agents/<agentId>/workspace/<memoryDir>/`\n2. **正则过滤** — 只保留文件名匹配 `filenamePattern` 的文件（默认 `^\\d{4}-\\d{2}-\\d{2}(-.+)?\\.md$`，即 `YYYY-MM-DD.md` 或 `YYYY-MM-DD-<slug>.md`）\n3. **时间窗口** — 只保留 `mtime` 在 `daysToLoad` 天内的文件\n4. **按 mtime 倒序** — 最新修改的排在前面\n5. **数量截断** — 至多保留 `maxFiles` 个文件\n6. **token 截断** — 累积字符数超过 `maxTokens * 4` 时，丢弃剩余文件（最旧优先丢弃）\n\n文件内容以纯文本形式读取，编码为 UTF-8。单个文件读取上限为 512KB，超出部分会被截断。\n\n## 多 agent 行为\n\n插件通过 `ctx.workspaceDir` 自动适配每个 agent 的 memory 目录。例如：\n\n- agent `ops` → 扫描 `~/.openclaw/agents/ops/workspace/memory/`\n- agent `kbadmin` → 扫描 `~/.openclaw/agents/kbadmin/workspace/memory/`\n\n每个 agent 的 session 只注入自己的 memory 文件，互不干扰。\n\n使用 `excludeAgents` 排除不需要注入的 agent：\n\n```json\n{\n  \"plugins\": {\n    \"memory-inject\": {\n      \"excludeAgents\": [\"kbadmin\", \"test-bot\"]\n    }\n  }\n}\n```\n\n排除的 agent 在 `session_start` 和 `before_prompt_build` 两个阶段都会被跳过，不会产生任何开销。\n\n## 性能 / token 开销\n\n- **每个 session 至多注入 `maxFiles` 个文件** — 默认 4 个\n- **注入只发生一次** — 第一个 `before_prompt_build` 触发后，后续同一 session 的构建不再重复注入\n- **文件读取为同步操作** — memory 文件通常很小，总读取量受 `maxTokens * 4` 字符上限约束\n- **注入内容作为 `prependContext`** — 出现在 prompt 最前面，不会改变消息历史\n\n对于典型的每天 2-3KB 的 memory 文件，4 个文件约消耗 800-1500 token，对 128K 上下文窗口基本无感。\n\n## 安装后验证\n\n端到端验证插件是否在工作的最可靠方法，是去 gateway 日志里找 `[memory-inject]` 注入消息。插件每次成功注入都只会输出一行。\n\n### 1. 准备 memory 文件\n\n插件扫描 `<workspaceDir>/<memoryDir>/`，文件名要匹配 `filenamePattern`（默认 `^\\d{4}-\\d{2}-\\d{2}(-.+)?\\.md$`）。以 `ops` agent 为例：\n\n```bash\ncd ~/.openclaw/agents/ops/workspace/memory\nNOW=$(date +%Y-%m-%d)\nYDAY=$(date -v-1d +%Y-%m-%d)\necho \"# 测试 memory\" > ${NOW}.md\necho \"# 昨天的笔记\" > ${YDAY}.md\n```\n\n`memory/` 目录是**按 agent 划分**的（每个 agent 都有自己的目录：`~/.openclaw/agents/<agentId>/workspace/memory/`）。选一个容易触发新会话的 agent —— 一般是你最常聊的那个。\n\n### 2. 触发一个新会话\n\n\"新会话\"指的是 gateway 第一次见到的 session。常用触发方式：\n\n- 在该 agent 从未回复过的 Discord 频道发消息（全新话题帖对每个 agent 都有效）\n- 在该 agent 的主会话中执行 `/new` 或 `/reset`\n- 重启 gateway（缓存重置，所有活跃会话都被当作新会话）\n\nCron 任务也是合法触发方式 —— 它们创建独立 session。\n\n### 3. 查看 gateway 日志\n\n跟踪 gateway 日志，搜索 `[memory-inject]`：\n\n```bash\n# macOS\ntail -F ~/Library/Logs/openclaw/gateway.log | grep --line-buffered memory-inject\n\n# 或一次性查询\ngrep \"\\[memory-inject\\]\" ~/Library/Logs/openclaw/gateway.log | tail -5\n```\n\n**成功**的输出长这样：\n\n```\n[plugins] [memory-inject] injected 1 memory file(s) (~399 tokens) into agent:ops:discord:channel:1478705016792551466\n```\n\n看到这行说明插件正常工作。如果没看到，参考下面的 [日志格式说明](#日志格式说明) 理解各种日志行的含义。\n\n### 多 agent 验证\n\n要确认插件对你**所有** agent 都生效，对每个 agent 重复步骤 2。最快的方式是给每个 agent 的 Discord 频道（或主话题）各发一条消息，然后查日志：\n\n```bash\ngrep \"\\[memory-inject\\]\" ~/Library/Logs/openclaw/gateway.log \\\n  | awk -F'into ' '{print $2}' \\\n  | sort -u\n```\n\n预期：每个 agent 一行，各有独立的 `agent:<id>:...` sessionKey。\n\n### 确认当前生效的配置\n\n想确认插件实际加载的配置：\n\n```bash\nopenclaw config get plugins.entries.memory-inject.config\n```\n\n默认值：\n\n```json\n{\n  \"enabled\": true,\n  \"memoryDir\": \"memory\",\n  \"daysToLoad\": 2,\n  \"maxFiles\": 4,\n  \"maxTokens\": 4000,\n  \"filenamePattern\": \"^\\\\d{4}-\\\\d{2}-\\\\d{2}(-.+)?\\\\.md$\",\n  \"excludeAgents\": [],\n  \"contextLabel\": \"Recent memory (auto-injected by memory-inject plugin)\"\n}\n```\n\n## 日志格式说明\n\n插件通过 `api.logger` 输出日志（OpenClaw 会加 `[plugins]` 前缀后写入 gateway 日志）。所有日志行都带字面量字符串 `[memory-inject]`，方便 grep。\n\n| 级别 | 格式 | 何时出现 |\n|------|------|----------|\n| `info` | `[memory-inject] injected N memory file(s) (~T tokens) into <sessionKey>` | 注入成功，每个 session 恰好一次 |\n| `warn` | `[memory-inject] session_start without sessionKey or sessionId; skipping` | `session_start` 触发时没有 session 标识（极少发生 —— 健康的 gateway 不应该出现） |\n| `error` | `[memory-inject] failed to load memory: <error message>` | 磁盘读取失败（权限错误、文件消失等）—— 失败开放，session 继续，不影响后续对话 |\n\n### 成功日志详解\n\n```\n[plugins] [memory-inject] injected 1 memory file(s) (~399 tokens) into agent:kbadmin:discord:channel:1478685251898445906\n└──────┘ └──────────────┘ └────── ┘         └─────┘  └─────────────┘ └──────────────────────┘\n   │            │             │                │             │                    │\n OpenClaw   插件 tag    文件数        预估 token 数        sessionKey —— 唯一标识\n 日志前缀              of files      = totalChars / 4      本次注入的 session\n```\n\n- **文件数**：经过 `maxFiles` 和 `maxTokens` 过滤后实际加载的文件数。可能小于 `daysToLoad` 允许的数量。\n- **预估 token 数**：字符数 / 4，保守估计。实际 token 数可能偏差 ±30%（CJK 压缩更好，代码更差）。\n- **sessionKey**：OpenClaw session 标识。Discord 场景下格式为 `agent:<id>:discord:channel:<channelId>`；cron 任务下为 `agent:<id>:cron:<jobId>:run:<runId>`。用它能关联到 session transcript。\n\n### 启用 debug 级日志\n\n插件只在 `info` / `warn` / `error` 级别输出。想看 OpenClaw 加载插件的诊断信息（包含本插件），提高 gateway 日志级别：\n\n```bash\nopenclaw config set diagnostics.logLevel debug\n```\n\n然后重启 gateway。启动时看包含 `memory-inject` 的日志，能确认插件的 hook 已经注册。验证完成后恢复原级别。\n\n## 故障排查\n\n### 没有找到 memory 文件\n\n1. **先看日志里的成功行。** 跑\n   `grep \"\\[memory-inject\\]\" ~/Library/Logs/openclaw/gateway.log`。如果完全没有，说明 hook 没触发 —— 跳到下一节。\n2. **检查文件命名是否符合 `filenamePattern`。** 默认要求 `YYYY-MM-DD.md` 或 `YYYY-MM-DD-slug.md`。像 `notes.md` 或 `2026-06-23.txt` 不会被匹配。详见 [memory 文件匹配规则](#memory-文件匹配规则)。\n3. **确认文件 mtime 在时间窗内。** `daysToLoad=2` 表示过去 48 小时内的文件。3 天前的文件即使名字带今天的日期也会被跳过。\n4. **确认 `enabled` 是 `true`**：`openclaw config get plugins.entries.memory-inject.config`。\n5. **检查 `excludeAgents` 列表。** 如果测试的 agent 在里面，插件会静默跳过（这是有意的 —— 不会对被排除的 agent 给出警告）。\n\n### hook 没有触发\n\n1. **检查 OpenClaw 版本**：`openclaw --version`。需要 2026.6+，`session_start` 和 `before_prompt_build` hook 是在这个版本加入的。\n2. **确认插件已加载**：`openclaw plugins list | grep memory-inject` 应该显示 `enabled` 状态。如果行不存在，安装失败 —— 跑 `openclaw plugins inspect memory-inject` 看详情。\n3. **确认安装后重启过 gateway。** Hook 只在启动时注册。运行中安装不重启的话，插件会显示 enabled 但 hook 不触发。\n4. **换个 session 触发方式。** 如果 `/new` 没触发 hook，试试全新的 Discord 话题帖 —— 有时主会话被恢复得太久，`session_start` 很久没触发了。插件专门为新会话设计，对\"恢复会话\"无效。\n\n### `injected 0 memory file(s)` 是正常输出\n\n如果日志显示 `injected 0 memory file(s)`，说明 hook 触发正常 —— 只是没找到匹配文件。这不是错误。可能原因：\n\n- workspace 下的 `memory/` 目录不存在或为空\n- 所有文件都不匹配 `filenamePattern`\n- 所有文件 mtime 都超出 `daysToLoad` 时间窗\n\n想让它注入，参考上面的 \"没有找到 memory 文件\" 步骤。\n\n### 日志中出现 error 行\n\n看到 `[memory-inject] failed to load memory: ...`：\n\n- **Permission denied**：gateway 进程没权限读 memory 文件。检查文件权限，确认 workspace 目录归运行 gateway 的用户所有。\n- **File too large**：文件超过 `maxTokens * 4` 字符。要么精简文件内容，要么调高 `maxTokens`，要么调低 `maxFiles` 让它被跳过。\n- **EISDIR / Not a file**：`memory/` 路径指向了文件而不是目录。检查 `memoryDir` 配置。\n\n插件在所有错误上**失败开放** —— 加载失败不会阻塞 agent 的 turn，session 会继续（没有注入）。\n\n## 开发\n\n想参与贡献？完整开发环境搭建见 **[CONTRIBUTING.md](CONTRIBUTING.md)**\n（构建、测试、类型检查命令、代码规范、发布流程）。\n\n### 项目结构\n\n```\nsrc/\n├── index.ts            # 插件入口，注册 hook\n├── inject.ts           # hook 逻辑：session_start + before_prompt_build\n├── memory-loader.ts    # 扫描、筛选、读取 memory 文件\n├── config.ts           # 配置解析和校验\n├── session-cache.ts    # session 缓存，保证每个 session 只注入一次\n└── types.ts            # TypeScript 类型定义\ntest/\n└── *.test.ts           # 单元测试\n```\n\n## 许可证\n\nMIT\n\n## 作者 / 反馈\n\n- 作者：[dannyge](https://github.com/dannyge)\n- 问题反馈：[https://github.com/dannyge/openclaw-memory-inject/issues](https://github.com/dannyge/openclaw-memory-inject/issues)\n- 贡献指南：**[CONTRIBUTING.md](CONTRIBUTING.md)**","readmeFilename":"README.zh.md"}