dsh-session-rail
Progress tab for the DSH right sidebar: the turn status of the session and the progress long-running tasks reported, in one tab beside the conversation.
Install
dsh plugin --profile web add dsh-session-rail
Sandbox test results
| Stage | Result |
|---|---|
| 1 install | ✓ |
| 2 list | ✓ |
| 3 mount | ✓ |
| 4 boot | — |
Four stages run in an isolated sandbox: install (network on) → list → mount → boot (last three with no network).
README
会话引导栏(Session Rail)
<p>
<a href="https://www.npmjs.com/package/dsh-session-rail"><img alt="npm" src="https://img.shields.io/npm/v/dsh-session-rail?color=2f81f7&label=npm"></a>
<a href="https://www.npmjs.com/package/dsh-session-rail"><img alt="downloads" src="https://img.shields.io/npm/dw/dsh-session-rail?color=3fb950"></a>
<a href="https://github.com/zengxiaolou/dsh-session-rail/blob/main/LICENSE"><img alt="license" src="https://img.shields.io/npm/l/dsh-session-rail?color=bf8700"></a>
<img alt="dsh plugin" src="https://img.shields.io/badge/DSH-plugin-7aa2ff">
<a href="https://github.com/zengxiaolou/dsh-session-rail/stargazers"><img alt="stars" src="https://img.shields.io/github/stars/zengxiaolou/dsh-session-rail?color=8250df"></a>
</p>
它解决什么
同时开着七八个工作区的时候,「哪里在跑、哪里在等我」是最难一眼看出来的:
场景 · 没有它 · 有它
想知道别的会话是不是跑完了 · 逐个展开工作区、点进去看 · 顶部一行 ●3 运行 ●5 未读,左栏文件夹行尾 ●2
有会话停下来问你问题 · 翻半天才发现它在等 · 询问 单独一段,橙色(宿主 warning 同色)
某个会话崩了 / 被打断 · 只能回想 · 出错 红、中断 灰,一眼分开
想直接跳到那个会话 · 先找再点 · 点计数钉住浮层,浮层里点行直达
截图
下列图为按应用包内真实主题色值渲染的示意图(不是真机截图),用于说明形态与配色;深浅色各自成立。
顶部五态计数(深色) · 左栏工作区徽标(深色)
给 DSH 右侧栏加一个常驻视图:进度,和已有的 PR 标签并排。显隐、宽度、+ 新标签菜单全部沿用宿主原生右栏,本插件不另起一列。
0.1.10 起,同一份数据再往两层:对话面板顶部标题条常驻五段计数(运行 / 询问 / 出错 / 中断 / 未读),左侧工作区行再各带一个 ● N 徽标——不用点开右栏、也不用逐个展开文件夹。
0.1.5 起移除了「变更」「来源」两个 tab(右侧栏太挤、日常用不上)。宿主侧的/changes、/sources只读接口保留下来当诊断口,客户端不再注册标签。
一个 tab
Tab · 显示什么 · 数据来源 · badge
进度 · ① 本会话运行状态:运行中/空闲、第几轮、本轮已用时长、工具调用数、最近一个工具、上下文占用(已用/窗口,按 65%/85% 变色);② 长任务列表:状态、百分比、最新消息、相对时间 · ① 会话事件流里的 turn/start、turn/end、tool/call;② <cwd>/.dsh-progress/<session-id>/*.jsonl(dsh-task-progress 协议) · 运行中的长任务数
进度 tab 的第一张卡不依赖任何 producer:只要会话在跑,就有「第 N 轮 · 1 分 45 秒 · 15 次工具调用 · bash」。
顶部会话计数
插在 conversation.session.header.utilities(宿主声明为 “右对齐的会话工具区”)里,order: -10 排在所有工具控件之前——也就是标题右侧、右侧图标按钮左侧那段空白。这段由 shell 的 ConversationSessionHeader 渲染,所以对话 / 轨迹 / 上下文 / 画廊等所有视图页共用同一处,切换页面不掉。
段 · 含义 · 数据来源
● N 运行(蓝) · 有活跃回合、且真的在干活的根会话数 · 客户端 sessions.list 的 running + /turns 排除“等你回答”
● N 询问(橙) · 回合停在 ask_user_question 上,等你回答 · 宿主 /turns 看当前回合内有无未 tool/result 的 ask_user_question 调用
● N 出错(红) · 上一个回合以 blocked / error 结束、且还没看过的 · 宿主 /turns 读会话日志尾部的 turn/end.data.reason.kind
● N 中断(灰) · 回合以 aborted / interrupted 结束(没做完就停了) · 同上
● N 未读(绿) · 已正常结束(completed / max-tokens)、但本浏览器还没看过的 · updatedAt 对比已读水位 + /turns 判定
- 没有现成字段:DSH 不记录“某个会话是否已读”,所以已读水位由客户端持有——首次加载把当时的全部会话记为已读(否则一上来就是几十条未读),之后“看着的会话”按
updatedAt前进水位,离开时正在跑、回来已经结束的会话由 running→false 这次跃迁直接记成未读。 - 颜色来自会话自己的结局:
turn/end的reason.kind决定色调——completed/max-tokens绿、aborted/interrupted中性灰、blocked/error红。查不到(会话已离开内存)返回unknown,落回绿色“未读”,不猜成别的颜色。 - “在跑”与“等你回答”分开算:回合开着不等于在干活。当前回合里有
ask_user_question调用、且它的tool/result还没出现 →question,从蓝色里扣掉,进橙色那段(官方 warning 色,和侧栏“等待回答”一致)。判定只看开着的那个回合:结果事件的 call id 在data.message.toolCallId(不在data.callId),答完之后同一回合继续干活就该回到“运行”,历史回合里没结果的调用也不能把后面的回合算成在等你。 - 只轮询结局:运行数订阅
sessions.list,状态真变才算;结局每 15s 向宿主批量问一次(单次最多 24 个),页面不可见时不发。 - 弱干扰:11px 三级文字色;数字为 0 的那段整段隐藏,五段都为 0 时退化成一颗很淡的点(
data-idle0.45 透明度,hover 回到 0.95)。 - 忽略:两层,回答两个不同的问题。① 默认规则——定时任务每跑一次就是一个新会话(
dsh-automation-session-前缀),跑完仍在“未读”里就会每次 +1;所以已正常结束的不计未读,error/interrupted照旧进红/灰段。② 显式忽略——浮层每行右侧一个「忽略」,写进localStorage的dsh-session-rail:ignore:v1({ v: 1, sessions: [...] }),被忽略的会话不再进任何一段,运行中的也一样。设置页只放一行「已忽略 N 条 · 清空」(settings.section),清单本身从浮层写。忽略只改计数:会话仍在侧栏、仍可打开。 - hover 预览,点击钉住:hover / 键盘 focus 只是“看一眼”,移开就收起;点一下 chip 把它钉住(
data-pinned),鼠标走进浮层不会掉,再点一次 / 点外面 / Esc 才关。浮层里的行才是跳转入口。 - 文案进的是插件自己的 locale 命名空间(
locale.register('session-rail', {zh, en})),跟随 GUI 语言切换;颜色走--dsw-alias-*别名 token(浮层用bg-layer-3实心面,不用会透出正文字色的bg-overlay)。中断用中性灰而不是黄色:主题没有第五个状态色,橙色已经让给“等你回答”,黄色会和它撞。
深色 · 深色 + hover
左栏工作区徽标
工作区行是宿主的闭合组件(ProjectRowItem),没有可注入的座位,所以徽标用原生 DOM 画在
[data-row-key^="workspace:"] 上,并由一个常驻在 sidebar.footer.action 的空组件每 1.5s 重画一次
(React 会替换行子节点,插件不持有行内的 React 树)。
- 口径:
启迪 /api/session-rail/workspaces返回工作区 → sessionIds(注册表自己的投影,已按 canonical cwd 过滤),
再对每个会话取 /turns 判定。running 计数不含停在提问上的会话;question 单独计。
- 只显示有事的工作区:
running + question = 0的行不画徽标,徽标里的颜色:有question用橙,否则用蓝。 - 开关:
localStorage["dsh-session-rail:workspace-badge:v1"] = "off"关掉,removeItem恢复默认开。 - 已知缺口:注册表
sessionIds未按归档集过滤,归档会话若仍在跑会被算进来;自动化会话(本机 69/230)目前计入,
若发现“运维行长期亮灯”,按 origin/会话名前缀再过滤。
⚠️ 未在真实 GUI 验证:徽标定位依赖 data-row-key 锚点与 sidebar footer 座位,两者都需要重启后手验(拖拽/展开后有无重影、关闭开关有无残留)。
交互
- 手动刷新:每张卡片标题右侧
↻;后台轮询只在标签可见时进行(会话状态 4s、进度 3s)。 - 不假成功:没有
cwd或没有长任务上报时如实说明,不退回到宿主进程目录去猜。
宿主路由
前缀路由 /api/session-rail:
GET /api/session-rail/turn?sessionId=<会话 id> GET /api/session-rail/turns?ids=<逗号分隔,最多 24 个> # 批量:每会话最后一个回合的结局 GET /api/session-rail/workspaces # 工作区 → sessionIds(左栏徽标用) GET /api/session-rail/progress?cwd=<绝对路径>&sessionId=<会话 id> GET /api/session-rail/changes?cwd=<绝对路径> # 0.1.5 起无客户端使用,保留为只读诊断口 GET /api/session-rail/sources?cwd=<绝对路径> # 同上 GET /api/session-rail/report?boot=&stage=&service=&tabs= # 客户端启动信标 GET /api/session-rail/state …(truncated)
Rendered from the README published on npm. Formatted only, not edited.
Versions
Published on npm::9,最后更新 2026-10-26