dsh-claude-style 0.12.2 → 0.12.3

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 CHANGED
@@ -4,6 +4,34 @@ All notable changes to `dsh-claude-style` are documented here, newest first.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.12.3] - 2026-10-10
8
+
9
+ [中文](#cn-0.12.3) | [English](#en-0.12.3)
10
+
11
+ <h3 id="cn-0.12.3">体验优化</h3>
12
+
13
+ - 推理回放窗口在宿主两版之间都能用:此前它按较新宿主才写的推理正文槽位找要裁剪的盒子,装在钉住那一版宿主上时找不到,推理期间读者看到的还是整段长文。现在窗口从宿主渲染出来的 Markdown 本身认起,往上取第一个真有盒子的祖先来裁剪,滑动的仍是这段 Markdown。
14
+ - 推理回放窗口不再先按固定高度裁剪再换回整段:此前的窗口一直是四行高,推理写满四行之后文字在窗口里往上滚,推理一停窗口撤下,整段文字接管这一行——窗口的高度与推理最终占的高度不是一回事,切换的那一下整块内容会跳一次。现在窗口跟着推理长高,长到它最终能占的高度(宿主给过程组正文的那个上限,标准档 400px)就停在那个高度上,文字这时才每 0.84 秒往上走两行,走到最新一行停住,上下边缘也在这时才渐隐;推理没长满之前,文字照平时那样一行行往下读,不再被渐隐遮住。
15
+
16
+ ### 问题修复
17
+
18
+ - 0.12.2 起,设置里存着早先「聊天区动画效果」档位(「增强」「重绘」「关闭」)的读者,宿主不再拒绝启动本插件:0.12.2 把这一项改回开关,宿主按开关核对配置,读到早先存下的档位名即判定配置无效,整个插件不启动——插件列表里显示「启动失败」,用量面板、消息搜索、模型说明、随包字体与按需加载的各项功能全部失效,设置里也没有 Claude Style 页。现在这一项同时接受开关值与早先的档位名,存着「增强」「重绘」的照旧开着,存着「关闭」的照旧关着;已经处在「启动失败」的桌面端重启一次即恢复。
19
+ - 手机宽度(390px 及以下)的输入区不再让上下文计量环压住右边的推理等级按钮:此前环按右端定位、等级按钮也按右端排,两者叠在一起,环还常常被挤出卡片;现在这一档为环留出它占的宽度,等级按钮落在它左边,卡片上的三个控件都不再越界。
20
+ - 装了壁纸插件(dsh-plugin-wallpaper-engine)时,配色留在 Claude 也能看到壁纸,文字照样清楚:此前皮肤把不透明画布直接画在窗口、侧栏与对话列上,壁纸被整片盖住;只让开外壳之后,会话正文、表格、侧栏条目与标题栏又直接压在花壁纸上读不清,设置窗口也变成透明。现在壁纸在播时外壳让开,整个窗口铺一层画布色遮罩——浅色是 86% 的象牙白,深色是 82% 的暖黑——侧栏、标题区、会话与底部读数落在同一块底子上;输入卡下面垫一块同宽的画布色托盘,滚过去的正文不会从统计行底下透出来;设置窗口、弹层、卡片与引导层照旧不透明。壁纸关掉后画布原样回来;配色选「跟随宿主」时的共存不变。
21
+ - 经局域网地址或隧道打开的页面(例如手机经 dsh-pocket 访问)不再回到出厂外观:此前这种页面上的主题风格、配色、吉祥物等全部按默认值显示,设置页一改动就报「设置存储服务异常」;现在页面显示 DSH 当前的设置,在运行 DSH 的电脑上改动后不需要刷新就跟上,设置页开头说明改动要在那台电脑上做,控件全部禁用。
22
+
23
+ <h3 id="en-0.12.3">Improvements</h3>
24
+
25
+ - The reasoning's streamed window works across both host versions: it used to look for the reasoning body through a slot only the newer host writes, so on the pinned host it found no box to clip and the reader saw the whole reasoning grow. It now reads the host's rendered Markdown itself and clips the nearest ancestor that has a box, sliding that Markdown inside it.
26
+ - The reasoning's replay window no longer clips to a fixed height and then hands the row back to the whole text: the window stood four lines tall, the text scrolled up inside it once it filled those lines, and the whole reasoning took the row over the moment the reasoning stopped — the window's height and the height the reasoning ended at were two different things, and that switch moved the block. The window now grows with the reasoning and stops at the height it will end up occupying (the host's own cap on a process group's body, 400px in the Standard tier), and only there does the text step up two lines every 0.84 s behind the softened edges, stopping at the newest line. Below that cap the reasoning is read line by line as it is written, with nothing faded.
27
+
28
+ ### Bug Fixes
29
+
30
+ - Since 0.12.2 the host no longer refuses to start the plugin for a reader whose settings still hold an earlier "Chat-area animations" choice ("enhanced", "redraw" or "off"): 0.12.2 turned that preference back into a switch, the host checked the stored config against a switch, judged the earlier choice name invalid and started nothing of the plugin — the plugin list showed it as failed to start, and the usage dashboard, message search, model copy, bundled fonts and every on-demand feature stopped working, with no Claude Style page in Settings. The preference now takes both the switch value and the earlier choice names: "enhanced" and "redraw" stay on, "off" stays off; a desktop already showing the failure recovers after one restart.
31
+ - On a phone-width composer (390px and under) the context meter no longer sits over the reasoning-level button at the row's right end: the meter is positioned from that end and so was the button, so the two overlapped and the meter was often pushed out of the card; the row now reserves the width the meter takes, the button lands before it, and all three controls stay inside the card.
32
+ - With the wallpaper plugin (dsh-plugin-wallpaper-engine) installed, the wallpaper now shows under the Claude palette and the text stays legible: the skin used to paint opaque canvases over the window, the sidebar and the conversation column and covered the wallpaper whole, and once the shell gave way the transcript, tables, sidebar entries and the title bar sat straight on a busy wallpaper while the settings window went transparent. While a wallpaper is up the shell now gives way and one mask in the canvas colour covers the window — ivory at 86% in light, warm black at 82% in dark — so the sidebar, the header, the transcript and the figures at the bottom read on the same ground; a canvas-coloured tray the width of the composer card keeps the transcript scrolling under the dock row from showing through; the settings window, popovers, cards and overlays keep their fill. The canvases return once the wallpaper goes; coexisting under "follow the host" is unchanged.
33
+ - A page opened through a LAN address or a tunnel (a phone reaching DSH through dsh-pocket, for example) no longer falls back to the default look: such a page showed the theme style, colours, mascot and every other setting at their defaults, and any change on the settings page reported that the settings store was unavailable. The page now shows the settings DSH holds and follows changes made on the computer running DSH without a reload, and its settings page opens with a line saying changes are made on that computer, its controls disabled.
34
+
7
35
  ## [0.12.2] - 2026-10-10
8
36
 
9
37
  [中文](#cn-0.12.2) | [English](#en-0.12.2)
@@ -26,7 +26,7 @@ What each feature does and where its switch lives; the five tabs, their rows and
26
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.
27
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.
28
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.
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.
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 that grows with it: the window is as tall as the text until it reaches the height reasoning may take, and there it stays while the text steps up two lines every 0.84 s (half a second of travel) behind a softened edge at each side, stopping at the newest 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
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.
31
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.
32
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.
package/docs/FEATURES.md CHANGED
@@ -26,7 +26,7 @@
26
26
  - **轮次状态行**:进行中、已停止与失败的轮次,状态移到这一轮工作的末尾:用时、输出的 tokens,以及模型此刻在做什么(或已停止、处理失败);进行中时,只要对话还在跟随末尾,这一行就停在输入框上方,不断追加的内容不再带着它上下移动,读者自己往回翻看时它照常随内容走。
27
27
  - **对话导航**:对话区右侧那列短横线每一轮一条,跟着你读到的位置走。鼠标碰到它,它就展开成一张列表:每一行写着开启这一轮的那条消息,正好落在它那条短横线原来的位置上——你正在读的那一轮还在原处,鼠标下面还是刚才那一轮;滚轮上下翻,点一行页面滑到那一轮,还没加载的早期对话先加载再跳;指针停在列表上时,对话区顶部的对话 / 轨迹标签照常显示。Alt+↑ / Alt+↓ 跳到上一轮或下一轮,连按会一轮一轮接着走;输入框里有草稿时这两个键留给输入框。跳到的那一轮开头会闪一条短横线。同时装着 [dsh-plugin-msg-nav](https://github.com/SherUnlocked-4869/dsh-plugin-msg-nav) 时,Alt+↑ / Alt+↓ 留给它。
28
28
  - **聊天区跟随**:思考行收起、工具调用行出现这些结构时刻,贴着底部的读者被交还给系统自己的跟随,内容成片到达时不再停在离底部几十像素的地方;「标准」与「简洁」档里封顶的过程组(思考与工具输出收在一个带滚动条的组体里)同样补到底部。补到底部走的是曲线:零散到达的字收得住尾巴,成片涌进的文字以一段稳速滑过去,再落到末尾。流式输出期间主滚动条的新内容也沿这条曲线推进,不再一帧写到底;输出很快时最新几行会短暂拖在屏幕下缘之外,流一停就滑到位。你自己发出的消息不走这条曲线:宿主把它滚进视野的那一下照旧一步到位。读者自己滚动离开底部之后,插件不再插手,直到他自己回到底部。
29
- - **自动开合与卷帘门**:模型还在思考时思考行开着,思考停下就收回去;运行中的过程组自动展开,这一段结束再收起。读者自己按过的行或组在当时的阶段里不再被改动。开着的那段思考停在一个几行高的窗口里,上下边缘渐隐,文字每 0.84 秒往上走两行(0.5 秒滑过去),走到最新一行就停住——推理再长也不把整列对话推着往下走;推理一停,窗口撤下,读者打开这一行读到的是完整文本,「动画」为「减弱」时不设这个窗口。过程组的标题改写成这一组装了什么:「执行 2 次思考,调用 1 次工具」,没有的项不写,数字随内容增加逐位滚动,这一段还在进行时整行带着宿主那样的扫光;放不下整句时改用「思考×2 · 工具×1」,位置宽回来再换回整句,控件的可访问名字始终是整句。点开或收起一行(工具卡片、思考行、命令卡片)以及过程组时,高度逐帧变化,下方内容被真的推开或收回;门只走读者看得见的那一段,内容再长也是同一速度,多张卡片的展开体整扇门一起走。
29
+ - **自动开合与卷帘门**:模型还在思考时思考行开着,思考停下就收回去;运行中的过程组自动展开,这一段结束再收起。读者自己按过的行或组在当时的阶段里不再被改动。开着的那段思考停在一个跟着它长高的窗口里:窗口先是和文本一样高,长到推理能到的最大高度就停在那里,只有到了这一刻文字才每 0.84 秒往上走两行(0.5 秒滑过去),走到最新一行就停住,上下边缘渐隐,也不再往下推整列对话;推理一停,窗口撤下,读者打开这一行读到的是完整文本,「动画」为「减弱」时不设这个窗口。过程组的标题改写成这一组装了什么:「执行 2 次思考,调用 1 次工具」,没有的项不写,数字随内容增加逐位滚动,这一段还在进行时整行带着宿主那样的扫光;放不下整句时改用「思考×2 · 工具×1」,位置宽回来再换回整句,控件的可访问名字始终是整句。点开或收起一行(工具卡片、思考行、命令卡片)以及过程组时,高度逐帧变化,下方内容被真的推开或收回;门只走读者看得见的那一段,内容再长也是同一速度,多张卡片的展开体整扇门一起走。
30
30
  - **模型正在做什么的那一行**:轮次进行中,对话末尾那一行不再是固定的「深度求索中,用时 N 秒 ···」,而是写出这一轮此刻在做的事:「正在思考」「正在准备工具调用」「正在调用工具」「正在写回答」,后面跟着这一轮已用的时间(用宿主自己的单位)。说法换掉时旧的向上淡出、新的从下方升起(约 0.15 秒,来自 transitions.dev 的「Text states swap」);读不出状态时(模型还没写出任何内容、也没有工具在跑)回到宿主自己的「深度求索中」;模型连续 10 秒没有开口时,计时后面多一枚「暂未响应」。这一行带扫光,宿主的小鲸鱼与读屏播报照旧;「动画」设为「减弱」时说法直接换掉,不做上面那三段。
31
31
  - **新文字淡入**:流式回答里新出现的字符先淡后实(约 0.12 秒),并按到达次序略作错开;整段一次到达的内容、几千字的突发与刚被折叠重排过的文字保持本色。
32
32
  - **文件变更行**:run_code 程序里派发出去的写入与编辑带上行尾的 `+n -m` 与可展开的改动卡片,路径可点开文件;失败与中断的行保留裁决信息。
@@ -18,6 +18,8 @@ Every feature that takes over part of the host's interface has its own switch; t
18
18
 
19
19
  In the settings dialog, this page's heading row ends with a GitHub mark; pressing it opens the plugin's repository in a new tab.
20
20
 
21
+ **Opened from a remote address**: DSH saves settings only from a page opened at a local address such as localhost. A page reached through a LAN address or a tunnel (a phone, another computer) shows the look and the settings DSH holds, and the settings page opens with a line saying so, its controls disabled. Settings changed on the computer running DSH reach the remote page without a reload.
22
+
21
23
  **Peak rate meter**: every row of the model menu carries the rate in force for that model right now. Peak, off-peak and a dated promotion each get their own mark, the colour separates expensive from cheap, and the multiplier is followed by how long it lasts; hovering the badge prints the whole judgement and what it becomes. 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, and a window crossing midnight belongs to the day it starts. A model with no schedule published carries no badge. The schedules are one snapshot in the public [offpeakclock.com](https://offpeakclock.com) catalog: the host half — not the page — fetches it, keeps a copy on disk and refreshes it every 24 hours, and judges by the copy shipped in the package when it cannot be reached.
22
24
 
23
25
  **Sidebar search**: with Sidebar search on, the sidebar carries a search box whose palette finds sessions (titles and content), projects, plugins, Skills and shortcuts; picking a content hit lands the page on the turn holding that message, paging that turn's records in first on a long history. Search box style places it: Cover the brand (the default) puts it in the brand row, standing over the brand while the pointer is anywhere over the sidebar and giving the brand back when the pointer leaves; Standalone gives it a row of its own under the brand row, shown always; Icon draws no box of the plugin's, keeping DSH's own search button where the host draws it and taking only its click over, so pressing it opens this plugin's palette. The content match reads your own messages and the model's answers alone: injected context, the Skill catalog and reasoning never reach the results.
@@ -28,7 +30,7 @@ In the settings dialog, this page's heading row ends with a GitHub mark; pressin
28
30
 
29
31
  **Automatic folding**: 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.
30
32
 
31
- **The reasoning's window**: the open reasoning 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), stopping at the newest line — a long reasoning never pushes the conversation down line by line, and the reader does not have to chase its last line. Once the reasoning stops the window comes off, and the reader who opens the row reads the whole text; with Animation set to Reduced the window is never set and the row lies open as the host drew it.
33
+ **The reasoning's window**: the open reasoning stands in a window that grows with it: the window is as tall as the text until it reaches the height reasoning may take (the host's own cap on a process group's body), and there it stays while the text steps up two lines every 0.84 s (half a second of travel) behind a softened edge at each side, stopping at the newest line. Below that cap nothing is faded and nothing slides — the reader follows the reasoning as it is written — and the conversation is only pushed down over the stretch up to the cap. Once the reasoning stops the window comes off, and the reader who opens the row reads the whole text; with Animation set to Reduced the window is never set and the row lies open as the host drew it.
32
34
 
33
35
  **Counted process headers**: a process group's header says what the group holds, in place of the host's list of activities — "2 thoughts, 1 tool call". Empty figures are left out, each number rolls 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 (a narrow window, a narrow row) falls back to the compact figures, `Thinking×2 · Tools×1`, and takes the sentence back when the room returns; the control's accessible name is the sentence either way.
34
36
 
package/docs/SETTINGS.md CHANGED
@@ -18,6 +18,8 @@
18
18
 
19
19
  设置对话框里这一页的标题行右端有一枚 GitHub 标识,按一下在新的标签页里打开插件仓库。
20
20
 
21
+ **从远程地址打开**:DSH 只保存从 localhost 等本机地址打开的页面所做的设置改动。经局域网地址或隧道打开的页面(手机、另一台电脑)显示的是 DSH 当前的外观与设置,设置页开头有一行说明,控件全部禁用。在运行 DSH 的电脑上改动设置后,远程页面不需要刷新就会跟上。
22
+
21
23
  **峰谷电表**:模型菜单的每一行标出该模型此刻的倍率。峰价、谷价与限时活动三种状态各有自己的图标,颜色区分贵与便宜,倍数后面跟着距离切换还有多久;鼠标停在徽章上,悬停提示写出此刻的完整判定与切换后的状态。判定按各家供应商自己发布的作息表与自己的时区做,工作日窗口之外、周末与法定节假日整日都算谷价,跨零点的窗口归它开始的那一天。没有任何作息表的模型不显示徽章。作息表是公开目录 [offpeakclock.com](https://offpeakclock.com) 里的一份快照,由宿主半边(而不是页面)取一次、在本机留一份缓存并按 24 小时刷新;连不上时按插件包里带的那份判定。
22
24
 
23
25
  **侧栏搜索**:开启后侧栏里多一个搜索框,打开的面板能找会话(标题与内容)、项目、插件、Skill 与快捷键;点开一条内容命中,页面落到那条消息所在的一轮,历史很长时先把这一轮的记录翻页读进来。「搜索框样式」决定它站在哪里:「覆盖品牌」(默认)把它放进品牌行,指针移到侧栏上时它盖过品牌,指针移开再把品牌让回来;「独立」在品牌行下方给它自己一行,一直显示;「图标」不画插件自己的搜索框,让 DSH 自己的搜索按钮留在原处,只把单击接管过来,点它打开的是本插件的面板。内容匹配只认你发出的消息与模型的回答,注入的环境提示、Skill 目录与推理过程都不进结果。
@@ -28,7 +30,7 @@
28
30
 
29
31
  **思考与过程自动开合**:模型还在思考时思考行开着,思考停下就收回去;运行中的过程组自动展开,这一段结束再收起。读者自己按过的行或组在当时的阶段里不再被改动。
30
32
 
31
- **推理回放窗口**:开着的那段思考停在一个四行高的窗口里,上下边缘渐隐,文字每 0.84 秒往上走两行(0.5 秒滑过去),到最新一行就停住——推理再长也不把整列对话推着往下走,读者也不必追着最新一行读。推理一停,窗口撤下,读者打开这一行读到的是完整文本;「动画」设为「减弱」时不设这个窗口,思考行照宿主的样子完整铺开。
33
+ **推理回放窗口**:开着的那段思考停在一个跟着它长高的窗口里:窗口先是和文本一样高,长到推理能到的最大高度(宿主给过程组正文的那个上限)就停在那里,文字从这一刻起每 0.84 秒往上走两行(0.5 秒滑过去),到最新一行就停住,上下边缘渐隐;窗口没长满之前文字不渐隐也不滑动,读者照着平时的样子往下读,整列对话也只在长到上限这一段被推开。推理一停,窗口撤下,读者打开这一行读到的是完整文本;「动画」设为「减弱」时不设这个窗口,思考行照宿主的样子完整铺开。
32
34
 
33
35
  **过程组标题上的计数**:过程组的标题不再只写「执行了命令,已读取文件,已调用工具等」,而是写这一组装了什么,例如「执行 2 次思考,调用 1 次工具」;没有的项不写,数字随内容增加逐位滚动,这一段还在进行时整行带着与宿主同样的扫光。这一行放不下整句时(窗口窄、过程组所在的行窄)改用简洁写法「思考×2 · 工具×1」,位置宽回来再换回整句;控件的可访问名字始终是整句。
34
36
 
@@ -7,7 +7,7 @@
7
7
  ## 决定
8
8
 
9
9
  - 「配色」与「字体」两项偏好各有 `claude`(默认)与 `host` 两档,写成 `<body data-dsh-claude-palette>` 与 `<body data-dsh-claude-typeface>`。
10
- - 每条写宿主令牌的规则都挂在 Claude 一档上:写 `--dsw-` 颜色令牌的规则挂配色门,写 `--dsw-font-*` 的规则挂字体门,漏挂即构建失败。把皮肤的画布刷到宿主框架上的规则(`<html>`、`<body>`、`#root`、侧栏、对话列)同样挂在 Claude 一档上。
10
+ - 每条写宿主令牌的规则都挂在 Claude 一档上:写 `--dsw-` 颜色令牌的规则挂配色门,写 `--dsw-font-*` 的规则挂字体门,漏挂即构建失败。把皮肤的画布刷到宿主框架上的规则(`<html>`、`<body>`、`#root`、侧栏、对话列)同样挂在 Claude 一档上。壁纸插件在播壁纸时那几处外壳不画,整窗铺一层画布色遮罩,见 D61。
11
11
  - 皮肤自己的节点只读私有令牌(`--dsh-claude-*`)与宿主令牌。宿主一档把每个私有令牌改成宿主令牌的别名(对照表在 `docs/STYLE.md` 的「Two palettes」),Claude 一档定义的每个私有令牌在宿主一档都必须有别名。
12
12
  - 卡片类的面(弹层、账号弹层、搜索面板)用宿主的浮层令牌 `--dsw-alias-bg-overlay`,宿主一档下给共用弹层外壳加背景模糊(D16)。皮肤自造的字体令牌是私有的 `--dsh-claude-font-serif` / `-prose` / `-code` / `-brand`,宿主一档回落到宿主的 `--dsw-font-family` 与 `--ds-font-family-code`。
13
13
  - 推理强度滑杆顶档的紫色、封号彩蛋页复刻的 Claude 页面在两档下都保留原色;半透明的中性悬停色与用量面板的数据配色写成字面值。
@@ -11,10 +11,11 @@
11
11
  - 端到端测试(Playwright)跑在装配好的宿主上:
12
12
  - `packages/testing/dsh-web.cjs` 起一个临时实例:`$DSH_HOME` 在 `.debug/` 下,本仓库以链接装进它的 web 配置,启动后交出带令牌的地址;通道自己的补丁走 `--patch` 覆盖层,profile 的用户层留给宿主;`resetState` 清掉会话与侧栏缓存,断言页面的场景因此从空会话列表开始。实例的标准输入是一条只由启动进程持有的管道,`packages/testing/lifeline.cjs` 经 `NODE_OPTIONS` 预加载进宿主,读到管道关闭就结束宿主:启动进程无论正常退出、抛出未捕获的错误、被 Ctrl+C 或 `taskkill /F` 终止,实例都随它结束,不会留在后台。
13
13
  - `packages/testing/mock-llm.cjs` 是脚本化的模型服务,按 Messages 协议回答宿主路由,脚本按请求顺序交付;只有模型是脚本化的,agent 循环、会话、客户端各层与渲染都是发行版宿主。
14
- - `packages/testing/e2e.cjs` 的每个场景各起一套实例,断言各自的东西:`conversation` 读者的消息成行、脚本回答的 Markdown 与思考过程归组;`narrow` 以 390×844 的手机窗口打开,断言输入框下沿那一行放得下权限档位、模型、推理等级与上下文圆环(权限收起下三角、两个选择器按窄屏上限截断、圆环不显示数字、四者都在卡片内且圆环不与旁边重叠);`statsPosition` 用补丁层把「对话统计信息位置」存成「独立成行」,断言这个值经宿主的设置命名空间到达页面、宿主的统计行与计量环在卡片下面排成自己的一行、皮肤自己的数字块没有建起来(`packages/testing/stats-position.cjs`:存档值与宿主设置表单这一段路,替代的宿主页面证明不了);`statsOverlay` 在「收进上下文」那一档下把计量环所在的 dock 与输入行两个盒子逐边对起来,把卡片在那一行下方留的空隙分别改成 0 与 16px 断言 dock 跟着那一行走、不停在写死的 4px 上,再把触发按钮在停放节点里左移 14px 断言行尾留出的宽度按两个盒子的并集算(`packages/testing/stats-overlay.cjs`;两个场景由 `stats-position.cjs` 一次导出,场景表所在那一份停在停止线上,长度不再增长);`tool` 工具调用单独成行并带调用编号、结果之后的回答渲染出来;`send` 发送起飞期间替身离开页面、真行不可见、读者的字每一帧都看得见、替身带走了输入卡片的字体;`scroll` 逐帧记录滚动位置与内容高度,断言没有一帧在内容没有变短时倒退、没有一帧在内容没有增长时把尾部留在视野之外;`readerScroll` 在轮次进行中自己滚一次滚轮,断言状态行的固定只在跟随自己移动位置时钉住、读者往回翻看时该行随内容走而不浮在内容上,它自己逐帧采样(`packages/testing/reader-scroll.cjs`:`packages/testing/e2e.cjs` 已到停止线,新场景各成一个模块,场景表仍在那份里);`processSummary` 让脚本化的模型先沉默过 10 秒再开口(`packages/testing/mock-llm.cjs` 的 `holdMs`),断言运行中那一行换成皮肤的等待行、计时用宿主的单位、过 10 秒挂出「暂未响应」、模型一开口就撤下,并在轮次结束后按每个过程组标题上的计数核对它收住的东西(`packages/testing/process-summary.cjs`);`importance` 走过首页、对话、草稿、流式输出、各个弹层与菜单、附件、暗色与品牌和配色的切换以及每条 `:hover` 规则的悬停,逐条判定皮肤的 `!important` 是否需要,一条多余即失败;设置 `DSH_IMPORTANCE_REFERENCE` 时每个状态还与一张旧样式表逐元素比对(D51);`shots` 亮暗两套截图。
14
+ - 端到端通道按职责分成几份:`packages/testing/e2e.cjs` 是运行器,为每个场景起一套实例、发出提示词、在轮次进行中逐帧采样、失败时写下现场;`packages/testing/scenarios.cjs` 是场景表,自带读取逻辑的场景各成一个模块挂进表里;`packages/testing/lane.cjs` 放运行器与场景共用的页面标记与断言形状;`packages/testing/contract-probe.cjs` 放契约表的逐条核对。场景可以给宿主的命令行与浏览器各加参数(`hostArgs`、`browserArgs`)。
15
+ - 每个场景各起一套实例,断言各自的东西:`conversation` 读者的消息成行、脚本回答的 Markdown 与思考过程归组;`narrow` 以 390×844 的手机窗口打开,断言输入框下沿那一行放得下权限档位、模型、推理等级与上下文圆环(权限收起下三角、两个选择器按窄屏上限截断、圆环不显示数字、四者都在卡片内且圆环不与旁边重叠);`statsPosition` 用补丁层把「对话统计信息位置」存成「独立成行」,断言这个值经宿主的设置命名空间到达页面、宿主的统计行与计量环在卡片下面排成自己的一行、皮肤自己的数字块没有建起来(`packages/testing/stats-position.cjs`:存档值与宿主设置表单这一段路,替代的宿主页面证明不了);`statsOverlay` 在「收进上下文」那一档下把计量环所在的 dock 与输入行两个盒子逐边对起来,把卡片在那一行下方留的空隙分别改成 0 与 16px 断言 dock 跟着那一行走、不停在写死的 4px 上,再把触发按钮在停放节点里左移 14px 断言行尾留出的宽度按两个盒子的并集算(`packages/testing/stats-overlay.cjs`;两个场景由 `stats-position.cjs` 一次导出);`tool` 工具调用单独成行并带调用编号、结果之后的回答渲染出来;`send` 发送起飞期间替身离开页面、真行不可见、读者的字每一帧都看得见、替身带走了输入卡片的字体;`scroll` 逐帧记录滚动位置与内容高度,断言没有一帧在内容没有变短时倒退、没有一帧在内容没有增长时把尾部留在视野之外;`readerScroll` 在轮次进行中自己滚一次滚轮,断言状态行的固定只在跟随自己移动位置时钉住、读者往回翻看时该行随内容走而不浮在内容上,它自己逐帧采样(`packages/testing/reader-scroll.cjs`);`processSummary` 让脚本化的模型先沉默过 10 秒再开口(`packages/testing/mock-llm.cjs` 的 `holdMs`),断言运行中那一行换成皮肤的等待行、计时用宿主的单位、过 10 秒挂出「暂未响应」、模型一开口就撤下,并在轮次结束后按每个过程组标题上的计数核对它收住的东西(`packages/testing/process-summary.cjs`);`importance` 走过首页、对话、草稿、流式输出、各个弹层与菜单、附件、暗色与品牌和配色的切换以及每条 `:hover` 规则的悬停,逐条判定皮肤的 `!important` 是否需要,一条多余即失败;设置 `DSH_IMPORTANCE_REFERENCE` 时每个状态还与一张旧样式表逐元素比对(D51);`remoteSettings` 让宿主多信任一个名字 `remote.test`、浏览器把它解析到本机,同一实例分别以 loopback 地址与这个名字打开,在本机页面改主题风格,断言远程页面不刷新就跟上、刷新后读到的仍是宿主的值、它的设置页开头有说明行且控件全部禁用、本机设置页照常可写,结束前把主题风格写回原值,因为设置文档在各场景共用的临时目录里(`packages/testing/remote-settings.cjs`,D60);`shots` 亮暗两套截图。
15
16
  - 截图沿用写盘前的隐私替换与泄漏扫描(`scripts/shared/privacy.cjs`,与 `scripts/shoot.cjs` 共用),两套明暗各写一张到本次运行的输出目录供人查看;仓库不存比对基线,画面是否变样由用户看过再定。
16
17
  - 持续集成(`.github/workflows/ci.yml`):构建检查、单元测试与完整冒烟在 Linux 上跑;完整冒烟另在 Windows 上跑一遍,读者的桌面端在 Windows,宿主半边在那里读会话目录、盘符路径与文件时间;端到端的行为场景与截图捕获在 Linux 上跑,宿主版本固定;`contract` 场景另对宿主最新的预发布版(npm 的 `alpha` 标签)跑一遍,宿主改动了皮肤读的契约时先在这里报出,只作预警,不挡合并。每个任务都有时限;工作流用到的 Actions 由 Dependabot 每周提更新(`.github/dependabot.yml`)。
17
- - `.debug/` 里有价值的探针已升级为有维护的工具:逐帧滚动记录并入 `packages/testing/e2e.cjs` 的 `scroll` 场景,发送过程录制并入 `send` 场景的逐帧采样,替身采样并入同一份采样;其余草稿在会话结束时删除。
18
+ - `.debug/` 里有价值的探针已升级为有维护的工具:逐帧滚动记录并入 `scroll` 场景,发送过程录制并入 `send` 场景的逐帧采样,替身采样并入同一份采样;其余草稿在会话结束时删除。
18
19
 
19
20
  ## 理由
20
21
 
@@ -7,7 +7,7 @@
7
7
  ## 决定
8
8
 
9
9
  - `html[data-dsh-skin]` 回答「这一页现在归谁」:皮肤中心在皮肤作画时盖上它(值是皮肤 id),它在即让路。`packages/client/src/shared/visual-owner.ts` 读它,`apply()` 开头同步读一次,之后无论启动时是否让路,都由观察总线上的一个订阅(D40)跟随真实翻转;判定每次重算,不跨翻转缓存。
10
- - 壁纸插件不是属主:壁纸画在外壳背后,本主题与它共存,配色选「跟随宿主」时弹层带上它的玻璃效果(D30)。
10
+ - 壁纸插件不是属主:壁纸画在外壳背后,本主题与它共存,配色选「跟随宿主」时弹层带上它的玻璃效果(D30);配色留 Claude 时外壳画布不画、整窗铺一层画布色遮罩(D61)。
11
11
  - 让路时:保留 `setHostContext`、`adoptSettingsForm` 与 `ctx.inject(['configForms'])`、`loadModelCopy` / `loadUsername` / `loadHdsl`、`adoptPrefs`,只安装 `settings` 一个功能;不盖 `data-dsh-claude-style`、不挂样式表、不跑调度器。让路期间 `adoptPrefs` 只更新偏好值、不往 body 写属性:表单随时可能应答,设置页的块也可能在让路之后才到(D39)。模块作用域的 `parkForeignSheets()` 照常运行(兄弟包的样式表不能等本皮肤)。
12
12
  - 抢回页面时(`own()`):盖上 `data-dsh-claude-style` 与 `data-dsh-claude-style-handoff`、重新 `adoptPrefs`、挂样式表、装齐功能、装调度器;已在装的功能不重复安装。交还页面时(`release(keep)`):跑完每个功能的 teardown、撤掉本包在 body 上的全部属性与样式表,`keep` 名单里的功能留下。
13
13
  - 宿主运行时收到 teardown 仍是唯一的一次性拆卸器:`teardown()` 先停归属观察,再 `release()`,再停对话插件观察与偏好绑定。
@@ -0,0 +1,31 @@
1
+ # D60. 设置读写走官方 Config 表单,非 loopback 页面只读设置文档
2
+
3
+ - **状态**:已实施
4
+ - **分组**:宿主边界
5
+ - **关联**:取代 D10;D11、D12、D29、D46
6
+
7
+ ## 决定
8
+
9
+ - 浏览器半边写设置只有 `configForms` 一条传输:绑定宿主实际提供的命名空间(候选依次为加载器入口 id、包名、`cordis.patch.yml` 插入的 id,以宿主的命名空间目录为准),读写都经表单控制器(值、写队列、修订号栅栏)。命名空间晚到时订阅目录,到达即绑定。
10
+ - 宿主对非 loopback 页面(局域网地址、隧道域名,由浏览器侧的 `location.hostname` 判定)只给内存态的表单:命名空间目录恒为 `unavailable`,从不读取设置文档,写入一律不落盘。皮肤以目录的 `unavailable` 认出这种页面,改用表单服务自己所依赖的读取 `remote.settings.describe()` 取自己命名空间的合并值,在 `settings/document-updated` 事件与 `connection/reset` 之后重读;宿主拒绝这次读取时抛出。
11
+ - 这种页面上皮肤的设置页只读:开头一行说明改动要在运行 DSH 的电脑上做,所有行放进一个禁用的 `fieldset`,标签页仍可切换浏览。皮肤不经 `remote.settings.mutate` 绕过宿主替远程页面保存设置的限制。
12
+ - 宿主半边导出 `Config` 作为 schema,只有 `.volatile()` 字段进表单。schemastery 以顶层 await 加守卫导入,解析不到时 `Config` 为 `undefined`、皮肤照常加载——这是「导入不包 try/catch」规定的唯一例外。
13
+ - 设置席位注册为 `plugins.bundle.config`(键为包名);宿主没有 `configForms` 时才注册整页的 `settings.section`。
14
+ - 偏好字段只有一份声明:`packages/contracts/src/prefs.ts` 的 `PREFS_DEFAULT`。宿主半边 `packages/host/src/settings.ts` 用它生成 `Config`(宿主构建把 contracts 的值内联进产物,contracts 不进 npm 包);浏览器半边的默认值与取值集合给出表单答复之前的初值与读到值时的规整。
15
+ - 字段类型按默认值的类型取纯 `string` / `boolean` / 字符串数组:取值集合在消费处判定,浏览器半边读到什么都做规整。存下的值可能还是早先类型的偏好,字段同时接受 `boolean` 与 `string`:`autoPopover` 早先是开关、后来长成多档,`chatAnimations` 早先是多档、后来又回到开关。宿主在启动插件之前用 `Config` 校验配置行,类型不符即校验失败,整个包都不启动——私有路由、设置表单与浏览器半边一起缺席;浏览器半边把两种类型都读成对应的取值。偏好的默认值换类型时,这个键同一次改动里加进这份名单,冒烟的宿主半边用早先类型的值校验一遍 `Config`。
16
+ - 偏好只存在宿主的设置文档里:早先存进浏览器本地存储的昵称与封号页语言,在表单第一次带值时写进表单,表单持有自己的值后删掉本地那份;只读页面不做这一步。
17
+
18
+ ## 理由
19
+
20
+ - 官方表单自带写队列与修订号,皮肤不重复实现一套同步。
21
+ - 皮肤的外观由偏好决定:远程页面拿不到设置文档时整套外观回到出厂默认,与宿主上的设定不符;读取本身宿主照常应答,只读不越过宿主不替远程页面保存设置的边界。
22
+
23
+ ## 代价
24
+
25
+ - `Config` 的顶层 await 让宿主半边晚一步求值(加载器本就等待导入,无实际影响)。
26
+ - 远程页面上的设置只能看不能改。
27
+
28
+ ## 重审条件
29
+
30
+ - 宿主提供不依赖 `Config` 的设置注册方式,或 `configForms` 契约再变。
31
+ - 宿主的表单服务对已认证的远程页面也读写设置文档:那时目录不再是 `unavailable`,皮肤回到表单这一条路,这条决策的只读部分随之删去。
@@ -0,0 +1,28 @@
1
+ # D61. 壁纸插件在播壁纸时,Claude 配色在整个窗口铺一层底色遮罩
2
+
3
+ - **状态**:已实施
4
+ - **分组**:宿主边界
5
+ - **关联**:取代 D59;D3、D30、D31、D49、D51
6
+
7
+ ## 决定
8
+
9
+ - 壁纸插件(`dsh-plugin-wallpaper-engine`)在 `body` 上挂 `data-we-wallpaper`,壁纸本体与它的暗化层、特效层是 `body` 的子节点,分别在 `z-index: -2` 与 `-1`;这个标记在即「有壁纸正在显示」。本插件只读这一个属性,它是别的插件的标记,不进 D3 的宿主契约表,读法写在用它的那几张表里。
10
+ - 标记在且配色为 Claude 时,`theme/wallpaper.css`(样式表顺序最后)做四件事:外壳让开——`body`、窗口框架、中栏、右栏、会话根节点(含会话滚动区的 `[data-phase]`)与侧栏不画底色,侧栏元素自己的 `--dsw-specific-sidebar-fill` 清成透明;一层遮罩——`body::after` 固定铺满窗口、`z-index: -1`,按文档顺序落在壁纸插件的各层之上、外壳之下,颜色是画布色,浅色 86% 不透明、深色 82%;输入区——座位本身、座位上方与会话顶部的两道渐隐不画,座位里垫一块与输入卡同宽的画布色托盘(卡片顶边以下到窗口底边),统计行与模型行落在它上面,滚过去的会话正文不会从卡片下方透出来;`tokens.css`、`typography.css`、`chrome.css` 里把画布刷到外壳上的规则挂 `:not([data-we-wallpaper])`,原有的配色门不动(D30)。
11
+ - `--dsw-alias-bg-base` 在 Claude 一档保持画布色,壁纸插件自己的清空被本插件的令牌块盖过:宿主用这个令牌画的面(设置窗口、各类浮层与卡片、引导层)照旧不透明。皮肤自己的面(弹层、账号弹层、搜索面板)同样不透明。
12
+ - 配色选「跟随宿主」时不铺遮罩,外壳与各面交给宿主与壁纸插件(D30)。
13
+
14
+ ## 理由
15
+
16
+ - 一层均匀的遮罩让侧栏、标题区、会话与底部读数落在同一块底子上,对比度处处一致,壁纸作为整窗的淡色背景透出。
17
+ - 让位按元素列出,基础令牌留在画布色:宿主以后新增的面默认可读,需要透出壁纸的只有已知的那几块外壳。
18
+ - 输入区的托盘与卡片同色同宽,挡住滚到下面的正文,又不在整栏宽度上多出一条更亮的带子。
19
+
20
+ ## 代价
21
+
22
+ - 壁纸只以约 14%(深色约 18%)的强度透出,遮罩比例写死,不随壁纸插件的暗化或玻璃滑条变化。
23
+ - 外壳让位按宿主的类名子串与属性列出;宿主给外壳换了元素或令牌,这几条要跟着改,失配由冒烟的 `host-palette` 用例发现。这个外来属性不在构建的属性检查之内(D51 只管 `data-dsh-*`)。
24
+
25
+ ## 重审条件
26
+
27
+ - 宿主提供主题层级或令牌分层机制时,外壳的让位改由层来声明(与 D30 同一条件)。
28
+ - 壁纸插件提供公开的遮罩或可读性契约(例如由它画遮罩、本插件只给颜色)时,改用那份契约。
@@ -25,7 +25,6 @@
25
25
  | 编号 | 决策 | 状态 |
26
26
  | --- | --- | --- |
27
27
  | [D3](D3-host-selectors.md) | 宿主选择器纪律 | 已实施 |
28
- | [D10](D10-settings-transport.md) | 设置传输只走官方 Config 表单 | 已实施 |
29
28
  | [D11](D11-private-routes.md) | 私有路由借宿主的请求栅栏;外来字符串只以文本上屏 | 已实施 |
30
29
  | [D19](D19-host-contracts.md) | 宿主契约与构建编号 | 已实施 |
31
30
  | [D28](D28-desktop-band.md) | 桌面标题带只在一处读取 | 已实施 |
@@ -34,6 +33,8 @@
34
33
  | [D33](D33-stylesheet-ownership.md) | 皮肤样式表带上本包自己的归属标记,兄弟包的样式表不认领 | 已实施 |
35
34
  | [D43](D43-overlay-and-upstream.md) | 覆盖层定位与等待扩展点 | 已实施 |
36
35
  | [D44](D44-contract-module.md) | 宿主契约模块与契约测试 | 已实施 |
36
+ | [D60](D60-settings-transport.md) | 设置读写走官方 Config 表单,非 loopback 页面只读设置文档 | 已实施 |
37
+ | [D61](D61-wallpaper-under-one-mask.md) | 壁纸插件在播壁纸时,Claude 配色在整个窗口铺一层底色遮罩 | 已实施 |
37
38
 
38
39
  ## 运行时
39
40
 
@@ -81,4 +82,4 @@
81
82
 
82
83
  ## 作废的编号
83
84
 
84
- D1(由 D36 取代)、D2(由 D43 取代)、D6(由 D40 取代)、D8(由 D46 取代)、D13(由 D42 取代)、D18(由 D46 取代)、D37(由 D51 取代)、D55(由 D58 取代)、D56(由 D58 取代)、D57(由 D58 取代)。
85
+ D1(由 D36 取代)、D2(由 D43 取代)、D6(由 D40 取代)、D8(由 D46 取代)、D10(由 D60 取代)、D13(由 D42 取代)、D18(由 D46 取代)、D37(由 D51 取代)、D55(由 D58 取代)、D56(由 D58 取代)、D57(由 D58 取代)、D59(由 D61 取代)。
Binary file
@@ -151,15 +151,15 @@
151
151
  "encoding": "br",
152
152
  "bytes": 109821
153
153
  },
154
- "b6d2c6e0d409.js": {
154
+ "b7b1e2f247e3.js": {
155
155
  "type": "text/javascript; charset=utf-8",
156
156
  "encoding": "br",
157
- "bytes": 19082
157
+ "bytes": 19464
158
158
  },
159
- "01a8f6d0dede.js.map": {
159
+ "2fb22164cb7e.js.map": {
160
160
  "type": "application/json; charset=utf-8",
161
161
  "encoding": "br",
162
- "bytes": 62537
162
+ "bytes": 63327
163
163
  }
164
164
  }
165
165
  }