@yfwu2020/dsh-think-flow

uitested: passnpmMIT

Chain-of-thought panel for the DSH Web right sidebar: folds the live reasoning stream of each session into turn → step groups carrying the reasoning text and the tool calls made in that step. Only the newest turn is expanded by default and earlier turns collapse to one line; steps are grouped into a

下载量 / Downloads
1,315
依赖体积 / node_modules
8.76 MB
测试时间 / Tested
2026-11-06
DSH 版本 / Version
0.2.2-rc.1

Install

dsh plugin --profile web add @yfwu2020/dsh-think-flow

Sandbox test results

StageResult
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

dsh-think-flow · 思维链可视化

在 DSH Web 的右侧栏开一个「思维链」标签页,
把模型的实时思考按 turn → step →(思考原文 + 工具调用) 聚合成能读的结构:
每一步在干嘛、调了什么工具、它在读哪个文件、哪一段正在等外部接口。

![release](https://github.com/yfwu2020/dsh-think-flow/releases)

![npm](https://www.npmjs.com/package/@yfwu2020/dsh-think-flow)

![license](./package.json)

![tests](./tests)

![DSH plugin](https://github.com/yfwu2020/dsh-think-flow)


它解决什么问题

DSH 的主对话界面不显示思维链。 而模型的思考恰恰是最值得看的东西:

它决定得对不对、有没有绕路、卡在哪一步。

但直接把思考流倒出来是没法读的。这是真实会话里量出来的一个 turn:

· 实测

一个 turn 的步数 · 53

一个 turn 的时长 · 1550 秒(约 26 分钟)

一个 turn 的思考量 · 7.1 万字

一个 turn 的工具调用 · 68 次

所以这个面板做了五件事,每一件都对应上面某个数字:

  • 按 step 聚合,不逐字渲染。reasoning 每秒几百个事件,逐事件重绘会把面板刷成幻灯片。

宿主侧按 step 折叠 + 120ms 合并推送(sseThrottleMs)。

  • 分层折叠。53 步全展开要滚几十屏;把"同一类活动"合并成阶段块。默认只展开最新一轮,

那一轮里只展开当前所在阶段;更早的轮次收成一行,点开才看。

例外:实时看过的那一轮不自动收 —— 生成中收起来会把前面那些组缩成一行标题,

生成完再收又会把读到一半的位置顶掉;要收手动点组头。

  • 显式画出「在等工具」。实测两步之间能有 47 秒模型零输出(联网检索中)——

不画出来,界面在这 47 秒里与卡死无法区分。

  • 轮次可回溯。正文只常驻最近 20 轮,更早的走全轮目录按需折回来;

翻到 100 轮之前也不用把它全塞进内存。

  • 思考可以变中文。英文 CoT 按段落机翻(官方 translator 服务,Bing/Google 匿名端点),

翻好一段显示一段;关掉就是原文。见 [中文思考(机翻)](#中文思考机翻)。

长什么样

<table>

<tr>

<td><img src="assets/panel-running.png" alt="正在思考" width="300"></td>

<td><img src="assets/panel-waiting.png" alt="正在等工具" width="300"></td>

</tr>

<tr>

<td align="center"><b>① 正在思考</b><br>当前步整块高亮、呼吸环 + 秒表实时涨;<br>每行右侧容量条 = 那一步的思考 Token 数</td>

<td align="center"><b>② 正在等工具</b><br>唯一的高亮块:<code>web_search 执行 · 已等 23s</code><br>把"在等外部接口"和"卡死"分开</td>

</tr>

</table>

<img src="assets/panel-done.png" alt="本轮完成:阶段分布小结" width="380">

本轮结束后补一块「这一轮想完了」:多少步、思考多少 Token、调了多少次工具,以及

思考花在哪了(读代码 / 跑命令 / 改文件 / 外部检索 / 问用户的比例)。

分布用同一色相只变深浅,不给每个阶段编一个颜色。

<table>

<tr>

<td><img src="assets/panel-expanded.png" alt="展开某一步" width="300"></td>

<td><img src="assets/panel-directory.png" alt="全轮目录" width="300"></td>

</tr>

<tr>

<td align="center"><b>③ 展开某一步</b><br>模型标题 → 次级标题(按工具参数算的派生标题)<br>→ 工具详情 → 按需取回的思考原文</td>

<td align="center"><b>④ 全轮目录</b><br>第二行标题<b>双击</b>就地变搜索框;<br>12 轮、100 轮都在这儿翻,搜索全在本地算</td>

</tr>

</table>

<img src="assets/panel-failure.png" alt="工具失败" width="380">

工具失败照宿主的判定显示(isError + error.code):行里一枚红标,

为什么失败在展开区紧跟它自己那条工具行(上图 ✗ INVALID_ARGS …)。

红只给错误文本,工具名不动 —— 失败的是这次调用,不是这个工具。

上面这些图不是另画的示意图:由 npm run shots 用构建产物里真正的组件渲染、
配宿主主题包里整段抓出来的真 token、headless Chrome 拍下来,宽度就是右侧栏真实的 380px。
数据来自 scripts/preview/demo-data.mjs,是合成的一段会话。

安装

# 从 npm(推荐)
dsh plugin --profile web add @yfwu2020/dsh-think-flow

# 或从 GitHub Release 的 tgz(同一个产物,不走 npm)
dsh plugin --profile web add /path/to/yfwu2020-dsh-think-flow-0.3.3.tgz

# 或从本地目录(开发用:改完不用重装,只重建)
dsh plugin --profile web add link:/path/to/dsh-think-flow

装完在 DSH 里落成三处:

位置 · 内容

~/.dsh/profiles/web/package.json · "@yfwu2020/dsh-think-flow": "<版本或 link:路径>"

~/.dsh/profiles/web/node_modules/@yfwu2020/dsh-think-flow · 软链 → 插件目录

profile 的 dsh.profile.bundles · 包名(按包名引用,与路径无关)

打开方式有两个:会话头部那个折线图标,或者右侧栏标签条上的「思维链」。

⚠️ 装完要重建进程:host 半是新的 bundle,需要重启 dsh web,之后硬刷新浏览器
(Cmd/Ctrl+Shift+R)。此后只改 client 半的改动会被 client-hmr 就地替换,不用刷新。

要求:DSH 运行时 >=0.1.7-rc(见 package.json 的 peerDependencies)。

0.1.7-rc 起 createSystemMessage 去掉了插件署名参数;更旧的运行时上行为不一致。

⚠️ npm 上 @deepseek-ai/* 这些包的 latest 还停在更旧的 0.0.1-rc.x,缺 WebServer
等 API —— 从源码构建时按 package.json 里钉的版本装,别用 latest。

配置项

改 profile 的 cordis.patch.yml 里 id: think-flow 那一行的 config:(覆盖,不要再 insert):

- id: think-flow
  config:
    maxTurnsPerSession: 20

键 · 默认 · 范围 · 含义

maxTurnsPerSession · 20 · 0–500 · 每个会话常驻多少轮的正文(0 = 不限)。⚠️ 这是正文窗口,不是"能看到多少轮"

maxIndexTurns · 2000 · 0–20000 · 目录(全轮骨架)最多记多少轮。一轮骨架几百字节,所以给得宽

coldTtlMs · 7200000 · 0–86400000 · 按需折进来的冷轮正文保留多久(空闲计时:读一次续一次期。0 = 不按时间收)

maxColdChars · 4000000 · 0–2e8 · 冷轮正文的硬上限。和 coldTtlMs 是两条独立策略,谁先到算谁

maxReasoningCharsPerStep · 120000 · 1000–400000 · 单个 step 的思考原文上限,超了从尾部保留并打上"这段不全"

maxSessions · 32 · 1–256 · 内存里同时跟踪多少个会话(LRU)

resyncSilenceMs · 15000 · 20–600000 · 内存轨迹多久没收到实时动静就算"可疑"(也是重折退避的基数,见下)

resyncMaxGapMs · 300000 · 0–3600000 · 重折退避的上限(0 = 关掉过期自愈)。不是"最多重折几次"—— 见下面的说明

sseThrottleMs · 120 · 0–2000 · 合并推送的最小间隔。别调到 0:流式每秒几百个事件

heartbeatMs · 15000 · 2000–120000 · SSE 心跳,防代理掐连接

snapshotTailChars · 4000 · 200–20000 · 连接快照里给"当前步"带多少字符原文(其余步骤走 /step 按需取)

titleStepChars · 420 · 80–4000 · 生成中文标题时,每一步最多喂多少字思考原文

titleTotalChars · 24000 · 2000–200000 · 一次标题请求的字符上限(整轮一起总结,一次调用)

titleReasoningEffort · 'low' · — · 生成标题的推理档位(压缩任务,低档就够)

titleCachePath · '' · — · 标题缓存路径。空 = ~/.dsh/think-flow/titles.json

autoTickMs · 5000 · 20–60000 · 自动标题(面板上的「实时」)的节拍器间隔

maxHydrateEvents · 20000 · 0–200000 · 历史回看时最多折入多少条落盘事件(从最新往回取)

maxTitledTurns · 640 · 0–10000 · 标题缓存最多保留多少轮

translateTarget · 'zh-CN' · — · 思考原文机翻的目标语言

translateProvider · '' · — · 机翻提供方(bing / google)。空 = 跟随 translator 服务自身的配置(默认 bing)。付费路由要写会话日志,本插件对会话只读,别用

translateMaxChars · 3600 · 200–4000 · 单个翻译请求的字符上限(再和 translator 的 maxTextChars 取小)

translateTimeoutMs · 20000 · 1000–120000 · 单次翻译请求超时

translateCachePath · '' · — · 译文缓存路径。空 = ~/.dsh/think-flow/translations.json

maxTranslationEntries · 4000 · 0–100000 · 译文缓存最多保留多少条(一段一条,LRU)

三条策略要一起看(它们管的是同一块内存):

turns(正文)        maxTurnsPerSession = 20   ← 常驻
  └ 更早的轮次按需折进来 = 冷轮正文
       ├ coldTtlMs    = 7,200,000   空闲 2 小时收回
       └ maxColdC

…(truncated)

Rendered from the README published on npm. Formatted only, not edited.

Versions

Published on npm::8,最后更新 2026-10-24

Links

GitHub · Homepage · npm

Same category