- Accueil
- Plugins
- Flux et automatisation
- dsh-heartbeat
dsh-heartbeat
kanadego/dsh-heartbeat
Agent réveillé selon son propre calendrier : par défaut toutes les 60 minutes, ±20 % (48–72). Parcourt les centres d’intérêt définis, stocke les trouvailles dans un pool local de notes et tient un profil de préférences. S’il trouve assez de contenu utile, transmet un court lot de notes à la session liée ; l’agent de cette session décide sur le moment s’il parle et quelle note utiliser. Le code fixe les heures calmes et occupées, la limite quotidienne et le délai de refroidissement. Si la décision après le gate est négative, les phases de décision et d’expression n’appellent aucun modèle ; la navigation a lieu avant le gate et est comptée séparément. Windows, Linux et macOS (prise en charge minimale sous Linux/macOS).
Installer
dsh plugin --profile web add github:kanadego/dsh-heartbeatREADME
dsh-heartbeat
让 DeepSeek Harness 的 agent 拥有持续存在感的心跳插件:她按节律自己醒来,维护记忆与画像、感知你的忙闲、按兴趣闲逛看新东西、把没说完的话带过下一拍,然后按分寸决定开不开口——开口要有真实来处,沉默要有具体理由。
一分钟了解
装好之后,全部能力都收在插件管理页的心跳面板里,日常使用零命令行:
| 心跳状态 | 会话绑定 |
|---|---|
![]() | ![]() |
| 素材池 | 用户画像(只读) |
|---|---|
![]() | ![]() |
展开看其余分区:兴趣范围 / 周报 / 节律 · 专注模式 · 换机迁移
| 兴趣范围 | 周报 |
|---|---|
![]() | ![]() |
设置页把节律、专注模式、换机迁移、账本与摘抄本入口收在一起:
截图为 v2.1.0。画像与会话绑定两张里的条目文字已打码。
它想解决的三件事:
| 你想要的 | 插件怎么给 |
|---|---|
| 零命令行 | 绑定会话、节律、素材池、画像、账本、迁移全在设置卡里;CLI 只留给脚本场景 |
| 不打扰、不烧 token | 静默时段 / 忙时窗口 / 每日上限 / 开口冷却 / 在场联动全是代码层判定——判「别说」时,之后的决策与表达两相根本不调用模型(闲逛相在闸门之前触发,另算) |
| 像活人,不像定时播报 | 素材分话题与聊天两仓,反刍成一句话再投递;说不说、说哪条,由你那个会话里的 agent 按当下处境拍板;没说完的话能留在心事匣里带到下一拍,看见想记的话就抄进摘抄本 |
快速开始
安装(npm 包,推荐)
dsh plugin --profile web add @kanadego/dsh-heartbeat
重启 DSH 即生效——插件自动创建专用心跳会话并按节律运行,之后日常无需任何操作。
心跳预设是自动装的:插件加载时直接向宿主注册(agentPresets.register(),v1.9.2 起),不需要任何手动操作,安装清单里也不再声明宿主包。缺失就按包内模板建好,已有文件永不覆写(你手改过的预设原样保留)。无论走哪条路径,没有这个预设心跳 agent 就是个"裸 agent",连 web_search 都看不见——想手动检查/修复用 preset status / preset install(见下节);把插件 config 的 installPreset 设为 false 可同时关掉运行时注册与目录自装,预设完全由你管。
从源码安装(开发/改造用)
dsh plugin --profile web add file:D:/path/to/dsh-heartbeat
数据放在哪
数据默认住在包外:<DSH_HOME>/heartbeat-data(没有 DSH_HOME 就是 ~/.dsh/heartbeat-data),重装与升级都不会碰它。老版本装在包目录里的 data/ 会在首次启动时自动搬过去(搬迁前先备份、逐文件校验通过才删原件,见下节「卸载」)。要换位置就用插件 config 的 dataDir,或环境变量 HEARTBEAT_DATA_DIR。
平台支持
Windows 上全部功能可用。v2.1.0 起 Linux / macOS 也能跑起来:心跳循环、表达与投递、时间注入、心事匣 / 账本 / 摘抄本、素材池、周报、设置面板与 RPC 通道都照常;依赖 PowerShell 的那几项——截屏、空闲检测、锁屏检测、前台窗口探测、桌面通知——在这两个平台上不可用,插件会直接按「探针失败」降级,不会卡住某一跳。代价是忙闲判定缺席:静默时段、每日上限、开口冷却照常生效,但「他大概在忙」这类窗口判断不会触发。
数据不跨平台搬家:data/vault.key 在 Windows 上由 DPAPI 保护,在 Linux / macOS 上是一份权限 0600 的密钥文件,两边互不相认。换平台就是重新开一份数据目录。
核心工作机制
一跳 = agent 自己醒一次(默认 60 分钟)。醒着的时候依次走七相,最后由留痕收尾:
维护 → 采集 → 闲逛 → 闸门 → Digest → 反刍备料 → 投递 → 留痕
│
判「别说」→ 本跳到此为止,决策与表达不再调模型
点此展开:七相详情与关键概念
① 维护 ── 清素材池 / 滚动日志 / 判断该不该合并画像
② 采集 ── 全屏截图(加密落盘)+ 忙闲判定 + 前台窗口类别
╰─ 观察:把绑定会话里你新说的话收进画像收件箱
②′ 闲逛 ── 条件触发:agent 自己按兴趣焦点用 web_search 看新东西
③ 闸门 ── 纯代码判定:静默窗 / 忙时 / 在场 / 每日上限 / 冷却
╰─ 判「别说」→ 本跳到此为止,决策与表达不再调模型
④ Digest ── 拼出「此刻状态」:画像 + 时间 + 素材池 + 待办
⑤ 反刍 ── 引擎室从素材池挑 ≤3 条,各压成一句话(备料)
⑥ 投递 ── 拼成素材包,送进你指定投递的那个会话
⑦ 留痕 ── 写审计日志 + 账本(真正开口了才计数)
│
▼
你读的那个会话 ── 那里的 agent 按当下处境,决定说不说、说哪条
文档里反复出现几个词,在这里一次说清:
| 词 | 意思 |
|---|---|
| 心跳 | 本插件的核心动作——不用你开口,agent 按固定节律自己「醒一次」:做维护、感知环境、决定要不要说话。醒一次叫一跳,默认 60 分钟一跳。 |
| 宿主 | 运行插件的那个程序,即 DSH 本体。心跳是挂在宿主里的插件——模型通道、会话、工具这些能力都由宿主提供。 |
| 客户端 | 宿主里负责界面的那一侧(Web 界面或者 DSH desktop)。设置页的心跳卡片属于客户端;卡片显示不出来,通常是客户端插件没加载成功,与心跳本体无关。 |
| 相 | 一跳内部的一个阶段。主循环共七相——维护 → 采集 → 闲逛 → 闸门 → Digest → 反刍备料 → 投递,最后统一由留痕收尾。每相结束都会在审计日志留一条 phase_done,所以「这一跳停在哪」可以直接查。 |
| 引擎室 | 跑心跳内部轮次的那个 agent,和你在会话里对话的 agent 是分开的。它只负责采集、反刍、备料,不直接跟你说话;真正开口的是你读的那个会话里的 agent。 |
| 心跳正身 | 心跳自己专用的一个会话,同时也是它的决策现场——每跳的推理轮次都在这里发生。它在会话列表里和普通会话长得一样,日常不用去动它(CLI 的 sessions list 会把它单独标出来)。 |
| 闸门 | 决定「这一跳能不能开口」的纯代码判定层,依次看:静默时段 → 你是不是在忙 → 你在不在场 → 今天说够没有 → 距上次开口够久没。全不通过就安静,并在日志里写下具体原因。它也是省 token 的关键——判「别说」时,之后的决策与表达两相根本不调用模型(已经跑过的维护、采集、闲逛不再重来,也不因为沉默而多花)。 |
| 观察 | 投递的反向动作——把绑定的会话里你新说的话收进画像收件箱,作为了解你的证据。它发生在采集相:只取当时有活 agent 的绑定会话、每跳最多 10 条、每条只留第一句(≤80 字),插件自己注入的消息会被跳过。 |
| 反刍 | 投递之前的备料步骤:引擎室从素材池挑出最值得说的几条,各压缩成一句话(不带理由、不排序)。名字取自反刍动物把食物嚼细再咽。 |
| 投递 | 把备好的素材包送进你某个会话的动作。把心跳绑定到常用会话,agent 就会「到你那个房间里说话」。 |
核心功能
心跳节律与分寸闸门
- 心跳节律:定时唤醒(默认 60 分钟一跳,卡片可调),按七相循环运行——维护 → 采集 → 闲逛 → 闸门 → Digest → 反刍备料 → 投递,末了由留痕收尾。每跳都有审计留痕,沉默必带原因。
- 节律随机化(v2.1.0):每跳的实际间隔在基准值上浮动 ±20%(
policy.heartbeat.intervalJitterPct,0–50,设 0 即关闭),不再踩准整点报时。启动那一跳固定 15 秒后、不参与抖动,约每跳不同的落点让心跳不显得机械。 - 专注模式(v2.1.0):需要安静时一键暂停心跳 N 分钟(1–1440),不碰配置、到时自动恢复;暂停期间不跳、不发消息、不计每日额度,状态栏显示「专注模式 · 至 HH:MM」。设置卡与 CLI(
focus <分钟>)同一份暂停状态,暂停落data/focus.json,重启后照样有效。 - 分寸闸门:静默时段、忙时窗口、每日表达上限、开口冷却、在场联动,全部是代码层的独立判定,不靠模型自觉。默认倾向开口,但你正忙或已到深夜时绝不打扰。
- 状态栏与时间感知:心跳把"此刻在干什么"(在闲逛 / 看到你在忙 / 在场待着…)注入日常会话——支持动态系统提示词的模型常驻系统提示词(KV-cache 安全追加),其余模型只在用户发起轮次时带一行。精确时间按 20–30 分钟节流注入,任务进行中绝不中途插话;子代理会话一律不注入(v2.1.0)——分身不该看见本体的时间账。
视觉与兴趣闲逛
- 视觉感知(可选):每跳对全屏截图做一次视觉识别(如果模型不支持多模态,支持经 ModLens 此类视觉辅助插件外接多模态模型),投递的素材包会带一句「(他此刻大概在:…)」;识别失败时画面与窗口标题一概不进任何提示词——隐私优先,宁可不说。
- 兴趣闲逛:按你定义的兴趣范围轮换挑焦点(同一条 3 天冷却),用
web_search看新东西(每次 3~9 轮搜索),结果由代码登记入素材池(每焦点至多 4 条,config/interests.json的max_seeds_per_focus可调)——模型只负责搜索筛选,不做任何写盘动作。入库前查重(v2.1.0):完全相同的网址、归一化后同名的条目、以及与近 30 天归档高度相似(标题相似度 >0.85)的一律丢弃,同一个话题不会被反复捡回来。话题库存见底(≤4 条)时自动触发补货闲逛(每天至多 2 次)。
素材池与投递闭环
- 素材池(话题 / 聊天双仓):话题库存 16 条 + 聊天素材 14 条,四条确定性淘汰(TTL / 消费退休 / 冷板凳 / 容量挤出);聊天种子来自画像合并时从对话里挑出的"值得聊的话题",有时效性——被说出口后至少活到下一次回收,有新证据还会继续留池(v1.9.1 之前是"投递过 1 次即退休",常常话刚出口上下文就断了)。归档区也有上限(默认 50 条),超出按最老优先裁掉;新增 / 合并 / 淘汰 / 裁剪 / 恢复 / 删除都会写进审计日志(只记编号与元数据,不记素材正文)。是缓存不是记忆,与画像单向隔离。
- 反刍投递(目标会话拍板):代码先凑好候选(话题随机 4 + 聊天最新 2,互补至多 6 条),引擎室挑 ≤3 条各压缩成一句,拼成素材包注入你读的会话——附一句「他此刻大概在:…」(视觉识别成功时)+声明「这是心跳插件素材投递」+素材清单(必要时附「也可以说一句真心话」)。说不说、说哪条,由目标会话里的 agent 按当下处境自己判断——决定不说就把正文留空(v1.9.3 起,但是受模型指令遵循能力限制,如想要更好的效果,建议在系统提示词/长期记忆中补充一条相应规则);话落到你眼前的会话后,agent 会按本次投递编号报账——哪几条被用上、是引用素材还是顺着自己发挥,都如实记下。
- 心事匣(v2.0.0 新增):给心跳一格便签,用来把没说完的话留给下一跳的自己。投递的素材包里会带上「你上跳留下的心事:…」,以及它留于第几跳、已搁多久、这期间被叫醒过几次;想留住就照原样再写一遍(字样一致算保留,年龄不重算),想换就直接写新的,什么都不做它下一跳自动清掉。不强制每跳留话——没话说就空着。生命周期由两个序号判定,只认真正的拍(启动那一拍不计入),所以「搁了几跳」永远是真的。
- 摘抄本(v2.0.0 新增):心跳自己的本子,用来留句子和想记住的小事。注册成模型工具
excerpt(add / list / remove),日常会话里的 agent 想到什么就当场抄下,不用谁下命令;数据落data/excerpts.md,明文、可直接手编——一本谁也翻不开的笔记本不叫笔记本,认不出的行在改写时会原样留着。它和另两本分工明确:账本记待办(会勾掉),心事匣是留给下一跳的一句引子(一格、会被盖掉),摘抄本只增不减,除非主动抹掉。 - 会话绑定:把心跳消息投递到你常用的会话(agent 会"到你房间里说话"),或观察会话内容喂养画像——投递/观察是两个独立开关,可双开。
记忆 · 账本 · 周报
- 用户画像:本地结构化档案(兴趣 / 项目 / 沟通偏好 / 心理基线),带来源与置信度,稳定特质不因时间遗忘;journal 单一权威,可校验、可重建、可解密导出。
- 周报:每 7 天一份,只报道这周干了些什么——表达与静默、新认识、账本、素材池、活跃高峰。由后台「心跳」署名写成平实中性的一句话档案,加密落盘,卡片可翻,默认只留最近 3 期(
policy.weekly.keepReports)。 - 账本工具:账本注册成模型工具,日常会话里的 agent 听到你提到待办/承诺会自己记账、完成后自己勾掉,不用你下命令——和心跳、CLI 记的是同一本账。
- journal 快照基点:画像 journal 超 5000 条自动折叠成快照 + 归档分片,重放成本有界;verify/rebuild 跨快照依然正确。
数据 · 迁移 · 焚毁
- 换机迁移:一键打包画像/账本/素材池/周报为口令加密容器(卡片或 CLI),新机器导入自动用本机主密钥重加密。
- 加密与焚毁:敏感文件 AES-256-GCM 整文件加密,数据密钥由 Windows DPAPI(CurrentUser) 保管在
data/vault.key(Linux / macOS 上是权限 0600 的原始密钥文件),只在进程启动解一次;旧版(1.x)留下的 DPAPI 容器照样能读,且在写入与每跳维护时自动改写成新格式(vault upgrade一次全换);一键焚毁运行时数据;模型出库仅限合并裁决的最小必要摘要。
Web 面板
心跳的日常操作都集中在 DSH 的插件管理页:插件管理 → dsh-heartbeat → 配置,打开即见面板。面板按 tab 分页,一个 tab 管一件事:
| Tab | 管什么 |
|---|---|
| 状态 | 此刻在干什么、上次心跳的结果、今日表达用量、时间注入与状态栏的最新情况 |
| 会话 | 把心跳投递到哪些会话、观察哪些会话——投递与观察是两个独立开关,可以双开 |
| 素材 | 话题 / 聊天两类素材的查看、归档与恢复,带关键字过滤 |
| 兴趣 | 闲逛的焦点清单与浏览时段 |
| 画像 | 四个分区只读查看(兴趣 / 进行中 / 沟通偏好 / 心理),支持导出 Markdown |
| 周报 | 每 7 天一份的周报:列表选期,展开阅读正文 |
| 设置 | 节律、时间注入、表达开关与专注模式;换机迁移;账本与摘抄本的打开入口 |
几点使用说明:
- 设置按「节律 / 时间与状态栏 / 表达 / 专注模式」分组,每组一句人话说明管什么,每个参数旁标着「多久生效」:改心跳间隔保存后立即重排节律,其余参数保存后从下一跳开始生效——都不用重启。
- 专注模式是独立开关:填分钟数、点按钮即刻暂停或恢复心跳,到点自动恢复,不参与「保存」。
- 换机迁移的导入是危险操作:会用迁移包覆盖本机的心跳数据(被替换的文件自动备份)。第一次点只亮起确认提示,再点一次「确认导入」才真正执行;改了文件路径或口令,确认态会退回。
- 周报默认收起正文,点日期选期、点「展开查看报告正文」阅读。
- 状态页是六格速览:上次心跳 / 插件版本 / 今日表达(带进度条,满额转黄)/ 时间注入 / 上次结果 / 此刻动态,右上角徽章一眼看出是在正常节律、专注模式还是静默。
- 面板就是普通网页组件:改完
client.js刷新页面即可看到新样子,不需要重启 DSH。
常见故障与诊断
第一现场永远是 data/logs/heartbeat.jsonl(每跳留痕,silent 必带原因)。
点此展开:高频报错与排错速查
| 症状 | 原因与处理 |
|---|---|
| 完全没有心跳(无任何日志行) | 插件没装入:确认 node_modules 里插件存在、启动无 "Failed to load plugins" 横幅;plugin_init 缺失 = apply 没跑 |
| 一直沉默 | 先看 silent 行的 reason:夜间静默窗 = 正常;白天 = cap 满 / 冷却未过 / 忙时窗口 / token-saver(见下条) |
审计出现 silent reason=token-saver、心跳整跳不动 | 节省 token 模式开着,且你已离开(闲置 ≥30 分钟)或锁屏——这是设计行为,不是坏了:暂停期间每 3 分钟只探一次环境(不花 token),你一回来就会恢复;绑定会话里出现新消息也算你在。不想要就关掉那个开关 |
| psy 分区一直空、画像只在其他分区增长 | psy 开关默认关闭:开着时画像合并才收 psy 条目。在设置卡里打开即可 |
闲逛永远秒结束、tool_policy 报 unknown global tool "web_search" | 预设没挂上(裸 agent):preset status → preset install,装好后 tool_policy 行应是 preset=mounted(heartbeat) restrict=ok |
| 设置页整块没有心跳卡片(数据照常写) | client 注册 id 与包名不一致被宿主静默剔除:三处必须严格等于包名,改完重启。若确认 id 没问题,看下一条 |
卡片整块消失 / 节律配置保存不了(0.1.7 宿主) | 旧版插件撞上 0.1.7 的接口换代(设置接口变更 + 客户端服务被删):升级到 v1.7.0 并重启;v1.7.0 已按三代接口自动适配 |
卡片分区报 加载失败: … HTTP 405 | RPC 路由没注册成功:审计里应出现 rpc_registered route=/api/heartbeat,没有 = dist 未同步,重装/同步后重启 |
节律配置保存不生效、重启后回默认(0.1.5 宿主) | v1.5.x 的已知问题(dsh-settings 包缺失 + 0.1.5 API 变更):升级到 v1.6.0 并重启;0.1.7 宿主的同类症状见上面「卡片整块消失」那条 |
投递没带「他此刻大概在:…」、审计有 screen_vision ok:false | 视觉识别失败:error 字段带 ModLens 具体报错;常见为 provider 未配置或网络超时。识别失败时画面/标题按隐私设计不进提示词,心跳其余功能不受影响 |
| 结果显示「心跳异常(decision: whenIdle timeout)」 | 反刍轮超时(240s 内没等到模型回话)。v1.6.0 起不再整跳报错:记 decision_deferred、本跳按沉默处理、素材自动留到下一跳。若反复出现,看该行 reason 与 ModLens 画面描述是否诱发跑题 |
每跳 beat_error: … reading 'length' | 宿主移除了 Session.events——插件版本与宿主不匹配,对照〈版本兼容〉换版本 |
引擎室轮次整轮失败、报 format v4 message requires a producer-owned source kind | 0.1.7 的会话日志(V4)拒绝旧版通用的消息来源标记——同样是版本不匹配:升级到 v1.7.0(改用自有来源标记) |
每轮报 prompt variable "{{model}}" has no value | agent 没有模型路由(审计 model 字段为 (none))——同样是版本不匹配症状 |
素材投递偶尔不成功、spoke_failed: non-Chinese output discarded | 目标会话 agent 收到素材包后回合以工具调用收尾,末行是 </tool_calls>(纯英文)被旧判定误拦。v1.5 起已修:跳过工具收尾标签、取最后一个含中文的行;整段无中文才拒。升级后重启即可 |
有 spoke 但会话里没出现这句话 | 投递目标当时没活 agent 且拉不起来:查 deliver_target_* 系列行;再查绑定 deliver 是否为 true |
| 素材包发了但目标没说话,想知道为什么 | 查 expression_dropped(v1.9.1 起记录,带丢弃原因);连续三次会在日志里补一条 expression_dropped_streak。v1.9.3 起「决定不说」是正常路径,不再算异常 |
日志出现 cursor_format_discarded / rpc_host_gate_missing / beat_watchdog / weekly_pruned | 都是 v1.9.1 起记录的正常自愈痕迹(weekly_pruned 为 v1.9.3 新增):分别为「旧游标格式升级丢弃、本跳全量重扫」「宿主未提供 RPC 闸门、危险端点已拒绝」「某跳超时被强制收尾」「周报超期被裁」。各出现一次不必管,反复出现再看同跳前后的其他行 |
| 侧栏某个会话行消失了 | 心跳刚往那个"当时没打开"的会话投递过,投完释放临时 agent 的正常副作用——刷新页面即回,内容零损失 |
升级 0.1.5 后旧会话打不开(unexpected member … / header version must be 3) | 会话格式 v3 迁移问题:前者用 scripts/repair-v0-members.mjs(预检→修复,自动备份);后者首次访问会自动迁移,属正常 |
升级 0.1.7 后会话目录里多出 .v4 文件 | 会话格式 V4 迁移的正常结果:首次访问该会话时转换,原 .v3 文件保留不删。注意这是单向的,降级回旧宿主可能读不了——升级前备份 ~/.dsh/sessions |
| 画像疑似损坏 | profile verify(只报不修)→ profile rebuild --check(看 diff)→ profile rebuild(真重建) |
Linux 上第一跳就 beat_error: vault spawn failed … powershell.exe ENOENT | v2.1.0 之前的版本主密钥依赖 PowerShell,非 Windows 上必然失败:升级到 2.1.0 即可。此时 data/vault.key 里是一份 0600 的原始密钥。注意数据不跨平台——Windows 的数据目录搬到 Linux 是解不开的(会明确报错,不会假装成功) |
装完显示 pending (waiting for service: settings),桌面上宿主起不来 | v2.1.0 之前把 settings 写进了模块级 inject,宿主不提供这个服务时插件永远 pending,桌面端 0.2.1-rc.3 上会连带壳崩(Web RPC failed + 崩溃弹窗按钮无响应)。升级到 2.1.0:设置表单改成 ctx.inject 延迟挂载,只靠 agents 就能起。若仍 pending,检查 agents 服务是否在,而不是 settings |
完整事件字典、宿主契约备忘与更多症状见 DESIGN.md §7。
CLI 命令
设置页卡片覆盖日常操作;CLI 面向高级用法与脚本场景:
node <插件目录>/dist/cli/index.js <命令>
点此展开:CLI 命令速查
| 分组 | 命令 | 说明 |
|---|---|---|
| 总览 | status | 工作区路径 + 策略摘要(今日 cap / 冷却 / 静默窗) |
| 素材池 | seeds add <text> [--tag t] [--topic x] [--confidence n] | 手写一条种子 |
seeds list [--archived] / seeds surface <id> / seeds archive <id> | 列表 / 计一次曝光 / 归档 | |
seeds gc / seeds stats | 跑确定性淘汰 / 池子状态 JSON | |
| 账本 | ledger add <text> / ledger list [--pending] / ledger done <id|子串> / ledger open | 待办登记 / 查询 / 勾掉 / 编辑器打开 |
| 摘抄本 | excerpt add <text> / excerpt list [n] / excerpt remove <id|子串> / excerpt open | 抄一条 / 翻最近十条(可指定条数)/ 抹掉一条 / 编辑器打开 |
| 闲逛 | browse status / browse dry / browse done <focus> | 状态 / 强制裁决预演 / 手动登记一次闲逛 |
| 节律 | focus [分钟] / focus off | 专注模式:暂停心跳 N 分钟(1–1440)/ 立刻恢复;不带参数只查状态 |
| 绑定 | sessions list | 枚举会话 id |
bind list / bind add <id> [--observe] / bind remove <id> | 绑定详情(正身也会列出)/ 绑定 / 解绑;--observe-only 仅观察、--no-deliver 关投递 | |
| 通知 | notify check / notify register / notify send | toast 通道体检 / 注册 / 测试发送(只提示新消息,不承载正文) |
| 画像 | profile list [--all] / profile export | 当前有效(含过期)/ 解密导出 Markdown |
profile verify / profile rebuild [--check] / profile wipe | journal 重放比对(只报不修)/ 重建(可先干跑)/ 清空(要 --yes;连快照、归档分片、迁移备份一起删,设定不动) | |
profile snapshot [--force] | 折叠 journal 为快照 + 归档分片(维护相到阈值也会自动做) | |
| 周报 | weekly list / weekly show [file] | 列出已生成的周报 / 打印某期(默认最新一期) |
| 迁移 | migrate export [file] / migrate import <file> | 打包记忆文件为口令加密容器(口令走 stdin 两行)/ 在新机器恢复(stdin 一行);卡片「换机迁移」分区同功能 |
| 加密 | vault status / vault upgrade | 盘上各格式容器计数 + 主密钥位置 / 把 1.x 的 DPAPI 容器就地改写成 AES-GCM(平时写入 / 每跳维护自动换代,这条是一次全换) |
| 日志 | logs cleanup [--dry-run] | 立即执行日志保留策略 |
| 预设 | preset status / preset install [--force] | 装没装、与模板是否一致 / 补装(--force 还原成模板) |
| 焚毁 | burn [--yes] [--all] | 预演(默认)→ 执行;运行时数据覆写 x3 后删除,设置保留(--all 连设置归零) |
数据与安全
信息存储
所有运行数据都在心跳数据目录(唯一可写位置,路径守卫强制),卸载或重装都不会丢:
| 文件 | 内容 | 状态 |
|---|---|---|
data/settings/ | 绑定、策略覆盖、节律配置(ui.json)、画像白名单、心跳状态(场景 + ≤30 字发言摘要) | 明文(用户设定要可手编) |
data/vault.key | 主密钥(AES 数据密钥;Windows 由 DPAPI 保护,其他平台是 0600 的原始密钥文件) | 🔒 本机本账户可解;不随迁移包移动;不跨平台 |
data/seeds.jsonl | 素材池 | 🔒 加密 |
data/profile.* | 画像三件套(journal / 物化视图 / 收件箱) | 🔒 加密 |
data/sent.json / data/browse.json / data/screen.* | 表达记录 / 浏览流状态 / 屏幕快照 | 🔒 加密 |
data/notepad.json | 心事匣:上一拍留给下一拍的一句引子 + 两个序号计数 | 🔒 加密 |
data/ledger.md | 账本(agent 的待办与话题来源,可直接手编) | 明文 |
data/excerpts.md | 摘抄本(留句子和小事,可直接手编) | 明文 |
data/profile_snapshot.json / data/profile_journal.archive-*.jsonl | 画像快照基点 / journal 归档分片 | 🔒 快照加密 / 分片明文 |
data/weekly/ | 周报(每 7 天一份,含画像/账本摘录) | 🔒 加密 |
data/envpulse.jsonl / data/logs/heartbeat.jsonl | 作息聚合 / 审计日志(含她发言的前 80 字摘录) | 明文,按保留策略滚动清理 |
data/cursors.json / data/preference.json / data/seed_report.jsonl / data/profile_rhythm.json / data/time-inject-state.json | 观察游标 / 话题偏好权重 / 素材报账流水 / 作息直方图 / 时间注入节流 | 明文(只含编号、计数与聚合,无对话原文) |
data/tmp/ / data/exports/ | 临时文件 / 画像导出 | 临时区 |
加密分两层:数据用 AES-256-GCM 整文件加密(带认证,改一个字节就解不开也不会给出一半内容),数据密钥存在 data/vault.key。在 Windows 上,那一个文件由 Windows DPAPI(CurrentUser 作用域) 保护——本机本账户可自动解密使用,其他账户、其他机器、云同步副本都解不开。防的是他人 / 他机 / 误同步,不防同账户的恶意软件——那是操作系统边界的事。
Linux / macOS 上没有 DPAPI:data/vault.key 里就是那 32 字节密钥本身,靠文件权限(0600,只有运行插件的账户能读)守着——防的是「别人翻到这份数据」和「误同步」,防不住已经拿到你这个账户的同机进程,比 Windows 少一层系统钥匙串。也正因为两端密钥互不相认,数据目录不跨平台搬家:Windows 写的密钥到 Linux 解不开,heartbeat vault status 会如实报出来。
1.x 写的文件用的是旧的 DPAPI 容器(KHBV1),v2.0 读得懂但写的是新容器(KHBV2):升级插件不会让任何旧数据变成打不开的死文件。旧格式会自己换掉——任何一次写入都落成新容器,每一跳的维护相另外顺带把长期没动过的一个旧文件就地改写;想一次全换完,跑 heartbeat vault upgrade(vault status 看盘上各格式各有多少)。
反过来要注意:KHBV2 只有 2.0 及以后的版本认识——升级到 2.0 之后不要再回退到 1.x,旧版本会把新容器当作打不开的文件。(要回退就趁早;跑过 vault upgrade 之后、或让数据写过一轮之后,就回不去了。)
安全边界
- 路径守卫:全部落盘经过守卫规范化比对,
..穿越、符号链接、8.3 短名、UNC 一律拒绝;data/是唯一可写目录。 - 模型工具硬限制:引擎室轮次的工具面由代码层白名单收窄——闲逛相唯一需要的
web_search,加上装了 billion-context 这类插件时的压缩三件套compress/decompress/acp_status(v1.8.0 起,免得长会话把自己撑爆)。账本、素材报账、心事匣、摘抄本这四个工具注册在全局层(你的日常会话里可用),引擎室轮次看不到它们。白名单管的是全局层:宿主自己注册在 agent 作用域的行不受它约束——实测引擎室那一跳拿到的完整工具面是 9 个:web_search(预设挂的)、compress/decompress/acp_status(billion-context)、ops_bash(dsh-ops)、schedule_create/schedule_list/schedule_update/schedule_delete(dsh-schedule)——后五个是宿主插件注册在 agent 自身层的行,白名单管不到它们(注意search_context与acp_cache是故意不放行的:前者与 dsh-acp 的同名工具撞名)。复用的 agent 也会重新钉一遍:插件重启后若引擎室会话正开着、agent 被宿主直接复用(日志里的agent_reuse_live),复用分支会单独调一次pinEngineRoomTools把白名单重新钉上,结果记在同一行tool_policy里、带reuse前缀——2026-10-17 修的,修之前这条路径不套白名单(实测漏到 62 个工具)。 - 建议 · 防注入:网页内容应视为数据而非指令(闲逛提示词中明示);画像裁决 prompt 同理(观察内容是数据,不应改写人格设定)。这是推荐的做法,是否采纳由使用者自行决定,并非安装即强制生效。
- 模型出库边界:画像合并调用走宿主模型通道(插件不持有任何云凭证),送四个分区(含 psy)的条目字段与 ≤1 句观察引语——不送对话原文、不送证据全量。(2026-10-07 调整:先前排除 psy,结果模型能往自己看不见的分区写,而 UPDATE 必须给 id、id 又只出现在条目视图里,psy 条目写进去就改不动了。)
- 一键焚毁:
burn(预演)→burn --yes(运行时数据覆写 x3 后删除,用户设置保留)→burn --all(连设置归零)。 - 数据通道鉴权:设置卡读写的
/api/heartbeat通道自身不持有凭证,靠宿主对/api前缀路由的门禁(Host / Origin 校验 + 浏览器会话 secret)。v1.9.1 起插件在注册时自检这道门禁还在不在(当时只拒六个「破坏性」端点);2.0 起不在就整个通道失败关闭:只放行几个只读低敏端点(status、config.get、sessions.list、bindings.get、weekly.list),其余一律拒绝并留痕(rpc_host_gate_missing)——包括所有涉及记忆内容的读取(画像摘要 / 分区、素材池、兴趣词、周报正文、迁移导出)。(2026-10-17 收紧。)
版本兼容
| 插件版本 | 适配的 DSH |
|---|---|
| v2.1.1 – v2.1.2(当前) | 0.2.0-rc.1 – 0.2.1-rc.5 |
| v2.0.0 – v2.0.1 | 0.2.0-rc.1 – 0.2.1-rc.2 |
| v1.7.4 – v1.9.3 | 0.2.0-rc.1 – 0.2.0-rc.2 |
| v1.7.2 – v1.7.3 | 0.1.7-rc.1 – 0.2.0-rc.1 |
| v1.7.0 – v1.7.1 | 0.1.5-rc.2 – 0.1.7-rc.2 |
| v1.2.x – v1.6.4 | 0.1.2-rc.1 – 0.1.5-rc.2 |
| v1.1 | 0.1.2-rc.1 |
| v1.0 | ≤ 0.1.1-rc.2 |
0.1.5 宿主须 ≥ v1.2.1(否则设置卡 RPC 405);v1.6.3 有渲染 bug,请直接用 v1.6.4。
⚠️ 升级宿主会触发会话格式自动迁移,且不可降级——
0.1.5起迁到 v3、0.1.7起迁到 v4(首次访问该会话时转换,原文件保留)。这动的是用户数据,升级前先备份~/.dsh/sessions。
卸载
dsh plugin --profile web remove @kanadego/dsh-heartbeat
卸载只拆插件本体(包、挂载行、注册项,无残留引用),不动用户数据——v1.9.2 起数据默认住在包外的 <DSH_HOME>/heartbeat-data(~/.dsh/heartbeat-data),重装、升级、卸载都不会碰它。想连数据一起删,先 burn --all 焚毁敏感内容再删目录。
点此展开:老版本数据怎么自动搬出去
老版本(≤ v1.9.1)装在包目录里的 data/ 会被自动搬出去:启动时若发现包内有数据、包外还没有,就递归复制过去——先备份一份、再逐文件校验(文件清单、大小、sha256 全部一致),全部通过才删原目录与备份;任何一步失败都原地不动,继续用包内那份,并留痕 data_dir_relocate_failed。搬完之后老位置不会再被读取,也不会再创建。
如果想自己指定位置(比如放到别的盘),在 profile 的 cordis.patch.yml 里给 heartbeat 覆盖:
- id: heartbeat
config:
dataDir: D:/your/workspace/heartbeat-data
显式指定时不会触发自动搬迁,也不会被上面的默认值覆盖——从包内搬出去这件事需要你手动做(照上面的路径拷过去即可)。
版本更新
v2.1.x
v2.1.0 · 2026-10-31(原生面板 · 专注模式 · 节律随机化 · 子代理不注入 · 最小 Linux 支持)
节律、暂停与闲逛三处的实际体验修整,外加一条只在子代理身上才看得到的注入泄漏。
- 专注模式:需要安静的时候一键暂停心跳,1–1440 分钟任选,到点自己恢复。不写配置文件、不重启、不影响别的设置;暂停期间一次都不跳,状态栏显示「专注模式 · 至 HH:MM」,设置卡和 CLI 认的是同一份状态(暂停落
data/focus.json,重启照样有效)。 - 节律不再踩整点:每跳间隔在基准值上浮动 ±20%(
policy.heartbeat.intervalJitterPct,0–50,设 0 关掉)。启动那一跳仍固定 15 秒后发起、不参与抖动。 - 子代理会话不再被注入时间:时间注入原先对所有 agent 生效,分身会话里也会冒出「当前本地时间…距上一条消息已过去…」。现在按会话头判定(
origin: subagent/delegationDepth > 0,老版本回退扫subagent/descriptor事件),子代理一律跳过。 - 闲逛去重 + 增量:入库前查重——完全相同网址、归一化后同名、与近 30 天归档相似度 >0.85 的条目直接丢弃(短标题不参与相似度判定,避免「话题素材 1 / 11」这类被误杀);每焦点带回的种子上限从 2 条提到 4 条,一次闲逛的收获不再被同 topic 合并规则吃掉。
- 原生面板:原来挤在设置页里的一串折叠区,改成插件管理页里的一个正经面板——状态 / 会话 / 素材 / 兴趣 / 画像 / 周报 / 设置七个 tab,各管一件事。顶部渐变标题栏、胶囊 tab、卡片化内容,状态页是六格指标。旧设置页面板随之退役,不再挂第二份 UI(宿主 0.2.1 起就有该插槽)。
- 最小 Linux 支持:心跳在 Linux / macOS 上能跑起来了。原先第一跳就卡死,因为主密钥要靠
powershell.exe解——现在非 Windows 平台改为把 32 字节密钥直接落成data/vault.key(0600,原子改名发布),加解密仍走 Node 的 AES-256-GCM;package.json的os同时从win32放开到三平台(此前npm install在这些平台上会直接被EBADPLATFORM拒掉)。截屏、空闲 / 锁屏检测、前台窗口、桌面通知仍只认 PowerShell,其他平台直接按「探针失败」降级——不再每跳白等一次进程启动,更不会拖住整跳。数据不跨平台迁移。 - settings 改软依赖:
settings从模块级inject里挪走了。cordis 把模块级 inject 当硬依赖——宿主不给这个服务,插件就一直停在pending (waiting for service: settings),桌面上光这一个 pending 就够把整个壳带崩(openInitialWindow报Web RPC failed,崩溃弹窗三个按钮全无响应)。设置表单本来只是便利:节律值来自data/settings/ui.json加 apply 时的config,没有它照跳。现在改由ctx.inject(['settings'], …)延迟挂载——心跳靠agents一个服务就能起,表单在服务出现时挂上、服务消失时副作用跟着回收。顺手清掉两条早已走不到的旧分支(0.1.5 的installSection与 0.1.1/0.1.2 的 free-function 回退),@deepseek-ai/dsh-settings随之从依赖里移除。
v2.1.2 · 2026-11-04(修复:原生面板槽位同时注册短名与全名)
⚠️ 升级提示:v2.1.1 存在渲染回归,建议直接跳过 v2.1.1 安装 v2.1.2。 v2.1.1 的面板槽位 key 只注册了 npm 全名
@kanadego/dsh-heartbeat,file:/ 本地安装方式下宿主报的 bundle 名是短名dsh-heartbeat,两者对不上时详情页整块配置区不会渲染(issue #8 跟进)。直接升级到 v2.1.2 即可恢复。
- 面板槽位 key 改为双注册:
plugins.bundle.config同一组件同时以dsh-heartbeat与@kanadego/dsh-heartbeat两个 key 注册,npm 安装与本地安装两种方式下面板都不再消失;scripts/panel-smoke.mjs冒烟断言同步覆盖双 key。
v2.1.1 · 2026-11-04(修复:原生面板在 DSH 0.2.1-rc.3+ 详情页完全不显示)
- 面板槽位 key 改回全名:
plugins.bundle.config的注册 key 误用短名dsh-heartbeat,而宿主 plugin-manager 按 npm 全名@kanadego/dsh-heartbeat(manifest dependencies 的 key)判定是否渲染插件详情页的配置区——key 对不上,面板「装了但看不见」(issue #8)。v2.1.1 把 key 改回@kanadego/dsh-heartbeat并同步修正冒烟断言;v2.1.0 的「必须用短名」结论是反的,见 CHANGELOG v2.1.0 段订正。
v2.0.x 及更早的更新记录已移至 CHANGELOG.md(README 这里只保留当前大版本 v2.1.x,插件市场的「更新内容」读的就是这一节)。
更早的版本(v1.9.x → v1.0.0,以及 v0.x 脚本外挂时代)见 CHANGELOG.md。
延伸阅读与致谢
- DESIGN.md — 深入的设计决策、宿主契约实测备忘与踩坑记录
- CHANGELOG.md — 完整版本历史
- tomsteve1102/presence-watch — 讨论起点与闸门思想
- kohaku-heartbeat — 前代项目,本插件为其重构
许可
下载量
Plugins associés
webnovel-writer
lingfengqaq/webnovel-writer
loopx (dsh-loopx-plugin)
loopx-project/loopx
ouroboros (dsh-plugin)
q00/ouroboros
loopx (dsh-loopx-plugin)
huangruiteng/loopx





