DSH HUB
HomePlugin StorePlugin PacksCommunityRankingsResourcesPublish Guide
Plugin source
Back to catalog

EIGHTfs /

dsh-session-manager

Verified

DSH 会话功能增强插件(重命名/分支/归档)

★ 0 Stars0 Forks0 IssuesN/A Community rating0 Confirmed installs
View on GitHub
READMESource: master@d3376c37

dsh-session-manager

DeepSeek Harness(DSH)会话管理增强插件:归档会话可恢复、支持删除会话、AI 自动重命名、非人为中断自动续跑、手动释放活跃会话、会话分组(Workspace)、会话导入导出(zip 合并式恢复 + 导入后自动续跑/修复联动)、用大白话解释内置菜单。

针对 DSH 0.1.0-rc.6 内置会话菜单的痛点:

痛点 内置行为 本插件
归档会话是单向陷阱 归档后从侧边栏隐藏,没有任何查看/恢复入口(官方 README 自认 "No Session deletion or unarchive control") 侧边栏新增「会话管理」面板,「已归档」页可查看并恢复(取消归档)
没有删除会话能力 内置界面完全无删除入口 面板支持删除会话(拒绝删除运行中会话 + 二次确认)
标题跟不上对话 只有「首条消息自动起名」一次性的;主题变了标题不变 每会话可勾选自动重命名:AI 分析最近对话,主题明显偏离时自动改标题
中断了不会自己继续 回合因崩溃/限流/超时中断后,只能人工重新打开会话再发消息 读取会话记录识别非人为中断,自动让 AI 继续完成原任务
活跃会话只增不减 会话一旦被打开就一直挂在内存,没有关闭/释放入口 置为不活跃 / 释放全部空闲:把空闲会话拆回冷状态,记录保留、可自动恢复挂载
菜单选项看不懂 「分叉会话」「归档会话」无任何解释 面板「说明」页用大白话解释 重命名 / 分叉会话 / 归档会话 分别是什么意思

内置菜单到底是什么意思

  • 重命名:改会话标题,不改内容。
  • 分叉会话:以当前会话「最后一个已完成的回合」为起点派生子会话——继承这段对话历史,自动命名「原标题 (N)」并打开;原会话完全不动。类似 git 分支:想换个方向探索又不破坏原会话时用它。
  • 归档会话:把会话从侧边栏所有分组中隐藏(相当于收进抽屉),数据保留在磁盘上。但内置菜单归档后界面上没有找回入口——本插件的「已归档」页可以恢复。

功能

  1. 会话管理面板:侧边栏底部(设置上方)新增「会话管理」入口,浮层面板三个视图:
    • 启动即自动加载 + 长效保存(v1.10.0):插件挂载时自动预取会话列表(不依赖打开面板),每次刷新结果写入 localStorage——面板重开/页面刷新秒显历史数据,无需等待
    • 全部会话:按工作区(分组)分节展示——会话自动归入其 cwd 的最深祖先分组(如 move-test 子目录会话归 move-test 组、其余归 workspace 根组),分组标题显示会话数、可点击折叠/展开,0 会话分组不显示,未匹配任何分组的会话归入「未分组」节(host 无分组 API 时自动回退平铺)。每条会话显示 标题 / 目录 / 最后活动时间 / 状态徽标(运行中、已归档、已中断),可 归档 / 删除;每条会话有自动重命名、自动续跑勾选框(自动重命名勾上后出现「分析」按钮可立即手动触发一次;被中断的会话出现「继续」按钮可立即手动续跑;live 空闲会话出现「置为不活跃」按钮),面板顶部有释放全部空闲
    • 已归档:列出被归档的会话,可 恢复 / 删除
    • 说明:解释内置三个菜单项 + 本插件新增的能力
    • 另见「会话分组」功能(设置 → 插件配置 → 会话分组卡片)
  2. 自动重命名(AI 分析主题偏移):
    • 给会话勾选「自动重命名」后,每次对话回合结束(turn/end),插件延迟几秒分析一次
    • 分析 = 折叠出最近最多 12 条用户消息 + 当前标题,调用 LLM(复用会话自身的模型路由 request/header 里的 provider/model)判断「主题/方向是否已明显偏离标题」
    • 明显偏离 → 生成 ≤20 字新标题,通过 sessionTitle.rename() 落盘(标题会 pin 住,内置首条消息自动起名不会覆盖)
    • 标题带实时状态后缀:「(运行中)」= 回合进行中、「(已中断)」= 崩溃/错误中断待续跑;回合开始/结束自动更新(主题由 LLM 生成、后缀由状态机维护,两者分离;可用 config.titleStateSuffix: false 关闭)
    • 成本控制:同会话分析最小间隔 5 分钟、至少新增 3 条用户消息才再分析、全局最多 2 个分析并发
    • 只对 live 会话生效(正在聊天/刚打开的会话);冷会话的勾选状态会持久化,等你打开它聊天后自动生效
  3. 自动续跑(非人为中断自动继续,核心新增):
    • 识别非人为中断:读取会话记录,只看最后一次回合边界——
      • turn/end reason.kind === "interrupted":DSH 崩溃修复写入的合成闭合(进程被杀/崩溃)
      • turn/end reason.kind === "error" 且错误码 ∈ {RATE_LIMIT, SERVER, TIMEOUT, EMPTY_RESPONSE}:可重试的基础设施错误
      • turn/end reason.kind === "aborted" 且非用户/目标主动取消:系统原因中断
      • 末尾是未闭合 turn/start(open turn):崩溃中断
      • 不算非人为中断:用户手动点「停止」、目标暂停(goal/parent)、普通完成、blocked、max-tokens、非可重试错误——这些不会自动续跑,但被中断的会话可手动点「继续」
    • 自动继续:live 会话直接 agent.followup(续跑提示);冷会话 ctx.agents.resume()(沿用会话最近的 provider/model + 原 agent preset 组合,保证工具齐全)→ 发送续跑提示(source=plugin,不伪造用户消息)→ 等回合结束 → flush → dispose() 释放 agent,活跃会话数回到基线
    • 触发时机:插件启动后首扫(15s)+ 周期扫描(默认 5 分钟)+ 每次回合结束事件判断
    • 防护(防死循环与资源堆积):每会话串行锁、全局并发上限(默认 2)、活跃(attached)会话上限(默认 12,达到后自动续跑暂停、手动仍可用)、同会话冷却(默认 15 分钟)、每会话自动续跑总次数上限(默认 3)、续跑回合超时取消(默认 20 分钟)
  4. 任务完成汇报(task-completion-report 管道,合并自 dsh-task-completion):
    • 约定注入:插件启动时把「任务结束必须用 ═ 分隔线 + ✅ 任务完成 + 交付/验证/遗留 三要素收尾」注入每个 agent 的系统提示(systemPrompt.section)——所有会话所有 AI 生效,无需用户反复叮嘱
    • 工具(agent 结束前可调用):task_completion_render 渲染标准收尾块;task_completion_check 自检文本是否满足格式,返回缺失项
    • API:/api/task-completion/{status,render,check}(curl 可验证)
    • 管道逻辑(渲染/校验)是纯函数(lib/core.js),「任务做完了吗/交付了什么」的判断仍留在 agent
  5. 会话导入导出(合并自 dsh-session-transfer v0.1.0,设置 → 插件配置 → 「会话导入导出」卡片):
    • 导出:会话日志(sessions/)+ 工作区注册表(storages/workspace.json)+ 投影缓存(session_projcache.json)+ 用户级技能(skills/*.md)打包 zip;可选含工作区文件(跳过 node_modules/.git/extracted 等可再生大目录 + 单文件 >100MB / 总量 >1GB 跳过)
    • 导入(合并式恢复):会话日志重映射到现网路径键、workspace.json 合并(现网保留 + 追加去重 + 孤儿引用跳过留痕)、归档状态保持、projcache 按 id 合并(fail-soft)、技能拷贝、工作区同名默认跳过(可配覆盖)、权限收紧 + 全量比对验证(注册表无悬空引用);导入前现网注册表自动留底到 <dshHome>/session-transfer/backups/<时间戳>/,可回退
    • 联动:导入完成后自动触发「自动续跑扫描」(可续会话立即进入续跑队列)+「损坏会话修复」(jsonl 格式问题自动修)——会话恢复走 session-manager 一条链路,git-rescue 的会话恢复联动也因此受益
    • 安全:zip 条目路径穿越防护(../绝对路径/盘符/反斜杠/NUL 全拒)、非法会话 id 拒绝、上传大小上限、ZIP64 明确报错
    • API 前缀:/api/session-manager/transfer/*(status/export/list/download/remove/import/backups)
  6. Host API(/api/session-manager/):
    • GET /list — 全部会话:id、标题(折叠自日志)、cwd、创建/最后活动时间、live / archived / running / autoRename / interruption(中断判定)/ autoContinue / continueRunning 状态;损坏的日志会带 inspectError 字段
    • POST /archive {sessionId} — 归档(原生 workspaceRegistry.archiveSession)
    • POST /unarchive {sessionId} — 取消归档
    • POST /delete {sessionId} — 删除(拒绝运行中 → detach → 取消归档 → workspace 记账清理 → 删除磁盘日志)
    • POST /auto-rename {sessionId, enabled} — 开关自动重命名;开启时立即分析一次
    • POST /analyze {sessionId} — 立即手动分析一次
    • POST /continue {sessionId} — 手动续跑(异步执行,立即返回 accepted,列表用 continueRunning 反映进行中)
    • POST /auto-continue {sessionId, enabled} — 逐会话开关自动续跑(覆盖全局默认)
    • POST /scan — 立即扫描一遍全部会话并自动续跑(测试/手动触发用)
    • POST /detach {sessionId} — 置为不活跃:释放一个 live 空闲会话(拒绝运行中 / subagent 拥有的会话;日志保留,可重新挂载)
    • POST /detach-all — 释放全部空闲:释放所有 live 空闲会话,返回 {released[], skipped[]}(跳过运行中 / subagent / 续跑中)
    • 高峰期省钱模式(/api/session-manager/peak-*,v0.7.0):
      • GET /peak-status — {enabled, isPeakHour, peakHours, peakHoursText, sessions:{id:{notifiedAt,ackedAt,paused}}}
      • POST /peak-pause {sessionId} — 高峰期暂停:detach 释放 + 记账 paused(运行中/subagent 拒绝 409)
      • POST /peak-resume {sessionId} — 清除暂停标记(重新打开/发消息自动挂载)
      • POST /peak-ack {sessionId} — 确认「继续跑」:本次高峰不再提醒、自动续跑放行
    • 任务完成汇报(/api/task-completion/):GET /status(插件状态)、POST /render {delivered, verified, remaining, status}(渲染收尾块)、POST /check {text}(校验收尾格式)
    • 会话导入导出(/api/session-manager/transfer/,v0.8.0,原 dsh-session-transfer 合并):
      • GET /status — 状态(home/workspace/会话数/技能数/导出数)
      • POST /export {includeSkills?, includeWorkspace?} — 生成导出包
      • GET /list — 导出历史列表
      • GET /download?id= — 下载导出包(zip)
      • POST /remove {id} — 删除导出包
      • POST /import(raw body zip)— 合并式恢复;导入后自动联动续跑扫描 + 会话修复
      • GET /backups — 导入留底列表
    • 会话分组(/api/session-manager/group/,原 dsh-session-group 合并):
      • GET /status — 分组数 / groupRoot / workspaceRoot / profile / dshHome / blockGroupNewSession
      • GET /list — 全部分组(workspaceId / path / title / sessionIds / createdAt / updatedAt)
      • POST /create {title? | path?} — 创建分组:mkdir(如缺)+ workspaceRegistry.create 采纳目录;默认在 <dshHome>/Group/<title> 建软链接 → workspace 项目目录
      • POST /delete {workspaceId} — 删除分组引用(目录与会话保留)
      • POST /rename {workspaceId, title} — 分组改名
      • POST /move {workspaceId, sessionId, handoff?} — 移动 = 归档原会话 + 分组下新建承接会话 + 交接(用户约定,2026-08-18):归档原会话(可还原)→ 在分组下新建会话(cwd=分组 path 自动归属,默认开启自动重命名)→ 把交接说明(默认说明原会话已归档 + 承接会话行为约束;可传 handoff 覆盖)作为首条消息发给新会话;返回 {oldSessionId, archived, newSessionId, handoffAccepted};归档被 DSH 拒绝时 → 409 archive-failed(实测运行中会话可正常归档交接)
      • POST /new-session {workspaceId?, handoff?} — 在分组下新建会话(cwd=分组 path 自动归属,默认开启自动重命名);不带 workspaceId 时默认落在 .dsh 上一层 workspace 工作区(不存在则自动新建文件夹);blockGroupNewSession: true 时拒绝 401;带 handoff 时创建后把交接说明作为首条消息发出)
      • POST /set-config {blockGroupNewSession} — 运行时热改「禁止分组下直接新建会话」(仅内存生效,持久化需改 patch config)
  7. 会话分组(原 dsh-session-group 插件合并):在 设置 → 插件配置 → 「会话分组」卡片 管理 Workspace 分组——
    • 创建分组:给分组名(默认在 <dshHome>/Group/<title> 建软链接,项目本体留在 workspace 根)或绝对路径;分组即侧边栏的一个归类容器
    • 分组列表:分组名 / path / 会话数,可重命名、删除(引用删除、目录与会话保留)
    • 移动会话:输入会话 ID + 目标分组。移动 = 工作移交(用户约定):原会话先归档(可还原),再在分组下新建一个承接会话,并把交接说明作为首条消息发给新会话(可传自定义 handoff)——因为 DSH 机制不允许已有会话跨 cwd 移动,这是唯一可靠的「把会话归到某分组」的方式;归档失败时才返回 409(实测运行中会话可正常归档交接)
    • 在分组下新建会话:cwd 自动取分组 path → 自动归属该分组;可带 handoff 把当前工作交接给新会话(首条消息即交接说明)
    • 承接会话行为约束(用户约定 2026-08-18):move / new-session 的交接说明自动附带「行为约定」——承接会话只简单了解情况 + 把已知信息总结发给用户,不直接开始写代码(即使发现原理/代码有 bug 也不动手,先汇报情况等用户指示)
    • 承接会话默认开启自动重命名(用户约定 2026-08-18):move / new-session 创建的承接会话自动打开「会话管理」面板的自动重命名开关(主题变化自动改标题),可在面板随时关闭
    • 「禁止在分组下直接新建会话」开关:开启后隐藏侧边栏每个分组行的「+」按钮并在服务端拒绝
  8. 高峰期省钱模式(DeepSeek 2026-08-17 起峰谷分时定价:高峰时段价格翻倍):
    • 高峰期暂停自动续跑(默认开启 peakPauseAutoContinue):处于高峰时段时,自动续跑不启动(省钱核心);用户点「高峰继续」(peak-ack)可放行单个会话,或过了高峰时段自动恢复
    • 高峰期提醒(peakRemindEnabled):回合结束时若在高峰时段且会话未确认过,记录「高峰期待确认」标记,面板显示高峰期横幅 + 会话行「高峰」徽标,提醒用户可用「置为不活跃」暂停非必要会话
    • 手动暂停/恢复:会话行「高峰继续」= 确认该会话本次高峰放行;「继续」= 清除暂停标记(被暂停的会话重新打开/发消息自动挂载)
    • 高峰时段可配置 peakHours(默认官方 9:00-14:00;支持多段与跨天,如夜间 21:00-2:00 用 [[21,2]])

配置(cordis.patch.yml 的 config,全部有默认值)

- insert:
    - id: dsh-session-manager
      name: dsh-session-manager
      config:
        enabled: true              # 自动续跑总开关
        defaultAutoContinue: true  # 单会话默认开启(面板可逐会话覆盖)
        maxConcurrent: 2           # 全局同时续跑会话数上限
        maxAttached: 12            # 活跃(attached)会话上限,达到后自动续跑暂停
        cooldownMs: 900000         # 同会话自动续跑最小间隔(15 分钟)
        maxContinuesPerSession: 3  # 每会话自动续跑总次数上限(防死循环)
        turnTimeoutMs: 1200000     # 单回合续跑最长等待(20 分钟),超时取消
        scanIntervalMs: 300000     # 周期扫描间隔(5 分钟)
        groupEnabled: true         # 会话分组功能总开关
        groupRoot: ""              # 分组根目录,默认 <dshHome>/Group(.dsh 下)
        workspacePath: ""          # 项目根目录,默认取默认 workspace 的 path
        blockGroupNewSession: false # 禁止在分组下直接新建会话(默认 false = 不屏蔽;新建会话默认落 workspace 工作区)
        peakHours: [[9,14]]        # 高峰期时段(DeepSeek 官方 9:00-14:00 价格翻倍;支持多段/跨天,如 [[9,14],[21,24]]、[[21,2]])
        peakRemindEnabled: true    # 高峰期提醒总开关(回合结束提醒用户可暂停)
        peakPauseAutoContinue: true # 高峰期暂停自动续跑(省钱核心;用户 ack「继续」或过高峰后恢复)

当前实例活跃会话数可用内置 RPC host.describe 查询(attachedSessions 字段),作为设置 maxAttached 的参考。

安装

开发/验证请使用隔离测试环境(主实例 ~/.dsh 是只读的),以本仓库内的干净环境脚本为例:

cd /vol1/@appshare/DeepSeekHarness/workspace
# 1) 复制插件源码
mkdir -p <env>/profiles/web/node_modules_local/dsh-session-manager
cp -r dsh-session-manager/{package.json,cordis.patch.yml,lib} <env>/profiles/web/node_modules_local/dsh-session-manager/
# 2) 补软链(镜像型 node_modules 必须)
ln -sfn ../node_modules_local/dsh-session-manager <env>/profiles/web/node_modules/dsh-session-manager
# 3) 注册三要素
#    cordis.patch.yml 追加:
#      - insert:
#          - id: dsh-session-manager
#            name: dsh-session-manager
#    package.json dependencies 追加:
#      "dsh-session-manager": "file:./node_modules_local/dsh-session-manager"
# 4) 重启实例

验证:

curl -s http://127.0.0.1:<port>/ | grep -o 'dsh-session-manager[^"]*'   # boot 含插件
curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:<port>/plugins/dsh-session-manager/client.js  # 200
curl -s http://127.0.0.1:<port>/api/session-manager/list

实现说明(内部变通,升级 DSH 需复核)

自动重命名部分:

  • 开关与分析记账持久化在独立存储域 dsh_session_manager(<DSH_HOME>/storages/dsh_session_manager.json),用 DSH 官方 storage-domain 机制(defineDomain + ctx.storageDomain.open),非手写文件
  • LLM 调用复用官方 dsh-session-title-llm 的模式:ctx.llm.stream + BlockAssembler + createUserMessage,模型路由取会话自身 request/header 里的 {provider, model}
  • 改标题走公开 API sessionTitle.rename(session, title)(与内置重命名同一入口),会把标题 pin 为 user 来源——副作用是内置「首条消息自动起名」不再覆盖它,这正是期望行为
  • 分析逻辑(prompt 构造 / 判别结果解析)导出为纯函数并有单测:node test-auto-rename.mjs(12 项断言,mock LLM 流)

自动续跑部分:

  • 中断判定:崩溃中断的冷会话,sessionPersistence.inspect() 会先套用 DSH 的 interruptedTurnClosers 崩溃修复(合成 turn/end reason.kind="interrupted"),插件直接读修复后的事件流即可;判定函数 interruptionInfo 导出为纯函数(node test-interruption.mjs,21 项断言)
  • 续跑机制参考 dsh-headless 直驱写法:ctx.agents.resume({resumeSessionId, agentOptions, setup}) 加载持久化会话并挂 agent → agent.followup() 发送续跑提示 → 回合结束 sessions.flush() → handle.dispose() 释放(活跃会话数回落)。setup 里 installModelSelection 安装会话最近模型路由、agentPresets.mount 挂载原 preset 组合(保证工具齐全)
  • 记账:autoContinue[sessionId] = {lastContinuedSeq, lastContinuedAt, continueCount},lastContinuedSeq >= 中断 turn/end 的 seq 视为已续过,配合冷却与总次数上限防死循环(node test-auto-continue.mjs,12 项断言)
  • 全链路 e2e:bash e2e-crash-continue.sh(真实创建会话 → SIGKILL 模拟崩溃 → 重启 → 插件首扫自动续跑 → 验证中断清除 + 记账落盘)

手动释放部分:

  • DSH 没有「关闭/释放会话」的公开入口:host.describe 的 attachedSessions 就是 ctx.agents.list().length,会话一旦被 UI 打开就常驻。detachSessionAgent 复刻 dsh-agent-loop 生命周期 dispose 的拆卸顺序:agent.cancel(keepInbox) → whenIdle → agent.scope.dispose()(卸载 agent 作用域 fiber 的注册项)→ agents 注册表移除 + agents.emitDisposed(entry)(复刻 detachEntered)→ sessions.flush → sessions.store 条目 detach()(触发 session/disposed → 持久化协调器 retire 落盘)
  • 守卫:运行中(open turn)拒绝;subagent 拥有的会话(hasApiRemoteSubagentOwner,即 header.origin==="subagent" 或父代理拥有)拒绝;冷会话幂等返回 not-live
  • 非破坏:日志完整保留;再次打开/发消息时 apiproxy 的 ensureSession 会从持久化自动重新挂载(排队中的 inbox 消息以 agent/inbox/spliced 事件持久化,重新挂载后由 Inbox 重放)
  • 单测:node test-detach.mjs(5 项断言);e2e:bash e2e-detach.sh(创建 2 会话 → 单条 detach → attached 2→1 → detach-all → 0 → 重新发消息自动挂载 → 1)

DSH 0.1.0-rc.6 没有公开的 unarchive / session-delete / session-detach API,本插件用到几处内部实现,均在 lib/index.js 注释标注:

  1. 取消归档:调用 dsh-workspace WorkspaceRegistry 的 state / setState(原型方法,非 # 私有)。setState 与原生 archiveSession 走完全相同的 domain.global.set → domain/changed 持久化路径,host-apiproxy 监听到变更后自动向所有客户端推送 host/archived-sessions-changed 帧——前端无需额外刷新。
  2. 删除 live 会话:调用 dsh-session SessionStore 内部 store 条目({sessionId, seq...} 索引)的 detach()——与 agent 拆卸会话同一路径,触发 session/disposed → 前端收 host/session-removed。
  3. 自动续跑:依赖 dsh-agent-loop 的 ctx.agents.resume() / agent.followup() / handle.dispose()(公开 API,见 dsh-headless 直驱示例)。
  4. 手动释放:agent.cancel()/whenIdle() 公开;agent.scope.dispose()、agents.store 条目删除 + agents.emitDisposed()、sessions.store 条目 detach() 为内部实现(与 agent-loop 自身 dispose 同一路径、同一顺序)。

删除流程:拒绝运行中(最后一个 turn 边界未闭合)→ live detach → 若已归档先取消归档 → 从 workspace 记账 detach(detachSession 公开方法)→ 用 sessionPersistence.listArtifacts() 定位并 fs.rm 会话目录(含 session.jsonl.zstd)→ sqlite 查询索引自动对账清理。先 detach 再删文件,避免持久化协调器把会话写回磁盘。

会话分组部分(lib/group.js,源码 + 实测三重印证):

  • 会话归属分组 = 会话 header 的 cwd 硬绑定:只有 cwd 恰好等于分组 path 的会话才能进该分组(Workspace.attachSession 强校验 realpath(cwd)===path);session.create 带 workspaceId 时 cwd 自动设为分组 path → 自动归属
  • 已有会话无法跨组移动(机制事实):attachSession 未暴露公开 RPC;insertSessionBefore 拒绝 "not accounted";GUI 拖拽只做组内排序;直接改 workspace.json 无效(注册表内存快照无文件 watcher,且 sessionIds getter 按 sessionPath(id)===path 过滤)。因此 move 走「归档原会话 + 分组下新建承接会话 + handoff 交接」(用户约定,2026-08-18):原会话归档(可还原)→ session.create {workspaceId} 在分组下新建 → session.prompt {mode:'queue'} 发交接说明 + 行为约束;归档失败(DSH 拒绝)→ 409 archive-failed 不新建(实测运行中会话可正常归档)
  • 分组目录布局:默认分组引用建在 <dshHome>/Group/<title>(软链接 → workspace 项目目录),项目本体留在 workspace 根,不把项目塞进 .dsh
  • new-session 走 HTTP 回环:host 侧没有公开的 session 创建服务方法,转发公开 RPC session.create {workspaceId}(与 GUI 分组行「+」按钮同一路径);handoff 交接说明再转发 session.prompt {mode:'queue'} 作为首条消息
  • 单测:node test-group.mjs(mock ctx + 内存 workspaceRegistry 假实现,10 项断言)

已知边界

  • unarchive / 删除 live 会话 / 自动续跑 / 手动释放依赖 DSH 内部实现,DSH 升级后需复核(见上)
  • 自动重命名只对 live 会话生效:sessionTitle.rename 要求会话在 store 中(sessions.get(id) 非空);冷会话(重启后未打开)勾选后不立即分析,等打开聊天、turn/end 触发时才生效。面板中可点「分析」手动触发
  • 自动重命名需要可用的 LLM provider(会话自身的模型路由);调用失败会在 API 响应和实例日志中如实报错(llm-failed)
  • 自动续跑只对「非人为中断」生效:可重试错误码集合固定为 RATE_LIMIT/SERVER/TIMEOUT/EMPTY_RESPONSE,其他错误请手动「继续」;自动续跑使用会话最后使用的模型路由,若该模型已不可用,续跑回合会失败(计入每会话次数上限,不会死循环)
  • 自动续跑在活跃会话数达到 maxAttached(默认 12)时暂停(手动「继续」不受限);续跑完成的冷会话会被释放(dispose),活跃数回落
  • 手动释放只对 live 空闲会话生效:运行中 / subagent 会话拒绝;被释放的会话若正被浏览器打开,会收到 host/session-removed 帧(从侧边栏消失),再次打开/发消息自动恢复挂载
  • 删除是硬删除:日志与记录一并清除,不可恢复(面板强制二次确认)
  • 删除后附件等旁路数据可能残留孤儿文件(不影响会话从 DSH 消失)
  • 面板 UI 需在浏览器人工确认(React 渲染不在 curl 验证范围内)
  • 会话分组:move 是「归档原会话 + 新建承接会话」的工作移交(原会话可还原,不会丢),不是把已有会话挂进分组——DSH 机制不允许跨 cwd 移动;归档失败才返回 409(实测运行中会话可正常归档交接);「在分组下直接新建会话」默认不屏蔽(blockGroupNewSession: false),new-session 不带 workspaceId 时默认落在 .dsh 上一层 workspace 工作区(无则自动新建,2026-08-19 用户约定);set-config 仅内存热改,持久化需改 patch config;new-session / move 依赖 HTTP 回环(PORT/TEST_DSH_PORT 环境变量定位自身端口,多端口部署需复核)
  • 会话分组客户端在 设置 → 插件配置 的「会话分组」卡片,React 渲染需浏览器人工确认

目录结构

dsh-session-manager/
├── package.json       # dsh.bundle.patch + dsh.client.platform/inject
├── cordis.patch.yml   # insert 注册 + 可选 config
├── lib/
│   ├── index.js       # host:list/archive/unarchive/delete/auto-rename/analyze/continue/auto-continue/scan/detach/detach-all/repair-sessions/peak-*
│   ├── group.js       # host:会话分组路由 /api/session-manager/group/*(原 dsh-session-group 合并)
│   ├── peak.js        # host:高峰期判定纯函数(isPeakHour/normalizePeakHours)
│   ├── core.js        # 任务完成汇报 纯函数(render/check)
│   ├── repair.js      # 会话日志损坏扫描/修复(纯函数)
│   └── client.js      # client:sidebar.footer.action「会话管理」入口 + 面板 + 设置页「会话分组」卡片
├── test-interruption.mjs  # 中断判定纯函数单测(22 项断言)
├── test-auto-rename.mjs   # 自动重命名分析逻辑单测(12 项断言)
├── test-auto-continue.mjs # 自动续跑流程单测(mock ctx,12 项断言)
├── test-detach.mjs        # 手动释放单测(mock ctx,5 项断言)
├── test-repair.mjs        # 会话修复单测
├── test-task-completion.mjs # 任务完成汇报单测
├── test-group.mjs         # 会话分组单测(mock ctx,13 项断言)
├── test-peak.mjs          # 高峰期判定单测(22 项断言)
├── e2e-crash-continue.sh  # 崩溃→重启→自动续跑 全链路 e2e
├── e2e-detach.sh          # 手动释放(置为不活跃)e2e
└── README.md
—/ 5

No ratings yet

Verified DSH bundle

Commit d3376c370531

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