dsh-pause-resume
DeepSeek Harness会话头中的一个按钮。它停止了正在运行的东西——要求一个运行的转弯 首先结束—将一个小计划写入磁盘,在重新启动后,相同的按钮使其工作 回来。
- ⏸-工作正在进行中。按下停止。
- ▶工作停止,或前一个进程留下工作要恢复。按恢复。
- 一个转弯自动停止了。按下继续未完成的内容。
- ⏸暗淡-没有停止,恢复或继续。
字形是唯一的状态。没有柜台,没有面板,没有徽章,也没有祝酒辞,因为一秒钟 指示器将成为同一事实的第二个真相来源。上次记者留了些东西给 一个人看,一句话的工具提示这么说,按钮仍然提供相同的字形。
它恢复了什么
| 工作 | 暂停 | 恢复 |
|---|---|---|
| 一个未完成的回合 | 转弯结束或取消,会话记录 | 挂载会话,然后显示一条可见的延续消息 |
| 一个被武装的目标 | 停顿了一下,修改了一下 | goals.resume 经过精确的修改;进球的驱动力继续自我驱动 |
| 这次会议只会实现这个目标 | 记录,没有停止 | 安装;重新开始的目标占据了一切 |
| 正在运行的后台作业 | 杀死并记录 | 仅记录:作业是一个活动过程,不能重放,因此延续消息命名它,如果工作仍然需要它,则轮流重新启动它 |
| 正常结束的会话 | 没有 | 原封未动,也从未被记录在案 |
| 结束/结束的会话 | 没有 | 没有 |
| 一个时间表 | 没有 | 没有 |
时刻表不暂停:时刻表服务没有禁用操作,只有删除和删除 人的时间表暂停它不是一个交易这个插件使。暂停时触发的计划 开始一个回合,但按钮一直显示▶而暂停计划等待:一个未决计划拥有主 动作,所以唯一诚实的下一步是完成恢复。计划将出现在该还原中 总结像任何其他工作开始后,新闻界。
暂停的作用是什么
出版社不会立即取消。它首先要求正在运行的转弯结束,然后才取消
窗口关闭时仍在运行的程序: wrapUpMs (默认3000; 0 马上约掉,as
0.9.0之前的每个版本都有)。在窗口内结束的转弯作为完成而停止;其余的
在时间结束时被取消,因此暂停仍然不会在它后面留下一个转弯。无论哪种方式
计划被写下来,会议被记录下来,下一步是一样的:按▶键恢复,
或者重新开始,让计划被拾起。当必须取消某些内容时,工具提示会显示
要继续的工作被保存;当一切都被自己包裹起来时,它没有说任何额外的东西。
如果窗口在未读的情况下关闭,媒体就会把它收回:一个没有发生的暂停
以后不能在恢复的会话中作为新指令重播。只有一条信息是
删除,仅适用于超时的会话,并且仅当它仍在排队时;当队列不在时
可读的报告说 retractUnavailable 而不是声明一个干净的队列。
一个没人会再坚持的计划会自动关闭。手动重启后,完成这些会话 自己就够了:每一个停下来的转身都是活下去的,向前走了,不再奔跑,所以 Plan解决了完成恢复的方式,并且按钮返回暂停,无需按下。只有 回合暂停本身停止被考虑,只有在积极的证据:一个会话仍在工作, 无法读取的会话列表或错误使计划完全保持原样。
简历如何运作
恢复并不是说工作还在继续。每个项目有三个诚实的步骤:
- 山。 停止的会话通过Harness恢复路径挂载,该路径保留其代理 预设。如果已挂载,则跳过该步骤。
- 继续,只有在新闻界取消了一个回合。 延续是一种平凡
用户消息通过
sessionController.prompt,使用从计划和派生的请求id 会话。id使重复恢复成为幂等的,并且消息在 文字记录,这样人们就能清楚地看到恢复的内容。 - 重新设定目标 随着修订,它暂停了。修改是这个人的否决权:如果
目标在暂停时改变了,它不是我们的,而项目是
skipped。
每一次尝试都用进程的id记录下来,但是日志是报告,而不是 承诺:下一个启动再次要求活的马具,而不是信任一个旧排。延续 请求id来自计划和会话,因此在回合开始前的重试将被重复数据删除 由主持人。一次失败将计划留在磁盘上,下一次按下重试仍然需要的每一项 工作。
子代理会话不能通过此进程挂载:它的父会话拥有路由。这一行是 报告一次作为父母的关注,而不是作为失败重试,所以它永远不会保持计划开放。
克拉什,不只是媒体
印刷机写快照。崩溃什么都不写,所以插件会保留心跳:
running.json 保存当前正在打开的会话和写入进程的id
它。上一个进程的记录被转换成一个崩溃计划 pending.json 心跳之前
文件被替换,所以第二次或第三次重启仍然看到相同的工作,并提供▶没有按
需要的。
崩溃记录比新闻更弱:它证明了一个会议的存在,而不是在会议结束后打开了一个回合 重新启动。还原附加每个录制的会话并读取实时回合。现在轮到他了 继续跑步;空闲的行被探针保留为空闲行,探针挂载该行并读取该行 不要提示它。无法读取或证明其状态的行被报告为未知,而未知则不是 完成:计划保留在磁盘上,按钮继续提供▶,下一次按压再次尝试。一个 无论其回合是否可证明,记录的进球都会被恢复,因为丢掉它是不可能的 这条路结束了一场崩溃的比赛,每个目标都被关注,没有一个重新开始。结束的会议 通常不输入文件。
同样的进程重新加载插件(热加载)看到它自己的id,并且知道没有什么可重载的
恢复。一个 pausing 在磁盘上发现的计划意味着媒体本身被中断了:那些会议是
如果不动,按钮会一直提供恢复功能,直到有人按下它。
停止不是一个出版社
一个回合可以在没有人按任何东西的情况下结束:提供者在自己的错误之后返回一个错误
重试,或者模型达到输出限制。这些回合是重启无法修复的情况
自己的,所以插件保留一个单独的小分类账, continue.json,并提供<s:2>而不是▶。这个
分类帐独立于暂停计划:它永远不会变成崩溃计划,永远不会暂停或取消
什么都可以,而且它本身不会发出任何信息。
成为候选人的条件:
- 最近一轮交易结束
error或max-tokens,没有以后的转弯开始或结束。 - 会话是一个根会话,没有父会话,也不是子代理。孩子停下来的回答是 它的母体的工具结果;继续让孩子一个人说话会变成没人读的对话。
- 转弯并没有结束
completed,aborted,interrupted或blocked. 手动暂停终止其 转身,所以一个人所要求的停止永远不会出现在这里;入学前的一个街区是工作 从不跑,独自一人。
新闻界继续在那一刻可见的行,一次两行,与一个普通的用户消息。 它不是重试循环:失败的行会留在分类账中,等待下一次按下按钮 当一切仍在等待时,返回到<s:2>。当一个新的回合开始时,一行就消失了 会话已经打开,当目标处于活动状态时,当会话结束时,或者当会话继续时 将完成。Title来自session自己的Title事件;没有加载任何东西只是为了命名 行。批处理的上限为40行,每一行在失败的按压中保持其尝试数。
每行都被标记为仅供显示: blocking 当它已经需要一个人或者它的错误代码是
一个重试无法修复(认证,权限,配额,未知模型,上下文长度), actionable 否则。
pendingContinue 这两项都有 count,因此,在批处理运行时,失败的工作仍然可见
运行;标签不会隐藏一行,也不会改变按下的动作——按下的动作仍在继续
每个可见的行。
在具有等待行的会话中启动新消息是接管:它清除该行,而没有 说什么旧作品的事。工作只在按下后才继续,从来没有在插件加载,从来没有 在一个计时器上,而不是因为前一批失败。
渐进还原(默认关闭)
一次恢复的六个长会话是一次恢复的六个上游模型请求,以及一个网关 与一条慢流相处愉快,与六条慢流相处往往不愉快。对于直接API用户来说,这通常是很好的 额外的等待是纯粹的成本,所以渐进恢复是 默认关闭: restore遵循 普通路径,没有添加间隔,没有请求池,没有安装冷却计时器。
当批量恢复遇到速率限制或超时时,打开它:共享帐户或网关配额; 容量有限的自托管代理,或者在一个环境中恢复多个会话 一次是失败的导火索。单会话超时没有帮助;那些需要 调查请求和上游。
两层,因为任何一层都足以打败另一层;
- 调度间隔。 会议根据血统深度以波的形式恢复,间隔为
restoreStartGapMs(3秒)加上起动之间最多0.4秒的抖动。 - 一个真实的请求池。 插件注册一个
llm/stream每个中间件持有一个许可证 适配器请求直到流结束,失败或被取消-不是在回合打开时,也不是在 第一个块到达,而不是当工具或子代理等待开始时(该请求结束)。 压缩进入同一个池purpose: 'compaction'每一次正式的重审都需要 新的许可证。守卫只在恢复运行时打开,所以普通的聊天永远不会排队 在它后面。
游泳池开始于 restoreCapacity 连续两条干净的溪流使它增加一条,达到
restoreMaxCapacity (2).连续两次失败将其降回为一次,并关闭池for
restoreCooldownMs (40秒),所以一个不舒服的上游不能被一个队列的会话锤击。一个
放弃流(那个人停顿了一下)既不是成功也不是罢工:取消很便宜。
当你按下恢复键时,开关被读取;运行中的批处理会保持初始设置,所以 在批处理过程中关闭该特性不能突然释放队列。按暂停键停止 当前的批处理。
可靠性不取决于这个开关。暂停和恢复会话、子代理和 后台作业、在恢复期间再次暂停、计划持久化、崩溃恢复、继续 关闭渐进式恢复后,重复数据删除和重试条目仍然适用。恢复循环 保持自己的小工人浪潮;只有对真实模型请求的额外限制是 可选的。
在执行还原时立即暂停。媒体停止发送消息,拒绝所有请求
还在等待许可,要求管束停止已经开始的工作,写下是什么
左背计划作为一种优秀的延续,而回归 paused 与
interrupted: true. 下一个印刷机又开始了同样的计划;延续请求id为每个周期,
因此,已经接受的消息将被重复数据删除,而不是发送两次。
/state 报告计划存在时的设置和队列: {progressive, active, enabled, capacity, running, queued, dispatched, failed, interrupted, cooldownUntil} 下 restore。这个
按钮本身只保留图标。
配置(全部可选):
| 关键 | 默认的 | 意义 |
|---|---|---|
restoreProgressive | false | 选择阶段恢复;没有平坦的小路 |
restoreCapacity | 1 | 恢复开始时允许的模型请求 |
restoreMaxCapacity | 2 | 上限的健康门可以提高到上限 |
restoreCooldownMs | 40000 | 在跨会话连续两次失败后暂停 |
restoreStartGapMs | 3000 | 恢复开始之间的间隔,加上抖动 |
wrapUpMs | 3000 | 在暂停取消之前,一个奔跑的转弯要结束多长时间 |
作用域,诚实地说:它管理通过该主机模型栈的请求。这个 Harness自己的恢复流和到达此主机之外的提供者的子代理不在 没有任何插件可以为它不拥有的公司网关承诺并发限制。这个 300秒的上游空闲超时是一个上游决策;渐进式恢复不能假装修复它, 但是它使恢复产生证据(一个会话,一个精确的请求)而不是雪崩。
恢复步距和堆的空间
恢复会话将其整个记录反序列化到Host堆中。一个大型会议是
它自己的GB规模,主机的V8大约有4gb的上限;过了它,这个过程就没有了
扔了,它就死了 FATAL ERROR: MarkCompactCollector: young object promotion failed. 测量
在2026-10-29上两次:64分钟后pid 91126 3.65 GB, 15分钟后pid 61989
以3.58 GB恢复15个会话。都离开了 crash-*-host.log 下
~/Library/Logs/DeepSeek Harness/。
因此,恢复的速度取决于它能承受的程度,而不仅仅是它必须做的事情。
- 只有这次撞车所中断的。 恢复崩溃计划记录的会话;历史 正常结束的会议永远不会被触及。自0.6.x以来没有改变。
- 最小的放在第一位。 队列是按文本大小排序的,所以轻会话优先,重会话优先
的最后一次。轻会话运行
restoreConcurrency(2)一次; - 繁重的会话单独运行。 其压缩文本在上面的会话
restoreHeavyMB有自己的一步;下一个开始时,它的回合结束,或之后restoreSettleMs(90年代) 作为上界。 - 按一下就可以清空队列。 仅因为先前恢复的会话被阻塞而保留的行
仍在工作的是由引擎自己重新尝试,一个
restoreSettleMs然后,直到什么都不剩。 在0.8.4之前,同一家出版社只安装了一个大的抄本,剩下的留给别人 再按一次,这就是partial每次重启后的样子。重试停止在 停止的人要求,就重新装填,并在之后restoreMaxAttempts恢复的回合 什么都没有。 - 堆门。 在每个步骤之前,恢复读取
v8.getHeapStatistics(). 如果头顶空间离开 低于restoreHeapReserveMB,回合没有进一步增加。一个没有得到它的会话 Turn记录在deferred而不启动加载它的转录本恰恰是代价 门存在,以避免-和下一个按或下一个启动拾取它。 - 在上马前预测。 校方还会估计一份成绩单需要的数量(六倍)
它的压缩大小),并在估计不符合净空(即净空)时保留行
左,所以一个巨大的会话在它被读取之前被拒绝,而不是在它增长堆之后。一个
不能读取大小的会话被视为重会话,并通过串行重路径;
/state.scheduling.unknownWeights报道称,这一轮无法测量有多少人。
一场阻止争吵的回合不会消耗计划:它会结束 partial,将每一行保存在磁盘上
以其 deferred 请注意, /state.restore.deferred 列出它不能挂载的内容。使用它
会删除唯一一个从未启动的工作记录,并且下一次启动将提供一个
在仍然欠一个大会话时进行清理恢复。
当一轮恢复了沉重的会话或产生 deferred, /state 也有
restartRecommended 随着堆使用情况和原因,客户端的工具提示切换到
“一旦行正在等待重新启动。”插件永远不会退出或重启主机本身:一个进程
是一个人的运行工作,和一个插件,杀死了一个更干净的堆将支付
它不拥有的数据。
忠告与它所涉及的工作一样长久:它会被保留 /state.scheduling.deferred
列出本轮保留的行(下一次按下也不能挂载它们)
健康的一轮,没有任何延迟,六个多小时前的建议被取消了
除非排队的人还在等。被保留的一行保留了它原有的意图
继续),并在下一次恢复时带着它回来。
这三个内存数字是从这个主机实际拥有的堆中派生出来的,而不是写在这里:
一个4 GB的V8上限和一个16 GB的V8上限不能共享一个预留,一个小上限一次只需要一个会话。
/state.scheduling 报告已解析的值 derived,上面写着它们的来源
堆而不是from config。
| 关键 | 默认的 | 意义 |
|---|---|---|
restoreConcurrency | 1 如果V8上限低于3 GB,则为 2 | 光会话在一个回合中立即恢复 |
restoreHeavyMB | heapLimitMB / 340,夹紧到8 - 48mb | 压缩的文本大小使会话很重 |
restoreHeapReserveMB | 22% V8的盖子,夹在320-1536 MB | 堆的净空,在这个净空下面没有任何东西 |
restoreSettleMs | 90000 | 上界等待一个沉重的回合 |
restoreMaxAgeHours | 72 | 更早的崩溃记录是存档的,而不是挂载的 |
这四个都是可选的;设置一个引脚的数字,并留下其他派生。
这是与渐进恢复不同的一层。 restoreProgressive, restoreCapacity,
restoreMaxCapacity 和 restoreCooldownMs 将真实模型请求限制在上游;这四个
限制一次恢复保留多少抄本以及执行多少会话。两者都可以打开,
两者都不能取代另一方。坠机证据,调度流程,还有 deferred /
restartRecommended 字段的描述见 docs/memory-safety.md。
支持的平台上
macOS, Windows和Linux。状态和日志通过 node:path 和 node:fs 只是,在
$DSH_HOME (或 ~/.dsh 当变量未设置时);没有东西叫壳,也没有东西出壳
来 stat, du 或 ps. 跨进程排除使用 session.lock 文件而不是仅限posix
调用。在Windows上,这个目录 fsync 没有等价物,因此跳过它—write仍然是
临时文件加 rename ——加上行尾,这是两者的唯一区别
平台。
安装
plugin_manager install_bundle dsh-pause-resume
或者使用包名从Harness插件管理器安装bundle。每一个配置
key是可选的(参见渐进式还原),并且插件不持有凭据。 allowRemote 存在于从另一个获得的挽具
机;Local-only是默认值。
保证和限制
- 排斥的。 这个阶段存在于主机上,在任何工作开始之前写入,所以有两个窗口,
双重压力机和工具调用不能重叠。第二个来电者被告知
busy——除了停顿 在恢复过程中,它在现场中断而不是拒绝:停止绝对不能是 等待的操作。 - 先持久后破坏。 在计划存储在磁盘上之前,不会取消任何回合。写入失败意味着 一切都没有停止。
- 有界的。 一直失败的还原保留在磁盘上,其行命名为;它不关闭
如果工作完成了。无法读取的行重试一次,然后报告真实值
进度或退出计划
partial与每行关注,所以按钮停止重复 无操作。手动继续的会话被恢复,永远不会重新发送,并且他们的注意力排清除为 他们一跑。一个超出预算的尝试会被观察得更久一些 称为失败,并且这个计划已经恢复的会话保持恢复,即使脊甲 在以后的启动中恢复它并移动它的回合。 - 幂等。 延续请求id来源于计划和会话,因此需要重试
不能发布相同的消息两次;已经移动的一转不再继续,一转
一人已续报
already running而不是再次被压迫。这个 Harness没有比较承认功能,因此在最后一次读取状态和接收状态之间会有一个亚秒级的窗口 提示录取;守卫缩小了它的范围,结果永远不会声称是原子性的。 - 诚实的。 不可读状态从不报告
paused. 一个会话被手工删除,一个目标被 另一方面,一个已经在运行的会话:每个会话都被跳过,并在结果中命名。 - 没有隐性收购。 没有公共API来分离代理,所以暂停保证是 “回合取消,目标暂停,工作终止”——而不是“进程冻结”。目标之所以持续,是因为 挽具有一个机制;普通会话通过一条可见的用户消息继续进行。
- 无第三方插件状态。 插件的进程内状态属于该插件的挂载。
- 默认为Local。 路由需要同源请求和插件头。远程使用必须 他选择了,但仍然不能跳过标题。
文件
所有国家都生活在 $DSH_HOME/pause-resume/:
| 文件 | 目的 |
|---|---|
snapshot.json | 印刷机停止了工作, pausing 或 paused |
pending.json | 保存到恢复完成的崩溃计划 |
journal/<planId>.jsonl | 还原尝试,并标记生成它们的引导 |
restores/<planId>.json | 存档的计划,作为上次恢复的记录保存 |
last-restore.json | 最后一次还原的摘要 |
running.json | 会话与开放的转向,为崩溃残留 |
continue.json | 转动那停止自己,等待一个继续按 |
每次写入都是一个唯一的临时文件, fsync, rename,然后是目录 fsync. 国家从来不是内部的
包。
发展
npm test
npm run audit
npm run smoke:host # boots a throwaway real Host on a free port and asserts the routes
npm run smoke:live # real Host + local mock model stream: pause, SIGKILL, restart, resume once
npm run smoke:maintenance # real Host: pause cancels an in-flight compaction, apart from the session turn
npm run smoke:wrapup # real Host + held model stream: the turn answers the pause as an ordinary completed turn
结束路径有自己的记录 docs/evidence/host-wrapup.json (这是一个真正的转折
窗内,所以计划欠一个延续),旁边 docs/evidence/host-live.json (一个
这是一个到期的窗口,媒体会收回自己的主导权)。
验证记录保存在 docs/acceptance-0.6.11.md (当前版本:重复失败保留
可持续性,暂停截断正在运行的批,承认所有权,移交证明,冷/陈旧的目标
恢复,继续后面的渐进式门,并阻止与可操作的行,与证明和
未经证实的两半被分开), docs/acceptance-0.6.10.md (自动停止旋转和一个继续按压), docs/acceptance-0.6.9.md (前一次评审的十个缺陷), docs/acceptance-0.6.7.md (一种移动
按钮而不重新启动任何东西), docs/acceptance-0.6.6.md (一个 unknown 划一个人
手工制作完成后,孩子们的排与根,比赛窗口,和
这还有待证实), docs/acceptance-0.6.5.md (0.6.5), docs/acceptance-0.6.0.md (0.6.0-0.6.1)
和 docs/evidence/. 从第二次评审到代码和证明的八项映射是
docs/objective-round2-closure.md. 工作生命周期倾听设计回顾,包括工作的原因
从来没有重启过,是吗? docs/design/job-lifecycle.md. 0.7.0恢复背后的内存安全策略
踱步-为什么恢复会杀死主机,崩溃证据,调度流程和一个人的字段
应该看看——是吗 docs/memory-safety.md。
lib/engine.js 不执行I/O; lib/snapshot.js 持续下去, lib/probe.js 拥有每个线束服务
契约(代理身份、目标修订、每个所有者的作业、继续提示),以及 index.js 只有
将它们连接到网络路由上。所有这些都可以在没有线束的情况下进行测试: test/apply.test.mjs 挂载
针对假注册表的插件。
麻省理工学院。
一行说明:会话头一个按钮,⏸ 停掉正在跑的回合、目标与后台任务;重启后同一个按钮变 ▶,把上次的工作 接回来。正常结束的会话不记录、不恢复;崩溃会接回记录里的会话与其目标,暂时无法确认状态的会话保持计划未完成,按钮继续给 ▶;日程不会被动 (该服务只有删除,没有停用),后台命令只记录不重跑。