Skip to content

Repository files navigation

宁静号 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(两种写法,取并集):① 一处声明、全容器生效——在 .opencode/serenity.jsontrajectory.skills: [名字, …]本 CCC 的每条轨迹被绑定期间都注入这些 skill 的全文(连 skiff 角色会话也算);② 只给这一条——在它的 SESSION.md 顶部 frontmatter 写 skills: [名字, …]。两者是并集:容器级在前(底座)、轨迹级追加(这条额外的)。⚠️ 是"绑定期间一直供着"而非"use 时灌一次"——改了配置或 frontmatter立即生效,也不随对话压缩消失;而 create 只新建、不夺走当前绑定 ⇒ 新轨迹要显式 use 才挂上。skill 名来自工作区数据,先过安全校验才会用于拼路径,找不到会在提示里明说"缺失"而不静默跳过⚠️ 重写 SESSION.md 时务必原样保留顶部 frontmatter(抹掉 = 静默撤销该轨迹的声明)

CRO —— 让轨迹自己判断什么时候该被叫醒

问题:上面那两条都要求先算好一个时刻("3 点叫我")。可该不该醒往往不是时间说了算:某条轨迹应该在"天亮 + 家里有人 + 非高峰"才醒;已经在干活就不该再叫一次;日志快满了,下次叫它时该要求它先整理

做法让一条轨迹自己带一段程序,由 ACC 在每次检查时跑它,由这段程序决定"现在该不该叫我、叫我的时候说什么"

内容
程序放哪 <CCC 根>/AGENT_SESSIONS/<轨迹目录>/continuous-re-occurrence.ts(放轨迹自己目录里 ⇒ 跟随轨迹跨载体存活、天然进 git)
开关 逐轨迹文件在 = 启用,文件不在 = 禁用(无 enabled 字段、无注册表)② 🔴 总闸:设置面板「CRO(轨迹自编程唤起)」(croEnabled,缺省)——关掉只停 CRO 阶段send-later / send-now / 唤醒表投递照常工作
谁跑它 ACC 的唤醒调度器(既有 5 分钟 tick)
给它什么 一条 stdin 进来的 JSON 快照:身份 / 时间 / 轨迹身体(SESSION.md 体积与 mtime、references/ 清单)/ 绑定与载体(绑定的、live 的、🔴 正在跑轮次的)/ 调度面(本轨迹在办唤醒、调度器状态)
它给我什么 stdout 一行 JSON{"wake":true,"prompt":"…","reason":"…"}{"wake":false}缺省 = 不打扰
写程序前先读 container_trajectory cro-guide —— 指南 + 一份可直接拿去自测的样例快照

几条设计上的硬约束(都不是随便定的):

  • 🔴 ACC 只"起进程",从不 import 你的程序——进程边界同时挡掉两件事:ACC 不必依赖工作区的源码路径(装机版在别处,两条路径就是两个真相源),以及一个用户程序的语法错会放倒整个容器
  • 🔴 半成品报错就行:程序报错 / 超时(60 秒硬超时,超了 kill)/ 输出非法 ⇒ 记一行 + 跳过本轮
  • 🔴 CRO 的任何失败都不影响既有机制——send-later / send-now / 唤醒表投递照常工作(这条有实测用例钉住,不是口头承诺)
  • 🔴 reason 强烈建议填:改成程序判定之后,"当时为什么叫了"不再能从时间表重建(原因在程序肚子里);不写,以后出事无法复现
  • 程序想要记住"上次判了什么",得自己记——写在自己轨迹目录里的状态文件(那是它自己的进程状态,ACC 物理上拿不到)。所以防抖也归程序:想"别叫太频繁"就自己记时间戳
  • ⚠️ 它不自带自测:指南里给的流程是先用开发名写(如 continuous-re-occurrence.dev.ts不会被启用)→ 配自测跑绿 → 再改名为正式名(因为"文件在 = 启用",改名这个动作就是上线动作

🔵 不是 autopilot 回归:退场的 autopilot 删的是判据内容(周期节拍 + 提示词),留下的是调度能力;CRO 补的是"在没人醒着的时候判断该不该醒"——那正是工作区自己做不到的那件(工作区的自排是"被唤起时才跑")。

⚠️ 历史(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 个用例

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages