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

@shgroup/dsh-serenity-hooks

v1.39.3

Published

宁静号 ACC harness(Native Cordis 插件)——给 DeepSeek Harness 装一个「AI 工作区」:11 个工具(container_fs/container_trajectory/dashboard/container_git/msm/praxis/handyman/localstore/container_admin/im-bridge/acc-diag)+ 机械约束(安全模式/工作区围墙/密钥守卫/对外输出守卫)+ 工作日志与原地重建 + 网页登录入口/微信桥/子角色

Readme

宁静号 ACC —— 给 DeepSeek Harness 装一个「AI 工作区」

一句话:装上这个插件,你在电脑上给 AI 划一块自己的工作区(就是一个普通目录), AI 在里面干活时就有了记忆、纪律、工具和边界——中途换模型、重启电脑、第二天再来,都能接着干。

适用 DeepSeek Harness(下称 DSH)0.1.5-rc.2 及以上。 想了解背后的想法(为什么叫"认知容器"),看 docs/cognitive-container-theory.md;本文只讲能干什么、怎么用

几个词先说明白(后面都用这几个词,不再解释):

| 词 | 说人话 | |---|---| | 工作区 / CCC | 一个目录,里面放一个 .serenity 空标记文件。DSH 在别的目录里跑,插件完全不插手;一旦你进到这种目录,它自动生效 | | 插件 / ACC | 就是这个仓库(npm 包 @shgroup/dsh-serenity-hooks)。它给 DSH 加工具、加约束、加记忆 | | MSM | 你写在工作区里的可执行小工具(一个脚本 + 一行注册)。AI 通过 msm("名字", ["参数"]) 调用它们 | | SESSION.md | 工作区里的"工作日志"。AI 把目标、决定、进度写进去,中断后再来就从这里接着干 |


1. 它到底解决什么问题

不吹概念,直接说四个每天都会遇到的麻烦:

| 麻烦 | 没有它 | 有了它 | |---|---|---| | AI 干到一半忘了自己在干什么 | 上下文一满,之前的目标、决定全丢,你得重讲一遍 | 每个工作区有一本工作日志,AI 每推进一段就写进去;上下文满了就"换载体"重来,日志还在原地,接着干 | | AI 到处乱翻、乱改文件 | 它能读你整台机器的文件,包括密钥 | 工作区有围墙:墙内随便用,墙外一律拒绝;密钥文件连"读"都读不到 | | 出门在外想用 | 只能坐在那台电脑前 | 自带一个带登录的网页入口(密码或手机验证码二选一),手机也能用 | | 家人想用微信问点事 | 得教他们装软件、开电脑 | 扫一次码把微信接上,家人在微信里说话,AI 用你定义的人格回话 |


2. 快速开始(2 分钟)

前置:Node ≥ 20(或 bun)、DSH 0.1.5-rc.2 及以上。

# 1. 装插件(自动加入 DSH 的 web profile)
dsh plugin --profile web add @shgroup/dsh-serenity-hooks

# 2. 重启 dsh web(插件和网页端界面一起生效)
dsh web

# 3. 验证:进到带 .serenity 标记的目录里开一个会话
#    · 会话开头会自动带上这个插件的身份说明和技能目录
#    · 网页端会话标题旁出现一个状态胶囊(绿点常亮 + SAFE 滑块)
#    · 输入 dashboard health,看到工作区三项检查全通过

卸载:dsh plugin --profile web remove @shgroup/dsh-serenity-hooks

从源码装(自己改代码时用):

git clone https://github.com/tellmewhattodo/dsh-serenity-plugin.git
cd dsh-serenity-plugin
dsh plugin --profile web add link:$(pwd)/hooks/dsh-serenity-hooks

⚠️ 别用 dsh plugin add github:... 这种写法——那个地址指向的是仓库根目录(不是插件包本身),装上了也不会生效。用 npm 或上面的 link: 方式。

安全模式:点一下网页端胶囊里的 SAFE 滑块,bash 就会从 AI 的工具列表里直接消失(不是报错,是它根本看不到这个工具)。于是 AI 只能走你注册过、测试过的小工具通道。这个开关是给你用的——AI 看不见、也打不开。


3. 装完之后你多了什么

3.1 十一个工具(其中两个按条件出现)

| 工具 | 干什么 | 什么时候用 | |---|---|---| | container_fs | 在工作区里管文件:列目录、找文件、复制、移动、新建、追加、在文件管理器里打开 | 需要看/整理工作区里的文件时 | | container_trajectory | 一条轨迹:它的身体(SESSION.md)+ 它的时间轴。建/看/切换/原地重建之外,还能登记未来唤醒(= 未来某时刻 + 一条消息,可唤醒自己,也可唤醒别的轨迹) | 任何多步骤的活儿,第一步就是它;想让 AI 未来某刻自动接着干也用它 | | dashboard | 仪表盘:工作区健康检查(三项)、当前时间、等待 | 进工作区先自查一下;等外部服务时用 | | container_git | git 操作:status / commit / push / log / pull / diff | 提交和推送代码;它绝不自动强推 | | msm | 小工具执行入口:msm("名字", ["参数"]);名字记不全就给候选;inspect=true 看用法 | 调用工作区里注册的任何小工具 | | praxis | 按需给 AI 注入三套"做事方法":输出自检(eap)、设计对齐(neat)、认知连续性(cce) | 要它把话说清楚 / 先对齐再动手时 | | handyman | 杂工:派一个便宜模型的助手干活。默认模式(foreground)= 一次串行委派、拿回结果;background 模式= 循环干活直到完成(完成码校验 / 轮次上限 / 自动重启 / 进度文件),也可一次派多个并行 | 大批量、重复性的活(扫描几十个技能、逐用例回归) | | localstore | 存密钥和配置(凭据、偏好两个命名空间) | API key、密码集中放一处,不进 git | | container_admin | 机务舱:管理子角色、管理小工具注册表、查看全部配置 | 定义"子角色"、注册新小工具、改配置时 | | im-bridge | 给 IM 联系人发消息(目前是微信):发文本、发文件、查已配置联系人、查通道状态。每次成功发送自动进工作区的消息记录 | 想让 AI 主动给家人/同事发消息(见 §6.6)。只在工作区配了微信桥时才出现,且只能发本工作区的消息 | | acc-diag | ACC 运行态诊断:一次调用出全报告——当前有多少会话活着、各自属于哪个工作区、唤醒时钟的武装态与 tick 次数、唤醒登记表的每一条(含状态 / 投递结果 / 补跑窗口) | ACC 维护者专用默认对所有工作区隐藏,只有在工作区配置里点名(exclusiveTools)才出现 |

改过名(旧名已彻底停用,没有兼容别名):下面每组的箭头链是逐个发布版本的名字,末项才是今名——cc_fscontainer_fs · cc_gitcontainer_git · session+session_rebuildlogbook(v1.30/1.31)→ trajectory(v1.32)→ container_trajectory(v1.34,今名) · acc_kitdashboard · acc_msmmsm(执行)+ container_admin(管理)· eap/neat/ccepraxis · skiff_admincontainer_admin role · autopilot-trajectorytrajectory(v1.32)→ container_trajectory(v1.34,今名)。老会话里看到旧名,一律取所在那一组的末项

3.2 机械约束(AI 绕不过去)

这些不是"提示词里劝它别做",而是机制上做不到

| 约束 | 你会看到的效果 | 为什么这样做 | |---|---|---| | 安全模式 | bash 从工具列表里消失(每一步都同步一次),就算它想调也会被兜底拦下 | 走注册过的小工具,比让 AI 自己拼 shell 命令可靠得多 | | 工作区围墙 | 墙内什么都能干,墙外一律拒绝(连路径都解析不出去) | AI 不该碰工作区之外的东西 | | 黑名单 / 治理文件 | 可配黑名单;.serenity 这类治理文件禁止 AI 写 | 防止 AI 把自己所在的"地基"改坏 | | 密钥文件守卫 | localstore.json所有工具拒绝(包括 read/grep/glob) | 密钥值在结构上就出不来 | | 对外输出守卫 | 对外面的会话(子角色 / ACP / 重建会话)如果答出敏感词,会被打回重答,并告诉它命中了哪个词、该怎么改 | 外面的人不该看到内部机制 | | 轨迹提醒 | 做久了会提醒 AI"把进度写回工作日志",并要求它回一个确认码 | 提醒是机制,不是靠自觉 | | 工作日志体积提醒 | 工作日志(SESSION.md)超过 200KB 时提醒 AI"停下来重写一遍",并附四条重写原则(保留骨架 / 细节挪到附件文件 / 该合并的合并 / 其余你自己判断) | 日志越写越厚就没人读得完;重写比堆积便宜。阈值按工作区可调(sessionKeeper.sessionMdMaxKB,0 = 关) | | 重建前交接 | 要重建上下文时,会要求 AI 先把"手头做到哪了 / 还差什么 / 下一步做什么"写进工作日志末尾的固定小标题下;重建后的它第一件事就是去读那一段接着干 | 上下文被清空,但手头的事不能丢——写侧与读侧用同一个标题,读的时候才找得到 |

3.3 对外的入口

| 入口 | 默认端口 | 给谁用 | |---|---|---| | DSH 主界面 | 3080 | 你自己在本机用(插件不碰这个端口) | | 网页登录入口 | 3081 | 外部/手机访问完整界面:登录后反向代理到 3080,可配工作区白名单 | | 微信主动发送入口 | 3082(只绑 127.0.0.1) | 工作区外的脚本/集成用它给微信发消息(公网到不了,所以不需要密钥)。工作区里的 AI 不走这个端口,直接用 im-bridge 工具 | | 子角色调试页 | 3099(只绑 127.0.0.1) | 你调试"子角色"时用,能切换工作区、看对话轨迹 | | ACP + 对外问答页 | 3100(只绑 127.0.0.1) | 程序化接入(JSON-RPC)+ 给别人用的问答页(key 认证,只返回答案,不返回内部轨迹) | | 微信桥 | 无需端口(出站长轮询) | 家人在微信里直接和 AI 说话 |

默认只监听 127.0.0.1 的入口,要暴露到公网由你自己决定(隧道 / 反代 / 端口映射都行),插件不绑定任何特定做法。

3.4 省你一步:用 opencode 的模型

想在 DSH 里用 opencode 的网关(opencode.ai/zen),本来除了配路由还得手抄一串请求头—— 这些头是 opencode 用来做会话亲和路由的,少写一个 x-opencode-session/zen/go 面就直接 400 拒绝。 插件装好就自动配,这一步你不用管:

| 你的情况 | 插件做什么 | |---|---| | 已经配了 opencode 路由,但缺头 | 只补缺的那几个;你手写过的值一律不动(头名不分大小写,X-Titlex-title 一样算数) | | 一个 opencode 路由都没有,但环境里有 OPENCODE_API_KEY | 自动建 opencode-go 路由并带全头(没有 key 的人不受影响,不会平白多出一组模型) |

  • 只管"会话族"的头x-opencode-session / X-Session-ID / x-opencode-client / x-opencode-project。 前两个名字是同一个值的两个别名——你写了其中一个,就用你的值补上另一个,不会出现两个互相打架的会话 id
  • 不冒充 opencode 官方客户端X-Title / HTTP-Referer 这类"身份头"只在免费档的滥用判别里起作用, 插件不注入(替你骗额度不是我们该做的事,付费面本来也不需要它们);User-Agent 是 DSH 的保留名,想注也注不了
  • 会话标识是固定的dsh-serenity):DSH 的请求头在路由解析时一次算好,只能给静态值。 好处是同一台机器的请求稳定落同一个上游(对缓存友好);代价是做不到"按会话分区"
  • 配的是你自己的文件:写入 DSH 的 settings(llm-pi-ai.providers.<路由>.headers),随时可改可删。 不想要这个自动配置,就把本插件的 opencodeProvider.autoConfigure 关掉(关掉后一切回到手抄)
  • 密钥不碰:插件只补路由和头,OPENCODE_API_KEY 放环境变量即可

4. 一个工作区长什么样

工作区就是一个普通目录,加一个标记文件:

my-workspace/                     ← 工作区根目录(放一个 .serenity 就成)
├── .serenity                     ← 标记:这个目录是一个工作区
├── .opencode/
│   ├── serenity.json             ← 工作区级配置:助手模型白名单 / 日志阈值 / 子角色
│   └── skills/                   ← 领域技能(每个技能 = 一个领域的知识 + 可能有小工具)
│       ├── home-media/           ←   例如:媒体(找片源 / 做字幕 / 推送)
│       ├── home-wealth/          ←   例如:家庭财务
│       └── …(每个技能可以自带脚本)
├── AGENT_SESSIONS/               ← 工作日志库:每个目录一本 SESSION.md
│   └── 2026-09-08--S142--xxx/
│       └── SESSION.md            ← 目标 / 决定 / 进度(永远留在这里,不会被搬走)
└── _tmp/                         ← 运行时落盘:你粘贴的图片和文件
    ├── images_from_user/
    └── files_from_user/

5. 能拿它做什么(12 个真实用例)

下面这些都在真实部署里跑着。地址、账号、路径都做了泛化。

| # | 你想干的事 | 实际怎么走 | |---|---|---| | 1 | 长期项目不断线 | container_trajectory create 建轨迹 → 每推进一段写进去 → 中断后 container_trajectory use 接上 → 上下文满了 container_trajectory rebuild 原地重建并自动继续 | | 2 | 批量同步代码 | 当前仓库 container_git commit/push;多个子仓库一条命令全同步(自动提交 + 推送) | | 3 | 做一集字幕 | 搜片源 → 下载 → Whisper 转写 → 翻译 → 双语 SRT → 机械质检(7 项)→ 推送订阅/邮件 | | 4 | 服务器巡检 | 一条命令出 CPU/内存/GPU/容器/服务报告;重启容器也在同一条白名单通道里 | | 5 | 内网服务定位 | 仓库全景(分类/技术栈/关联)+ 设备端口扫描 | | 6 | 家庭财务 | 结构化记录资产/负债/收支/预算,随时查询汇总;房贷利率对比这类宏观跟踪 | | 7 | 家人档案 | 成员资料统一维护,工作区是唯一真相源 | | 8 | 想法随手记 | 想到什么就聊,AI 访谈式问清 → 结构化归档 → 定期回顾你的思考模式 | | 9 | 手机/外出使用 | 浏览器打开 http://内网地址:3081 → 输密码或 6 位验证码 → 直接用完整界面 | | 10 | 粘贴资料自动处理 | 粘图片 → 自动落盘 → 视觉模型识别(快递单/截图/图表);粘 PDF/压缩包 → 自动落盘 → 提取文本/解压/读表格 | | 11 | 微信里用 AI | 面板扫一次码 → 家人在微信发消息(文字/语音/图片/文件)→ 路由到指定子角色 → 回复回到微信 | | 12 | 定时自己干活 | 工作区配好巡航(间隔/目标会话/焦点/偏见脚本)→ 到点自动唤醒并注入焦点,全程在你眼前发生,可随时介入 |

典型一天

早上  服务器巡检(一条命令)→ 一切正常
上午  同步昨天的代码 → 子仓库全部推送
午间  收到 PDF 账单 → 粘进对话 → 自动落盘 + 表格提取 → 记进财务
下午  做一集视频字幕(转写 → 翻译 → 双语 SRT → 质检)→ 推送订阅
晚间  手机登录 3081 处理运维(验证码验证)
全程  每段工作都落在 SESSION.md 里 → 轨迹连续,随时换人/换模型/换机器接着干

6. 对外入口详解

6.1 网页登录入口(3081)

插件自己起第二个监听器,请求流程是:

外部浏览器 → http://内网IP:3081
  → 没登录 → 极简登录页(用户名 + 密码,或 6 位动态验证码,二选一;手机端适配)
  → 提交 → scrypt 校验 / TOTP 校验 + CSRF 校验 + 连续失败锁定(5 次 → 15 分钟指数退避)
  → 通过 → 下发 HttpOnly cookie(SameSite=Strict,24 小时滑动续期)→ 302 跳转
  → 已登录 → 反向代理到 127.0.0.1:3080(改写过 Host/Origin,作为信任栅栏)
  → 工作区列表按白名单过滤 + 新建工作区做校验
  → WebSocket 升级也转发(101 回写 + 双向错误监听,防止连接被压垮)

6.2 微信桥

工作区级配置(.opencode/serenity.jsonweixin 段),凭据放在工作区的 localstore.json(不落 git 明文)。 DSH 一个进程可以同时带多个工作区,每个工作区各自对接自己的微信。

  • 扫码绑定:设置面板 → 微信桥 → 选工作区 → 扫码(手机微信确认)→ 机器人 token 自动写入凭据
  • 多账号:每个账号独立扫码、独立移除
  • 能收什么:文字、语音(微信服务端自带转写,无需额外识别)、图片、文件 (图片和文件会从微信 CDN 下载并解密,落到 _tmp/weixin-inbound/,再把路径告诉 AI)
  • 正在输入:处理期间微信会显示"正在输入…"
  • 回复干净:自动剥掉思考过程,微信只看到正文
  • 记得住:同一个微信号对应固定会话,重启后恢复历史,不会"失忆"
  • 路由:微信号 → 子角色(精确匹配优先,* 兜底)
  • 主动发消息(v1.31.0):用 im-bridge 工具,AI 自己就能发—— im-bridge({channel:"weixin", action:"send", user:"yh", text:"内容"}) (发文件:action:"send-file" + file:"<工作区内的路径>",可加 caption)。 这个工具只能发本工作区的消息(没有"目标工作区"参数,不会发错容器),发出的消息会自动被记录。 它只在工作区配了微信桥时才出现在工具列表里——没配就看不到,而不是"看得到但一调就报错"。 (旧办法是工作区里自己写个小工具走 3082 端口,v1.31.0 起已退役;3082 保留给工作区外的脚本。)
  • 让 AI 自己决定怎么回(v1.30.10):配置 "weixin": { "autoReplyWithLastMessage": false } 后,插件不再自动把 AI 最后那段话转给用户,而是每轮告诉它"你必须自己发",并附上一条可直接照抄的 im-bridge 调用。 适合需要过程汇报、想分多条发、或者该安静就安静的角色。默认 true(保持原行为)。 该发却没发时,插件会打回提醒(最多 2 次);还是不发送,可以再开 "fallbackOnNoSend": true 让插件兜底把那轮的话转给用户(记录为 source: "reply-fallback"), 保证"消息不丢"。
  • 消息记录:配一个 weixin.hook 脚本,每收/发一条消息就把事件(JSON)喂给它,存哪里由你决定。 记录里 source: "reply" 表示"回复用户",source: "proactive" 表示"AI 主动发起", source: "reply-fallback" 表示"AI 没发、插件兜底发的"。
  • 排障msm("weixin-doctor", ["status"|"diag"|"verify"|"guide"])

6.3 子角色(Skiff)

你可以从一个"什么都能干"的助手身上,切出一个能力受限的小角色——不只是问答,也可以带操作能力:

{
  "skiff": {
    "roles": {
      "qa": {
        "model": "provider/model",              // 这个角色单独用哪个模型
        "msms": ["web-search", "vlm-describe"], // 它能调哪些小工具
        "tools": ["read", "grep", "glob"],      // 它能用哪些平台工具
        "systemPromptFile": "roles/qa.md"       // 它的人格与边界(也可以直接内联)
      }
    }
  }
}
  • 两份白名单分开配(小工具 / 平台工具),没列出来的一律隐藏
  • 调试页(3099)可以切工作区、看轨迹;回答用 markdown 渲染,思考过程折叠
  • container_admin role validate 校验配置,apply 才真正生效

6.4 对外问答页(3100)

  • key 认证(常量时间比较 + 失败 IP 锁定 + 可轮换)+ 容器白名单(留空 = 全部开放)
  • 只给答案:响应里只有 answer / answer_html / sessionId——内部轨迹、工具结果、机制信息都不出去
  • 默认只监听 127.0.0.1;要给别人用,怎么暴露(隧道/反代/端口映射)由你决定

6.5 轨迹与定时唤醒(trajectory)

trajectory(轨迹)是一等概念:一个工作区里可以有任意多条轨迹并行。

定时唤醒:用 container_trajectory send-later 登记一条"唤醒" = 未来某时刻 + 一条消息——可以给自己预约,也可以唤醒别的轨迹;落在工作区内的 AGENT_SESSIONS/wake-registry.json(可读可审计),到点由中心调度器投递,不阻塞、不等待、也不回执

即时投递:用 container_trajectory send-now 把一条消息现在就递过去,并且不排队——目标在内存里且正在跑轮次,就 steer 当场注入当前轮;目标空闲就立即起一轮;目标不在内存里就冷载入后投递等效于直接唤醒,但不等调度器的 5 分钟节拍)。它有同步回执(告诉你走了 live 还是冷载入),不落注册表(那张表专管"未来时刻")。

  • 两者只差两处:时刻(现在 / 未来)与回执(有 / 无)。"预约"天生是 fire-and-forget(不可回收、不回执),"递话"则是一次调用一次答复——各自语义干净,不把两种语义塞进同一个动作(🔴 更名:这对动作原名 wake-later / send-message,现名 send-later / send-now——族名取共享词干 send-、轴取 -later/-now,因为「唤醒」是两条路径共有的属性,不配做区分;硬切无别名

  • ⚠️ 回执只到"已注入 / 已起轮":它不表示目标已经执行或答复。要确证"目标真的动了",得看它自己的 SESSION.md不得凭回执结案

  • ⚠️ 唯一的例外路径steer 不可用时退回排队(fail-safe:宁可排队,不可静默丢消息)——此时回执文案写明"steer 不可用 ⇒ 退回 followup"。send-later 不受影响:预约的本职是"到点唤起",在跑时排队不打断当前轮是它被实证验收过的行为

  • 目标没打开也能唤醒:会话不在内存里时先把它载入再投递(冷唤醒);载入不了则条目留在登记表里并记下原因,不静默丢弃

  • "周期"归工作区自己:要一轮接一轮,就由收到唤醒的那条轨迹在每轮结束时再排一次下一轮——ACC 只提供"到点投递一条消息"这个原语,不替工作区决定节拍(焦点、节拍、偏见都由工作区自定;任意条轨迹并行、互不干扰)

  • 轨迹可以自带 skill:在它的 SESSION.md 顶部 frontmatter 写 skills: [名字, …],这条轨迹被绑定期间的每个请求都会注入这些 skill 的全文(适合把某个领域的做事方法直接挂在轨迹上);skill 名来自工作区数据,先过安全校验才会用于拼路径,找不到会在提示里明说"缺失"而不静默跳过

⚠️ 历史(v1.35.0 起已退场):ACC 曾自带一套"周期自唤醒 autopilot"——插件内时钟 + 工作区配置里的 topPrompt/偏见脚本 + 面板「周期自唤醒」开关 + container_admin autopilot 三动作(status/init/generate-bias)。v1.35.0 起整段删除。理由:它相对当时的 wake-latersend-later)只多两样——"周期节拍"与"提示词注入",而这两样工作区自己就能做(见上);且后者反而更强(支持冷会话唤醒,而 autopilot 要求目标会话已在内存里)。老会话 / 老文档里看到 container_admin autopilotautopilot-trajectory--auto 目录后缀、[Autopilot Trajectory · 唤起] 等字样,均按本条理解:那是已删除的机制。

6.6 安全模型

| 层面 | 做了什么 | |---|---| | 登录 | scrypt 密码哈希 + 常量时间比较 + 256-bit token + 24 小时滑动有效期 + 审计日志 | | 双因素 | TOTP(兼容 Authenticator),扫码绑定;密码和验证码二选一 | | 防爆破 | 按账号锁定:连续失败 5 次 → 锁 15 分钟,且指数退避 | | 防 CSRF | 登录双提交 + 配置写入校验 Origin + 服务端 token 集合(多标签页不冲突) | | 凭据 | 集中放 localstore.json(默认禁止提交到 git);密钥文件对工具结构性隔离 | | 对外输出 | 敏感词检测 → 打回重答,并告知命中词和规避方向 |


7. 配置分四层

| 层 | 位置 | 放什么 | |---|---|---| | DSH 原生设置 | DSH 的 settings.yaml | 简单开关:网关 / 重建 / 会话命名、重建阈值、子角色开关与调试端口、ACP 与问答页开关、巡航总开关(默认关)opencode 路由自动配置(默认开) | | 插件全局文件 | ~/.dsh/serenity-hooks.json(权限 0600) | 网关账号(scrypt + TOTP)、监听地址与端口、工作区白名单、cookie 安全开关、问答页 key | | 工作区配置 | .opencode/serenity.json | 助手模型白名单、日志阈值、安全模式黑名单、子角色、巡航(间隔/会话/焦点/窗口)微信(账号/路由/开关) | | 工作区凭据 | localstore.json | 密钥与本地偏好;微信机器人 token 也在这一层 |

原则:插件是全局的,工作区是具体的——账号、开关、阈值归插件层;角色、凭据、本地偏好归工作区层。


8. 上下文快满了怎么办

AI 一次能"记住"的内容有上限。满了不用你手动开新会话:

| 机制 | 说人话 | |---|---| | 工作日志(SESSION.md) | AI 的"笔记本",永远留在原地。目标、决定、进度都写这儿 | | 原地重建(container_trajectory rebuild) | 快满时它会提示 AI 主动重建:把这一轮对话清空,但重新注入"你是谁 + 继续 S### 的工作"——载体换了,活儿接着干。重建后的 token 计量也正确回落 | | 进度提醒 | 做久了会按计分提醒 AI 把进度写回日志,并要求它回确认码 | | 沉淀纪律 | 重建前如果产生了有价值的认知,先把它写进相关技能(而不是丢掉) |


9. 给插件开发者

pnpm typecheck          # 类型检查(node + 浏览器端两套)
pnpm test               # 全量测试(当前 80 个文件 / 1186 个用例)
pnpm build              # 打包(lib/index.js + client.js)
  • 开发用小工具scripts/dsh-develop.ts——typecheck / test / build / status / commit / push / version / bump / deploy / lockfile / host-upgrade / restart-web / publish / pack-check / github-push 一条龙。 lockfile = 重生成锁文件 + 用 --frozen-lockfile 自检(CI 的 Install (hooks) 同款判定); pack-check 会在发布前核对打包产物是否完整(曾经踩过"发到 npm 少了文件"的坑);scripts/dsh-crash-investigate.ts 用来查崩溃(只读)。 ⚠️ 改完 package.json 依赖后必须跑 lockfile 并提交锁文件 —— v1.31.6 漏了这一步,CI 从此一直红(红在"测试根本没跑",见 CHANGELOG v1.31.10)
  • 宿主类型基准 = devDependencies(v1.31.11):tsconfig.json / client/tsconfig.jsonpaths 指向仓库内 node_modules/@deepseek-ai/*,由精确钉版的 devDependencies 提供 → 新增 paths 条目必须同时加 devDependency(否则 tsc 静默回落 node_modules = 假绿,CI 的 typecheck 也就形同虚设)。机械闸门见 tests/compliance.test.ts F7;升级宿主时只改 package.json 一处 + 重跑 lockfile
  • 升级宿主(v1.31.12)dsh-develop host-upgrade <版本|dist-tag> 全局升级 DSH CLI(包名硬编码 @deepseek-ai/dsh、默认官方源、--dry-run 预览)→ 把 package.json 的 peer/devDeps 基准抬到同一版本 + 重跑 lockfilecompliance.test.ts F6c/F7d 与 host-manifest.test.ts 会强制各声明面同步,漏一处必红)→ restart-webdashboard healthdshVersion
  • 诊断会话打不开(v1.31.13)dsh-develop session-doctor —— 会话日志体检(只读)。 --probe 走宿主真实读取路径判定(msm("dsh-develop", ["session-doctor","--probe","--summary"]) 可全量跑)。 ⚠️ 两个易误读点:① readStoredLog存储层读、不走格式迁移 ⇒ 它对历史世代报 "no upgrade path" 属正常现象,不是损坏证据;判断"用户能不能打开"要看应用面 open(id,'read')。② 本工具修的两个真实缺陷见 CHANGELOG v1.31.13(rebuild 写的 user/messageid/role ⇒ 会话永久打不开findSessionLog 不认 session.vN.jsonl.zstd ⇒ 清理静默失效)
  • 架构:Cordis 原生插件,用 DSH 的正式接口注册工具和拦截点——从不修改 DSH 本体
  • 代码地图docs/codebase-overview-v1.22.md
  • 设计决策:见 CHANGELOG.md 和维护技能 dsh-serenity-plugin-development
  • 发布:npm @shgroup/dsh-serenity-hooks + GitHub 双仓库同步推送

10. 和 opencode 版是什么关系

| | opencode-serenity-plugin | dsh-serenity-plugin(本仓库) | |---|---|---| | 跑在 | OpenCode | DeepSeek Harness | | 实现 | 独立 | 独立(不复用源码,但遵循同一套标准) | | 系统提示词 | system.transform | systemPrompt.section,平台无关的部分逐字对齐 | | 工具 | msm / container_fs / logbook 等 | container_fs / container_trajectory / dashboard / container_git / msm / praxis / handyman / localstore / container_admin + 两个条件出现的(im-bridge / acc-diag) |

同一个工作区可以随时换运行时.serenity 标记、.opencode/skills/、配置、AGENT_SESSIONS/ 的文件格式都一致; 差别只在平台层(工具名、注入方式),换过去以后 AI 收到的约束是一样的。


11. 常见问题

Q:装完没反应? 先确认你进的是带 .serenity 标记的目录。不是工作区的话,插件完全不介入。进去后输入 dashboard health 看三项检查。

Q:bash 怎么不见了? 安全模式开着——这是设计,不是 bug。走注册过的小工具比让 AI 自己拼命令可靠。关掉胶囊里的 SAFE 滑块就回来了。

Q:3081 登录被锁了? 连续失败 5 次锁 15 分钟(指数退避)。等锁过期,或检查账号的验证码绑定状态。

Q:上下文快满了怎么办? 先让 AI 把进度写回 SESSION.md,然后按提示调用 container_trajectory rebuild。轨迹会自动接续,不用手动开新会话。

Q:对外问答页会返回内部信息吗? 不会。只返回答案本身,内部轨迹和工具结果都不出去。

Q:微信桥里,AI 的回复是怎么发出去的? 默认由插件自动把它的最后一段话转发给你。如果配了 autoReplyWithLastMessage: false,插件就不转了,改由 AI 自己发——所以这时候它如果没发,你就收不到消息(没有兜底,这是刻意设计)。

Q:主动发的微信消息会被记录吗? 会。和工作区里配的 weixin.hook 记录脚本走同一条路,事件里标 source: "proactive";自动回复标 source: "reply"


12. 延伸阅读


许可

MIT(见 LICENSE

版本:v1.31.13 | 前置:DSH 0.1.5-rc.2+ / Node ≥ 20 或 bun | 测试:80 个文件 / 1186 个用例