DSH HUB
HomePlugin StorePlugin PacksCommunityRankingsResourcesPublish Guide
Plugin source
Back to catalog

notpdpton /

notpdpton/dsh-session-continue

Verified

会话非正常结束时,在输入框上方显示提示条与「继续」按钮。

★ 0 Stars0 Forks0 IssuesN/A Community rating0 Confirmed installs
View on GitHub
READMESource: main@5bc2be63

会话中断继续 · dsh-session-continue

一个独立的 DeepSeek-Harness 插件:会话非正常结束时,在输入框上方显示提示条与「继续」按钮。

插件只有一个包,自带 Host 半边与浏览器半边,没有子包、没有运行时依赖,也不 依赖任何其他插件。

项 值
包名 dsh-session-continue
插件名(诊断用) dsh-session-continue
投影键 sessionContinueInterruption
版本 0.1.0
依赖 无

解决什么问题

Agent 的一轮对话可能并不是「正常结束」的:

  • 进程被杀 / 崩溃,日志尾部那一轮永远没有 turn/end;
  • 重启、刷新页面、断线,正在跑的一轮被中途掐断;
  • 任务本身出错、被阻止,或输出撞到长度上限;
  • 你自己按了停止,但活还没干完。

这些情况下工作都停在了半路上。插件把「这一轮是怎么结束的」「停在那一轮」「当时 的任务清单」折叠成一小份状态,在输入框上方显示一条提示,并提供「继续」按钮: 点一下就把接续指令填进输入框并提交,模型于是知道上次没跑完、应该接着做。

装上之后长什么样

提示条在 conversation.input.dock 槽位,位于输入框正上方(排在自带的待办 dock 之上)。收起时只有一行:状态点、标题「会话未正常结束」、以及一句话的原因。 展开「详情」后多三行:中断轮次、错误代码、错误信息——展开区没有分割线,它就在卡片 自己那块表面上往下长。右侧三个按钮:详情 / 继续 / 忽略。

  • 只在会话没有正常结束且 agent 当前不在运行时出现;
  • 「忽略」只对这一次中断生效,下一条中断会重新出现;
  • 任务清单不在提示条里重复(自带的待办面板就在正上方),而是随「继续」 指令一起发给模型。

插件卡片在「插件」页显示为「会话中断继续」,图标是蓝底播放三角。

两个开关在「插件」页本插件自己的详情页里(plugins.bundle.config)。插件名、图标、 包名与版本号都由插件页自己绘制,这里只放开关:

开关 默认 作用
恢复进度与任务清单 开 「继续」时附带未完成的任务清单与中断轮次
提示手动停止的会话 开 关掉后只提示非你主动结束的会话

插件本身的启用/禁用由「插件」页那张卡片上的开关控制,详情页只放这两个偏好,不重复一个总开关。 侧边栏里不会多出一个「会话中断继续」的设置项——两个开关不值得占一格导航。

安装

从 npm 安装

在 DSH 的「插件」页选择「添加插件」,填入包名 dsh-session-continue,装好后在 bundle 列表里确认 dsh-session-continue 已启用。

命令行等价写法:

npm install dsh-session-continue

从 Git 仓库安装

同样在「插件」页选择安装,填入本仓库的地址(<主机>/<账号>/dsh-session-continue)。 仓库地址不写进包内文本:一个包不该带着某个账号名四处走。

本地开发安装

把源码目录 link 进 profile,并把包本身加入 bundle 列表:

// <profile>/package.json
{
  "dependencies": {
    "dsh-session-continue": "link:<本仓库的绝对路径>"
  },
  "dsh": {
    "profile": {
      "bundles": [
        // ...
        "dsh-session-continue"
      ]
    }
  }
}

包内的 cordis.patch.yml 会插入唯一的一行,把包挂进配置树;浏览器半边由 package.json 的 dsh.client 声明发现,不需要第二行。

实现要点

Host 半边(index.js)向 ctx.sessionProjections 注册一个名为 sessionContinueInterruption 的投影单元,把整条会话日志折叠成浏览器需要的少量状态。放在投影里而不是浏览器里, 是因为浏览器只持有一个分页的事件窗口,而投影折叠永远看到完整日志。

投影声明了 wire 视图,所以值在 Host 侧算好、由框架缓存后推给客户端。wire 视图 必须保持引用稳定:注册表用 Object.is 比较相邻两次 view 的结果,只要变了就发布, 而一次发布要花掉一个控制流帧、一次客户端 store 写入、一次整份会话列表快照重建和一次 对话区重渲染。一轮里每个工具调用都会产生一个 step/start 和一个 step/end,它们不 改变任何客户端渲染的东西,所以折叠把它们记在只属于 Host 的字段里(openStep、 hasTurns),wire 视图不包含这两个字段——于是它们永远不触发发布。

浏览器半边(client.js)只从 wire 视图读八个字段:status、turn、reason、 abortCause、errorCode、errorMessage、partialMessage、todos。

判定的难点:主动停止 vs 被动中断

两种情况的日志一模一样:turn/end { kind: 'aborted', reason: { kind: 'user' } }。 你自己按停止会写它,Workspace 停会话(归档工作区、退出应用)也会调 agent.cancel({ kind: 'user' }),注释里明说是「照用户自己停的样子来」。

能区分的只有 partialMessage:按停止时模型正在流式输出,harness 会把已经吐出来的 那段以 interrupted: true 的消息落盘;而在一轮之间被杀掉(刷新、重启、重连)没有 流在飞,也就不会有这条消息。

没有这条消息时默认判为中断而不是「用户主动停止」:多显示一条不需要的提示是无害的, 漏显示一条崩溃后的提示会丢工作。

详细的设计推演、边界与实测数据见 docs/design.md。

目录结构

dsh-session-continue/
├── index.js            Host 半边:interruption 投影(键 `sessionContinueInterruption`)
├── client.js           浏览器半边:提示条与设置页
├── cordis.patch.yml    挂载本插件的一行 patch
├── package.json
├── icon.svg            Plugins 页面的图标(36×36 画布)
├── locale/             Plugins 列表的标题与描述
│   ├── zh.json
│   └── en.json
├── docs/
│   └── design.md       设计推演:判定规则、wire 契约、代价
└── test/               离线验证脚本

验证

test/ 下的脚本全部离线运行,不需要启动 DSH、不需要安装依赖、不联网。它们加载 实际发布的文件(用 window.__ModuleLoader__ 的 shim 捕获浏览器半边入口)来校验, 而不是校验一份副本。

只读会话日志的那几个脚本需要 Node ≥ 22.15:它们用 node:zlib 的 zstd 解压, 更早的版本没有这个 API。插件本身对 Node 没有要求——Host 半边一个 import 都没有, 浏览器半边只从模块表取 react。

cd test

# 一次跑完所有强制校验
node run.mjs

# 或逐个跑
node verify-manifest.mjs       # 清单、exports、patch、locales、图标、身份卫生
node verify-resolve.mjs        # Host 会为这个包解析的每一个资源
node verify-metadata.mjs       # 插件管理器的显示元数据读取(exports 语义)
node verify-client.mjs         # 槽位注册、词典、提示条渲染决策
node verify-layout.mjs         # 提示条两态对齐的静态审计
node verify-continue.mjs       # 「继续」动作与两个开关
node verify-icons.mjs          # 图标:结构、自洽、调色板、几何、渲染
node audit-perf.mjs            # 用真实会话日志量一次折叠与发布次数

会话日志相关的诊断脚本需要一个真实会话目录作参数(默认读 $DSH_HOME/sessions,再退回 ~/.dsh/sessions),它们只读不写:

node dump-session.mjs    <sessionDirOrId>   # 逐事件打印一轮的结构
node explain-session.mjs <sessionDirOrId>   # 这个会话为什么显示/不显示「继续」
node explain-aborts.mjs  <sessionDirOrId>   # 主动停止与刷新/重启中断的区分
node scan-signals.mjs                       # 扫描全部会话的判别信号
node verify-fold.mjs     <sessionDir> ...   # 用真实日志跑一遍折叠

没有会话目录时这些脚本会明确说明「没有语料」并跳过,不会假装通过——一个没有语料 的机器是「没测」,不是「通过」,把两者混为一谈正是绿灯最容易骗人的地方。

会话根目录按 $DSH_HOME/sessions → ~/.dsh/sessions 的顺序解析,也可以用参数 直接给一个目录;所有脚本只读。

许可

MIT

—/ 5

No ratings yet

Verified DSH bundle

Commit 5bc2be6381f4

Community comments

No comments yet. Be the first to write one.

DSH HUB

A community index for DSH plugins. Not an official GitHub or DeepSeek AI product.

CommunityResourcesAPIAbout