dsh-claude-style 0.12.0 → 0.12.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +140 -0
- package/README.en.md +6 -27
- package/README.md +5 -24
- package/THIRD_PARTY_NOTICES.md +71 -0
- package/docs/FEATURES.en.md +7 -5
- package/docs/FEATURES.md +7 -5
- package/docs/SETTINGS.en.md +21 -7
- package/docs/SETTINGS.md +21 -7
- package/docs/STYLE.md +9 -0
- package/docs/decisions/D10-settings-transport.md +1 -0
- package/docs/decisions/D17-permission-presets.md +3 -0
- package/docs/decisions/D22-search-panel.md +6 -5
- package/docs/decisions/D27-context-stats.md +13 -5
- package/docs/decisions/D29-feature-switches.md +2 -2
- package/docs/decisions/D32-chat-interactions.md +3 -3
- package/docs/decisions/D34-turn-navigator.md +1 -1
- package/docs/decisions/D36-modules-and-bundling.md +1 -1
- package/docs/decisions/D38-assets.md +3 -3
- package/docs/decisions/D39-on-demand-loading.md +19 -9
- package/docs/decisions/D41-scroll-owner.md +3 -3
- package/docs/decisions/D42-feature-manifest.md +3 -4
- package/docs/decisions/D45-testing.md +2 -2
- package/docs/decisions/D49-visual-yield.md +2 -2
- package/docs/decisions/D5-model-copy.md +5 -2
- package/docs/decisions/D51-css-toolchain.md +3 -1
- package/docs/decisions/D54-peakrate-meter.md +33 -0
- package/docs/decisions/D58-redraw-retired.md +29 -0
- package/docs/decisions/D9-style-performance.md +2 -0
- package/docs/decisions/README.md +6 -4
- package/lib/assets/01a8f6d0dede.js.map.br +0 -0
- package/lib/assets/31253ed42440.js.br +0 -0
- package/lib/assets/5063c46824b6.js.br +0 -0
- package/lib/assets/55a6154f87b5.js.map.br +0 -0
- package/lib/assets/5b286686ae65.js.br +0 -0
- package/lib/assets/5e05b29d5005.js.br +0 -0
- package/lib/assets/668d06ca781b.js.map.br +0 -0
- package/lib/assets/930546669455.js.map.br +0 -0
- package/lib/assets/968fcbfc3e22.js.br +0 -0
- package/lib/assets/abdc076dfd70.js.map.br +0 -0
- package/lib/assets/ac9b0e625837.js.map.br +0 -0
- package/lib/assets/ad2905345a69.js.br +0 -0
- package/lib/assets/b6d2c6e0d409.js.br +0 -0
- package/lib/assets/c52e41b4842b.js.map.br +0 -0
- package/lib/assets/manifest.json +70 -0
- package/lib/client.js +8 -7754
- package/lib/client.js.map +4 -4
- package/lib/host/cache-file.js +31 -0
- package/lib/host/peakrate-catalog.js +171 -0
- package/lib/host/peakrate.js +121 -0
- package/lib/host/routes.js +19 -0
- package/lib/host/search.js +131 -39
- package/lib/host/session-events.js +19 -0
- package/lib/host/settings.js +6 -1
- package/lib/host/usage-cache.js +5 -25
- package/lib/host/usage-fold.js +1 -17
- package/lib/host/usage.js +5 -4
- package/lib/model-descriptions.json +261 -106
- package/lib/peakrate-catalog.json +1601 -0
- package/package.json +4 -2
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,146 @@ All notable changes to `dsh-claude-style` are documented here, newest first.
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [0.12.2] - 2026-10-10
|
|
8
|
+
|
|
9
|
+
[中文](#cn-0.12.2) | [English](#en-0.12.2)
|
|
10
|
+
|
|
11
|
+
<h3 id="cn-0.12.2">新增功能</h3>
|
|
12
|
+
|
|
13
|
+
- 设置页「侧栏」页新增「侧栏搜索」下的「搜索框样式」三档:「覆盖品牌」(默认)把搜索框放进品牌行、指针移到侧栏上时盖过品牌;「独立」在品牌行下方给它自己一行并一直显示;「图标」不画插件自己的搜索框,保留 DSH 自己的搜索按钮,只把单击接管过来,点它打开本插件的面板。切换不需要刷新页面。
|
|
14
|
+
- 写在输入卡片下面那一行数字重新有了自己的弹层:这一行此前只显示六个读数,宿主统计行上那些明细(模型用时、工具调用用时、首 token 平均、输出速度,以及缓存命中、未缓存输入、缓存读取、写回、输出这些用量行)在「写在单独一行」这一档下无处可看。现在这一行本身就是宿主那张上下文弹层的第二个触发口——按一下这些数字,弹层就在这一行上方打开,内容仍是同一份:宿主自己的上下文行加上这一段会话的数字明细,两种位置下都由同一份数据填充;按一下再收起,回车与空格同样开合、Esc 收起,弹层开着时这一行自己也报出展开状态。悬停开合仍只归计量环那条路径:指针停在数字上不展开弹层。窗口尺寸或输入区变化时弹层照旧重新量位置。
|
|
15
|
+
- 设置页「对话」页新增「对话统计信息位置」:会话统计与 Token 用量此前只有一个去处——输入区上下文圆环的弹层。现在默认把它们写在输入卡片下面单独一行:轮数与步数、输出速度、读入与写回的 tokens、缓存命中率,末尾就是那个圆环,宿主统计行上的图标一个都不出现;也可以选「收进上下文」,回到弹层那一份。这一行里的数字一有变化就逐个字符重新入场(每走一个步骤、流式输出期间都在动,没变的数字保持不动),缓存命中率与圆环按各自的无极色阶取色(命中率九成的红到 99% 的深绿,占用两成的绿到四成的红,两个色标之间由浏览器在 OKLCH 里插值)。窗口窄到这一行放不下时它按固定顺序让位——先去缓存那截的字样,再去轮数与步数,再去圆环旁的数字(环留下),然后把读入与写回合成一个合计并去掉箭头,最后把数字折叠成 k / M / B——数字不再挤在一起互相压字,窗口宽回来时按同一顺序退回。这一项从此有自己的设置,不再与「重绘权限控件」共用一个开关;设置表单多了一个字段,正在运行的宿主重启一次才会提供它。
|
|
16
|
+
- 设置对话框「Claude Style」页的标题行右端新增一枚 GitHub 标识,按一下在新的标签页里打开插件仓库(https://github.com/Nwflower/dsh-claude-style)。标识的颜色取次一级的文字色,深浅两套配色各自跟随;指针移上去底部铺一层悬停底色、图形加深,键盘焦点落到它上面时出现一圈强调色描边,读屏念出「在 GitHub 上打开本插件」。插件页上那一份沿用宿主自己的标题行,不加这枚标识。
|
|
17
|
+
|
|
18
|
+
### 体验优化
|
|
19
|
+
|
|
20
|
+
- 中文界面下权限选择器的档位名改用宿主自己的中文名:分段控件上的当前档位与弹层里的每一行此前写死为皮肤的 Claude 英文名(Read only / Accept edits / Full access),中文界面里只有名字下面那行说明是中文;现在界面语言是中文时这几处读宿主 `permission.access` 文案表里的原文——「仅可查看」「工作区内修改」「完全权限」,宿主调整自己的用词时皮肤跟着变;切成别的界面语言仍是皮肤的名称。
|
|
21
|
+
- 侧栏搜索的会话内容搜索从秒级等待变成即答:每个会话的语料(读者的消息与助手的回答)此前只留在宿主进程内存里,宿主每次重启后的第一次搜索都要把全部会话日志重读一遍——本机 260 个会话约 30 秒;现在它落一份 `$DSH_HOME/cache/dsh-claude-style/search/<会话 id>.json`,重启后只读这些文件,约 1.4 秒,存档会话里只有修订号变过的才重读,宿主开着的会话按事件序号只读新增的那一段。查询本身也从整篇正则扫描改成小写子串查找,本机 260 个会话、8252 条消息的语料上单次查询 5–20 毫秒(此前约 0.5 秒)。语料缓存按需构建:只有读者真的搜索时才会读日志、才会落盘。在一台还没有缓存的机器上,第一次搜索仍要读完全部会话日志一次。
|
|
22
|
+
- 会话数字那一行不再用 · 把各段隔开:轮数与步数、输出速度、读入与写回的 tokens、缓存命中率之间此前各插一个 · 符号,行一窄就要多让一档;现在这些符号去掉,各段只靠行自己的间距分开(间距从 6px 放到 10px),一行能容下的数字更多,抄出来也是一段干净的话。端到端通道与冒烟用例各新增一条读数:那一行的 DOM 里一个 · 都不出现。
|
|
23
|
+
- 搜索面板里点开一条内容命中,现在落到那条消息所在的一轮,不再只停在这个会话的开头:面板按命中消息的事件序号,从会话的整篇轮次大纲里找出它属于哪一轮,等这一轮进了已加载窗口再经宿主的刻度定位。会话历史很长时,定位前会先把这一轮的记录翻页读进来;找不到对应轮次时停在会话本身,与从前一样。
|
|
24
|
+
- 过程组的标题不再只写「执行了命令,已读取文件,已调用工具等」,改写这一组装了什么:「执行 2 次思考,调用 1 次工具」。没有的项不写,数字随内容增加逐位滚动(160 ms,减弱动效时直接落位),这一段还在进行时整行带着与宿主同样的扫光;控件的可访问名字始终是这句完整的话,读屏念到的与看到的一致。标题放不下整句时(窗口窄,或这一行本身不长)改用简洁写法「思考×2 · 工具×1」,位置宽回来再换回整句——两种写法都不会被省略号截断。能否放下按标题所在容器给它的宽度判断,不按它当前有多宽。计数按过程组内部每一行的种类算:带 `data-chat-group-part="reasoning"` 的助手步算思考、其余助手步算输出、工具调用算工具、命令与其它记录算记录,工具行内部的调用不重复计入。
|
|
25
|
+
- 轮次进行中,对话末尾那一行不再固定写「深度求索中,用时 N 秒 ···」,而是说出这一轮此刻在做的事:「正在思考」「正在准备工具调用」「正在调用工具」「正在写回答」,后面跟着这一轮已用的时间(用宿主自己的时间单位)。读不出状态时(模型还没写出任何内容、也没有工具在跑)回到宿主自己的「深度求索中」——这正是读者那一刻在宿主界面上看到的同一句话;模型连续 10 秒没有开口时,计时后面再挂出「暂未响应」。说法换掉时走一段三段式交替(transitions.dev 的「Text states swap」):旧的那句一边模糊一边向上淡出,淡出之后才换成新的,新的一句从下方升上来;「动画」设为「减弱」时直接换掉,不做这三段。这一行带扫光,宿主的小鲸鱼与读屏播报照旧,关闭「聊天区动画效果」后宿主原来的写法原样回来。轮次状态行里的同一句说法与这一行共用一处(`shared/turn-activity.ts`):正在思考、正在准备工具调用、正在调用工具、正在写回答现在读的是同一份文案。
|
|
26
|
+
- 模型推理期间,思考行里的推理文字不再一行行把整列对话往下推着长:它停在四行高的窗口里,上下边缘渐隐,文字每 0.84 秒往上走两行(0.5 秒滑过去、曲线 cubic-bezier(0.22, 1, 0.36, 1)),走到最新一行就停住,读者始终看得见推理的结尾。这一套来自 transitions.dev 的「Reasoning stream」,按实时文字改写:不克隆、不循环。推理一停(或读者把这一行收起),窗口撤下、位移归零,读者打开这一行读到的是完整文本;「动画」设为「减弱」时不设窗口。端到端通道新增 `reasoningStream` 场景:在真实宿主上核对窗口高度与遮罩、每一步的位移与过渡、位移从不越过内容末尾(实测走到 211px 正好等于文本 303px 减窗口 92px),以及推理结束后窗口撤下、完整文本 303px 铺开。
|
|
27
|
+
- 设置页的「品牌标识」改名为「主题风格」,并从「外观」页移到「通用」页最前面:这一项选的是整套品牌标识与配色色系,此前排在「外观」页首位,而同页的配色、字体与吉祥物都只改一样东西;现在它与用户名、动画效果这些通用项排在一起,「外观」页只剩配色、字体、吉祥物与出现位置。可选的品牌、存下的设置值与切换后的效果都不变。
|
|
28
|
+
|
|
29
|
+
### 问题修复
|
|
30
|
+
|
|
31
|
+
- DeepSeek 品牌下侧栏品牌区的 HARNESS 徽标重新显示:皮肤此前把宿主标志里的胶囊徽标与徽标上的字形一并隐藏,品牌区只剩下鲸鱼与 deepseek 字样;现在宿主的整幅标志(鲸鱼、deepseek 字样与 HARNESS 徽标)原样保留,徽标沿用 DeepSeek 蓝的胶囊底与反白字形。Claude 品牌下品牌区照旧画皮肤自己的标。
|
|
32
|
+
- 输入行右端的上下文计量环不再跟着宿主的行高、空隙与药丸宽度跑偏:把数字收进上下文弹层那一档下,皮肤把卡片下面那一条 dock 盖到输入行上,此前是按「行高 28px、这一行距容器底 4px、给行尾留出计量环自身的宽度 +8px」这几个写死的数放它——它们都属于宿主,卡片的空隙或行高不同,计量环与读数就整体离开那一行(0.2.0-rc.2 的 macOS 端实测偏 4 CSS px,与本机相差一个空隙),药丸比宿主停放的那个节点宽时行尾的文字还会被药丸底色压住。现在行高与空隙由 composer 每次经过从输入行自己量出来(`--dsh-claude-meter-row-offset`、`--dsh-claude-meter-row-height`),留出的宽度按「停放节点与触发按钮两个盒子并起来」再 +8px 算,量在行或容器尺寸变化时做;端到端通道新增 `statsOverlay` 场景:卡片下方的空隙分别改成 0 与 16px 后 dock 的两个盒子边仍与输入行逐边相同(量出的空隙跟着由 4px 变 0 与 16px),再把触发按钮在停放节点里左移 14px,断言行尾文字与药丸左缘仍留 8px。
|
|
33
|
+
- 进行中的状态行只在插件自己跟随末尾时停在输入框上方:此前只要宿主还报着「跟随在开」,读者往上翻看历史时这一行仍按固定位置浮在输入框上方、压住正在读的内容,直到宿主自己发现读者离开末尾。现在读者接管滚动(滚轮、触摸、拖动滚动条、滚动键、页内查找,以及对话导航跳到某一轮)期间,这一行的固定整个让开,随内容一起走;读者自己回到底部后跟随继续,这一行也回到输入框上方。端到端通道新增 `readerScroll` 场景:轮次进行中滚一次滚轮,读者滚动之前该行 158 帧停在 426px,之后 382 帧无一处停在固定位置、全部随内容移动。
|
|
34
|
+
- 侧栏搜索的内容匹配不再搜进注入上下文与推理过程:`user/message` 里由宿主注入的环境快照、Skill 目录、AGENTS.md 与压缩检查点此前一并进了语料,于是搜到的「会话」里出现读者从没打过、模型也没答过的字;现在只收人类发出的消息(按事件自带的 `source.kind === 'user'`)与助手回答里的文本块,推理块、工具调用与工具结果都不进。实测同一条会话里,只出现在 Skill 目录里的字符串与只出现在推理块里的字符串都从命中列表里消失,读者自己发的原文仍照常命中。
|
|
35
|
+
- 会话数字的入场动画不再把整屏内容顶来顶去:数字一变化,新字符就从自己位置下方 8px 滑入,而这一行与对话共用宿主同一个滚动容器——滑入的那几像素越过输入区底边,把容器的可滚动高度顶大 3px(实机测得 1649 → 1652),末尾跟随随即补偿,输入卡片与上方对话跟着上下跳一次,动画落回时再跳一次;流式输出期间每个数字都在动,这一跳就一直重复。现在这一行把自己裁掉(`overflow: clip`),入场留在行内,容器的可滚动高度不再跟着数字变化。端到端通道的 `statsPosition` 场景新增一条读数:在同一帧里写一次数字、量容器可滚动高度的增量,必须是 0(改前为 3)。
|
|
36
|
+
- 会话数字那一行不再把上方的对话推来推去:窗口窄到这一行放不下时,它按台阶让位,第三个台阶让出的是计量环旁的数字,而那个数字正是宿主触发按钮的高度——按钮一矮,输入区底部这一行就跟着矮,上方的对话按这一行排、并把末尾钉在它上面,于是数字每跨过这一档,整屏内容就上下跳一次,来回两下。现在让位只让出宽度:触发按钮保持一行的高度(20px 行高加宿主自己的上下各 1px),圆环留在原位,行高不随台阶起落变化,对话也不再移动。端到端通道的 `statsPosition` 场景新增一条读数:在同一帧里量「让出读数」与「读数在位」两种情况下这一行的高度,两者必须相同。
|
|
37
|
+
|
|
38
|
+
### 移除
|
|
39
|
+
|
|
40
|
+
- 「聊天区动画效果」不再是三档,也不再是两档分段控件,而是一个开关:开启时播放本插件的这一套,关闭时把聊天区交回宿主。上一版接在「重绘」档上的会话视图(插件自己渲染的对话区:链路折叠与计数行、推理卡片、逐词淡入、按宿主「工作步骤展示」分档的收拢、子会话的第二份视图)整体移除,那套实现来自 dsh-better-display 的整份移植,读者装上那个插件就能得到同样的界面,本插件再维护一份的代价大于收益。此前存下「重绘」或「增强」的读者照旧开着这一项,存下「关闭」的照旧关着,不需要重新设置。同时移除的还有:插件自己的「工作步骤展示」桥接、只为阅读视图装上的宿主内部开发依赖与 TSX 工具链、端到端场景 reader / readerOpen / readerTurnNav / stepDisplay 与冒烟用例 chat-reader。搬到开关下的两处视觉仍出自那个实现,它的许可说明留在第三方声明里。搜索面板点开内容命中仍在会话里落到那一轮,改经宿主的刻度跳转。
|
|
41
|
+
|
|
42
|
+
### 其他变更
|
|
43
|
+
|
|
44
|
+
- 端到端通道与 `packages/testing/dsh-web.cjs` 起的临时宿主随启动它的进程一起结束:此前启动进程被强制终止或抛出未捕获的错误时,`dsh web` 实例留在后台继续占用端口与 `$DSH_HOME`,它的目录随后被删掉时还会持续占满一个以上的 CPU 核心;现在启动进程无论以哪种方式结束,宿主都在随后一秒内退出。
|
|
45
|
+
|
|
46
|
+
<h3 id="en-0.12.2">New Features</h3>
|
|
47
|
+
|
|
48
|
+
- The Sidebar tab gains a Search box style choice under Sidebar search: Cover the brand (the default) keeps the box in the brand row, standing over the brand while the pointer is over the sidebar; Standalone gives it a row of its own under the brand row, shown always; Icon draws no box of the plugin's and keeps DSH's own search button in place with only its click taken over, so pressing it opens this plugin's palette. Switching needs no reload.
|
|
49
|
+
- The line of numbers under the input card has its own popover again: that line showed six readings, while the detail the host's statistics row carries — model time, tool time, first-token average, output speed, and the usage rows for cache hits, uncached input, cache reads, cache writes and output — had nowhere to be read with the statistics asked onto a line of their own. The line is now the second trigger of the host's context panel: pressing the figures opens that panel above the line, holding the same session's data — the host's own context rows followed by the numbers' own detail rows, filled from one source in either position; pressing again puts it away, Enter or Space does the same from the keyboard, Escape closes it, and the line reports its own expanded state while the panel stands. Opening and closing on hover stays the ring's own path: resting a pointer on the figures never unfolds the panel. The panel re-takes its placement when the window or the composer changes.
|
|
50
|
+
- The settings page's Conversation tab gains Conversation statistics position: the session statistics and the token usage used to have one place to live — the popover of the composer's context ring. By default they now stand on a line of their own below the input card: the turns and steps, the output speed, the tokens read in and written back and the cache-hit share, with the ring itself at the end and none of the host row's icons; Inside the context popover is still available for the panel's own set. A figure on that line re-enters character by character whenever it moves (every step and all through a streaming answer, while the figures that did not move stay still), and the cache share and the ring each take their own colour band (the share from red in the nineties to dark green at 99%, the occupancy from green at a fifth to red at two fifths, mixed between stops by the browser in OKLCH). A window too narrow for the whole line makes it give way in a fixed order — first the cache share's words, then the turns and steps, then the number beside the ring (the ring stays), then the tokens read in and written back as one total without the arrows, and last the counts folded into k / M / B — so figures never crowd each other or draw over one another, and the same order gives them back as the window grows. The row answers to a setting of its own from now on rather than sharing the permission control's switch, and the settings form carries one more field, which a running host serves after a restart.
|
|
51
|
+
- The Claude Style page in the settings dialog now ends its heading row with a GitHub mark; pressing it opens the plugin's repository (https://github.com/Nwflower/dsh-claude-style) in a new tab. The mark takes the secondary label ink, following each palette; the pointer gets the skin's hover plate with a darker mark, the keyboard gets an accent focus ring, and the accessible name reads "Open the plugin on GitHub". The copy on the plugin's own page keeps the host's heading and carries no mark.
|
|
52
|
+
|
|
53
|
+
### Improvements
|
|
54
|
+
|
|
55
|
+
- On a Chinese interface the permission selector names its tiers in the host's own Chinese words: the trigger's current tier and every popover row used to read the skin's fixed Claude names (Read only / Accept edits / Full access) with only the description line under each name in Chinese; with the interface in Chinese those names now come from the host's `permission.access` dictionary — 仅可查看 / 工作区内修改 / 完全权限 — so the skin follows the host when it rewords them, while any other interface language still reads the skin's names.
|
|
56
|
+
- The sidebar search's session-content search answers at once instead of after a wait: each session's corpus (the reader's messages and the model's answers) used to live in the host process's memory alone, so the first search after every host restart re-read every session log — about 30 seconds for 260 sessions on this machine. It now keeps one `$DSH_HOME/cache/dsh-claude-style/search/<sessionId>.json`, which a restart reads back in about 1.4 seconds; a stored session is re-read only when its revision moved, and a session the host holds open contributes only the events appended since the last fold. The query itself reads lowercased text instead of scanning with a regular expression: 5–20 ms per query over 260 sessions and 8252 messages on this machine, against about 0.5 s before. The cache is built on demand — logs are read, and files written, only when the reader actually searches, and the first search on a machine with no cache still reads every session log once.
|
|
57
|
+
- The line of session numbers no longer separates its groups with ·: a · stood between the turns and steps, the output speed, the tokens read in and written back and the cache-hit share, and a narrow line gave up a step sooner for them. Those glyphs are gone, the groups stand apart by the line's own gap alone (widened from 6px to 10px), the line fits more figures, and copying it out leaves a clean sentence. The end-to-end lane and the smoke each gain a reading: the line's DOM carries not one ·.
|
|
58
|
+
- Picking a content hit in the search palette now lands on the turn holding that message instead of stopping at the top of the session: the palette reads the message's event sequence, finds the turn it belongs to in the session's whole-log outline, and positions there through the host's marks once that turn is in the loaded window. On a long history the turn's records are paged in first; when no turn can be found the reader stops at the session itself, as before.
|
|
59
|
+
- A process group's header no longer reads as the host's list of activities ("ran a command, read a file, called a tool, …"): it says what the group holds — "2 thoughts, 1 tool call". Empty figures are left out, each number rolls as the work grows (160 ms, set at once under reduced motion), the whole line sweeps the way the host's words do while that piece of work runs, and the control's accessible name is that sentence, so what a screen reader announces matches what is on screen. A header without the room for the sentence (a narrow window, a short row) falls back to the compact figures, `Thinking×2 · Tools×1`, and takes the sentence back when the room returns — neither wording is cut off with an ellipsis. The room is read from what the header's own container gives it rather than from how wide it happens to be. The counts come from each row the group holds: an assistant step carrying `data-chat-group-part="reasoning"` counts as a thought, any other assistant step as an output, a tool call as a tool, and commands and other records as records; a tool row's own inner calls are not counted twice.
|
|
60
|
+
- While a turn runs, the line at the end of the conversation no longer reads a fixed "Deep diving for N s ···": it says what that turn is doing now — "Thinking…", "Preparing a tool call…", "Running tools…", "Writing…" — with the time the turn has taken beside it in the host's own units. Where no state can be read (the model has written nothing and no tool is running) it falls back to the host's own "Deep diving", which is the very line the reader sees in the host's interface at that moment; once the model has been silent for ten seconds "No response yet" appears beside the clock. A wording that changes runs transitions.dev's "Text states swap": the old one blurs and fades upward, the text changes once it has gone, and the new one rises from below — with Animation set to Reduced the wording is written at once and none of the three phases runs. The line sweeps, the host's whale and its screen-reader announcement stay, and switching Chat-area animations off brings the host's own wording back as it was. The turn status line reads the same four states from one place (`shared/turn-activity.ts`).
|
|
61
|
+
- While the model reasons, the reasoning text in its thinking row no longer grows line by line and pushes the whole conversation down: it stands in a window four lines tall with a softened edge at each side, and the text steps up two lines every 0.84 s (half a second of travel on cubic-bezier(0.22, 1, 0.36, 1)), stopping at the newest line so the reader always sees how the reasoning ends. This comes from transitions.dev's "Reasoning stream", read as live text: no copy and no wrap. Once the reasoning stops — or the reader folds the row — the window comes off and the offset returns to zero, leaving the whole text for the reader who opens the row; with Animation set to Reduced the window is never set. The lane gains a `reasoningStream` scenario: on the real host it checks the window's height and mask, the offset and the transition of each step, that the offset never passes the content's end (measured 211px, exactly the text's 303px less the window's 92px), and that the window comes off afterwards leaving the whole 303px of text.
|
|
62
|
+
- The settings page's Brand mark is renamed Theme style and moves from the top of the Appearance tab to the top of the General tab: the row picks the whole brand mark and colour family, and it used to lead a tab whose other rows — Colours, Typefaces, Mascot — each change one thing; it now stands with the general choices, while the Appearance tab keeps Colours, Typefaces, Mascot and Where it appears. The brands on offer, the stored values and what a switch does are unchanged.
|
|
63
|
+
|
|
64
|
+
### Bug Fixes
|
|
65
|
+
|
|
66
|
+
- The sidebar's brand area shows the HARNESS badge again under the DeepSeek brand: the skin used to hide the host mark's pill badge together with the letterforms inside it, leaving the whale and the deepseek wordmark alone; the host's whole lockup — whale, deepseek wordmark and HARNESS badge — now stands as it is drawn, the badge keeping its blue pill and reversed-out letters. The Claude brand still draws the skin's own mark.
|
|
67
|
+
- The context meter at the composer row's right end no longer drifts with the host's own row height, gap or pill width: with the numbers asked into the context popover the skin lays the dock under the card over the toolbar row, and it used to place it from fixed numbers — a 28px row, 4px above the containing block's bottom, and the meter node's own width plus 8px kept free at the row's end. All of them belong to the host, so a card leaving a different gap under that row, or a taller row, carried the ring and its reading off the row entirely (4 CSS px off on a macOS host running 0.2.0-rc.2, whose gap differs from this machine's by exactly that), and a pill wider than the node the host parks it in let the ring's hover face cover the row's own text. The composer pass now measures the row's height and gap from the row itself (`--dsh-claude-meter-row-offset`, `--dsh-claude-meter-row-height`) and computes the room as the union of the parked node and the trigger button, plus 8px, re-reading both when the row or the stack changes size. The end-to-end lane gains a `statsOverlay` scenario: with the card's gap under that row moved to 0 and to 16px the dock's box still matches the row's edge for edge (the measured gap follows, 4px to 0 and to 16px), and a trigger shifted 14px left inside its parked node still keeps 8px between that node's row text and the pill's left edge.
|
|
68
|
+
- A running turn's status line rests above the composer only while the plugin's own follow is the one moving the position: as long as the host still reported its follow as on, scrolling back through the history left the line floating at the pinned place over the content being read until the host noticed the reader had left the tail. The line's pin now stands down for the whole time the reader owns the scroll — wheel, touch, a drag of the scrollbar, the scroll keys, in-page find, and a jump to a turn — and travels with the content instead; once the reader comes back to the bottom the follow resumes and the line rests above the composer again. The end-to-end lane's new `readerScroll` scenario scrolls the wheel once during a live turn: 158 frames at 426px before the reader's wheel, and 382 frames after it with no frame at the pinned place and every frame moving with the content.
|
|
69
|
+
- The sidebar search's content match no longer reaches into injected context and reasoning: the environment snapshots, Skill catalog, AGENTS.md and compaction checkpoints the host injects as `user/message` used to enter the corpus, so "session" hits carried text the reader never sent and the model never answered. Only the reader's own messages (by the event's own `source.kind === 'user'`) and the text blocks of assistant answers are collected now; reasoning blocks, tool calls and tool results stay out. On a real session, a string that exists only in the Skill catalog and one that exists only in a reasoning block both left the hit list, while the reader's own words still match.
|
|
70
|
+
- The session numbers' entrance no longer shoves the whole column around: every time a figure moves, its new characters slide up from 8px below their place, and the line shares the host's one scroll container with the conversation — those few pixels reach past the composer's bottom edge and grow that container's scrollable height by 3px (1649 to 1652, measured on a live host), which the tail pinning answers by moving the input card and the conversation above it once, and once more when the entrance settles. With figures moving all through an answer, that movement repeated for as long as the answer streamed. The line now clips itself (`overflow: clip`), so the entrance stays inside the row and the container's scrollable height no longer follows the numbers. The end-to-end lane's `statsPosition` scenario gains a reading: within one frame it writes a figure once and measures how much the container's scrollable height grew, which must be 0 (it was 3).
|
|
71
|
+
- The line of session numbers no longer shoves the conversation above it around: when a window is too narrow for the whole line, the line gives way one step at a time, and the third step gives up the number beside the context ring — the very number that makes the host's trigger as tall as it is. A shorter trigger made the composer's bottom row shorter, and since the conversation above is laid out from that row and pins its tail to it, every crossing of that step moved the whole column, once each way. The step now gives up width alone: the trigger keeps its one-line height (a 20px line inside the host's own 1px padding), the ring stays where it was, the row's height no longer follows the ladder, and the conversation stays put. The end-to-end lane's `statsPosition` scenario gains a reading: within one frame it measures that row with the reading given up and with the reading back, and the two must match.
|
|
72
|
+
|
|
73
|
+
### Removals
|
|
74
|
+
|
|
75
|
+
- Chat-area animations is no longer three-way, nor a two-way segmented control, but a switch: on plays this plugin's set, off hands the conversation back to the host. The conversation view the Redraw tier used to hand the area to (the plugin's own rendering of the conversation — folded chains with their counted rows, reasoning cards, the per-word fade, the fold ranges that followed the host's Work details setting, a second view for a sidebar child session) is removed whole: that implementation was a full port of dsh-better-display, and a reader who installs that plugin gets the same interface, so a second copy kept here cost more than it returned. A reader who had stored Redraw or Enhanced keeps the setting on, and one who had stored Off keeps it off, with nothing to reconfigure. Also removed: the plugin's own Work details bridge, the host-internal development dependencies and the TSX toolchain that only the reading view needed, the end-to-end scenarios reader / readerOpen / readerTurnNav / stepDisplay and the smoke case chat-reader. The two pieces of that look which moved under the switch are still derived from that implementation, so its notice stays in the third-party notices. Picking a content hit in the search palette still lands on the turn holding that message, through the host's own marks.
|
|
76
|
+
|
|
77
|
+
### Chores
|
|
78
|
+
|
|
79
|
+
- The scratch hosts that the end-to-end lane and `packages/testing/dsh-web.cjs` start now end with the process that started them: a launcher that was killed or died on an uncaught error used to leave its `dsh web` instance running in the background, holding its port and `$DSH_HOME`, and spinning more than one CPU core once that directory was deleted; now the host exits within a second however the launcher ends.
|
|
80
|
+
|
|
81
|
+
## [0.12.1] - 2026-10-09
|
|
82
|
+
|
|
83
|
+
[中文](#cn-0.12.1) | [English](#en-0.12.1)
|
|
84
|
+
|
|
85
|
+
<h3 id="cn-0.12.1">新增功能</h3>
|
|
86
|
+
|
|
87
|
+
- 「聊天区动画效果」的「重绘」档换上插件自己的会话视图:它直接占据宿主「对话」视图的位置,标签条上不再多出一个标签,宿主转到「对话」的跳转同样落到它;档位离开「重绘」时宿主的「对话」原样回来。轮次进行中,新出现的一段思考把同一条链上此前的思考、正文与工具收成一行(思考×N · 输出×M · 工具×K),数字随内容跳变,用户插话重新开一条链,收拢走收缩、计数、停顿、展开四段时序;轮次成功结束后过程与中间叙述收起、只留最终回答与它的复制、分叉、反馈操作,失败、中断与等待批准的轮次保持展开,读者选中文字期间推迟折叠,历史轮次随时可以点开。思考在卡片里按阅读节奏滑动跟随,卡片只放思考的文字,读者滚回末尾即重新跟随;收进折叠的思考每段只占一行,写作「思考 · 内容」并带着思考卡片的边框,与中间输出一眼分开,按一下边框随全文展开;正文由宿主的 Markdown 渲染,新出现的词逐个淡入;工具行写出目标、改动行数与慢调用的计时,展开后是宿主自己的工具详情、输入与原始记录。轮次进行中的每一种状态(等待模型、思考、输出、准备与使用工具、等你操作)都由最新一条消息下面同一行说出;等待模型时这一行计时,过 10 秒标出「暂未响应」,进行中的过程也从这一行展开与收起。页面上装有 dsh-better-display 的阅读视图时这一份不登记;桌面端随带的 0.2.0 宿主与 npm 上的 0.2.1 宿主都能读。「动画」设为「减弱」时一律直接落位。
|
|
88
|
+
- 模型选择器的每一行标出该模型此刻的倍率:峰价、谷价与限时活动三种状态各有自己的图标,颜色区分贵与便宜,倍数后面跟着距离切换还有多久,鼠标停在徽章上读到「此刻的判定 · 多久后转为哪个状态」的完整一句,距切换不足一分钟时读 `<1m`。判定按各家供应商自己发布的作息表与自己的时区做(工作日窗口之外、周末与法定节假日整日算谷价,跨零点的窗口归它开始的那一天,夏令时切换按真实时刻计算,落进夏令时空档的窗边落在跳变那一刻);没有作息表的模型不显示徽章,把标准费率整天在走的供应商按其作息表显示。限时活动按文档声明的日期与时刻边界起止(结束时刻就是切换那一刻,已经结束的活动不会再生效)。作息表来自公开目录 offpeakclock.com 的一份快照:宿主半边取一次、在 `$DSH_HOME/cache/dsh-claude-style/peakrate.json` 留一份缓存、每 24 小时刷新一次,经 `/dsh-claude-style/peakrate` 下发(`POST` 强制重拉),连不上时按插件包里带的那份判定;浏览器半边只在功能装上时读一次,第三方地址不经过页面。构建核对匹配表里每一行点到的那条作息确实在包内快照里、且属于同一个供应方,对不上即构建失败。设置页「输入区」页新增「峰谷电表」子项,关闭后各行的徽章消失,模型选择器关闭时该项目变灰不可操作。
|
|
89
|
+
|
|
90
|
+
### 体验优化
|
|
91
|
+
|
|
92
|
+
- 设置页「对话」页的「聊天区动画效果」从开关改成三档分段控件:关闭、增强、重绘。「关闭」把聊天区交回宿主;「增强」是原来的全套动效(跟随、自动开合与卷帘门、新文字淡入、文件变更行、聊天气泡动效);「重绘」交给另一套动效,接上的是聊天气泡动效与插件自己的阅读视图。旧版本存下的开关取值照旧生效(开 = 增强,关 = 关闭),不需要重新设置。
|
|
93
|
+
- 页面启动时插件占用的主线程时间减少:设置页、内容搜索、吉祥物、发送动效、对话导航、上下文弹层与封号彩蛋这七个首屏可以缺席的功能离开 `lib/client.js`,各自成为一个块,由插件已有的资产路由 `/dsh-claude-style/assets/` 提供,页面被接管后立即请求、到达后安装。在本地临时宿主上实测(两种产物各载入 20 次取中位数):`lib/client.js` 从 776 KB 降到 712 KB,前 3 秒的主线程长任务从 713 ms 降到 648 ms,皮肤生效时刻从导航后 298 ms 提前到 280 ms;七个块经 brotli 压缩后共 33 KB,比主产物晚约 5 ms 到达。块与它的 source map 各自按自身内容的哈希命名,浏览器不会把旧的 map 当成新的那份;构建拒绝主产物与块同时携带同一个模块(构建期生成的模块也在其中,它经共享表读主产物里的那一份)。插件更新后页面换代时,块已经在磁盘上:构建把主产物写在最后,先写新资产、再写清单、最后删清单里没有的文件。
|
|
94
|
+
- 设置页「侧栏」页新增「面板悬浮卡片」开关:开启(默认)时右侧栏停靠的面板仍是悬浮卡片——四周留 8px、16px 圆角、1px 描边与投影;关闭后停靠的面板铺满整列、贴住四边,分栏时每栏铺满各自那一栏,两栏之间只留宿主的接缝线。切换不需要刷新页面。
|
|
95
|
+
- 模型选择器每一行的说明改由一张按名字模式认领的有序规则表得出:带上日期后缀、把官方点号写成连字符或下划线(`glm-5-3-flashx`)或换一个售卖方前缀,仍然读到同一句;`k3-256k`、`ernie-5`、`minimax-m3-1m`、`deepseek-v41-flash` 这类目录拼法各自落到所在产品线的规则上,不必再逐条登记。带版本数字或最高级的说明写成锚定该版本的规则(`glm-5.3`、`gpt-5.4`、`qwen3.8-max`、`step-3.7-flash`、`celeris-1` 等),同产品线的其他版本读到线级文案;目录里现有的 25 个模型 id 里,除 Grok 与 ERNIE 两行按另一条记录改写外,其余解析出的句子与改动前逐条相同。
|
|
96
|
+
- 「重绘」档里轮次进行中的那条状态行(「正在思考」「正在使用工具」这些)上下各收进 30px,贴着最新一条消息读,不再像独占一行。实测:该行与上方轮次之间原有的 26px 空隙收掉,行内文字与它的下一条内容之间的距离也少 30px;这一行仍按内容居中,高度不变。为了让它在压上去时不露出旧内容的接缝,这一行补了一圈底色投影,并抬到上方内容之上。
|
|
97
|
+
- 「重绘」档的思考卡片只留思考本身:参考实现搬来的「思考 · 第 N 步」抬头、「暂停跟随 / 跟随最新」与「完整阅读 / 收起」两个按钮,以及为展开态在会话里量出的阅读高度都不再出现,卡片的边框里就是思考的文字,高度由预览高度与内容决定。跟随仍按阅读节奏走,滚回卡片末尾就重新跟随,而上一版要靠按钮点回来的那一步现在由滚动自己完成;展开一段思考仍是从折叠里那行文字点开,于是每段思考在折叠里保持一行,读全文按一下即可。
|
|
98
|
+
- 「重绘」档的一轮过程现在按宿主「工作步骤展示」的当前档位成形,两侧设置不再各行其是:插件不新增自己的档位控件,只读宿主 `ui-chat` 命名空间的档位并在每次有轮次开始时重读,读不到时按网页端缺省档「详细」。「简洁」把整条链收成一行,中间输出的正文也进这一行的计数;「标准」收拢最后一段思考之前的全部步骤,中间输出随最后一段思考留在行外;「详细」把结尾的中间输出留成自己的一行、收拢它之前的全部步骤;「完全展开」与「详细」同形,另外把收进折叠的思考画成整张推理卡片(全文,而不是「思考 · 内容」一行),工具仍由读者自己按开。宿主自己的设置行仍是唯一控件,插件不代写。
|
|
99
|
+
- 模型选择器里 Grok 与 ERNIE 两行的说明改写:Grok 的规则从匹配 4.5 改成匹配 Grok 4 整条产品线,`grok-4`、`grok-4.5`、`grok-4-2026` 这些拼法读到同一句「全球最智能的模型之一,支持原生工具使用以及实时搜索功能。」;ERNIE 5 一行改成「2.4 万亿参数的原生全模态大模型。」,不再列激活比例与上下文长度。
|
|
100
|
+
- 插件的样式表以压缩后的文本随包发出:注释与排版只留在源文件里,整张样式表从 349 KB 降到 208 KB,`lib/client.js` 从 712 KB 降到 570 KB。页面画出的样子不变:端到端通道把压缩前后的两份样式表放到同一个页面上,22 个页面状态逐元素比对计算值,全部一致。压缩还把 `!important` 审计过去豁免的一部分规则变成可以逐条判定的(同一个属性写两遍的规则,压缩后只剩一条声明):判定之后,输入区停止按钮、侧栏进行中指示与聊天区跟随尾部上页面并不需要的 46 处 `!important` 从源样式表里去掉了。审计也随之收紧:处在条件不成立的 `@media` / `@supports` 里的规则不再参与判定,它们的 `!important` 不会因为页面当时不在那个条件里就被判成多余。在本地临时宿主上实测(两种产物各载入 20 次、做两轮,取中位数):插件包的求值时间从约 9.0 ms 降到约 8.3 ms;启动阶段的其余计时差别落在两轮之间的波动以内。
|
|
101
|
+
|
|
102
|
+
### 问题修复
|
|
103
|
+
|
|
104
|
+
- 长会话里流式输出期间的卡顿减少:跟随在每一批文字到达时都要问的几个问题不再落到整个文档上——会话的滚动容器与消息列读一次后保留(换会话、切「轨迹」页签时旧节点会从文档里移除,届时重新读取),流式标记改在消息列里查找,宿主「回到底部」按钮的存在本身就是「跟随已关闭」的判据,而同一帧里读到的高度只读一次,交给收回宿主写下的末尾、判断是否继续滑行这两处共用。在 120 轮、4286 个节点的临时会话上实测:插件发出的文档级查询从 3263 次降到 2762 次(−15%),整页最长的一次停顿从 270ms 降到 234ms;文档越大,省下的每次全页样式重算越多。
|
|
105
|
+
- 模型选择器里当前在用的模型、当它所属的供应商不在第一级列表里时,会单独占一级列表最下面一行——这一行过去绕过了其余各行共用的行构造,因此没有峰谷徽章,也没有厂商标志与说明;现在它与列表里的每一行走同一个构造,徽章、标志、说明和行高内边距都一致。
|
|
106
|
+
- 「重绘」档里收进折叠的一段思考,展开后再点它的文字没有反应,只能点右侧的折角按钮才能收起。文字上的点击此前只在收起时挂着,展开后整行文字只剩选择文字的作用。现在文字两态都可点:收起时点它展开,展开时点它收起;一次以选中文字收尾的落点不改开合,选中文字期间推迟折叠的行为照旧。
|
|
107
|
+
- 进行中的状态行不再随流式内容上下跳动。此前该行只在宿主自己的「跟随还开着」标记下钉住,而流式期间跟随的滑动会把滚动位置停在末尾之前,宿主把这次写入读成读者离开了末尾并摘掉标记,于是每一片内容到达时该行退回文档流、被内容底部推下去,滑动追上来再把它拉回:视口 1280×600 下实测,标记缺席的 115 帧里该行顶边在 447px 与 573px 之间移动,而钉住位是 426px。现在滑动持有位置期间在聊天列上写下自己的标记,该行按宿主标记或滑动标记任一钉住,内容突发的追加不再带动它:同一场景里标记缺席的 112 帧内顶边恒为 426px。往回翻看历史时两个标记都不在,该行照常留在文档位置,不会浮在读者正在读的内容上。
|
|
108
|
+
- 「重绘」档里轮次状态行的文字在长短之间切换时,被替换下去的那一段会暂时折成两行、溢出状态行的高度(视口 1280×900 实测:状态行高始终 32px,而退出中的文字片段为 84×48px)。原因是两层文字在替换的同一帧里用新文字的宽度排布了旧文字:状态行按隐藏的丈量层取宽,绝对定位的文字层虽然被同一层撑开,浏览器在这一帧仍把旧文字按它原来的窄宽度断行。现在丈量层与被替换的两层都不换行,文字生长期间各行始终单行,状态行高度不再跳变。
|
|
109
|
+
- 修复 **重新编译后设置页等延后功能从设置里消失、要重新开关插件才回来**:构建原先先写 `lib/client.js`、几秒之后才重写 `lib/assets/`,而客户端热重载只认主产物,页面在新块落盘之前就换代,按当时那份清单请求新块得到 404,延后的功能各报告一次并退役。现在资产按「先写新文件、再写清单、最后删清单里没有的文件」落盘,`lib/client.js` 写在最后:换代的那一代要的块已经在磁盘上、也已经在清单里。
|
|
110
|
+
|
|
111
|
+
### 其他变更
|
|
112
|
+
|
|
113
|
+
- 开发机上新增构建标记 `DSH_CLAUDE_STYLE_DEBUG=1`:链接安装的检出重建时,资产清单继续带着上一代仍然存在的条目并保留它们的文件,宿主在启动时读到旧主产物的页面不会因为一次重建丢掉延后的功能。发布构建与持续集成里这个标记不生效,清单就是这一次构建自己的资产;构建日志会说明当前处于哪一档。
|
|
114
|
+
- 构建把 Deepy 帧图的矢量化结果与资产的 brotli 压缩结果按输入哈希缓存在 `.debug/build-cache/`,只改 TypeScript 后的重建从约 14 秒降到约 1.7 秒,`lib/` 与不带缓存时逐字节相同;新增 `npm run dev`,监听构建读取的目录,每次保存后重新构建(带 `DSH_CLAUDE_STYLE_DEBUG=1`),构建失败时保留上一次的 `lib/` 并继续监听。
|
|
115
|
+
|
|
116
|
+
<h3 id="en-0.12.1">New Features</h3>
|
|
117
|
+
|
|
118
|
+
- The Redraw tier of Chat-area animations swaps in the plugin's own conversation view: it takes the place of the host's Chat view itself, no extra tab appears in the strip, and whatever the host sends to Chat lands on it; leaving the Redraw tier brings the host's Chat back as it was. While a turn runs, a new thought folds the thinking, output and tools before it in the same chain into one row (Thinking×N · Output×M · Tools×K) whose figures roll as the work grows, a message from the reader starts a new chain, and each fold runs a shrink, count, pause, reveal sequence. Once a turn completes, its process and interim narration fold away and the final answer stays with its copy, branch and feedback actions; a failed, stopped or waiting turn stays open, a text selection holds the fold, and any past turn opens again. Thinking glides inside its card at reading pace, the card holds the thought's text alone, and scrolling it back to its end resumes the follow; a thought inside a fold takes one line, reading "Thinking · …" inside the thinking card's frame so it never passes for interim output, and a press grows the frame to its whole text; the answer is the host's own Markdown with each new word fading in; a tool row names its target, the lines it changed and how long a slow call has run, and opens onto the host's own tool view, its input and the raw record. Every live state of a running turn (waiting on the model, thinking, writing, preparing and using a tool, waiting for you) is said by one line under the newest message; while the model is silent the line times the wait and marks it "No response yet" past 10 seconds, and the running process opens and closes from it. With dsh-better-display's reading view on the page this one does not register; it reads both the 0.2.0 host the desktop ships and the 0.2.1 host on npm. With Animation set to Reduced everything lands at once.
|
|
119
|
+
- Every row of the model picker now carries the rate in force for that model: peak, off-peak and a dated promotion each get their own mark, the colour separates expensive from cheap, the multiplier is followed by how long it lasts, hovering the badge reads one line — the judgement now, and what it becomes and when — and a switch under a minute away reads `<1m`. The judgement is made from each provider's own published schedule in that provider's own time zone (outside the weekday windows, and on weekends and public holidays in full, the rate is off-peak; a window crossing midnight belongs to the day it starts; a daylight-saving change is resolved against real instants, so a window edge inside a skipped hour falls at the transition), and a model with no schedule published carries no badge while a provider billing a flat standard rate all day keeps the badge its schedule describes. A dated promotion runs between the day and instant bounds the document states (its closing instant is the switch itself, so an expired promotion never applies again). The schedules come from one snapshot in the public offpeakclock.com catalog: the host half fetches it, keeps a copy in `$DSH_HOME/cache/dsh-claude-style/peakrate.json`, refreshes every 24 hours and serves it over `/dsh-claude-style/peakrate` (`POST` fetches again first), and falls back to the copy shipped in the package when it cannot be reached; the browser half reads it once when the feature installs, and the third-party address never goes through the page. The build checks that every row of the mapping table names a profile the shipped snapshot yields and belongs to the same provider, and fails on a row that does not. The Composer settings tab gains a Peak rate meter sub-row under the model picker: off removes the badges, and turning the picker off greys the row out.
|
|
120
|
+
|
|
121
|
+
### Improvements
|
|
122
|
+
|
|
123
|
+
- The Conversation tab's Chat-area animations row is a three-way segmented control now — Off, Enhanced and Redraw — in place of its switch. Off hands the conversation back to the host; Enhanced is the set that was there before (the follow, the automatic folding with its rolling door, the text fade, the file change rows and the send flight); Redraw hands the area to a second set, whose members are the send flight and the plugin's own reading view. A switch value stored by an earlier build keeps its meaning (on reads as Enhanced, off as Off), so nothing has to be set again.
|
|
124
|
+
- Less main-thread time at page start: seven features the first frames can do without — the settings page, content search, the mascot, the send animation, the conversation navigator, the context popover and the account-hold easter egg — leave `lib/client.js` for chunks of their own, served by the plugin's existing asset route `/dsh-claude-style/assets/`, requested as soon as the page is taken and installed on arrival. Measured on a local scratch host (20 page loads of each build, medians): `lib/client.js` falls from 776 KB to 712 KB, main-thread long tasks in the first 3 s from 713 ms to 648 ms, and the skin takes the page 280 ms after navigation instead of 298 ms; the seven chunks are 33 KB brotli-compressed and arrive about 5 ms after the bundle. A chunk and its source map are each named by their own content, so the browser never reads an older map as the current one; the build refuses a module the bundle and a chunk would both carry, generated modules included — those are read from the bundle's own copy through the shared table. After an update the chunks are already on disk when a page swaps to the new bundle, because the build writes the new assets first, the manifest next, the files it does not name last, and the main bundle after all of them.
|
|
125
|
+
- The Sidebar tab gains a Float docked panels switch: on (the default) keeps the right sidebar's docked panels as floating cards — 8px inside the column, a 16px radius, a hairline and an elevation; off fills the column and hugs its edges, each pane filling its own column when the dock is split, with only the dock's own resting line left on the seam. Switching needs no reload.
|
|
126
|
+
- Every model row's description now comes from one ordered table of name-pattern rules: a dated suffix, a separator spelled differently (`glm-5-3-flashx`) or another reseller's prefix still reads the line's own sentence, and catalog spellings such as `k3-256k`, `ernie-5`, `minimax-m3-1m` and `deepseek-v41-flash` land on their product line's rule without an entry of their own. Copy carrying a version's numbers or a superlative sits on a rule anchored to that version (`glm-5.3`, `gpt-5.4`, `qwen3.8-max`, `step-3.7-flash`, `celeris-1` and the rest), while another version of the same line reads the line-level copy; of the 25 model ids the catalog names, every one but the Grok and ERNIE rows another record rewrites resolves to the same sentence as before.
|
|
127
|
+
- In the Redraw tier the live status line ("Thinking", "Using a tool" and the rest) comes in by 30px above and below, so it reads with the newest message instead of as a row of its own. Measured: the 26px gap it used to leave to the turn above is gone, and the distance from its text to whatever follows it drops by 30px as well; the line stays centred in its own height, which is unchanged. A base-coloured shadow now runs under and over the line where it draws over the content above, so the older content never shows at its edge.
|
|
128
|
+
- A thinking card in the Redraw tier now holds the thought and nothing else: the "Thinking · Step N" heading, the Pause following / Follow latest and Read in full / Collapse controls that came with the ported implementation, and the reading height it measured against the conversation while expanded are gone, so the card's frame is the thought's text with its height set by the preview and the text itself. The follow still runs at reading pace, and scrolling the card back to its end resumes it — the step the buttons used to do is now the scroll's own. Opening a thought still starts from its line inside a fold, so each thought keeps one line there and a press reads it in full.
|
|
129
|
+
- In the Redraw tier a turn's process now takes the shape of the host's Work details setting, so the two settings stop disagreeing: the plugin adds no tier control of its own — it reads the host's `ui-chat` value, re-reads it whenever a turn opens, and falls back to the Web client's default, Detailed, when the host serves none. Compact gathers a whole chain into one row, the intermediate output's own text included in that row's figures; Standard gathers everything before the last thought and leaves the intermediate output outside it, beside that thought; Detailed keeps the trailing intermediate output as its own row and gathers what came before; Verbose matches Detailed and draws a thought inside a fold as its whole reasoning card instead of the one-line "Thinking · …", with tools still opened by the reader alone. The host's own settings row stays the only control: the plugin never writes the value.
|
|
130
|
+
- Two lines of the model picker's copy are rewritten: Grok's rule now claims the whole Grok 4 line rather than the 4.5 build, so `grok-4`, `grok-4.5`, `grok-4-2026` and the rest read one sentence — one of the most intelligent models in the world, with native tool use and real-time search — and the ERNIE 5 row now reads a native omni-modal model with 2.4 trillion parameters, without the activation share or the context length.
|
|
131
|
+
- The plugin's stylesheet ships minified: comments and formatting stay in the source files, the sheet falls from 349 KB to 208 KB and `lib/client.js` from 712 KB to 570 KB. Nothing it paints changes: the end-to-end lane puts the sheet before and after minifying on the same page and compares computed values element by element across 22 page states, all identical. Minifying also brings rules the `!important` audit used to exempt within reach of it (a rule declaring one property twice keeps a single declaration once minified): judged one by one, the 46 `!important`s the page never needed — on the composer's stop button, the sidebar's ongoing indicator and the chat area's follow tail — leave the source sheets. The audit tightens with it: a rule inside a `@media` or `@supports` condition the page is not in is no longer judged, so its `!important` cannot be called redundant for a condition that keeps it out of the cascade. Measured on a local scratch host (two rounds of 20 page loads of each build, medians): evaluating the plugin's bundle takes about 8.3 ms instead of about 9.0 ms; the other startup timings move by less than they vary between rounds.
|
|
132
|
+
|
|
133
|
+
### Bug Fixes
|
|
134
|
+
|
|
135
|
+
- Less jank while an answer streams in a long session: the questions the follow asks on every batch of arriving text no longer go to the document — the conversation's scroller and its message column are read once and kept (a session switch or the Trajectory tab removes the old node, and the reading is taken again), the streaming mark is looked for inside the message column, and the presence of the host's back-to-end button is itself the reading that its follow is off. What a frame does read it reads once and shares between taking back the end the host wrote and deciding whether to keep walking. Measured on a 120-turn, 4286-node scratch conversation: the plugin's document-level queries fall from 3263 to 2762 (−15%) and the page's longest single stall from 270ms to 234ms; the larger the document, the more each avoided whole-page style recalculation is worth.
|
|
136
|
+
- In the model picker, the model in force gets a row of its own at the bottom of level 1 when its provider is not listed there. That row was built apart from every other row, so it carried no peak rate badge, no vendor mark and no description line; it now goes through the same row builder as the rest of the list, with the same badge, mark, description and row metrics.
|
|
137
|
+
- In the Redraw tier a thought inside a fold could only be closed from the chevron button: once its line was open, a press on the text itself did nothing, because the text carried a click only while closed and left the whole line to text selection afterwards. The text now toggles in both states — closed, a press opens it, open, a press closes it again — while a press that ended as a selection changes nothing, and a selection still holds the fold off as before.
|
|
138
|
+
- The live turn's status line no longer moves with the streaming answer. It was pinned only under the host's own following mark, and while an answer streams the follow's glide holds the scroll position short of the end; the host reads that write as the reader leaving the tail, takes the mark away, and the row falls back into the flow, where each burst pushes it down and the glide pulls it back (measured at 1280×600: with the mark off, the row's top travelled between 447px and 573px in 115 frames, while the pin sits at 426px). The glide now writes its own mark on the chat column while it holds a position, and the row is pinned under either mark, so a burst costs it nothing: in the same scenario the row's top stayed at 426px in all 112 frames the host's mark was off. Scrolled away from the tail neither mark is present, so the row keeps its document place instead of floating over what the reader went back to read.
|
|
139
|
+
- In the Redraw tier a turn's status label briefly broke onto two lines while the text changed — the leftover half hung out of the row (measured at a 1280×900 viewport: the status row stayed 32px tall while the outgoing segment measured 84×48px). Two layers of text replace each other, and in the same frame the old text was laid out at the new text's width: the row takes its width from a hidden sizer, and the absolutely positioned copies are widened by it, yet the browser still broke the old text at its earlier, narrower width in that frame. The sizer and both copies now keep to one line, so a growing label stays on one line and the row keeps its height.
|
|
140
|
+
- Fix **the settings page and the other deferred features vanishing from a rebuild until the plugin was switched off and on**: the build wrote `lib/client.js` first and replaced `lib/assets/` seconds later, and since the client half of hot reload watches only the bundle, a page swapped to the new bundle before its chunks were on disk, asked for them under the previous manifest, got a 404, and each deferred feature reported once and retired. New asset files now land first, the manifest after them, the files it does not name last, and `lib/client.js` is written after all of them: the generation a page swaps to finds its chunks already on disk and already in the manifest.
|
|
141
|
+
|
|
142
|
+
### Chores
|
|
143
|
+
|
|
144
|
+
- New build flag for a linked checkout, `DSH_CLAUDE_STYLE_DEBUG=1`: a rebuild keeps the entries an earlier build shipped and their files, so a page that booted the previous bundle does not lose the deferred features to a rebuild. The flag is inert in a release build and in CI, where the manifest carries exactly this build's assets; the build log says which mode ran.
|
|
145
|
+
- The build caches the Deepy sheets' vectors and the assets' brotli payloads in `.debug/build-cache/` under the hash of their inputs, so a rebuild after a TypeScript-only change drops from about 14 s to about 1.7 s while `lib/` stays byte-identical to an uncached build; the new `npm run dev` watches what the build reads and rebuilds on every save (with `DSH_CLAUDE_STYLE_DEBUG=1`), keeping the previous `lib/` and watching on when a build fails.
|
|
146
|
+
|
|
7
147
|
## [0.12.0] - 2026-10-07
|
|
8
148
|
|
|
9
149
|
[中文](#cn-0.12.0) | [English](#en-0.12.0)
|
package/README.en.md
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
|
|
19
19
|
## Preview
|
|
20
20
|
|
|
21
|
-
The settings page's
|
|
21
|
+
The settings page's Theme style row switches between the Claude and DeepSeek palettes, and light/dark follows your system's color mode. In each group the top row is the Studio home page and the bottom row a Markdown conversation, light on the left and dark on the right.
|
|
22
22
|
|
|
23
23
|
### Claude
|
|
24
24
|
|
|
@@ -73,42 +73,18 @@ What the plugin does and what each setting changes is documented: [Features](doc
|
|
|
73
73
|
|
|
74
74
|
## Fonts
|
|
75
75
|
|
|
76
|
-
> **Important: the Anthropic fonts
|
|
76
|
+
> **Important: the Anthropic fonts do not ship with the npm package; they are in this repository for download and study only.**
|
|
77
77
|
|
|
78
78
|
| Font | Used for | File |
|
|
79
79
|
|---|---|---|
|
|
80
80
|
| Anthropic Sans Web Text | Interface / UI | [`packages/assets/src/fonts/anthropic/AnthropicSansWebText.ttf`](https://github.com/Nwflower/dsh-claude-style/raw/main/packages/assets/src/fonts/anthropic/AnthropicSansWebText.ttf) |
|
|
81
81
|
| Anthropic Serif Web Text | Conversation body / Markdown | [`packages/assets/src/fonts/anthropic/AnthropicSerifWebText.ttf`](https://github.com/Nwflower/dsh-claude-style/raw/main/packages/assets/src/fonts/anthropic/AnthropicSerifWebText.ttf) |
|
|
82
|
-
| JetBrains Mono Variable | Code / code blocks | [`packages/assets/src/fonts/JetBrainsMonoVariable.ttf`](https://github.com/Nwflower/dsh-claude-style/raw/main/packages/assets/src/fonts/JetBrainsMonoVariable.ttf), [`packages/assets/src/fonts/JetBrainsMonoItalicVariable.ttf`](https://github.com/Nwflower/dsh-claude-style/raw/main/packages/assets/src/fonts/JetBrainsMonoItalicVariable.ttf) |
|
|
83
|
-
| Inter | Interface when Anthropic Sans is absent | [`packages/assets/src/fonts/InterVariable.woff2`](https://github.com/Nwflower/dsh-claude-style/raw/main/packages/assets/src/fonts/InterVariable.woff2) |
|
|
84
|
-
| Noto Serif | Conversation body when Anthropic Serif is absent | [`packages/assets/src/fonts/NotoSerifVariable.woff2`](https://github.com/Nwflower/dsh-claude-style/raw/main/packages/assets/src/fonts/NotoSerifVariable.woff2) |
|
|
85
|
-
|
|
86
|
-
JetBrains Mono, Inter and Noto Serif are licensed under the SIL Open Font License 1.1 and ship with the npm package; nothing to set up. Inter and Noto Serif nearly match the two Anthropic fonts in letter height and width, so without the Anthropic fonts they stand in and the interface and conversation text keep their layout. Both carry only the Latin characters the Anthropic fonts cover; Chinese text keeps using the system's Chinese fonts.
|
|
87
82
|
|
|
88
83
|
To enable the Anthropic fonts, choose one of the following:
|
|
89
84
|
|
|
90
85
|
① Install them on your system — on Windows, double-click each `.ttf` and choose "Install"; on macOS, import them with Font Book.
|
|
91
86
|
|
|
92
|
-
② Skip the install — copy the `.ttf` files into `$DSH_HOME/dsh-claude-style/fonts
|
|
93
|
-
|
|
94
|
-
> The Anthropic Sans and Serif fonts are the property of Anthropic, licensed for personal use only, and are not covered by this project's MIT license.
|
|
95
|
-
|
|
96
|
-
## Skin center handoff
|
|
97
|
-
|
|
98
|
-
This theme is also offered as a **skin** in the DSH Skin Center. Selecting it there hands the whole page to this
|
|
99
|
-
plugin; selecting another skin or the official default takes the page back without a reload.
|
|
100
|
-
|
|
101
|
-
- The answer holds from the first frame: the Skin Center stamps `html[data-dsh-skin]` into the served document, so a
|
|
102
|
-
page that boots with a skin already painting never flashes a frame of this theme first.
|
|
103
|
-
- While another skin paints the page this theme mounts no stylesheet, installs no feature and claims no document
|
|
104
|
-
attribute at all. It takes the page back when the skin leaves and gives it back when a skin returns, a skin
|
|
105
|
-
picked after the page loaded included.
|
|
106
|
-
- A wallpaper plugin is not another owner: while a wallpaper renders this theme keeps working, as described in
|
|
107
|
-
[Settings](docs/SETTINGS.en.md) under "Alongside other theme plugins".
|
|
108
|
-
- The settings page and every stored preference survive the handoff. A skin taking the screen does not uninstall
|
|
109
|
-
anything, and closing the Skin Center does not throw away what you configured here.
|
|
110
|
-
- `data-dsh-claude-style-handoff` on `body` marks a build that can do this; the Skin Center offers the row only
|
|
111
|
-
while it is there.
|
|
87
|
+
② Skip the install — copy the `.ttf` files into `$DSH_HOME/dsh-claude-style/fonts/`.
|
|
112
88
|
|
|
113
89
|
## Installation
|
|
114
90
|
|
|
@@ -126,6 +102,7 @@ dsh plugin --profile web add Nwflower/dsh-claude-style # GitHub source
|
|
|
126
102
|
```
|
|
127
103
|
|
|
128
104
|
3. From the [plugin market](https://github.com/dsh-market/dsh-market)
|
|
105
|
+
4. From the Skin Center of the dsh-web-all plugin
|
|
129
106
|
|
|
130
107
|
Keep only one theme enabled at a time. dsh ≥ 0.1.7 is required, and a restart of DeepSeek Harness brings the full feature set.
|
|
131
108
|
|
|
@@ -144,6 +121,8 @@ The conversation navigator's opening list, keyboard jumps and landing line follo
|
|
|
144
121
|
|
|
145
122
|
The animation frames of Deepy the pixel whale come from the Deepy whale theme pack drawn by calmly-eating-bugs ([@wp3171216237](https://github.com/wp3171216237)), and ship with the plugin by the author's permission. Many thanks to the author! GIFs of all 20 animations, contributed by the author, are in [docs/gifs/](docs/gifs/).
|
|
146
123
|
|
|
124
|
+
The enhanced animations in the chat area are modified from [dsh-chat-ux](https://github.com/alm-allen/dsh-chat-ux) (MIT).
|
|
125
|
+
|
|
147
126
|
The pixel crab (Clawd) is a character of Anthropic, and all rights in it remain with Anthropic. Its laptop animation is taken from Claude Code; the animations of its other states are drawn by this project after that character. The crab's frames are not covered by the MIT license (see [LICENSE](LICENSE)). This plugin is an unofficial fan work, not affiliated with or endorsed by Anthropic.
|
|
148
127
|
|
|
149
128
|
## Related projects
|
package/README.md
CHANGED
|
@@ -80,6 +80,7 @@ dsh plugin --profile web add dsh-claude-style # npm 包(推
|
|
|
80
80
|
```
|
|
81
81
|
|
|
82
82
|
3. 通过[插件市场](https://github.com/dsh-market/dsh-market)安装
|
|
83
|
+
4. 通过dsh-web-all插件的皮肤中心安装
|
|
83
84
|
|
|
84
85
|
同一时刻建议只启用一个主题。安装后推荐重启 `DeepSeek Harness`以获得完整能力。
|
|
85
86
|
|
|
@@ -89,40 +90,18 @@ dsh plugin --profile web add dsh-claude-style # npm 包(推
|
|
|
89
90
|
|
|
90
91
|
## 字体
|
|
91
92
|
|
|
92
|
-
>
|
|
93
|
-
>
|
|
94
|
-
> Anthropic Sans/Serif 字体版权归 Anthropic 所有,仅供个人使用,不适用 MIT 许可。
|
|
95
|
-
>
|
|
96
|
-
> **重要:Anthropic 字体不随 npm 包分发,仅在仓库 [`packages/assets/src/fonts/anthropic/`](packages/assets/src/fonts/anthropic/) 供下载**。
|
|
93
|
+
> **重要:Anthropic 字体不随 npm 包分发,仅在仓库供下载学习研究**。
|
|
97
94
|
|
|
98
95
|
| 字体 | 用途 | 文件 |
|
|
99
96
|
|---|---|---|
|
|
100
97
|
| Anthropic Sans Web Text | 界面 / UI | [`packages/assets/src/fonts/anthropic/AnthropicSansWebText.ttf`](https://github.com/Nwflower/dsh-claude-style/raw/main/packages/assets/src/fonts/anthropic/AnthropicSansWebText.ttf) |
|
|
101
98
|
| Anthropic Serif Web Text | 对话正文 / Markdown | [`packages/assets/src/fonts/anthropic/AnthropicSerifWebText.ttf`](https://github.com/Nwflower/dsh-claude-style/raw/main/packages/assets/src/fonts/anthropic/AnthropicSerifWebText.ttf) |
|
|
102
|
-
| JetBrains Mono Variable | 代码 / 代码块 | [`packages/assets/src/fonts/JetBrainsMonoVariable.ttf`](https://github.com/Nwflower/dsh-claude-style/raw/main/packages/assets/src/fonts/JetBrainsMonoVariable.ttf)、[`packages/assets/src/fonts/JetBrainsMonoItalicVariable.ttf`](https://github.com/Nwflower/dsh-claude-style/raw/main/packages/assets/src/fonts/JetBrainsMonoItalicVariable.ttf) |
|
|
103
|
-
| Inter | 没有 Anthropic Sans 时的界面字体 | [`packages/assets/src/fonts/InterVariable.woff2`](https://github.com/Nwflower/dsh-claude-style/raw/main/packages/assets/src/fonts/InterVariable.woff2) |
|
|
104
|
-
| Noto Serif | 没有 Anthropic Serif 时的正文字体 | [`packages/assets/src/fonts/NotoSerifVariable.woff2`](https://github.com/Nwflower/dsh-claude-style/raw/main/packages/assets/src/fonts/NotoSerifVariable.woff2) |
|
|
105
|
-
|
|
106
|
-
JetBrains Mono、Inter 与 Noto Serif 采用 SIL Open Font License 1.1,随 npm 包分发,无需任何操作。Inter 与 Noto Serif 的字高、字宽与两款 Anthropic 字体几乎一致,没有启用 Anthropic 字体时由它们代替,界面与正文的排版不会因此变样;两者只含 Anthropic 字体覆盖的拉丁字符,中文照旧使用系统中文字体。
|
|
107
99
|
|
|
108
100
|
Anthropic 字体启用(二选一):
|
|
109
101
|
|
|
110
102
|
① 安装到系统——Windows 双击 `.ttf` → 「安装」,macOS 用「字体册」导入;
|
|
111
103
|
|
|
112
|
-
② 免安装——把 `.ttf` 复制到 `$DSH_HOME/dsh-claude-style/fonts
|
|
113
|
-
|
|
114
|
-
## 皮肤中心交接
|
|
115
|
-
|
|
116
|
-
在 DSH 皮肤中心里,这套主题同时以**皮肤**的身份出现。选它即把整页交给本插件;换选别的皮肤或官方默认时,
|
|
117
|
-
页面在不需要刷新的情况下交还回来。
|
|
118
|
-
|
|
119
|
-
- 判定从第一帧就成立:皮肤中心把 `html[data-dsh-skin]` 注入服务端 HTML,因此带着皮肤启动的页面不会先闪过
|
|
120
|
-
一帧本主题。
|
|
121
|
-
- 别的皮肤在画时,本主题不挂样式表、不安装任何功能、不占用任何文档属性;皮肤离开时立刻接管,皮肤回来
|
|
122
|
-
时再次让出,页面启动之后才选的皮肤也一样。
|
|
123
|
-
- 壁纸插件不算另一个属主:壁纸在渲染时本主题照常工作,见[设置说明](docs/SETTINGS.md)里的「与其他主题插件同时使用」。
|
|
124
|
-
- 交接期间设置页与所有偏好都还在:别的皮肤占屏不等于卸载,关掉皮肤中心也不丢这里配过的东西。
|
|
125
|
-
- `body` 上的 `data-dsh-claude-style-handoff` 标记支持交接的构建;皮肤中心只在这一属性存在时才提供该选项。
|
|
104
|
+
② 免安装——把 `.ttf` 复制到 `$DSH_HOME/dsh-claude-style/fonts/`。
|
|
126
105
|
|
|
127
106
|
## 文档
|
|
128
107
|
|
|
@@ -139,6 +118,8 @@ Anthropic 字体启用(二选一):
|
|
|
139
118
|
|
|
140
119
|
像素小鲸鱼 Deepy 的动画帧图来自 calmly-eating-bugs([@wp3171216237](https://github.com/wp3171216237))绘制的 Deepy 小鲸鱼主题包。
|
|
141
120
|
|
|
121
|
+
聊天区域内的增强动效修改自 [dsh-chat-ux](https://github.com/alm-allen/dsh-chat-ux)(MIT)。
|
|
122
|
+
|
|
142
123
|
像素螃蟹(Clawd)是 Anthropic 的角色形象,相关权利归 Anthropic 所有。螃蟹掏出电脑敲代码的动画取自 Claude Code,其余各个状态的动画由本项目按这一形象绘制。螃蟹的帧图不适用 MIT 许可(见 [LICENSE](LICENSE))。本插件是非官方的爱好者作品,与 Anthropic 没有关联,也未获其认可。
|
|
143
124
|
|
|
144
125
|
## 友链
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Third-Party Notices
|
|
2
|
+
|
|
3
|
+
This package includes material from the projects below. Each keeps its own license; the MIT license of this package does not relicense it.
|
|
4
|
+
|
|
5
|
+
## dsh-better-display
|
|
6
|
+
|
|
7
|
+
The counted figures on a process group's header (`packages/client/src/features/chat-fold/process-summary.ts` and the `dsh-claude-process-summary-*` rules in its stylesheet) and the line while the model works (`packages/client/src/features/chat-wait/`, its stylesheet): their roll timing and curve, the shimmer sweep over the figures, the clock's type and colour and the overtime badge follow dsh-better-display's fold summary and live status line. The source files name it in their headers.
|
|
8
|
+
|
|
9
|
+
Source: <https://github.com/aa2246740/dsh-better-display>
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
MIT License
|
|
13
|
+
|
|
14
|
+
Copyright (c) 2026 dsh-better-display contributors
|
|
15
|
+
|
|
16
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
17
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
18
|
+
in the Software without restriction, including without limitation the rights
|
|
19
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
20
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
21
|
+
furnished to do so, subject to the following conditions:
|
|
22
|
+
|
|
23
|
+
The above copyright notice and this permission notice shall be included in all
|
|
24
|
+
copies or substantial portions of the Software.
|
|
25
|
+
|
|
26
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
27
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
28
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
29
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
30
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
31
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
32
|
+
SOFTWARE.
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## transitions.dev
|
|
36
|
+
|
|
37
|
+
The Number pop-in transition (`packages/client/src/features/context-stats/stats-digits.ts` and the `dsh-claude-digit-*` rules in `packages/client/src/features/composer/inline-bar.css`) is ported from transitions.dev's "Number pop-in": its keyframes, its distance, blur, stagger and easing tokens, and one span per character with the last two delayed behind the rest — renamed into this package's own classes and tokens.
|
|
38
|
+
|
|
39
|
+
The "Text states swap" transition (`packages/client/src/features/chat-wait/chat-wait.ts` and the `dsh-claude-chat-wait-label` rules in its stylesheet) is ported the same way: its three-phase sequence (leave upward with a blur, change the text out of sight, enter from below), its duration, shift, blur and easing tokens as this package's own custom properties, and the reflow that releases the entry pose. The snippet's `prefers-reduced-motion` guard is answered by the animation choice this skin resolves onto `<body>` (D26), which already folds the system setting in.
|
|
40
|
+
|
|
41
|
+
The "Reasoning stream" transition (`packages/client/src/features/chat-fold/reasoning-stream.ts` and the `data-dsh-claude-reason-window` rules in that feature's `fold-motion.css`) is ported as well: its window (a few lines tall with a mask at each edge rather than painted gradients), its hold, step, lines, fade and easing tokens, and the stepping clock — read as live text, so there is no copy and no wrap and the steps stop at the newest line.
|
|
42
|
+
|
|
43
|
+
Source: <https://transitions.dev/detail.html?t=number-pop-in> · <https://transitions.dev/detail.html?t=text-states-swap> · <https://transitions.dev/detail.html?t=reasoning-stream> · <https://github.com/Jakubantalik/transitions.dev>
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
Transitions.dev License
|
|
47
|
+
Copyright (c) 2026 Jakub Antalik / Transitions.dev
|
|
48
|
+
|
|
49
|
+
Summary: you (and any coding agent working for you) may use the transitions
|
|
50
|
+
and skills in this repository in unlimited personal and commercial projects,
|
|
51
|
+
modify them freely, and ship them to your users. The tooling is MIT. The one
|
|
52
|
+
restriction is that you may not redistribute the transitions library itself
|
|
53
|
+
as a competing product.
|
|
54
|
+
|
|
55
|
+
Permission is granted, free of charge, to any person or automated agent
|
|
56
|
+
obtaining these transitions to:
|
|
57
|
+
|
|
58
|
+
- use them in unlimited personal and commercial projects;
|
|
59
|
+
- copy, paste, and modify them freely;
|
|
60
|
+
- ship them to end users as part of your own product or website;
|
|
61
|
+
- install and run the skills in any coding agent (Claude Code, Cursor,
|
|
62
|
+
GitHub Copilot, Codex, Gemini CLI, and others) to apply the transitions
|
|
63
|
+
to your code.
|
|
64
|
+
|
|
65
|
+
Restriction: you may not redistribute the library itself. You may not
|
|
66
|
+
repackage, resell, or publish the collection (or a substantial part of it) as
|
|
67
|
+
a competing transitions library, motion pack, or animation kit. Use the
|
|
68
|
+
transitions in your products, not as a product of their own.
|
|
69
|
+
|
|
70
|
+
Full terms: https://transitions.dev/terms.html
|
|
71
|
+
```
|
package/docs/FEATURES.en.md
CHANGED
|
@@ -12,7 +12,8 @@ What each feature does and where its switch lives; the five tabs, their rows and
|
|
|
12
12
|
- **Mascot**: A pixel companion stands on the composer's top edge and changes its animation with what the agent is doing (thinking, writing and calling tools, several sessions at work, subagents, waiting on you, compacting the context, finished, failed, asleep). Follow the brand shows the pixel crab under Claude and Deepy the whale under DeepSeek; either can be picked for good, or none. Where it appears keeps it to the new-conversation page, or puts it in conversations as well.
|
|
13
13
|
- **Greeting and hint**: The new-conversation page greets you by name with a line that changes with the time of day, and the empty composer shows Claude's own hint.
|
|
14
14
|
- **Permission control**: The composer's permission menu becomes a row of segments. The presets are the host's own catalog, a plugin's preset included; the new-conversation page shows the one a new session will start in.
|
|
15
|
-
- **Session numbers**: The session statistics and the token usage
|
|
15
|
+
- **Session numbers**: The session statistics and the token usage follow the host's data live, on a line of their own below the input card — turns and steps, the output speed, the tokens read in and written back, the cache-hit share, with the context ring itself at the end. The line is not only a reading: pressing it opens that ring's popover, which still holds the host's own context rows followed by this session's detail rows, and pressing it again puts them away (opening and closing on hover stays the ring's own path); Inside the context popover keeps the numbers there alone. A number that moves re-enters character by character (the last two a beat behind), no separator glyph stands between the groups — the line's own gap is what sets them apart — and the cache share and the ring's occupancy each take their own colour band.
|
|
16
|
+
- **Peak rate meter**: Every row of the model picker carries the rate in force for that model right now: peak, off-peak and a dated promotion each get their own mark, the colour says expensive or cheap, and the countdown says how long it lasts; hovering reads the whole judgement, the state in force and what it becomes and when. Each provider is judged on its own clock, public holidays are off-peak in full, and windows crossing midnight and daylight-saving changes are resolved against real instants.
|
|
16
17
|
- **Model picker**: The composer's model menu becomes a two-level card: the first level holds the official service and the quick providers you picked, each model with its vendor mark and a line of description; the second level holds the rest.
|
|
17
18
|
- **Effort**: The reasoning effort gets a trigger of its own beside the model, opening a slider. It switches with the model picker, since the host keeps the effort inside its own model menu.
|
|
18
19
|
- **Home page directory and preset menus**: The directory and agent-preset menus on the new-conversation page are drawn as the skin's popover cards, parked over their own buttons, one open at a time.
|
|
@@ -21,17 +22,18 @@ What each feature does and where its switch lives; the five tabs, their rows and
|
|
|
21
22
|
- **Account-hold easter egg**: The account row at the top of the account popover opens a full-page replica of Claude's account-hold page. Every control on it, and Esc, closes it, and nothing it names actually happens. Its language is chosen on the General tab.
|
|
22
23
|
- **One-frame theme switch**: Switching between light and dark changes borders, shadows and fills in the same frame, instead of the colours first and the borders easing in after.
|
|
23
24
|
- **In progress / Archived**: The sidebar's workspace section splits into In progress and Archived; Archived is one flat list whose rows can be restored or deleted.
|
|
24
|
-
- **Sidebar search**: A search box in the sidebar
|
|
25
|
-
- **Turn status line**: A running, stopped or failed turn shows its status at the end of the turn's work: the elapsed time, the output tokens and what the model is doing now (or that it stopped or failed); while the turn runs the line
|
|
25
|
+
- **Sidebar search**: A search box in the sidebar opens a palette that finds sessions (titles and content), projects, plugins, Skills and shortcuts, through the host's own dialog and navigation; picking a content hit lands on the turn holding that message rather than at the top of the session. Search box style places it: Cover the brand (the default) keeps it in the brand row, standing over the brand while the pointer is over the sidebar; Standalone gives it a row of its own under the brand row, shown always; Icon leaves the host's own search button in place and takes only its click over.
|
|
26
|
+
- **Turn status line**: A running, stopped or failed turn shows its status at the end of the turn's work: the elapsed time, the output tokens and what the model is doing now (or that it stopped or failed); while the turn runs the line rests above the composer for as long as the conversation follows its tail, so content arriving below no longer drags it around, and scrolling back yourself leaves it travelling with the content. Off restores the host's turn status.
|
|
26
27
|
- **Conversation navigator**: The column of short marks at the conversation's right edge holds one per turn and follows where you are reading. Reach it with the pointer and it opens into a list: each row carries the message that started its turn and sits exactly where that turn's mark was — the turn you are reading stays in place, and the turn under the pointer is still under it. The wheel scrolls the list and a click glides the page to the turn, loading earlier history first when it is not loaded yet; the Chat / Trajectory tabs at the top of the conversation stay up while the pointer is on the list. Alt+↑ / Alt+↓ jump to the previous or the next turn, and held or repeated they keep stepping; while the composer holds a draft the keys stay with it. The turn you land on flashes a short line over its start. With [dsh-plugin-msg-nav](https://github.com/SherUnlocked-4869/dsh-plugin-msg-nav) installed too, Alt+↑ / Alt+↓ stay with that plugin.
|
|
27
28
|
- **Chat-area follow**: At the structural moments — a thinking row folding, a tool call row arriving — a reader sitting at the bottom is handed back to the host's own follow, instead of being left tens of pixels short by the burst of content; a process group capped in the Standard and Compact tiers (thinking and tool output kept in one scrolling body) is caught up the same way. Catching up runs on a curve: a trickle of characters settles softly and a burst glides at one steady speed before landing. While content streams, the main scroller's own follow is walked along that curve too rather than written to the end in a single frame — with a fast stream the newest lines trail just below the fold and slide into place once it stops. A message you send does not go through it: the host's scroll to bring it into view lands at once. Once the reader scrolls away from the bottom himself, the plugin stays out of it until he returns.
|
|
28
|
-
- **Automatic folding and the rolling door**: A thinking row opens while the model reasons and folds back when it stops; a running process group opens and folds back once that piece of work ends. A row or group the reader pressed himself keeps what he chose for that phase. Opening or closing a row (a tool card, a thinking row, a command card) or a process group moves the height frame by frame, really pushing the content below away or pulling it back. The door only rolls the stretch the reader can see, so any length moves at the same speed, and a body holding several cards rolls as one door.
|
|
29
|
+
- **Automatic folding and the rolling door**: A thinking row opens while the model reasons and folds back when it stops; a running process group opens and folds back once that piece of work ends. A row or group the reader pressed himself keeps what he chose for that phase. The open reasoning stands in a window a few lines tall with a softened edge at each side: the text steps up two lines every 0.84 s (half a second of travel) and stops at the newest line, so a long reasoning never pushes the conversation down line by line; once the reasoning stops the window comes off and the reader who opens the row reads it whole, and with Animation set to Reduced the window is never set. A process group's header says what the group holds — "2 thoughts, 1 tool call", empty figures left out — each number rolling as the work grows, and the whole line sweeps the way the host's words do while that piece of work runs; a header without the room for the sentence falls back to `Thinking×2 · Tools×1` and takes the sentence back when the room returns, with the sentence as the control's name either way. Opening or closing a row (a tool card, a thinking row, a command card) or a process group moves the height frame by frame, really pushing the content below away or pulling it back. The door only rolls the stretch the reader can see, so any length moves at the same speed, and a body holding several cards rolls as one door.
|
|
30
|
+
- **The line saying what the model is doing**: While a turn runs, the line at the end of the conversation is no longer a fixed "Deep diving for N s ···": it names what that turn is doing now — "Thinking…", "Preparing a tool call…", "Running tools…", "Writing…" — with the time the turn has taken beside it in the host's own units. A wording that changes runs transitions.dev's "Text states swap": the old one blurs and fades upward, the new one rises from below (about 0.15 s). Where no state can be read (the model has written nothing and no tool is running) it falls back to the host's own "Deep diving", and once the model has been silent for ten seconds "No response yet" appears beside the clock. The line sweeps, and the host's whale and its screen-reader announcement stay; with Animation set to Reduced the wording is written at once, with none of those three phases.
|
|
29
31
|
- **New text fades in**: Characters arriving in a streaming answer start faint and settle over about 0.12 s, staggered slightly by arrival order; a block arriving whole, a burst of thousands of characters and text that just reflowed from a fold stay solid.
|
|
30
32
|
- **File change rows**: A write or edit dispatched from inside a run_code program carries the `+n -m` tail and an expandable diff card, and its path opens the file; a failed or interrupted row keeps its verdict.
|
|
31
33
|
- **Send flight**: On submission the composer card lifts and narrows into the bubble as it travels, the flying copy carrying the bubble's colour from its first frame and its words re-flowing into the shape; it meets the message row, where the real bubble shows underneath and the flying copy fades out, so the words sharpen into place.
|
|
32
34
|
- **Composer caret motion**: The composer's text caret is drawn by the plugin and glides when it moves; a question card's answer box and a queued message's inline editor are covered as well. The Conversation tab offers Every move (the default), Explicit moves and Off.
|
|
33
35
|
- **Chat / Trajectory tabs**: The Chat / Trajectory tab strip at the top of the conversation is redrawn as a segmented control and lifted onto the title's line when it fits.
|
|
34
36
|
- **Header in the title bar**: On the desktop the session title and the header's controls rise into the window's own caption row: whichever side fits is placed there — the title at the left, the controls at the right — and the rest of the title row closes up to the left.
|
|
35
|
-
- **Settings page**: The settings page appears both in the settings dialog (the "Claude Style" tab) and on the plugin page, in five tabs: General, Appearance, Composer, Sidebar and Conversation. Every feature that takes over part of the host's interface has its own switch; turning it off brings the host's original back at once, without a reload.
|
|
37
|
+
- **Settings page**: The settings page appears both in the settings dialog (the "Claude Style" tab) and on the plugin page, in five tabs: General, Appearance, Composer, Sidebar and Conversation. Every feature that takes over part of the host's interface has its own switch; turning it off brings the host's original back at once, without a reload. In the settings dialog the heading row ends with a link to the plugin's repository.
|
|
36
38
|
|
|
37
39
|
<!-- features:end -->
|
package/docs/FEATURES.md
CHANGED
|
@@ -12,7 +12,8 @@
|
|
|
12
12
|
- **吉祥物**:输入框上沿站着一只像素小伙伴,随智能体的工作状态换动画(思考、写回答与调用工具、多个会话同时工作、子代理、等你操作、压缩上下文、完成、失败、睡着)。「跟随品牌」在 Claude 品牌下是像素螃蟹,在 DeepSeek 品牌下是小鲸鱼 Deepy,也可以固定选一个或者关闭;「出现位置」决定它只在新会话页出现,还是新会话页和对话页都出现。
|
|
13
13
|
- **问候语与提示语**:新会话页的问候语按时段换着说,带上你的名字;输入框的空白提示换成 Claude 的那一句。
|
|
14
14
|
- **权限控件**:输入区的权限菜单换成一排分段按钮,档位以宿主的目录为准,别的插件加的档位也在里面;新会话页上显示新会话会用的那一档。
|
|
15
|
-
- **会话数字**:会话统计与 Token
|
|
15
|
+
- **会话数字**:会话统计与 Token 用量随宿主的数据实时更新,在输入卡片下面单独占一行:轮数与步数、输出速度、读入与写回的 tokens、缓存命中率,末尾就是上下文圆环自己;这一行不只是读数——按一下它,圆环那张弹层就打开,里面照旧是宿主自己的上下文行加上这一段会话的数字明细,再按一下收起(悬停开合只归那个圆环);也可以选「收进上下文」,把数字只留在那张弹层里。数字一有变化就逐个字符重新入场(末两位稍慢),各段之间没有分隔符号、只靠间距分开,缓存命中率与圆环占用按各自的无极色阶取色。
|
|
16
|
+
- **峰谷电表**:模型选择器的每一行标出该模型此刻的峰谷:峰价、谷价与限时活动三种状态各有自己的图标,颜色表示贵还是便宜,并跟上距离切换还有多久;悬停读到完整的一条,讲出此刻的判定与切换后的状态。各家供应商按各自时区的作息判定,法定节假日整日算谷价,跨零点与夏令时都按真实时刻计算。
|
|
16
17
|
- **模型选择器**:输入区的模型菜单换成两级卡片:第一级是官方服务与你挑的快捷供应商,每个模型带厂商标志与一句说明,第二级是其余模型。
|
|
17
18
|
- **工作强度**:模型旁边有一个自己的工作强度按钮,点开是一条滑杆;它跟着模型选择器一起开关,因为宿主把工作强度放在自己的模型菜单里。
|
|
18
19
|
- **新会话页的目录与预设菜单**:新会话页上目录与智能体预设的两个菜单画成皮肤的弹层卡片,停在各自的按钮上方,一次只开一张。
|
|
@@ -21,17 +22,18 @@
|
|
|
21
22
|
- **封号彩蛋**:点账号弹层顶上的账号行,会打开一张仿 Claude「账号已暂停」的整页彩蛋;页上的每个按钮和 Esc 都把它关掉,什么都不会真的发生。语言在设置页「通用」里选。
|
|
22
23
|
- **亮暗切换一步到位**:切换亮色与暗色时,边框、阴影与底色在同一帧换好,不会先换颜色、再慢慢补上边框。
|
|
23
24
|
- **进行中 / 已归档**:侧栏的工作区分成「进行中」与「已归档」两档;已归档是一张平铺的列表,每一行可以恢复或删除。
|
|
24
|
-
-
|
|
25
|
-
- **轮次状态行**:进行中、已停止与失败的轮次,状态移到这一轮工作的末尾:用时、输出的 tokens
|
|
25
|
+
- **侧栏搜索**:侧栏里有一个搜索框,打开的面板能找会话(标题与内容)、项目、插件、Skill 与快捷键,用宿主自己的对话框与导航;点开一条内容命中会落到那条消息所在的一轮,而不只是会话开头。「搜索框样式」选它的位置:覆盖品牌(默认)把它放在品牌行、指针移到侧栏时盖过品牌,独立在品牌行下方给它自己一行并一直显示,图标则保留宿主自己的搜索按钮、只把单击接管过来。
|
|
26
|
+
- **轮次状态行**:进行中、已停止与失败的轮次,状态移到这一轮工作的末尾:用时、输出的 tokens,以及模型此刻在做什么(或已停止、处理失败);进行中时,只要对话还在跟随末尾,这一行就停在输入框上方,不断追加的内容不再带着它上下移动,读者自己往回翻看时它照常随内容走。
|
|
26
27
|
- **对话导航**:对话区右侧那列短横线每一轮一条,跟着你读到的位置走。鼠标碰到它,它就展开成一张列表:每一行写着开启这一轮的那条消息,正好落在它那条短横线原来的位置上——你正在读的那一轮还在原处,鼠标下面还是刚才那一轮;滚轮上下翻,点一行页面滑到那一轮,还没加载的早期对话先加载再跳;指针停在列表上时,对话区顶部的对话 / 轨迹标签照常显示。Alt+↑ / Alt+↓ 跳到上一轮或下一轮,连按会一轮一轮接着走;输入框里有草稿时这两个键留给输入框。跳到的那一轮开头会闪一条短横线。同时装着 [dsh-plugin-msg-nav](https://github.com/SherUnlocked-4869/dsh-plugin-msg-nav) 时,Alt+↑ / Alt+↓ 留给它。
|
|
27
28
|
- **聊天区跟随**:思考行收起、工具调用行出现这些结构时刻,贴着底部的读者被交还给系统自己的跟随,内容成片到达时不再停在离底部几十像素的地方;「标准」与「简洁」档里封顶的过程组(思考与工具输出收在一个带滚动条的组体里)同样补到底部。补到底部走的是曲线:零散到达的字收得住尾巴,成片涌进的文字以一段稳速滑过去,再落到末尾。流式输出期间主滚动条的新内容也沿这条曲线推进,不再一帧写到底;输出很快时最新几行会短暂拖在屏幕下缘之外,流一停就滑到位。你自己发出的消息不走这条曲线:宿主把它滚进视野的那一下照旧一步到位。读者自己滚动离开底部之后,插件不再插手,直到他自己回到底部。
|
|
28
|
-
-
|
|
29
|
+
- **自动开合与卷帘门**:模型还在思考时思考行开着,思考停下就收回去;运行中的过程组自动展开,这一段结束再收起。读者自己按过的行或组在当时的阶段里不再被改动。开着的那段思考停在一个几行高的窗口里,上下边缘渐隐,文字每 0.84 秒往上走两行(0.5 秒滑过去),走到最新一行就停住——推理再长也不把整列对话推着往下走;推理一停,窗口撤下,读者打开这一行读到的是完整文本,「动画」为「减弱」时不设这个窗口。过程组的标题改写成这一组装了什么:「执行 2 次思考,调用 1 次工具」,没有的项不写,数字随内容增加逐位滚动,这一段还在进行时整行带着宿主那样的扫光;放不下整句时改用「思考×2 · 工具×1」,位置宽回来再换回整句,控件的可访问名字始终是整句。点开或收起一行(工具卡片、思考行、命令卡片)以及过程组时,高度逐帧变化,下方内容被真的推开或收回;门只走读者看得见的那一段,内容再长也是同一速度,多张卡片的展开体整扇门一起走。
|
|
30
|
+
- **模型正在做什么的那一行**:轮次进行中,对话末尾那一行不再是固定的「深度求索中,用时 N 秒 ···」,而是写出这一轮此刻在做的事:「正在思考」「正在准备工具调用」「正在调用工具」「正在写回答」,后面跟着这一轮已用的时间(用宿主自己的单位)。说法换掉时旧的向上淡出、新的从下方升起(约 0.15 秒,来自 transitions.dev 的「Text states swap」);读不出状态时(模型还没写出任何内容、也没有工具在跑)回到宿主自己的「深度求索中」;模型连续 10 秒没有开口时,计时后面多一枚「暂未响应」。这一行带扫光,宿主的小鲸鱼与读屏播报照旧;「动画」设为「减弱」时说法直接换掉,不做上面那三段。
|
|
29
31
|
- **新文字淡入**:流式回答里新出现的字符先淡后实(约 0.12 秒),并按到达次序略作错开;整段一次到达的内容、几千字的突发与刚被折叠重排过的文字保持本色。
|
|
30
32
|
- **文件变更行**:run_code 程序里派发出去的写入与编辑带上行尾的 `+n -m` 与可展开的改动卡片,路径可点开文件;失败与中断的行保留裁决信息。
|
|
31
33
|
- **聊天气泡动效**:提交消息时输入卡片浮起、一路收成那条气泡:飞行的这一份从第一帧就是气泡的颜色,草稿里的字跟着形状重新排,最后接上真实的消息行——真实气泡在下面先显示出来,飞行的那份淡出,文字逐渐变清晰。
|
|
32
34
|
- **输入框插入符动效**:输入框里的光标由插件自己绘制,移动时滑过去;提问卡片的作答框与排队消息的行内编辑框同样覆盖。设置页的「对话」页有三档:每一格(默认)、只在移动时、关闭。
|
|
33
35
|
- **对话 / 轨迹标签条**:对话区顶部的对话 / 轨迹标签条重画成分段控件,放得下时抬到标题那一行。
|
|
34
36
|
- **会话标题进入顶栏**:桌面端把会话标题与顶栏一行的控件抬进系统标题栏:放得下时标题靠左、控件靠右,放不下的一侧留在原来的行里,标题行的其余内容顺势左移。
|
|
35
|
-
- **设置页**:设置页同时出现在设置对话框(「Claude Style
|
|
37
|
+
- **设置页**:设置页同时出现在设置对话框(「Claude Style」标签页)与插件页,分为通用、外观、输入区、侧栏、对话五个分页;每一项接管宿主界面的功能都有自己的开关,关闭后宿主原来的界面原样回来,不需要刷新页面。设置对话框里这一页的标题行右端是插件仓库的入口。
|
|
36
38
|
|
|
37
39
|
<!-- features:end -->
|