Skip to content

dsh-session-control

Verified

dsh-session-control · v1.1.0 · MIT · Web UI

DSH web GUI session management and service control: delete sessions (including ungrouped ones, with graceful agent termination) from a Settings page, plus restart / shutdown the dsh web host. · dsh Web GUI 会话管理与服务控制:设置页一键删除会话(含未分组、优雅终止 agent)+ 重启/关闭宿主服务。

Install

dsh plugin add dsh-session-control

Confirm the layer applied with dsh --profile default --dump-config — see the install guide.

Source

Published to npm without a public repository. Inspect the package contents before installing.

Tags

Creators

Readme

dsh-session-control

DSH web GUI 会话管理与服务控制插件:设置页「会话管理」一键删除会话(含未分组 / 已归档 / 空会话,运行中的会话先优雅终止再物理删除),设置页「服务控制」重启 / 关闭 dsh Web 宿主(隐藏控制台,重启后页面自动恢复)。

一个包、两个功能,零修改 dsh 安装文件,与现有补丁互不干扰(路由挂 /dsh-sc/*,不占 RPC 路由)。

安装

发布到 npm 后:

dsh plugin --profile web add dsh-session-control

本地未发布时用 link 安装:

dsh plugin --profile web add link:D:\WorkSpacee\project-006-dsh-web插件化\code\plugin\dsh-session-control

安装后重启 dsh web,设置页出现「会话管理」(order 30)与「服务控制」(order 40)两个分区。

使用

  • 会话管理:按工作区分组列出全部会话(含未分组桶),每行显示运行状态、归档标记与最近活动时间,垃圾桶按钮弹确认框。删除 = 优雅终止 live agent → 等待最终落盘(轮询 sessionPersistence.list())→ 从各 workspace 摘除账目 → 清归档标记 → 物理删除会话目录 → 发出 workspace/session-deleted(宿主据此广播 host/session-removed 帧,侧边栏与所有标签页同步消失)。客户端删除成功后调用公开的 sessions.refresh() 重拉列表兜底;遇到 session-not-found(会话已在别处删除)也立即刷新列表,幽灵条目不再残留。
    • 优雅终止是双层的,不依赖补丁:优先用 agentLoop.ownership.liveById(已打补丁 / 新版 dsh 原生带 disposeById);缺失时回退到公开的 AgentHandle——插件在宿主启动时包装 ctx.agents.create/resume,把每个 { agent, dispose } 句柄按 sessionId 捕获(lib/agent-handles.js),删除时直接 handle.dispose()。因此未打补丁的 dsh(如 rc.2)也能删除空闲/挂载中的会话,不再误报「该会话正在使用中」。
  • 服务控制:重启 = 分离拉起内置 web-restarter.mjs → 3.5s 后优雅 dispose 自身 → 4s 重启器兜底强杀 → 隐藏控制台(non-detached powershell + Start-Process -WindowStyle Hidden)拉起新宿主 → 冒烟检查端口;客户端轮询 origin,观测到宕机窗口后等新宿主就绪再 location.reload()。关闭 = 1s 后 dispose + exit,5s 硬退出兜底。

安全

所有路由仅接受同源回环请求(127.0.0.1 / ::1 / ::ffff:127.0.0.1,拒绝任何转发链头,Origin 必须与 Host 同源),与 dshmarket 的 trustedRestartRequest 同一纪律。

架构

文件 职责
package.json dsh.bundle.patchcordis.patch.ymldsh.client.inject 声明 client 依赖(connection/runtime/locale/ui-settings);exports["./client"]
cordis.patch.yml 插入 profile 层栈的插件条目
lib/index.js host 插件入口:ctx.inject(["webServer","workspaceRegistry","sessionPersistence"]),安装 AgentHandle 捕获并挂路由
lib/agent-handles.js 包装 ctx.agents.create/resume 捕获 AgentHandle 并按 sessionId 索引;disposeById 优雅终止(未打补丁 dsh 的终止路径)
lib/routes.js `POST /dsh-sc/delete
lib/delete-session.js 会话删除流程(对齐 project-006 补丁语义,全部走公有面 + 运行时探测降级)
lib/lifecycle.js 重启器拉起(保留当前 argv)与优雅关闭调度
lib/web-restarter.mjs 分离重启器(隐藏控制台纪律,禁止改动 spawn 方式)
client/client.js __ModuleLoader__ bundle:两个 settings.section + zh/en 文案 + 自注入 CSS

非公开面(ownership.liveById、registry 内部 state 助手)全部 optional-chain + 优雅降级:有就用最贴近补丁的原生路径,没有就回退到公开的 AgentHandle,缺失时功能降级为「尽力而为 / 明确报错」而非崩溃。

开发

node --check lib\*.js lib\*.mjs client\client.js   # 静态校验
node test\verify-client.cjs                        # 客户端 bundle 结构校验

隔离 E2E(不碰真实 profile / 会话):

$env:DSH_HOME = "D:\Temp\opencode\dsh-e2e"
dsh plugin --profile e2e add link:D:\...\dsh-session-control
# 编辑 D:\Temp\opencode\dsh-e2e\profiles\e2e\package.json 的 bundles 加上 @deepseek-ai/dsh-web-app
node "D:\Program Files\nodejs\node_global\node_modules\@deepseek-ai\dsh\lib\bin.js" --profile e2e --port 18080

伪造会话 artifact(zstd,header 的 cwd 必须与目录一致,目录名规则 --<encoded-cwd>--/<id>/):

const h = JSON.stringify({type:"session",version:0,id:"e2e-session-0001",createdAt:Date.now(),delegationDepth:0,cwd:"e2e-fake"});
fs.writeFileSync(".../sessions/--e2e-fake--/e2e-session-0001/session.jsonl.zstd", zlib.zstdCompressSync(Buffer.from(h+"\n")));

发布

npm publish --access public

版本

  • 1.1.0:优雅终止不依赖补丁——agentLoop.ownership.liveById 缺失(未打补丁 / rc.2)时,回退到包装 ctx.agents.create/resume 捕获的公开 AgentHandle 来按会话终止 agent,修复「空闲会话误报正在使用中,无法删除」。zero 修改 dsh 文件。
  • 1.0.1:修复删除会话失败——客户端改用公开的 sessions.refresh()(不再调用私有的 recordMutation);session-not-found 时刷新列表移除幽灵条目;host 侧删除成功后发出 workspace/session-deleted,让所有客户端经 host/session-removed 帧同步移除。
  • 1.0.0:会话删除 + 服务控制,目标 @deepseek-ai/[email protected]