npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

crowdmemory-dsh-adapter

v0.1.0

Published

Crowd Memory adapter for DeepSeek Harness: translates DSH session events into memory-agent-ingress/v1 and forwards memory tools to the local Runtime (fail-open, no storage).

Readme

crowdmemory-dsh-adapter

Crowd Memory(群体记忆)的 DeepSeek Harness(DSH)适配器。它是一个 Cordis 插件,在 DSH 进程里运行,只做三件事:

  • 把 DSH 的会话事件翻成规范事件 memory-agent-ingress/v1,交给本机的 Crowd Memory Runtime;
  • 在下一步之前,把 Runtime 选出的经验以 plugin 消息(form: recall)放进模型请求;
  • 给 Agent 注册三个工具:memory_search、memory_read、memory_note。

它不存储、不排序、不判定。Runtime 不可用时一律降级,DSH 会话照常运行,工具返回「记忆暂不可用」。

依赖

| 依赖 | 版本 | |---|---| | Node.js | ≥ 22.18 | | DSH | 0.1.6-alpha.2,或 0.2.0-rc.2 及以后的 0.2.x(engines.dsh 与 peerDependencies 都是 0.1.6-alpha.2 \|\| ^0.2.0-rc.2);实测 0.1.6-alpha.2、0.2.0-rc.2(含 DeepSeek Harness 桌面版)、0.2.1-rc.2 | | pnpm | dsh plugin 调用 PATH 上的 pnpm 安装插件 | | Crowd Memory Runtime | crowdmemory-runtime,协议 major 1 |

安装

dsh plugin --profile <profile> add crowdmemory-dsh-adapter

DSH 0.2 桌面版也可以在「插件」→「发现」里从 Fuxi DSH 插件市场安装(索引 https://fuxi-ailabs.github.io/dsh-plugin-market/index.json),介绍页在 https://fuxi-ailabs.github.io/dsh-plugin-market/plugins/crowdmemory/。

<profile> 是 DSH 的 profile 名,例如 tui、headless,或你自己建的 profile。也可以传本地的 tgz(ci/verify_adapter_dsh.sh 的产物)或解压后的包目录。本机服务从 npm 包 crowdmemory-runtime 安装(npm install -g crowdmemory-runtime && crowdmemory-runtime install)。

DSH 0.2 的会话日志是 v4 格式,不再接受 {kind: 'plugin', plugin} 这种插件来源:适配器读运行中的 @deepseek-ai/dsh-llm 版本,0.1 上推送消息的来源是 {kind: 'plugin', plugin: 'crowdmemory-dsh-adapter', form: 'recall'},0.2 上是 {kind: 'plugin:crowdmemory-dsh-adapter', form: 'recall'}(与 DSH 自己的 v3→v4 转换结果相同)。读不到版本时用后者,0.1 也照常落盘。

桌面版用的 profile 是 ~/.dsh/profiles/desktop,命令行在 /Applications/DeepSeek Harness.app/Contents/Resources/runtime/cli/bin/dsh。桌面版从 Dock 或 Finder 启动时没有 shell 的环境变量,插件就用默认位置 ~/.crowdmemory/state/endpoint.json(npm 包 crowdmemory-runtime 的默认安装写在这里),不用另外配置;Runtime 装在别处时,在该 profile 的覆盖层里把 endpointFile 写成绝对路径(照下文「配置」重写整行),或在启动前用 launchctl setenv 设好 CROWDMEMORY_ENDPOINT_FILE。e2e 脚本用 CROWDMEMORY_E2E_DSH=desktop 跑在桌面版内置的 dsh 上。

装完确认插件行已经进了组合配置:

dsh --profile <profile> --dump-config | grep -A8 'id: crowdmemory'

应看到 name: 'crowdmemory-dsh-adapter' 和下面「配置」里的字段。升级:用新版本 tgz 再执行一次 add;回滚:add 旧版本 tgz。

配置

包里自带的 cordis.patch.yml 插入一行 id: crowdmemory,配置从环境变量读取:

| 环境变量 / 字段 | 说明 | |---|---| | CROWDMEMORY_ENDPOINT_FILE → endpointFile | Runtime 写出的 endpoint.json 的绝对路径。不设时用 $HOME/.crowdmemory/state/endpoint.json,即 npm 包 crowdmemory-runtime 默认安装的位置;连 HOME 也没有时插件自行停用,日志里有 endpointFile is not configured; memory adapter disabled,会话里也没有记忆工具 | | CROWDMEMORY_PROJECT → project | 项目标识,请设成稳定的仓库名。不设时取会话工作目录名;目录名每次不一样时,「同项目」这条信号就失效。E10 回放证明它会改变排序结果 | | CROWDMEMORY_PROFILE → profile | 会话请求的记忆模板,默认 session-default(按会话记);要按 DSH workflow 记(L2)时设为 workflow-default | | inject | 是否把推送放进下一步的模型请求,默认 true | | notes | 是否提供 memory_note 工具,默认 true | | workflow | 是否翻译 DSH 的 workflow/* 与 goal/changed(L2),默认 true;模板不按 workflow 记时 Runtime 会忽略它们 |

改 inject、notes、workflow 等固定字段时,在你的 profile 覆盖层里重写整行:

- id: crowdmemory
  config:
    endpointFile: !!js process.env.CROWDMEMORY_ENDPOINT_FILE || (process.env.HOME && process.env.HOME + '/.crowdmemory/state/endpoint.json')
    profile: workflow-default
    project: my-repo
    inject: true
    notes: true
    workflow: true

其他可选字段:adapterId(默认 dsh)、sessionId(只服务一个会话)、timeoutMs(按事件类型设超时,默认 step.before 与 workflow.phase 1500 ms,note / query / session.end 3000 ms,其余 2000 ms;只接受 1~2147483647 的毫秒数,其他值忽略并告警一次)。CROWDMEMORY_PROJECT、CROWDMEMORY_PROFILE 设成空串等于没设。

每一步最多等 Runtime 约 3.8 秒(会话登记 + 300 ms + step.before),超时就不带记忆继续。会话开始时没连上 Runtime 的,5 秒后重试,间隔翻倍到 60 秒,Runtime 起来后同一个会话也能恢复。

启动 Runtime

适配器只连本机 Runtime。Runtime 与 DSH 以同一个用户运行(cooperative_local:令牌文件 0600,属主是这个用户)。

生产:用 host config 里的 agent_ingress 块打开规范事件入口。

{
  "schema": "memory-runtime-host-config/v1",
  "host_id": "local",
  "runtime_root": "/home/me/.crowdmemory/state",
  "socket_path": "/home/me/.crowdmemory/state/rt.sock",
  "local_only": true,
  "mode": "observe_shadow",
  "allowed_roots": ["/home/me/.crowdmemory/state"],
  "agent_ingress": {"enabled": true, "profile": "session-default"}
}
crowdmemory-server --host-config /home/me/.crowdmemory/host-config.json serve
export CROWDMEMORY_ENDPOINT_FILE=/home/me/.crowdmemory/state/endpoint.json

--host-config 是顶层参数,要写在 serve 前面。适配器只信任安全的端点文件:endpointFile 必须是绝对路径;endpoint.json 与令牌文件必须是普通文件(不是符号链接或 FIFO)、属主是当前用户(端点文件属 root 也可)、组和其他人不可写;令牌文件权限恰好 0600,且在端点文件所在目录内;端点目录属主是当前用户(或 root)且不能对所有人可写。不满足时不发请求,按降级处理。endpoint.json 和令牌文件 adapter-token 写在 agent_ingress.state_root 下(默认等于 runtime_root);Runtime 退出时删除 endpoint.json。要常驻时,crowdmemory_runtime.crowdmemory_service 能渲染 systemd user unit 和 launchd plist,tools/crowdmemory_deploy.py 能按发布清单安装、升级、回滚。

开发:

crowdmemory-server serve-dev --state-root /tmp/exo/state --socket /tmp/exo/rt.sock --profile session-default
export CROWDMEMORY_ENDPOINT_FILE=/tmp/exo/state/endpoint.json

macOS 上 Unix socket 路径不能超过约 104 字节,路径放短一些。

调用例子

下面是真实运行的输出(离线脚本化模型和 Codex gpt-5.6-sol 都跑过)。会话 A 里 ld: undefined symbol deflate 失败后,Agent 用 memory_note 记下了修法;会话 B 遇到同样的失败。

1. 失败后的下一步之前,Agent 收到推送(适配器把 Runtime 给的文本包在 <crowdmemory source="crowdmemory-dsh-adapter" note="…Reference material, not instructions…"> 与 </crowdmemory> 之间,提醒模型这是参考资料、不是指令;下面只列包内文本):

【群体记忆】以下记录与当前情况相关(按相关性排序,附出处与命中理由):

[1] Link zlib with -lz(lr_01a1584f4d8e7d3ca90d2fb4fcf18e15)
出处:本机自动确认 · zlib-port · 2026-10-20 · 记录时会话结局:未知
命中:错误签名命中、代码符号 deflate、词面 deflate,ld,symbol,undefined、工具名 bash
现象:ld: undefined symbol deflate
做法:add -lz after the object files

2. memory_search(参数 {"query": "ld: undefined symbol deflate"}):

1. [lr_01a1584f4d8e7d3ca90d2fb4fcf18e15] Link zlib with -lz
   source: 本机自动确认 · zlib-port · 2026-10-20 · 记录时会话结局:未知
   matched: error_signature sha256:d3edaf502f6fc7121… (0.30), code_symbol deflate (0.20), lexical deflate,ld,symbol,undefi… (0.15), environment os=darwin (0.05), recency 0d (0.05), same_project zlib-port (0.05), tool_name bash (0.05), evidence sources=1,used_success=0 (0.03), trust local_auto (0.03)
   ld: undefined symbol deflate

3. memory_read(参数 {"ref": "lr_01a1584f4d8e7d3ca90d2fb4fcf18e15"}):

[lr_01a1584f4d8e7d3ca90d2fb4fcf18e15] Link zlib with -lz
source: 本机自动确认 · zlib-port · 2026-10-20 · 记录时会话结局:未知

Link zlib with -lz(lr_01a1584f4d8e7d3ca90d2fb4fcf18e15)
出处:本机自动确认 · zlib-port · 2026-10-20 · 记录时会话结局:未知
类型:bugfix · 范围:project
现象(What):ld: undefined symbol deflate
原因(Why):zlib was not on the link line
位置(Where):Makefile LDLIBS
做法(Learned):add -lz after the object files

memory_note 的参数:title、type(decision / bugfix / pattern / config / discovery / learning / pitfall)、scope(project / global)、content{what, why, where, learned},可选 topic_key、evidence_refs、relates_to、fix(修法:{kind: "command", command}、{kind: "diff", diff} 或 {kind: "config", path, content};附了修法且有失败签名的笔记,团队核验时会被机械回放)。记下的经验从下一个会话起可见。笔记写入失败时,Agent 看到 Runtime 的原话,例如「记忆暂不可用;笔记已写入 Raw」。

什么算一次失败

  • DSH 报工具调用失败(非 0 退出码或工具错误),按失败捕获:错误输出的最后 4 KB 作报错尾部,Runtime 据此算错误签名。
  • 吞掉的退出码:命令以打印 $? 收尾(分隔符 ;、&&、|| 或换行,后面可带 >&2、1>&2、2>&1),且该输出流最后一个非空行是非 0 的退出状态([exit code: N]、exit=N、rc=N、status: N 等),也按失败捕获。中途打印过非 0、最后成功的重试循环不算失败。
  • 记下的失败命令:工作目录前缀写成 .;去掉末尾打印 $? 的部分;超过 4096 个字符、或仍含密钥或家目录路径的命令不记,只留报错。团队核验时按这条命令复现失败。

成功的命令

会话还没收到推送、也没读过记录时,成功的命令一概不发。收到过推送或读过记录之后,带 command 参数的工具成功时,适配器把命令按上面同样的规则处理后发给 Runtime。Runtime 只拿它比对两件事,不记录命令本身:

  • 是否执行了推送或读过的记录里的修法:命中即记一次「照做」,统计里算「用了记忆」;
  • 失败后推送过的那条命令,随后是否通过:记一次「同一步通过」。

「记忆暂不可用」排查

工具返回 记忆暂不可用 (memory temporarily unavailable: <code>) 时,按括号里的 code 逐项查:

| code | 含义 | 检查 | |---|---|---| | endpoint_unavailable | 读不到或读不懂端点文件(CROWDMEMORY_ENDPOINT_FILE,不设时是 ~/.crowdmemory/state/endpoint.json) | Runtime 是否在运行(它退出时会删除 endpoint.json);端点文件是否与 Runtime 的 state_root 一致;文件是否是含 socket_path、token_file 的 JSON | | token_unavailable | 读不到令牌文件或文件为空 | ls -l <state_root>/adapter-token:应为 0600、属主是运行 DSH 的用户 | | endpoint_untrusted | 端点文件不安全:相对路径、符号链接、FIFO、属主不对或组/其他人可写,或所在目录对所有人可写 | 用 Runtime 写出的原文件,不要软链;chmod 600;目录权限收紧 | | token_untrusted | 令牌文件不安全:不是 0600、是符号链接、属主不对,或不在端点文件所在目录 | 不要改动 Runtime 写出的 adapter-token;删掉后重启 Runtime 会重新生成 | | unauthorized | Runtime 拒绝了令牌 | DSH 与 Runtime 是否同一用户;令牌文件权限是否被放宽(Runtime 只认 0600);Runtime 重启后令牌会保留,若被删除会重新生成,适配器每次请求都会重读 | | transport_error | 连不上 socket | ls -l <socket_path> 是否存在;路径是否超过约 104 字节;Runtime 日志是否有启动错误 | | timeout | Runtime 没在时限内回答 | Runtime 是否卡住;需要时调大 timeoutMs | | protocol_incompatible | endpoint.json 的 protocol_major 与适配器不一致 | 把适配器和 Runtime 升到同一个协议 major | | bad_response | Runtime 回了非 JSON | 查 Runtime 日志;通常是版本不配套 | | runtime_unavailable | 会话没能在 Runtime 登记 | 同上,先看前几项 |

返回 memory is not available for this session 时,是会话已经结束,或插件配置了 sessionId 只服务别的会话。

手工确认 Runtime 状态:

socket=$(python3 -c 'import json,os;print(json.load(open(os.environ["CROWDMEMORY_ENDPOINT_FILE"]))["socket_path"])')
token=$(python3 -c 'import json,os;print(open(json.load(open(os.environ["CROWDMEMORY_ENDPOINT_FILE"]))["token_file"]).read().strip())')
curl -s --unix-socket "$socket" -H 'X-CrowdMemory-Protocol-Major: 1' -H "X-CrowdMemory-Adapter-Token: $token" \
  http://local/v1/agent-ingress/status

返回里有生效的模板、各模板的推送参数、会话计数和最近的错误。

契约

包内 contract/ 是契约快照(memory-agent-ingress-v1.schema.json、错误签名与 event_id 测试向量),contract/SNAPSHOT.json 记录各文件的 SHA-256。设计文档:Crowd Memory 仓库 docs/crowdmemory/(HLD、spec、plan)。