@fuxi-ailabs/crowdmemory-opencode-adapter
v0.1.1
Published
Crowd Memory adapter for opencode (1.x and 2.x): translates opencode session events into memory-agent-ingress/v1, folds Runtime pushes into the next model step and adds the memory tools (fail-open, no storage).
Keywords
Readme
crowdmemory-opencode-adapter
npm 发行包:@fuxi-ailabs/[email protected],要求 Node.js ≥22.18 和本机 Runtime。
Crowd Memory(群体记忆)的 opencode 适配器。它是一个 opencode 插件,在 opencode 进程里运行,做的事和 DSH 适配器相同:
- 把 opencode 的会话事件翻成规范事件
memory-agent-ingress/v1,交给本机的 Crowd Memory Runtime; - 在会话第一步和工具失败后的那一步之前,把 Runtime 选出的经验放进模型请求,之后每一步都留在原位;
- 给 agent 加三个工具:
memory_search、memory_read、memory_note。
它不存储、不排序、不判定。Runtime 不可用时一律降级,会话照常运行,工具返回「记忆暂不可用」。
同一个包同时支持 opencode 的两条发布线:
| opencode | 包名 / 安装方式 | 插件入口 |
|---|---|---|
| 1.x(npm opencode-ai,实测 1.19.5) | opencode.json 的 plugin | default.server(input, options) |
| 2.x(brew / npm @opencode/cli,实测 2.2.5) | opencode.json 的 plugins | default.setup(ctx) |
两边的加载器各取自己的字段,互不影响。
安装与配置
装好 Runtime(见仓库的 distributions/memory-runtime-npm),然后在 opencode 配置里加插件。
opencode 1.x:
{
"plugin": [["@fuxi-ailabs/[email protected]", { "project": "my-repo" }]]
}opencode 2.x:
{
"plugins": [{ "package": "@fuxi-ailabs/[email protected]", "options": { "project": "my-repo" } }]
}本地开发时把包名换成这个目录的绝对路径(先 pnpm build)。
| 选项 / 环境变量 | 说明 |
|---|---|
| endpointFile / CROWDMEMORY_ENDPOINT_FILE | Runtime 写出的 endpoint.json 的绝对路径;都不设时用 ~/.crowdmemory/state/endpoint.json |
| project / CROWDMEMORY_PROJECT | 项目标识,请设成稳定的仓库名;不设时取会话工作目录名 |
| profile / CROWDMEMORY_PROFILE | 记忆模板,默认 session-default |
| inject | 是否把推送放进模型请求,默认 true |
| notes | 是否提供 memory_note,默认 true |
| CROWDMEMORY_LOG | 设了才把插件日志写到 stderr(默认静默,TUI 占着终端) |
事件对照
| Crowd Memory | opencode 1.x | opencode 2.x |
|---|---|---|
| session.start | session.created(子会话带 parentID),或第一步时查会话 | session.created,或第一步时查会话 |
| step.before + 推送 | experimental.chat.messages.transform | session hook context |
| tool.result | 下一步时读历史里已结束的工具调用,加 message.part.updated | tool hook execute.after |
| context.compaction | session.compacted 后取 summary: true 的消息 | session.compaction.ended 的 text |
| subagent.end | 父会话的 task 工具结束(后台任务不算结束) | 父会话的 subagent 工具结束(后台运行不算结束) |
| session.end | 子代理结束、session.deleted、插件 dispose | 子代理结束、session.deleted、插件清理 |
| memory_* 工具 | tool | tool.transform,直接暴露(codemode: false) |
规则与 DSH 适配器一致:一个会话只发一次 session.start,Runtime 起不来就按 5 秒起、翻倍到 60 秒重试;同一会话的事件排队,保证工具结果先于下一步的 step.before 到达;一步最多等约 3.8 秒,晚到的推送留到下一步;写文件只记路径;推送或读取过记忆之后,成功的命令也上报。
和 DSH 的差别
- 没有 L2:opencode 没有 workflow 引擎和 goal 事件,不声明
workflow_events、goal_events。 - 输出合在一起:opencode 把 stderr 并进 stdout,错误尾部和签名按合并后的输出算,同一个错误在两边的签名可能不同。
- 召回消息不落盘:opencode 每一步都从存储重建消息,适配器把召回记在内存里、每步插回原位。进程重启后旧召回不再出现;压缩后,锚点消息不在了,召回随之丢弃。
- 会话结束:opencode 没有“会话结束”事件。主会话在删除或 opencode 退出时结束,子会话在父会话的子代理工具结束时结束。
开发
pnpm install
pnpm typecheck
pnpm test # 模拟 1.x / 2.x 宿主 + 假 Runtime(真实 Unix socket)src/core/、contract/、tests/fake-runtime.mjs、e2e/auth-proxy.mjs、tests/core-copies.test.ts 是适配器公共包 distributions/memory-adapter-core 的副本(Runtime 客户端、错误签名、脱敏、掩码判断、推送包装、重放命令、三个记忆工具的文案与返回),CORE.json 记了哈希。不要在这里改:改公共包,再在那里跑 npm run sync,否则 tests/core-copies.test.ts 和仓库门禁都会失败。
真机端到端(脚本化模型 + 假 Runtime,配置与数据放在临时目录,不碰本机 opencode):
OPENCODE1=/path/to/opencode-1.x e2e/run-e2e.sh 1
OPENCODE2=/path/to/opencode-2.x e2e/run-e2e.sh 2通过的标准:会话 A 依次发出 session.start → step.before → tool.result(失败)→ step.before → note → session.end;会话 B 遇到同样的失败后,下一次模型请求带有 <crowdmemory> 推送。
