← 返回列表
未验证
在会话左侧显示圆点进度条,点击即可跳转任意提问
尚未跑自动兼容性验证,可查看页面内的依赖与入口分析。 · 最近上游提交 2026/8/26 · 已提供中文文档
DeepSeek Harness Web GUI 的回合进度轨插件(dsh-plugin)
综合分
27.8
GitHub 分
27.8
用户评分
—
★ Stars
0
周下载量
—
安装插件(需先安装 dsh CLI 引擎:npm install -g @deepseek-ai/dsh)
dsh plugin --profile web add HenryHwong/dsh-ui-turn-rail该插件未发布到 npm,走 GitHub 源安装(pnpm 若拦截 prepare 脚本,按其提示在 pnpm-workspace.yaml 的 allowBuilds 中放行后重跑)
数据截至 2026/9/16(元数据每日更新 · 实装验证按队列轮转,单条结论的验证时间见上方)
依赖的 DSH / Cordis 模块
@deepseek-ai/dsh-client-locale@deepseek-ai/dsh-client-runtime@deepseek-ai/dsh-client-test-runtime@deepseek-ai/dsh-client-ui-conversation@deepseek-ai/dsh-client-ui-primitives@deepseek-ai/dsh-client-ui-slots@deepseek-ai/dsh-invariants@deepseek-ai/dsh-session-stats@deepseek-ai/cordis用户评分
还没有人投票,来当第一个
订阅周报,不错过优质插件更新
每周一封 · 高评分插件 + 新用户活动
README
dsh-ui-turn-rail
🌐 语言 / Language: English · 简体中文
DeepSeek Harness Web GUI 的回合进度条插件:钉在会话滚动视口左侧的圆点竖条,已加载回合各一个圆点,支持每轮提问摘要、一次点击深度加载历史、以及 AI 选项的摘要显示。
GitHub 话题:dsh-plugin · deepseek-harness
功能
- 常驻可见的进度条。圆点条 sticky 在会话滚动视口上,转录区滚动时始终可见——即使超长对话也不会消失。
- 每个「提问已加载」的轮次一个圆点,提问尚未进入窗口的轮次用虚线占位点表示。AI 回复与思考过程不视为已加载的提问:提问还没翻页进来的轮次始终是占位点。
- 提问摘要。悬停圆点可看到该轮第一个提问的单行预览。人工输入(user 节点)和从 AI 提供的选项中选择(steering 节点)都会生成摘要。
- 一次点击深度加载。点击占位点后,插件会持续翻页,直到目标回合的提问真正进入窗口(页面边界可能先加载到该轮首个节点、而提问在更早的页里),然后直接跳到该提问所在行。
- 点击已加载圆点:把转录区滚到该轮提问处。
- 可滚动的圆点窗口。进度条一次显示约十个圆点,可内部滚动;读者移动时当前轮圆点自动跟入视野。
安全
- 纯展示。进度条只渲染会话快照里已有的数据。它不会产生任何模型可见输入、不会写会话日志、不发网络请求、不接触任何凭据。
- 模型体验:不进入任何模型请求;Token 影响无;KV 缓存影响无。
- 不新增权限。宿主插桩(见下)只给聊天视图加一个只读座位;不引入新 RPC、权限或密钥处理。
- 数据都在宿主。所有派生(轮次顺序、节点→轮次映射、摘要)都基于客户端 ChatSnapshot 计算;进度条自身不持有任何会话状态。
前置要求
一个 DeepSeek Harness 检出(或已发布的 @deepseek-ai/dsh-* 包)且已应用宿主插桩——进度条注册进 ui-conversation 聊天视图必须声明的 conversation.chat.rail 座位(见下)。没有该座位时插件可以加载但不渲染(座位渲染 fallback: null)。
安装
插件支持两种安装方式。两种都不会自动化宿主插桩——那是针对 harness 检出的源码级补丁(见宿主插桩),无论包怎么装都必须应用并重建。
方式一——通过 dsh plugin 的 bundle 安装(推荐)
本仓库是一个 DSH bundle:package.json 声明了 dsh.bundle.patch → ./cordis.patch.yml,因此 profile 插件管理器会把它作为补丁层安装,补丁会把插件插入 web profile 的浏览器花名册。
直接从 git 仓库安装(无需发版 npm):
dsh plugin --profile web add @huanghanheng/dsh-ui-turn-rail
或发布到 npm 后(更短的 spec):
dsh plugin --profile web add @huanghanheng/dsh-ui-turn-rail
dsh plugin 在 profile 目录里执行 pnpm add,并自动对账 dsh.profile.bundles:manifest 声明了 dsh.bundle.patch 的依赖会自动加入层栈。
然后应用宿主插桩——profile 运行的检出必须有该座位,进度条才会渲染。本仓库附带现成补丁,一条命令应用(然后重建 web 客户端):
scripts/apply-instrumentation.sh /path/to/harness-checkout
(cd /path/to/harness-checkout && pnpm run build)
方式二——手动 npm 安装
包发布到 npm,且构建产物(lib/)已提交,因此可以像普通包一样安装:
在应用运行的 profile 目录(或应用本身)里:
npm install @huanghanheng/dsh-ui-turn-rail
或:pnpm add @huanghanheng/dsh-ui-turn-rail
手动 npm install 不会自动加 bundle 层——需要在 profile manifest 里声明,补丁才会插入插件行:
// $DSH_HOME/profiles/web/package.json
{
"dependencies": { "@huanghanheng/dsh-ui-turn-rail": "^0.1.0" },
"dsh": { "profile": { "bundles": ["@huanghanheng/dsh-ui-turn-rail"] } }
}
或者直接运行 dsh plugin --profile web add @huanghanheng/dsh-ui-turn-rail,它会替你完成安装与 bundle 层对账(等价于方式一)。
然后应用宿主插桩并重建,与方式一完全相同。
宿主插桩(无法打包的部分)
座位声明在 ui-conversation 的槽位契约里,跳转/翻页手势必须操作 ChatView 的私有滚动锚定——这两者都无法作为插件交付,因此 dsh plugin add 无法自动化它。本仓库把确切改动存为 patches/chat-rail-seat.patch(基于 harness master b150a551b8);用 scripts/apply-instrumentation.sh 或 git apply --3way 应用后重建即可。如果你的检出已有漂移,请按下述改动手工应用。以下是确切改动:
packages/client/ui-conversation/src/client/contract/slots.ts
1. SlotMap 条目:
'conversation.chat.rail': { kind: 'single'; scope: 'session'; owner: ChatTurnRailOwnerProps }
2. Owner 数据契约:
export interface ChatTurnRailOwnerProps {
currentTurn: number | undefined
loadingOlder: boolean
hasMore: boolean
onJump: (key: string) => void
onLoadOlder: () => Promise
}
3. 在 ChatViewSlotProps 的 PropsRenderSlots 联合里加 'conversation.chat.rail'。
4. 把注入的分页契约放宽为返回 promise:
loadOlder: () => Promise
packages/client/ui-conversation/src/client/apply.ts
在聊天视图 entry 的 children 里声明该座位:
children: {
'conversation.chat.node': { kind: 'keyed', scope: 'session', inject: CHAT_NODE_INJECT },
'conversation.message.images': { kind: 'single', scope: 'session' },
'conversation.chat.rail': { kind: 'single', scope: 'session' },
},
packages/client/ui-conversation/src/client/chat/ChatView.tsx
1. 用于滚动位置归因的节点键→轮次映射:
const chat = useSession(s => s.chat)
const turnByKey = useMemo(() => {
const map = new Map()
for (const turn of chat.timeline.turnOrder) {
for (const key of chat.locations.getTurn(turn)) map.set(key, turn)
}
return map
}, [chat])
2. 在滚动处理器里跟踪 currentTurn(从 turnOf(anchorKey) 或钉在底部时的最新轮次设置)。
3. loadOlderAnchored 返回分页 promise:
const loadOlderAnchored = (): Promise => {
// ...原有分页锚定逻辑...
return loadOlder()
}
4. 用 owner 数据渲染座位:
{renderSlot('conversation.chat.rail', {
currentTurn,
loadingOlder,
hasMore,
onJump: jumpTo,
onLoadOlder: loadOlderAnchored,
}, { fallback: null })}
开发
pnpm install
pnpm vitest run tests/ # 单元测试(模型 + 组件,jsdom)
pnpm bundle # tsdown 客户端打包(需要 harness 的 clientBundle preset)
测试覆盖回合模型(tick 派生、人工/AI 选项摘要、占位点)和组件(跳转、跨页边界的一次点击翻页、当前轮跟随、窗口滚动)。
许可证
MIT扫码进群