dsh-claude-style 0.10.5 → 0.11.0
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 +108 -0
- package/README.en.md +22 -4
- package/README.md +22 -4
- package/docs/STYLE.md +4 -4
- package/docs/decisions/D10-settings-transport.md +25 -0
- package/docs/decisions/D11-private-routes.md +26 -0
- package/docs/decisions/D12-fail-fast.md +36 -0
- package/docs/decisions/D14-account-surface.md +25 -0
- package/docs/decisions/D15-hdsl-contract.md +23 -0
- package/docs/decisions/D16-popover-baseline.md +22 -0
- package/docs/decisions/D17-permission-presets.md +22 -0
- package/docs/decisions/D19-host-contracts.md +26 -0
- package/docs/decisions/D20-sliding-pill.md +25 -0
- package/docs/decisions/D21-archived-list.md +23 -0
- package/docs/decisions/D22-search-panel.md +28 -0
- package/docs/decisions/D23-turn-status.md +26 -0
- package/docs/decisions/D24-mascot.md +34 -0
- package/docs/decisions/D25-ban-screen-titlebar.md +23 -0
- package/docs/decisions/D26-motion-preference.md +22 -0
- package/docs/decisions/D27-context-stats.md +26 -0
- package/docs/decisions/D28-desktop-band.md +22 -0
- package/docs/decisions/D29-feature-switches.md +24 -0
- package/docs/decisions/D3-host-selectors.md +27 -0
- package/docs/decisions/D30-palette-and-typeface.md +25 -0
- package/docs/decisions/D31-windows-titlebar.md +23 -0
- package/docs/decisions/D32-chat-interactions.md +32 -0
- package/docs/decisions/D33-stylesheet-ownership.md +25 -0
- package/docs/decisions/D34-turn-navigator.md +28 -0
- package/docs/decisions/D35-selection-scope.md +22 -0
- package/docs/decisions/D36-modules-and-bundling.md +34 -0
- package/docs/decisions/D37-css-toolchain.md +27 -0
- package/docs/decisions/D38-assets.md +28 -0
- package/docs/decisions/D39-on-demand-loading.md +22 -0
- package/docs/decisions/D4-composer-gate.md +22 -0
- package/docs/decisions/D40-observation-bus.md +34 -0
- package/docs/decisions/D41-scroll-owner.md +24 -0
- package/docs/decisions/D42-feature-manifest.md +25 -0
- package/docs/decisions/D43-overlay-and-upstream.md +30 -0
- package/docs/decisions/D44-contract-module.md +25 -0
- package/docs/decisions/D45-testing.md +27 -0
- package/docs/decisions/D46-monorepo.md +34 -0
- package/docs/decisions/D47-build-output.md +23 -0
- package/docs/decisions/D48-documentation.md +27 -0
- package/docs/decisions/D5-model-copy.md +26 -0
- package/docs/decisions/D7-one-package.md +22 -0
- package/docs/decisions/D9-style-performance.md +23 -0
- package/docs/decisions/README.md +76 -0
- package/host/harness-home.js +21 -0
- package/host/hdsl.js +3 -14
- package/host/index.js +5 -12
- package/host/routes.js +234 -313
- package/host/search.js +1 -1
- package/host/settings.js +61 -174
- package/host/usage.js +39 -68
- package/lib/client.js +19501 -12216
- package/lib/model-descriptions.json +40 -0
- package/package.json +2 -2
- package/docs/architecture.md +0 -315
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,114 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to `dsh-claude-style` are documented here, newest first.
|
|
4
4
|
|
|
5
|
+
## [0.11.0] - 2026-10-06
|
|
6
|
+
|
|
7
|
+
[中文](#cn-0.11.0) | [English](#en-0.11.0)
|
|
8
|
+
|
|
9
|
+
<h3 id="cn-0.11.0">新增功能</h3>
|
|
10
|
+
|
|
11
|
+
- **对话导航**:对话区右侧的轮次短横线改由插件绘制,间距与展开后的列表行高一致。鼠标碰到它立刻展开成一张列表,每一轮一行,写着开启这一轮的那条消息,每一行正好落在它那条短横线原来的位置上,正在读的那一轮保持原位;滚轮上下翻,点一行页面滑到那一轮(只滑最后一小段,约三分之一秒),还没加载的早期对话先加载再跳;指针停在列表上时,对话区顶部的对话 / 轨迹标签照常显示。Alt+↑ / Alt+↓ 跳到上一轮或下一轮,连按会接着走,输入框里有草稿时不接管;跳到的那一轮开头闪一条短横线。同时装着 dsh-plugin-msg-nav 时 Alt+↑ / Alt+↓ 留给它。设置页「对话」页新增「对话导航」开关,默认开启,关闭后恢复系统原来的轮次短横线与悬停预览。
|
|
12
|
+
|
|
13
|
+
### 体验优化
|
|
14
|
+
|
|
15
|
+
- **聊天区跟随的滑动更平稳**:流式输出时每来一行,画面滑完都会多跳一下(约 1.7 像素);代码块这样的大块内容到达时,滚动一下子就冲到最快。现在滑动从静止平稳起步、停下时不再跳动;最新一行被压在屏幕下缘的时间按回放测算少了约四分之一到三分之一(一行一行输出时 533 → 400 毫秒,快速输出时 1350 → 1000 毫秒)。超过 1200 像素的距离不再一帧跳过去,而是先到离目标 1200 像素处,再滑完剩下的一段。
|
|
16
|
+
- **聊天气泡动效落地更平滑**:飞行结束的那一刻,气泡里的文字会瞬间变深、像换了字重。现在落地时真实气泡在飞行的气泡下面先显示出来,飞行的那份在 0.16 秒内淡出,文字是逐渐变清晰的;上浮的终点也正好落在气泡上,不再差出一两个像素。
|
|
17
|
+
|
|
18
|
+
### 问题修复
|
|
19
|
+
|
|
20
|
+
- **流式输出时画面不再忽而一下子顶上去、忽而往回掉**:正文变长时,聊天区有时一下子跳到最底,有时底部的状态行先往下掉一截再滑回来——宿主自己的贴底与插件的平滑跟随在同一帧里先后改写滚动位置,宿主那一下总是后写、直接画了出来,下一批文字到达时插件又把已经显示出来的位置拉回去。现在宿主的贴底在画出来之前就交给平滑跟随,正文变长时画面只会平稳上移;在本地一段带停顿的模拟输出里,停顿后头几行直接跳到最底的情况从每段都有变为没有,位置往回退的帧数为零。切换会话之后同样如此。
|
|
21
|
+
- **聊天气泡飞行时的底色跟着变成气泡的颜色**:输入框的底色画在卡片里层时(首页的输入框就是这样),飞起来的气泡一路保持输入卡片的白底,接上真实气泡的那一刻才突然换成气泡的颜色,工具栏那一行背后还会先露出一条气泡色。现在底色从输入框所在的那一块开始,随形状一起渐变成气泡的颜色,到终点时正好铺满整个气泡。
|
|
22
|
+
- **切换会话与新建会话不再卡住**:装着本插件时,点开另一条会话或新建会话,页面会僵住一到两秒,长对话里尤其明显。原因是选中文字的配色作用于整个页面,浏览器每一轮样式重算都要为页面上每个元素算一次选中样式;现在这套配色只作用于对话正文与输入框里承载文字的块级元素(段落、列表、标题、引用、代码)。实测单次切换的样式重算从 0.9–2.4 秒降到 0.11–0.51 秒(未装插件时约 0.05 秒);侧栏、设置页与弹层里的选中配色回到宿主默认。
|
|
23
|
+
- **装卸或更新别的插件之后,本插件的界面不再失去样式**:此前别的插件加载、重新加载或更新之后,本插件的整个界面有时会变回宿主原本的样子,插件的标记却还留在页面上。现在无论别的插件如何装卸,本插件的外观都保持不变。
|
|
24
|
+
- **同时装着的别的插件不再丢失样式**:一个插件自己挂上去、没有归属标记的样式表,会被下一个加载的插件记在自己名下,并在那个插件重新加载时被删掉——同时装着的表情包插件就曾这样整份失去样式,只能刷新页面恢复。现在这类样式表在本插件看到它的当时就被标记为无主,之后任何插件的加载、重新加载与更新都不再碰它。
|
|
25
|
+
- **小鲸鱼帧图顶端的灰线消失**:Deepy 演某几段动画时,帧图最上方有时会闪出一条约 1 像素高的灰线,站在哪里、窗口多大不同就时有时无。现在任何站位、任何一段动画都不再出现,小鲸鱼的样貌与动作不变。
|
|
26
|
+
- **子智能体工作室的节点详情小窗不再把会话统计与 Token 用量带走**:打开工作室、点开一个子智能体的节点详情小窗之后,输入区上下文面板里的「会话统计」与「Token 用量」两段画到了那个小窗下面,没有底色地压在对话内容上,上下文面板只剩宿主自己的三行。现在两段仍留在上下文面板里。
|
|
27
|
+
|
|
28
|
+
<h3 id="en-0.11.0">New Features</h3>
|
|
29
|
+
|
|
30
|
+
- **Conversation navigator**: the turn marks at the conversation's right edge are drawn by the plugin, spaced at the height of the list they open into. Reaching them with the pointer opens that list at once, one row per turn carrying the message that started it, each row exactly where its mark was and the turn being read left in place; the wheel scrolls the list and a click glides the page to the turn (only the last stretch, about a third of a second), 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 keep stepping when repeated, leaving the keys alone while the composer holds a draft; the turn you land on flashes a short line over its start. With dsh-plugin-msg-nav installed too, Alt+↑ / Alt+↓ stay with it. A Conversation navigator switch on the settings page's Conversation tab, on by default; off restores the host's own turn marks and hover preview.
|
|
31
|
+
|
|
32
|
+
### Improvements
|
|
33
|
+
|
|
34
|
+
- **The chat-area follow glides more evenly**: every streamed line ended its glide with an extra hop of about 1.7px, and a large block such as a code block set the scroll off at full speed at once. The glide now builds up from rest and comes to a stop without a hop, and the newest line spends a quarter to a third less time under the bottom edge on a replayed stream (line-by-line output 533 → 400 ms, fast output 1350 → 1000 ms). A distance past 1200px is no longer covered in one frame: the position goes to 1200px short of the target and glides the rest.
|
|
35
|
+
- **The send flight lands more smoothly**: the moment the flight ended, the bubble's words darkened at once, as if their weight had changed. The real bubble now shows underneath the flying one as it lands, and the flying copy fades out over 0.16 s, so the words sharpen into place; the rise also ends exactly on the bubble rather than a pixel or two past it.
|
|
36
|
+
|
|
37
|
+
### Bug Fixes
|
|
38
|
+
|
|
39
|
+
- **Streaming no longer jerks the chat area up or drops it back**: as the reply grew, the chat area sometimes jumped straight to the end and sometimes the status line at the bottom dropped a step before gliding back — the host's own pin to the end and the plugin's glide both wrote the scroll position in the same frame, the host's write always came last and was painted, and the next piece of text had the glide pull an already painted position back. The host's pin is now handed to the glide before it paints, so a growing reply only ever moves the view up smoothly; on a local simulated stream with pauses, the first lines after a pause no longer jump to the end (previously they did in every burst), and no frame moves the position backwards. The same holds after switching sessions.
|
|
40
|
+
- **The send flight's fill turns into the bubble's colour on the way**: where the composer paints its fill on an inner layer (as the home page's composer does), the flying bubble kept the composer's white all the way and switched to the bubble's colour only as it met the real bubble, with a strip of bubble colour showing early behind the toolbar row. The fill now starts on the part of the card the composer paints and changes into the bubble's colour along with the shape, covering the whole bubble when it arrives.
|
|
41
|
+
- **Switching and starting sessions no longer stalls**: with the plugin installed, opening another conversation or starting a new one froze the page for a second or two, worst in long conversations. The selection colours applied to the whole document, so every style pass had the browser compute selection styling for every element on the page; they now apply to the blocks that carry text in the conversation and in the composer — paragraphs, lists, headings, quotes, code. Measured on one switch, style recalculation went from 0.9–2.4 s to 0.11–0.51 s (about 0.05 s with the plugin off); selection colours in the sidebar, settings and popovers go back to the host's own.
|
|
42
|
+
- **Loading, reloading or updating another plugin no longer strips this plugin's styling**: after another plugin was loaded, reloaded or updated, the whole interface could fall back to the host's own look with this plugin's markers still on the page. The plugin's appearance now survives any other plugin being loaded, reloaded or removed.
|
|
43
|
+
- **Another plugin installed beside this one no longer loses its styling**: a stylesheet a plugin mounts without an ownership tag is taken into whichever package loads next and deleted when that package reloads — the meme plugin lost its entire styling that way, and only a page refresh brought it back. Such a sheet is now marked as unowned the moment this plugin sees it, and no plugin's load, reload or update touches it afterwards.
|
|
44
|
+
- **A grey line no longer flashes along the top of Deepy's frames**: while some animations played, a line about one pixel tall could appear at the top of the frame and vanish again, depending on where the whale stood and how large the window was. It no longer appears in any position or animation, and the whale looks and animates exactly as before.
|
|
45
|
+
- **A node detail in the subagent studio no longer takes the session statistics and the token usage with it**: with the studio open and a subagent node's detail popped up, the session statistics and the token usage sections drew under that popup with no surface of their own, over the conversation, leaving the composer's context panel with only the host's three rows. Both sections stay in the context panel now.
|
|
46
|
+
|
|
47
|
+
**Full Changelog**: [v0.10.6...v0.11.0](https://github.com/Nwflower/dsh-claude-style/compare/v0.10.6...v0.11.0)
|
|
48
|
+
|
|
49
|
+
## [0.10.6] - 2026-10-05
|
|
50
|
+
|
|
51
|
+
[中文](#cn-0.10.6) | [English](#en-0.10.6)
|
|
52
|
+
|
|
53
|
+
<h3 id="cn-0.10.6">新增功能</h3>
|
|
54
|
+
|
|
55
|
+
- **聊天气泡动效**:提交消息的那一下,输入卡片原样浮起一份,一边飞一边把多余的收掉——工具栏左右两组贴着最近的角缩小、淡出,描边与阴影跟着形状收回,草稿里的字跟着变窄的形状一行一行重新排——落地时正好就是那条真实气泡;真实气泡在飞行期间藏着,落定后原位出现。设置页的「动画效果」选了「减弱」、两端不在同一屏、或起点读不到(快捷键与程序化提交)时都不飞;页面切到后台时另有定时器兜底,藏起来的消息一定会放出来。与对话区其他动画一起合并在设置页「对话」页的「聊天区动画效果」开关里,默认开启。
|
|
56
|
+
- **文件变更行**:从 run_code 程序里派发出去的写入与编辑按直接调用的样子显示——行尾带 `+n -m`,展开是改动卡片,路径可点开文件;失败与中断的行保留裁决信息、不再给路径链接,状态另有给读屏的说明。改动内容无法从参数推出的调用保留系统的输入 / 输出卡片。与对话区其他动画一起合并在设置页「对话」页的「聊天区动画效果」开关里,默认开启。
|
|
57
|
+
- **新到的文字先淡后实**:流式回答里新出现的字符从两成不透明度开始,约 0.12 秒内坐实到它自己的颜色,并按到达次序略作错开,读起来像文字正被写下。整段一次到达的内容(切会话、翻历史)、一次几千字的突发、以及刚被折叠重排过的文字都保持本色;主线程忙不过来时它自己让路,闲下来再继续。与对话区其他动画一起合并在设置页「对话」页的「聊天区动画效果」开关里,默认开启。
|
|
58
|
+
- **折叠不再瞬间切换,展开体像卷帘门一样拉下来**:读者点开或收起一行(工具卡片、思考行、命令卡片)或一个过程组时,高度逐帧变化,下方内容被真的推开或收回。门只走读者看得见的那一段,两千像素的展开体和两万像素的展开体在眼前的速度一样;展开体里是多张卡片时(代码卡片加输出卡片)整扇门一起走,不会先挤没能缩的那一张。主线程卡住时门停一下再接着走,不会跳变;读者自己滚动离开底部之后,收尾不会把他拽回去。它与其他对话区动画一起挂在「聊天区动画效果」这个开关上(默认开启),关掉后读者点开收起恢复系统原来的瞬开瞬收。
|
|
59
|
+
- **思考行与过程组自动开合**:模型还在思考时思考行自动开着,思考停下就收回去;运行中的过程组自动展开,这一段过程结束再收起,组体展开时组头的标签仍带实时细节的流光。读者自己按过的行或组,在当时的阶段里不再被改动;「详细」与「完全展开」两档不收纳组体,插件不碰它们。与对话区其他动画一起合并在设置页「对话」页的「聊天区动画效果」开关里,默认开启。
|
|
60
|
+
- **输入框插入符动效**:输入框里的光标改由插件自己绘制,移动时带一段位移过渡;提问卡片的作答框与排队消息的行内编辑框同样覆盖。设置页的「对话」页新增三档:每一格(默认,连打字也滑)、只在移动时(方向键与点击才滑,打字瞬时)、关闭(完全不动手,用浏览器自己的光标)。任何一次测量失败都会把原生光标还回来,不会出现光标看不见的情况。
|
|
61
|
+
- **聊天区跟随交给系统自己的跟随,封顶的工作过程不再掉队**:思考行收起、工具调用行出现这些结构时刻,贴着底部的读者现在被交还给系统自己的跟随,内容成片到达时不再停在离底部几十像素的地方;「标准」与「简洁」档里封顶的过程组(思考与工具输出收在一个带滚动条的组体里)同样补到底部,最新两行不再长期悬在下方。补到底部是按曲线走完的:零散到达的字收得住尾巴,一次涌进上百个 token 那样的厚块则以一段恒定速度滑过去,再落到末尾——流式输出时新加的一行把上文顶起来是平滑的,不再几十像素一下地跳。流式输出期间主滚动条的跟随也交给同一条曲线:系统原来是把末尾一帧写到位,现在这段位移由插件接管并滑过去;输出很快时最新几行会短暂拖在屏幕下缘之外,流一停就滑到位。读者自己发出的消息不受这条曲线影响:宿主把新消息滚进视野的那一下照旧一步到位,插件在消息到达前后短暂让开。读者自己滚动离开底部之后,插件不再插手,直到他自己回到底部。与对话区其他动画一起合并在设置页「对话」页的「聊天区动画效果」开关里,默认开启。
|
|
62
|
+
- **与 dsh-chat-ux 共存**:本机同时装着 [dsh-chat-ux](https://github.com/alm-allen/dsh-chat-ux) 时,上面这几项整体让位——那个插件实现了同一批交互,两套同时生效会互相拦点击、抢同一批按钮、往宿主同一个座位键位按同一优先级注册。设置页的「对话」页把「聊天区动画效果」与「输入框插入符动效」两行的控件禁用,控件本身仍显示你自己设的值,下面另起一行用强调色写明「该选项由 dsh-chat-ux 管理」;你的设置不会被改写,那个插件中途装卸也照常跟随。它不在时这些交互按本插件自己的开关运行。
|
|
63
|
+
|
|
64
|
+
### 体验优化
|
|
65
|
+
|
|
66
|
+
- **权限菜单在窗口上方放不下时改为在控件下方展开**:权限分段控件的卡片固定朝上展开,窗口很矮时它的上缘顶出屏幕外,最上面几项点不到。现在上方容不下整张卡片时,它在控件下方展开。
|
|
67
|
+
- **上述动效跟随「动画效果」设置**:卷帘门过渡、聊天气泡动效、新文字淡入、插入符的滑动与闪烁、组头的流光此前只认系统的「减少动态效果」:设置页选「减弱」关不掉它们,选「总是」在系统开着减弱时也照样不动。现在它们读的是设置页解析出的那一档。
|
|
68
|
+
|
|
69
|
+
### 问题修复
|
|
70
|
+
|
|
71
|
+
- **「更多模型」的二级弹层在指针离开后收拢**:指针从「更多模型」挪到一级列表的模型行上之后,二级弹层在宽限期结束后收起,一级弹层保持不动。修复前只要指针还在一级弹层里它就永远挂着,遮住一级列表。
|
|
72
|
+
- **模型选择器打开二级弹层的瞬间即定位**:此前打开动作先定位后标记打开,而定位只认已标记打开的卡片,于是二级弹层沿用上一次的位置(连同上一次的窗口宽度算出的坐标),要等下一次指针事件才可能被纠正。现在先标记打开再定位,每次打开都落在当前位置。
|
|
73
|
+
- **插入符拆除后在途的那一帧不再落笔**:瞬落一帧之后恢复过渡属性的那次补写走的是一处未登记的帧,插件拆除时取消不到它,时机凑巧时它会在拆除之后对已收回的图层写入一次。现在这帧与队列帧一样登记在案,拆除时一并取消,回调也不再越过拆除线。
|
|
74
|
+
- **「文件变更行」的开关此前不起作用**:关掉它之后,run_code 程序里派发出去的写入与编辑仍然按新的样式显示。现在关掉即交还系统原来的行,打开即时接管,不需要刷新页面。
|
|
75
|
+
- **拖入附件后,输入区工具栏打开的面板不再被附件区域遮住**:附件存在时,从输入区工具栏按钮打开的面板(模型选择、思考强度等)中间被上方那块附件区域盖住一大截,只在卡片上方和输入框下方各露出一条边,面板里的行点不到。现在这类面板完整显示。
|
|
76
|
+
- **侧栏账号区因故障停用后,设置快捷键不再失灵**:插件的侧栏账号区出错退役后,按 Ctrl+,(macOS 为 ⌘,,网页版宿主为 Ctrl+Alt+,)什么都不打开。现在按键交还宿主,宿主自己的设置快捷键照常打开设置。
|
|
77
|
+
|
|
78
|
+
### 其他变更
|
|
79
|
+
|
|
80
|
+
- **昵称与封号页语言只存在设置里**:早先在宿主半边不认这两个字段时存进浏览器本地的值,会在打开页面后写进插件设置,本地那份随后删除;此后两项与其他设置一样只保存在宿主的设置表单里。
|
|
81
|
+
|
|
82
|
+
<h3 id="en-0.10.6">New Features</h3>
|
|
83
|
+
|
|
84
|
+
- **Send flight**: on submission the composer card lifts as it is and sheds what is extra on the way — the toolbar's two groups shrink and fade into their nearest corners, the hairline and shadow shrink with the shape, the words in the draft re-flow into the narrowing shape a line at a time — landing exactly on the real bubble, which hides while the flight is up and reappears in place when it lands. Nothing flies when the animation choice is Reduced, when the two ends are not on one screen, or when the origin cannot be read (a shortcut or a programmatic submission); a timer releases a hidden message if the page is in the background. It rides the Chat-area animations switch on the settings page's Conversation tab, on by default.
|
|
85
|
+
- **File change rows**: a write or edit dispatched from inside a run_code program is shown like a directly called one — the row carries the `+n -m` tail, expands into the diff card and its path opens the file; a failed or interrupted row keeps its verdict, drops the path link and announces its state to a screen reader. A call whose changed text cannot be derived from its arguments keeps the host's IN/OUT card. It rides the Chat-area animations switch on the settings page's Conversation tab, on by default.
|
|
86
|
+
- **New text fades in**: characters arriving in a streaming answer start at a fifth opacity and settle to their own colour in about 0.12 s, staggered slightly by arrival order, so the text reads as being written. A block arriving whole (a session switch, a page of history), a burst of thousands of characters and text that just reflowed from a fold all stay solid; when the main thread is too busy the fade gives way and resumes once it is free. It rides the Chat-area animations switch on the settings page's Conversation tab, on by default.
|
|
87
|
+
- **Folds no longer snap: a body rolls down like a door**: opening or closing a row (a tool card, a thinking row, a command card) or a process group now 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 a two-thousand-pixel body and a twenty-thousand-pixel one move at the same speed in front of him; a body holding several cards (a code card plus an output card) rolls as one door rather than squeezing away the card that can shrink. A stalled main thread does not make it jump — the door pauses and carries on — and a reader who scrolled away from the bottom is not pulled back when the fold settles. It rides the Chat-area animations switch together with the entrance fade of an expanded body (on by default); with that switch off, a reader's own press snaps open and shut the way the host does it.
|
|
88
|
+
- **Thinking rows and process groups open and close by themselves**: 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, its header keeping the live-detail sweep while the body is open. A row or group the reader pressed himself keeps what he chose for that phase, and the Detailed and Fully expanded tiers — which do not cap a body — are never touched. It rides the Chat-area animations switch on the settings page's Conversation tab, on by default.
|
|
89
|
+
- **Composer caret motion**: the composer's text caret is drawn by the plugin and glides between positions; a question card's answer box and a queued message's inline editor are covered as well. The Conversation tab gains a three-way choice — Every move (the default, typing included), Explicit moves (an arrow key or a click glides, a keystroke lands instantly) and Off. A measurement that fails hands the native caret back, so a caret is never lost.
|
|
90
|
+
- **The chat area's scroll goes back to the host's own follow, and a capped piece of work no longer lags behind**: at the structural moments — a thinking row folding, a tool call row arriving — a reader sitting at the bottom is now 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, so the last two lines no longer hang below the fold. Catching up runs on a curve: a trickle of characters settles softly, and a thick burst — a hundred-odd tokens arriving at once — glides at one steady speed before landing, so while text streams a new line pushes the text above it up smoothly instead of in forty-pixel steps. While content streams, the main scroller's follow runs along the same curve: where the host wrote its end in one frame, that displacement is now taken over and walked, so with a fast stream the newest lines trail just below the fold and slide into place once it stops. A message the reader sends is not affected by that curve: the host's scroll to bring it into view lands at once, and the plugin stands down around the arrival. Once the reader scrolls away from the bottom himself, the plugin stays out of it until he returns. It rides the Chat-area animations switch on the settings page's Conversation tab, on by default.
|
|
91
|
+
- **Coexisting with dsh-chat-ux**: with [dsh-chat-ux](https://github.com/alm-allen/dsh-chat-ux) installed on the same machine these effects stand down whole — that plugin implements the same interactions, and two copies intercept each other's clicks, press the same controls and register the same seat key at the same priority. The settings page's Conversation tab disables the Chat-area animations and Composer caret motion rows while each one goes on showing the value you set, with a line underneath in the accent colour reading "Managed by dsh-chat-ux"; your settings are not rewritten, and the hand-over follows that plugin being loaded or removed mid-session. With it gone they run on this plugin's own switches as usual.
|
|
92
|
+
|
|
93
|
+
### Improvements
|
|
94
|
+
|
|
95
|
+
- **The permission menu opens below the control when it does not fit above**: the permission control's card always unfolded upward, so in a short window its top edge ran off-screen and the first rows could not be clicked. It now opens below the control when the card does not fit above.
|
|
96
|
+
- **Those animations follow the Animation setting**: the rolling door, the send flight, the token fade, the caret's glide and blink and the header's live-detail sweep used to read the system's reduced-motion query alone, so Reduced on the settings page did not stop them and Always did nothing while the system asked for reduced motion. They now read the resolved choice.
|
|
97
|
+
|
|
98
|
+
### Bug Fixes
|
|
99
|
+
|
|
100
|
+
- **The More-models card folds once the pointer leaves**: moving the pointer from the More-models cell onto a model row of the first level now folds the second level after the grace, the first level staying put. Before, it hung open as long as the pointer stayed anywhere in the first level, covering its list.
|
|
101
|
+
- **The model picker places its second level at the moment it opens**: the open path used to place the card before marking it open, and the placement only reads cards marked open — so the card kept its previous position (with coordinates computed for the previous window width) until some later pointer event corrected it. It is marked open first and placed after, so every open lands on the current position.
|
|
102
|
+
- **The caret's teardown no longer leaves a frame that still draws**: the one-off frame that hands the transition back after an instant landing was untracked, so the teardown could not cancel it and, given the right timing, it fired after the teardown and wrote into a layer that had already been released. It is tracked like the queue's frame now — cancelled with the rest, and its callback stands down past the teardown.
|
|
103
|
+
- **The File change rows switch did nothing**: with it off, a write or edit dispatched from inside a run_code program still drew the new row. Off now hands the host's own row back and on takes it over, without a reload.
|
|
104
|
+
- **A panel opened from the composer's toolbar is no longer covered by the attachment area**: with an attachment in the composer, a panel opened from a toolbar button — the model picker, the reasoning-effort slider — lost its middle to the attachment area above it and showed only a strip above the card and another below the input box, so none of its rows could be clicked. Such panels now draw in full.
|
|
105
|
+
- **The settings shortcut keeps working after the sidebar account area is switched off by a fault**: once the plugin's sidebar account area failed and retired, Ctrl+, (⌘, on macOS, Ctrl+Alt+, in the web host) opened nothing. The keys now go back to the host, and the host's own settings shortcut opens the settings as usual.
|
|
106
|
+
|
|
107
|
+
### Chores
|
|
108
|
+
|
|
109
|
+
- **The nickname and the account-hold page's language live in the settings alone**: a value kept in the browser's local storage while the host half did not know these fields yet is written into the plugin settings when the page opens, and the local copy is removed afterwards; from then on both are saved in the host's settings form like every other setting.
|
|
110
|
+
|
|
111
|
+
**Full Changelog**: [v0.10.5...v0.10.6](https://github.com/Nwflower/dsh-claude-style/compare/v0.10.5...v0.10.6)
|
|
112
|
+
|
|
5
113
|
## [0.10.5] - 2026-10-04
|
|
6
114
|
|
|
7
115
|
[中文](#cn-0.10.5) | [English](#en-0.10.5)
|
package/README.en.md
CHANGED
|
@@ -77,11 +77,27 @@ The settings page appears both in the settings dialog (the "Claude Style" tab) a
|
|
|
77
77
|
| Appearance | Brand mark, Colours, Typefaces, Mascot, Where it appears |
|
|
78
78
|
| Composer | Composer restyle, Home layout, Redraw the model picker (with Quick providers under it), Redraw the permission control |
|
|
79
79
|
| Sidebar | Collapse the sidebar settings area, Sidebar search, In progress / Archived view |
|
|
80
|
-
| Conversation | Turn status line, Chat / Trajectory tabs |
|
|
80
|
+
| Conversation | Turn status line, Conversation navigator, Chat-area animations, Composer caret motion, Chat / Trajectory tabs |
|
|
81
81
|
|
|
82
|
-
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.
|
|
82
|
+
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. The conversation area's animations — the follow, the automatic folding with its rolling door, the text fade, the file change rows and the send flight — share one Chat-area animations switch; the caret keeps its own three-way choice.
|
|
83
83
|
|
|
84
|
-
**Alongside other theme plugins**: with Colours and Typefaces set to Follow the host, the skin no longer rewrites the host's colours and fonts and keeps only its layout and controls; the colours are left to DSH itself, or to another theme plugin enabled at the same time. With [dsh-wallpaper-engine](https://github.com/elysia395/dsh-wallpaper-engine), for example, the wallpaper shows through the sidebar and the conversation, and the skin's own popovers take that plugin's glass, translucent and blurring the picture behind them.
|
|
84
|
+
**Alongside other theme plugins**: with Colours and Typefaces set to Follow the host, the skin no longer rewrites the host's colours and fonts and keeps only its layout and controls; the colours are left to DSH itself, or to another theme plugin enabled at the same time. With [dsh-wallpaper-engine](https://github.com/elysia395/dsh-wallpaper-engine), for example, the wallpaper shows through the sidebar and the conversation, and the skin's own popovers take that plugin's glass, translucent and blurring the picture behind them. **Alongside [dsh-chat-ux](https://github.com/alm-allen/dsh-chat-ux)**: that plugin implements the same chat-area interactions (the rolling door, automatic folding, the token fade, file change rows, the send flight, the drawn caret), and two copies of them intercept each other's clicks and press the same controls. So this skin stands down when it sees that plugin: the Chat-area animations and Composer caret motion rows on the settings page's Conversation tab have their controls disabled while each still shows the value you set, with a line underneath in the accent colour reading "Managed by dsh-chat-ux". Your settings are not rewritten, and they take effect as they are once dsh-chat-ux is removed.
|
|
85
|
+
|
|
86
|
+
**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.
|
|
87
|
+
|
|
88
|
+
**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.
|
|
89
|
+
|
|
90
|
+
**Send flight**: on submission the composer card lifts as it is and narrows into the bubble as it travels, its words re-flowing into the shape, landing on the message row: the real bubble shows underneath and the flying copy fades out, so the words sharpen into place.
|
|
91
|
+
|
|
92
|
+
**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.
|
|
93
|
+
|
|
94
|
+
**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.
|
|
95
|
+
|
|
96
|
+
**A rolling door for folds**: 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. It rides the Chat-area animations switch, together with the entrance fade of an expanded body.
|
|
97
|
+
|
|
98
|
+
**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.
|
|
99
|
+
|
|
100
|
+
**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.
|
|
85
101
|
|
|
86
102
|
**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.
|
|
87
103
|
|
|
@@ -131,12 +147,14 @@ Keep only one theme enabled at a time. dsh ≥ 0.1.7 is required, and a restart
|
|
|
131
147
|
| Document | Contents |
|
|
132
148
|
| --- | --- |
|
|
133
149
|
| [Design tokens](docs/STYLE.md) | Palette, typography, shapes, source layout, and host-selector discipline (in English) |
|
|
134
|
-
| [Architecture decisions](docs/
|
|
150
|
+
| [Architecture decisions](docs/decisions/README.md) | One file per decision: build and source, the host boundary, the runtime and each feature's trade-offs, and the architecture migration in progress (in Chinese) |
|
|
135
151
|
| [Changelog](CHANGELOG.md) | Version history |
|
|
136
152
|
| [Contributing](CONTRIBUTING.md) | Building from `src/`, commit conventions, and the screenshot and regression tooling (in English) |
|
|
137
153
|
|
|
138
154
|
## Acknowledgements
|
|
139
155
|
|
|
156
|
+
The conversation navigator's opening list, keyboard jumps and landing line follow SherUnlocked-4869's [dsh-plugin-msg-nav](https://github.com/SherUnlocked-4869/dsh-plugin-msg-nav) (MIT).
|
|
157
|
+
|
|
140
158
|
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 [showcase/gifs/](showcase/gifs/).
|
|
141
159
|
|
|
142
160
|
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.
|
package/README.md
CHANGED
|
@@ -75,11 +75,27 @@
|
|
|
75
75
|
| 外观 | 品牌标识、配色、字体、吉祥物、出现位置 |
|
|
76
76
|
| 输入区 | 输入区重绘范围、首页版面、重绘模型选择器(及其下的快捷供应商)、重绘权限控件 |
|
|
77
77
|
| 侧栏 | 折叠侧栏设置区、侧栏搜索、进行中 / 已归档视图 |
|
|
78
|
-
| 对话 |
|
|
78
|
+
| 对话 | 轮次状态行、对话导航、聊天区动画效果、输入框插入符动效、对话 / 轨迹标签条 |
|
|
79
79
|
|
|
80
|
-
|
|
80
|
+
每一项接管宿主界面的功能都有自己的开关,关闭后宿主原来的界面原样回来,不需要刷新页面。对话区的那几项动画(跟随、自动开合与卷帘门、新文字淡入、文件变更行、聊天气泡动效)合成一个「聊天区动画效果」开关,插入符动效仍是自己的三档。
|
|
81
81
|
|
|
82
|
-
**与其他主题插件同时使用**:「配色」与「字体」选「跟随宿主」后,本插件不再改写宿主的颜色与字体,只保留布局和控件;颜色交给 DSH 自己,或者交给同时启用的其他主题插件。例如与 [dsh-wallpaper-engine](https://github.com/elysia395/dsh-wallpaper-engine)
|
|
82
|
+
**与其他主题插件同时使用**:「配色」与「字体」选「跟随宿主」后,本插件不再改写宿主的颜色与字体,只保留布局和控件;颜色交给 DSH 自己,或者交给同时启用的其他主题插件。例如与 [dsh-wallpaper-engine](https://github.com/elysia395/dsh-wallpaper-engine) 一起用时,壁纸透过侧栏与对话区显示出来,插件自己的弹层随壁纸插件的玻璃效果变成半透明并模糊背后的画面。**与 [dsh-chat-ux](https://github.com/alm-allen/dsh-chat-ux) 同时使用时**:那个插件实现了同一批聊天区交互(卷帘门、自动开合、文字淡入、文件变更行、聊天气泡动效、插入符动效),两套同时生效会互相拦点击、抢同一批按钮。所以本插件在检测到它时让位:设置页「对话」页的「聊天区动画效果」与「输入框插入符动效」两行控件禁用,但仍显示你自己设的值,下面另起一行用强调色注明「该选项由 dsh-chat-ux 管理」;你的设置不会被改写,卸载 dsh-chat-ux 之后原样生效。
|
|
83
|
+
|
|
84
|
+
**聊天区跟随**:思考行收起、工具调用行出现这些结构时刻,贴着底部的读者被交还给系统自己的跟随,内容成片到达时不再停在离底部几十像素的地方;「标准」与「简洁」档里封顶的过程组(思考与工具输出收在一个带滚动条的组体里)同样补到底部。补到底部走的是曲线:零散到达的字收得住尾巴,成片涌进的文字以一段稳速滑过去,再落到末尾。流式输出期间主滚动条的新内容也沿这条曲线推进,不再一帧写到底;输出很快时最新几行会短暂拖在屏幕下缘之外,流一停就滑到位。你自己发出的消息不走这条曲线:宿主把它滚进视野的那一下照旧一步到位。读者自己滚动离开底部之后,插件不再插手,直到他自己回到底部。
|
|
85
|
+
|
|
86
|
+
**思考与过程自动开合**:模型还在思考时思考行开着,思考停下就收回去;运行中的过程组自动展开,这一段结束再收起。读者自己按过的行或组在当时的阶段里不再被改动。
|
|
87
|
+
|
|
88
|
+
**聊天气泡动效**:提交消息时输入卡片原样浮起、一路收成那条气泡,草稿里的字跟着形状重新排,落地正好接上真实的消息行:真实气泡在下面先显示出来,飞行的那份淡出,文字逐渐变清晰。
|
|
89
|
+
|
|
90
|
+
**文件变更行**:run_code 程序里派发出去的写入与编辑带上行尾的 `+n -m` 与可展开的改动卡片,路径可点开文件;失败与中断的行保留裁决信息。
|
|
91
|
+
|
|
92
|
+
**新文字淡入**:流式回答里新出现的字符先淡后实(约 0.12 秒),并按到达次序略作错开;整段一次到达的内容、几千字的突发与刚被折叠重排过的文字保持本色。
|
|
93
|
+
|
|
94
|
+
**卷帘门过渡**:点开或收起一行(工具卡片、思考行、命令卡片)以及过程组时,高度逐帧变化,下方内容被真的推开或收回;门只走读者看得见的那一段,内容再长也是同一速度,多张卡片的展开体整扇门一起走。它与展开体的入场淡入一起挂在「聊天区动画效果」这个开关上。
|
|
95
|
+
|
|
96
|
+
**输入框插入符动效**:输入框里的光标由插件自己绘制,移动时滑过去;提问卡片的作答框与排队消息的行内编辑框同样覆盖。设置页的「对话」页有三档:每一格(默认)、只在移动时、关闭。
|
|
97
|
+
|
|
98
|
+
**对话导航**:对话区右侧那列短横线每一轮一条,跟着你读到的位置走。鼠标碰到它,它就展开成一张列表:每一行写着开启这一轮的那条消息,正好落在它那条短横线原来的位置上——你正在读的那一轮还在原处,鼠标下面还是刚才那一轮;滚轮上下翻,点一行页面滑到那一轮,还没加载的早期对话先加载再跳;指针停在列表上时,对话区顶部的对话 / 轨迹标签照常显示。Alt+↑ / Alt+↓ 跳到上一轮或下一轮,连按会一轮一轮接着走;输入框里有草稿时这两个键留给输入框。跳到的那一轮开头会闪一条短横线。同时装着 [dsh-plugin-msg-nav](https://github.com/SherUnlocked-4869/dsh-plugin-msg-nav) 时,Alt+↑ / Alt+↓ 留给它。
|
|
83
99
|
|
|
84
100
|
**吉祥物**:输入框上沿站着一只像素小伙伴,随智能体的工作状态换动画(思考、写回答与调用工具、多个会话同时工作、子代理、等你操作、压缩上下文、完成、失败、睡着)。「跟随品牌」在 Claude 品牌下是像素螃蟹,在 DeepSeek 品牌下是小鲸鱼 Deepy,也可以固定选一个或者关闭;「出现位置」决定它只在新会话页出现,还是新会话页和对话页都出现。
|
|
85
101
|
|
|
@@ -130,12 +146,14 @@ dsh plugin --profile web add dsh-claude-style # npm 包(推
|
|
|
130
146
|
| 文档 | 说明 |
|
|
131
147
|
| --- | --- |
|
|
132
148
|
| [设计令牌](docs/STYLE.md) | 调色板、字体、形状,源码结构与宿主选择器纪律(英文) |
|
|
133
|
-
| [架构决策](docs/
|
|
149
|
+
| [架构决策](docs/decisions/README.md) | 每条决策一个文件:构建与源码、宿主边界、运行时与各个功能的取舍,以及正在进行的架构迁移 |
|
|
134
150
|
| [更新日志](CHANGELOG.md) | 版本历史 |
|
|
135
151
|
| [贡献指南](CONTRIBUTING.md) | 如何从 `src/` 构建、提交规范与截图/回归工具(英文) |
|
|
136
152
|
|
|
137
153
|
## 鸣谢
|
|
138
154
|
|
|
155
|
+
对话导航的展开列表、快捷键跳转与落点横线参考了 SherUnlocked-4869 的 [dsh-plugin-msg-nav](https://github.com/SherUnlocked-4869/dsh-plugin-msg-nav)(MIT)。
|
|
156
|
+
|
|
139
157
|
像素小鲸鱼 Deepy 的动画帧图来自 calmly-eating-bugs([@wp3171216237](https://github.com/wp3171216237))绘制的 Deepy 小鲸鱼主题包。
|
|
140
158
|
|
|
141
159
|
像素螃蟹(Clawd)是 Anthropic 的角色形象,相关权利归 Anthropic 所有。螃蟹掏出电脑敲代码的动画取自 Claude Code,其余各个状态的动画由本项目按这一形象绘制。螃蟹的帧图不适用 MIT 许可(见 [LICENSE](LICENSE))。本插件是非官方的爱好者作品,与 Anthropic 没有关联,也未获其认可。
|
package/docs/STYLE.md
CHANGED
|
@@ -305,7 +305,7 @@ Its horizontal place is the one thing the skin takes over. ui-chat hangs the
|
|
|
305
305
|
panel from the anchor's LEFT edge and only then clamps it into the viewport
|
|
306
306
|
(`useStatDialog`, align `start`), so a trigger at the end of the composer row
|
|
307
307
|
leaves the panel against the window's right margin instead of under the ring.
|
|
308
|
-
`features/
|
|
308
|
+
`features/context-stats/session-stats.js` reads the meter's right edge and the
|
|
309
309
|
panel's own layout width — `offsetWidth`, not its rect: the entrance scales the
|
|
310
310
|
box, and a transformed rect is two per cent narrower than the one that settles —
|
|
311
311
|
and writes `--dsh-claude-context-panel-left` with the mark that turns it on;
|
|
@@ -314,7 +314,7 @@ host's inline value. The reading is re-taken when the panel's box changes (a
|
|
|
314
314
|
`ResizeObserver`) and when the viewport moves (`reposition('viewport')`).
|
|
315
315
|
|
|
316
316
|
What the skin appends to it is the session's numbers
|
|
317
|
-
(`features/
|
|
317
|
+
(`features/context-stats/session-stats.js`), read from the host's `sessionStats`
|
|
318
318
|
and `tokenUsage` projections — the same durable whole-log values the host's own
|
|
319
319
|
pills render — never by opening the host's stat dialogs. The labels and the
|
|
320
320
|
duration / token templates come from the host's `chat` locale namespace, so the
|
|
@@ -597,6 +597,6 @@ plays its reaction.
|
|
|
597
597
|
- A surface's stylesheet sits beside its feature under `src/features/<feature>/`;
|
|
598
598
|
the look no single feature owns is in `src/theme/`, and the parts several
|
|
599
599
|
features share (the popover card and rows, the sliding highlight) are in
|
|
600
|
-
`src/shared/`. The
|
|
601
|
-
|
|
600
|
+
`src/shared/`. The host selector discipline and the style checks the build
|
|
601
|
+
runs are in `docs/decisions/` (D3, D4, D9, D19, D30, D37).
|
|
602
602
|
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# D10. 设置传输只走官方 Config 表单
|
|
2
|
+
|
|
3
|
+
- **状态**:已实施
|
|
4
|
+
- **关联**:D29、D46
|
|
5
|
+
- **迁移**:偏好字段改在 `packages/contracts` 声明一次、两半各自生成,两份核对随之取消(待实施,随 D46);在那之前两半各有一份,由构建逐键核对
|
|
6
|
+
|
|
7
|
+
## 决定
|
|
8
|
+
|
|
9
|
+
- 浏览器半边只有 `configForms` 一条传输:绑定宿主实际提供的命名空间(候选依次为加载器入口 id、包名、`cordis.patch.yml` 插入的 id,以宿主的命名空间目录为准),读写都经表单控制器(值、写队列、修订号栅栏)。命名空间晚到时订阅目录,到达即绑定。
|
|
10
|
+
- 宿主半边导出 `Config` 作为 schema,只有 `.volatile()` 字段进表单。schemastery 以顶层 await 加守卫导入,解析不到时 `Config` 为 `undefined`、皮肤照常加载——这是「导入不包 try/catch」规定的唯一例外。
|
|
11
|
+
- 设置席位注册为 `plugins.bundle.config`(键为包名);宿主没有 `configForms` 时才注册整页的 `settings.section`。
|
|
12
|
+
- 偏好字段只有一份声明:宿主半边 `host/settings.js` 的 `PREFS_DEFAULT` 生成 `Config`;浏览器半边的默认值与取值集合给出表单答复之前的初值与读到值时的规整,两者逐键逐值相同。
|
|
13
|
+
- 偏好只存在宿主的表单里:早先存进浏览器本地存储的昵称与封号页语言,在表单第一次带值时写进表单,表单持有自己的值后删掉本地那份。
|
|
14
|
+
|
|
15
|
+
## 理由
|
|
16
|
+
|
|
17
|
+
- 官方表单自带写队列与修订号,皮肤不重复实现一套同步。
|
|
18
|
+
|
|
19
|
+
## 代价
|
|
20
|
+
|
|
21
|
+
- `Config` 的顶层 await 让宿主半边晚一步求值(加载器本就等待导入,无实际影响)。
|
|
22
|
+
|
|
23
|
+
## 重审条件
|
|
24
|
+
|
|
25
|
+
- 宿主提供不依赖 `Config` 的设置注册方式,或 `configForms` 契约再变。
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# D11. 私有路由借宿主的请求栅栏;外来字符串只以文本上屏
|
|
2
|
+
|
|
3
|
+
- **状态**:已实施
|
|
4
|
+
- **关联**:D21、D22、D38
|
|
5
|
+
- **迁移**:公开静态资产改为 D38 的通用资产路由与它的文件名校验(待实施);在那之前公开资产是模型文案、字体与 `/deepy/<名字>.png`
|
|
6
|
+
|
|
7
|
+
## 决定
|
|
8
|
+
|
|
9
|
+
- 宿主半边的私有路由(`/username`、`/usage`、`/session-search`、`/hdsl`、`/hdsl-skin.png`、`POST /session-delete`)处理前先调 `connection.requestRejection(req)`,拒绝即回 401/403。宿主没有这个服务时,插件自带的替代只放行回环请求:回环 Host、无跨站标记、Origin 与 Host 一致。
|
|
10
|
+
- 公开静态资产不经栅栏,但请求里的文件名必须符合固定格式,读取只落在一个目录里。
|
|
11
|
+
- 删除会话另加四道:只接受 POST;id 符合宿主的会话 id 格式;正在打开的会话拒绝;解析后的目录必须留在会话根目录内。删除发生在宿主半边,浏览器只提交 id。
|
|
12
|
+
- 删除成功时宿主半边经 `workspaceRegistry.unarchiveSession` 把 id 移出归档集合;归档集合里存储目录已消失的条目同样按删除成功应答并移出,否则归档列表会一直留着这一行。会话根目录读不了是故障,答 500。
|
|
13
|
+
- 用量汇总只读:别的插件的账本只读不写,自己的缓存放在 `$DSH_HOME/cache/dsh-claude-style/`。
|
|
14
|
+
- 浏览器半边:来自设置、账号服务、系统或其他插件的字符串只用 `textContent` 或元素属性写入;图标复制节点,不重新解析标记。
|
|
15
|
+
|
|
16
|
+
## 理由
|
|
17
|
+
|
|
18
|
+
- 插件路由不在宿主自己的栅栏之内;`dsh web` 绑定 `0.0.0.0` 时局域网可以直接访问,而页面能驱动执行 shell 命令的智能体。
|
|
19
|
+
|
|
20
|
+
## 代价
|
|
21
|
+
|
|
22
|
+
- 路由依赖宿主的 connection 服务。浏览器同源请求带会话 cookie、桌面壳经 `forwardWebRequest` 转发到回环 Host,两种都核对过能通过。
|
|
23
|
+
|
|
24
|
+
## 重审条件
|
|
25
|
+
|
|
26
|
+
- 宿主提供自带鉴权的路由注册时迁移过去,删掉本地替代。
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# D12. 快速失败与功能隔离
|
|
2
|
+
|
|
3
|
+
- **状态**:已实施
|
|
4
|
+
- **关联**:D29、D38、D42
|
|
5
|
+
- **迁移**:隔离的登记从 FEATURES 表改为功能清单(D42,待实施);D38 实施后,下面「浏览器半边允许的 catch」里 Deepy 帧图矢量化的两处随之删除
|
|
6
|
+
|
|
7
|
+
## 决定
|
|
8
|
+
|
|
9
|
+
- 出错的地方直接抛出,不吞错误、不静默回退。宿主服务可能缺席时,用可选链与 `typeof` 表达「没有这个服务」,不用 try/catch;宿主服务是否存在以 `ctx.get` 的返回值判断(cordis 对缺席的服务返回 `undefined`)。可选的文件(读者放进来的字体、HDSL 头像、尚未建立的会话根目录)用 `existsSync` 或 `statSync(…, { throwIfNoEntry: false })` 判断。
|
|
10
|
+
- 功能隔离:teardown 最先注册且幂等;每个功能单独安装,装不上的报告一次并退役;每轮刷新里每个功能单独执行,连续失败 3 轮即报告并退役。刷新机制自身装不上时整体回到宿主原样。
|
|
11
|
+
- 退役就是运行这个功能自己的 teardown,交还它接管的宿主界面:页脚接管与输入框重绘的门控强制关闭;权限控件替换的宿主控件由它自己的标记把守、随它的 teardown 交还。每个功能的 teardown 是它的 DOM 与标记的唯一清理。
|
|
12
|
+
- 需要隔离、但错误必须可见的地方用 `reportError`:`notifyAll` 逐个通知监听函数,某个出错就报告、其余照常;卸载时单个功能失败报告后继续;功能开关(D29)关闭某个功能时它的 teardown 抛错,同样报告,这个功能在本代内不再装回。
|
|
13
|
+
- 浏览器半边允许的 catch,每处写明原因:
|
|
14
|
+
- 上述隔离。
|
|
15
|
+
- 宿主以抛错表达的预期状态:设置表单的 `set()` 拒绝不属于该配置的字段;`modelDirectories.directoryFor` 对还没建立的会话抛错,下一轮重试;`sessionQuery.readSession` 以 `SESSION_QUERY_CORRUPT_SESSION` / `SESSION_QUERY_SESSION_NOT_FOUND` 表示某个存档读不了或已被删,内容搜索与用量汇总把这一个会话记为空并记一条警告。
|
|
16
|
+
- 文件变更行解析流式工具的原始参数:参数逐块到达,半截 JSON 是正常的中途状态,解析不了就交回宿主的输入 / 输出卡片(`features/chat-files/file-row-model.js`)。
|
|
17
|
+
- Promise 上表示「宿主半边没有应答」或「宿主自己会提示」的失败回调。
|
|
18
|
+
- Deepy 帧图矢量化两处:Cache API 拒绝读写时当作缓存永远未命中(每次页面加载重转,控制台警告一次);表图能解码但转换失败时回退为原 PNG 播放(控制台警告一次)。
|
|
19
|
+
- 宿主半边允许的 catch,每处写明原因:
|
|
20
|
+
- `webServer.register` 以抛错拒绝已被别的插件占用的路径:逐条注册,被拒的记警告,其余照常(宿主半边的纤程失败会连带撤下浏览器半边的整个包)。
|
|
21
|
+
- 卸载时逐个运行路由的撤销函数,单个失败记警告后继续。
|
|
22
|
+
- 删除会话的请求体不是 JSON 时答 400;删除过程中的任何故障答 500 并带错误信息。
|
|
23
|
+
- 成本计量插件的账本是别的插件的文件,读取与它的写入没有协调,解析不了时当作没有账本、改用本地折算。
|
|
24
|
+
- 用量汇总自己的缓存只省工作量:读不了时记警告并整体重算覆盖,写不进时记警告、本轮结果照常返回。
|
|
25
|
+
|
|
26
|
+
## 理由
|
|
27
|
+
|
|
28
|
+
- 被吞掉的错误会在别处以更难排查的方式出现;隔离只负责不让一个功能拖垮其他功能,失败本身必须留下记录。
|
|
29
|
+
|
|
30
|
+
## 代价
|
|
31
|
+
|
|
32
|
+
- 功能失效时界面上没有提示,只有控制台记录;依赖同一宿主服务的功能会一起退役。
|
|
33
|
+
|
|
34
|
+
## 重审条件
|
|
35
|
+
|
|
36
|
+
- 宿主提供插件级的错误上报时,把报告接过去。
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# D14. 账号表面:一套行模型,两个挂载点
|
|
2
|
+
|
|
3
|
+
- **状态**:已实施
|
|
4
|
+
- **关联**:D16
|
|
5
|
+
|
|
6
|
+
## 决定
|
|
7
|
+
|
|
8
|
+
- 插件的行(账号头部、其他插件的页脚条目、设置行)只出现在账号弹层里,由 `features/account/surface.js` 每轮判定挂载点。
|
|
9
|
+
- 宿主有账号区时(桌面端),宿主的账号行就是入口(插件只打标记供样式重绘),插件把容器插到宿主账号菜单列表的首位,宿主渲染它自己的行;宿主没有账号区时(网页端),插件自建账号行与弹层。
|
|
10
|
+
- 宿主的行不复制、不移动、不转发点击。插件的行被点击后需要收起菜单时,派发一次带 `__dshHostMenuEscape` 标记的 Escape 交给宿主菜单;皮肤的全局键盘路径见到这个标记就跳过。
|
|
11
|
+
- 账号头部打开封号彩蛋时,全窗浮层让指针「离开」行与菜单:浮层打开期间悬停收起停止工作,退出后页脚保持进入时的样子。
|
|
12
|
+
- 插进去的容器比宿主自己的行晚一帧到,卡片随之变高,宿主再晚一帧按新高度重新摆位。所以悬停或按下账号行时先给 `<body>` 打 `ACCOUNT_ARMED_ATTR`,卡片在这段时间不上色;`surface.js` 看到插件的行已在列表里、且卡片的行内摆位连续两次读数相同之后才打 `ACCOUNT_READY_ATTR`,入场动画挂在这个标记上。行内没有摆位时行一到就放行;始终不静止的卡片在有限帧数后放行。
|
|
13
|
+
|
|
14
|
+
## 理由
|
|
15
|
+
|
|
16
|
+
- 宿主菜单自带定位、动画、键盘遍历与关闭;插进去的行加入同一套键盘遍历,账号区不依赖宿主菜单的渲染时序与标签文字。
|
|
17
|
+
- 淡入从卡片最终的高度与位置开始,不会先贴着底部出现再往上跳。
|
|
18
|
+
|
|
19
|
+
## 代价
|
|
20
|
+
|
|
21
|
+
- 宿主菜单关闭即卸载,容器每轮重新确认并插入;卡片的显现要等插件的行到位与宿主重新摆位(约两三帧),这段时间卡片不上色。
|
|
22
|
+
|
|
23
|
+
## 重审条件
|
|
24
|
+
|
|
25
|
+
- 宿主为账号菜单提供追加行的插槽时改用插槽;宿主把插件的行算进它自己的首次渲染时,去掉这段等待。
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# D15. HDSL 账号契约:宿主半边转发,浏览器半边只认一条回退顺序
|
|
2
|
+
|
|
3
|
+
- **状态**:已实施
|
|
4
|
+
- **关联**:D11
|
|
5
|
+
|
|
6
|
+
## 决定
|
|
7
|
+
|
|
8
|
+
- 宿主半边读 harness 启动时填好的启动环境快照(`ctx.launchEnvironment`),只信 `process` 与 `user-env` 两层(项目目录的 `.env` 会随仓库被克隆);契约版本不为 `1` 时回 `{ contract: false }`。不 import harness 的启动环境包(`link:` 安装的插件解析不到它)。
|
|
9
|
+
- `GET /dsh-claude-style/hdsl` 回账号元数据,不含头像文件路径;`GET /dsh-claude-style/hdsl-skin.png` 回贴图字节,路径只来自环境、永远不来自请求。契约在进程生命周期内不变,读一次并记住。
|
|
10
|
+
- 浏览器半边:昵称 = 自定义昵称 → 官方账号昵称 → HDSL 昵称 → 探测昵称缓存 → 探测昵称 → `User`;头像 = 官方账号头像 → HDSL 头像 → Claude 徽标。两条回退都经 `src/core/host.js` 的身份存储,欢迎语与账号行只读这一处。
|
|
11
|
+
- 启动器给的是贴图集:按启动器账号列表同样的裁法取头部(脸的 8×8 贴图块按盒子 1/18 内缩,帽子层铺满),方形绘制;画完主动请求一轮刷新。
|
|
12
|
+
|
|
13
|
+
## 理由
|
|
14
|
+
|
|
15
|
+
- 契约只需读一次;两条回退收在一处,各处显示不会各自漂移;裁法与启动器一致,同一个玩家在两处长得一样。
|
|
16
|
+
|
|
17
|
+
## 代价
|
|
18
|
+
|
|
19
|
+
- 桌面端的账号行由宿主渲染,HDSL 头像只作用于插件自己的表面;启动器内置的默认形象没有像素可用,回退到徽标。
|
|
20
|
+
|
|
21
|
+
## 重审条件
|
|
22
|
+
|
|
23
|
+
- HDSL 契约升级版本(按指纹取图、账号 UUID)时改接新通道;宿主提供统一的「显示名 / 头像」服务时改接宿主。
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# D16. 弹层基准:一套外壳、一个停留时长、一次只开一张
|
|
2
|
+
|
|
3
|
+
- **状态**:已实施
|
|
4
|
+
|
|
5
|
+
## 决定
|
|
6
|
+
|
|
7
|
+
- 外壳:插件自建的卡片(权限、模型、推理强度、账号、快捷供应商)都带 `.dsh-claude-popover-card`,共用底色、边框、圆角、阴影、内边距、层级、开关动画与暗色配色;行、角标、勾号、状态行、主体用中性类名(`dsh-claude-popover-item` 等)。各功能的样式只写位置、宽度与展开方向。
|
|
8
|
+
- 停留与宽限统一为 `shared/popover.js` 的 `POPOVER_OPEN_DELAY` / `POPOVER_CLOSE_DELAY`(100ms);例外连同理由写在使用处(模型选择器两级卡片的收起宽限 150ms)。
|
|
9
|
+
- 互斥:`registerPopover(name, close)` 登记每张弹层的关闭方式,`closeOtherPopovers(name)` 在打开前关掉其余的。一个弹层的多层卡片按一项登记;宿主的菜单由驱动它的功能登记。登记表只存关闭函数,按名字覆盖登记,热重载后新一代的函数替换旧一代。
|
|
10
|
+
- hero 行一项登记对应两个宿主菜单,`hero-menu.js` 自己再做一次互斥,依据是「已展开的触发器」。
|
|
11
|
+
|
|
12
|
+
## 理由
|
|
13
|
+
|
|
14
|
+
- 同一个交互问题分处写必然漂移;共用外观用中性类名,改一个功能的样式不会波及别的功能。
|
|
15
|
+
|
|
16
|
+
## 代价
|
|
17
|
+
|
|
18
|
+
- 登记表是模块级状态,功能卸载时必须 `unregisterPopover`。
|
|
19
|
+
|
|
20
|
+
## 重审条件
|
|
21
|
+
|
|
22
|
+
- 宿主提供统一的弹层管理(全局互斥或焦点陷阱)时改接宿主。
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# D17. 权限档位以宿主目录为准,皮肤只做表现层
|
|
2
|
+
|
|
3
|
+
- **状态**:已实施
|
|
4
|
+
|
|
5
|
+
## 决定
|
|
6
|
+
|
|
7
|
+
- 段位与弹层行都按宿主的 `permissionPresets` 目录构建:目录里有的档位才画,没有的整条不出现。
|
|
8
|
+
- `PERMISSION_SEGMENTS` 只描述格子:每格列出可绑定的档位、取第一个宿主提供的(部署自己的自动档优先于宿主内置的 Auto review),一个都绑不上就不画。
|
|
9
|
+
- 档位名与说明来自皮肤的 `PERMISSION_PRESETS`,不认识的档位用目录自带的名字与说明,机器值永不上屏;档位声明的 `icon` 不画,列表保持纯文字。
|
|
10
|
+
- 切换走宿主的 `/permission <preset>`。
|
|
11
|
+
|
|
12
|
+
## 理由
|
|
13
|
+
|
|
14
|
+
- 目录变化时不漏档位,第三方档位(例如 auto mode 插件的 `auto-mode`)成为一等条目,接入新档位不用改皮肤代码。
|
|
15
|
+
|
|
16
|
+
## 代价
|
|
17
|
+
|
|
18
|
+
- 档位集合变化时重建行与段位;不认识的档位以宿主给的名字出现。
|
|
19
|
+
|
|
20
|
+
## 重审条件
|
|
21
|
+
|
|
22
|
+
- 宿主原生支持档位图标、且界面有了统一的档位图形语言时,再考虑画图标。
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# D19. 宿主契约与构建编号
|
|
2
|
+
|
|
3
|
+
- **状态**:已实施
|
|
4
|
+
- **关联**:D3、D44
|
|
5
|
+
- **迁移**:这些契约并入契约模块并由契约测试核对,见 D44(待实施);在那之前由冒烟检查的替代宿主页面按宿主真实结构复现
|
|
6
|
+
|
|
7
|
+
## 决定
|
|
8
|
+
|
|
9
|
+
- 插槽定位点:宿主渲染器保证每个插槽外面有 `[data-slot="<key>"]` 包装层(ui-renderer 的 scoped-slots),供外部定位。例如访问模式按钮按 `[data-slot="conversation.input.permission"]` 查找,跳过插件自己插进去的按钮。
|
|
10
|
+
- 控件标记:输入框按宿主 InputBar 的结构给按钮打 `data-dsh-claude-control`——`commands`(工具行里唯一打开 listbox 的按钮)、`stop` / `send`(提交区的主按钮,按图标区分:停止画 rect,提交箭头画 path;排队与插话是同一个提交按钮换了文字)、`access`(权限插槽里的按钮)。样式写成 `button[data-dsh-claude-control="…"]`。
|
|
11
|
+
- 弹层角色随开合写撤:宿主把文档里每个 `[role="menu"]`(ui-primitives 的 `modalSelector`,与 `[role="dialog"][aria-modal="true"]` 同列)当作占据前景的菜单,快捷键派发、`closeTopModal`、Esc-Esc 停止序列与 dock 标签菜单都按它判定。皮肤为量宽高而常驻 `<body>` 的弹层卡片关闭时只是视觉上藏起来,所以 `role="menu"` 经 `setMenuPopoverOpen`(`src/shared/popover.js`)与 `data-open` 同写同撤,卡片开着才持有这个角色;`quickProviders` 的卡片本就开时挂载、关时摘除,不经过它。
|
|
12
|
+
- 构建编号:构建取产物内容的哈希写成 `BUILD_ID`,运行时写到 `<body data-dsh-claude-style>` 的值上;页面跑的是哪一版以它为准。热重载替换插件代码而不重新加载页面,页面的加载时间说明不了代码版本。
|
|
13
|
+
|
|
14
|
+
## 理由
|
|
15
|
+
|
|
16
|
+
- 界面文字与哈希类名随语言、版本变化,结构与契约更稳定。
|
|
17
|
+
- 关闭的卡片若持有 `role="menu"`,宿主会把整套快捷键判给一个看不见的菜单。
|
|
18
|
+
|
|
19
|
+
## 代价
|
|
20
|
+
|
|
21
|
+
- 结构判断依赖宿主 InputBar 的现状,宿主改版时需要核对。
|
|
22
|
+
- 宿主按 `modalSelector` 判定快捷键这一侧,测试只查皮肤自己的不变量:关闭的弹层卡片不持有 `role="menu"`。
|
|
23
|
+
|
|
24
|
+
## 重审条件
|
|
25
|
+
|
|
26
|
+
- 宿主给这些控件提供自己的 `data-*` 标记时,直接读宿主的标记。
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# D20. 分段控件共用滑动高亮
|
|
2
|
+
|
|
3
|
+
- **状态**:已实施
|
|
4
|
+
- **关联**:D26、D40
|
|
5
|
+
- **迁移**:尺寸变化改经观察总线订阅(D40,待实施)
|
|
6
|
+
|
|
7
|
+
## 决定
|
|
8
|
+
|
|
9
|
+
- 视图标签、权限分段、进行中 / 已归档与设置页的分段控件共用 `createSlidingPill`:量出当前项相对控件内边距盒的位置与宽度,写成两个自定义属性,控件的伪元素用 transform 与 width 过渡滑过去。
|
|
10
|
+
- 属性与首次位置在同一次调用里写入,初次出现不滑入;控件隐藏或没有当前项时撤掉属性,当前项恢复自己的底色。
|
|
11
|
+
- 宽度因字体加载而变化时重新定位。
|
|
12
|
+
- 滑动不受「减少动态效果」设置影响(用户要求始终播放)。
|
|
13
|
+
- React 渲染的控件(设置页)在布局副作用里同步,赶在绘制之前。
|
|
14
|
+
|
|
15
|
+
## 理由
|
|
16
|
+
|
|
17
|
+
- 四处分段控件是同一个交互,一份实现保证一样的手感。
|
|
18
|
+
|
|
19
|
+
## 代价
|
|
20
|
+
|
|
21
|
+
- 每轮刷新读两个元素的位置;在已经排过版的帧里开销很小。
|
|
22
|
+
|
|
23
|
+
## 重审条件
|
|
24
|
+
|
|
25
|
+
- 宿主的分段控件自带滑动高亮时改用宿主的。
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# D21. 已归档列表跟随宿主的两份客户端数据
|
|
2
|
+
|
|
3
|
+
- **状态**:已实施
|
|
4
|
+
- **关联**:D11
|
|
5
|
+
|
|
6
|
+
## 决定
|
|
7
|
+
|
|
8
|
+
- 侧栏「已归档」是插件自己的平铺列表,订阅宿主 `workspaces.list`(归档集合)与 `sessions.list`(标题、时间、来源),两者都就绪后按宿主「仅已归档」的规则重算:只收已有会话摘要、非子代理、非空白占位的归档会话,按更新时间排序,内容不变时不重建。
|
|
9
|
+
- 宿主自带的筛选状态在 ui-workspace 私有的视图 store 里,不是客户端服务,不用它。
|
|
10
|
+
- 取消归档走 `workspaces.unarchiveSession`;删除走宿主半边的私有路由(D11)。浏览器删除成功后重拉一次会话列表基线,让已删除会话的旧摘要立刻离开列表;其余失败记警告。
|
|
11
|
+
- 点击已归档行显示宿主的同一条提示:宿主的 Toast 组件加 `workspace` 文案表里的 `toast.archivedNotOpenable`(宿主的提示通道是私有的)。
|
|
12
|
+
|
|
13
|
+
## 理由
|
|
14
|
+
|
|
15
|
+
- 宿主的筛选只能靠点它的菜单改;按宿主同一规则重算,列表内容与宿主一致。
|
|
16
|
+
|
|
17
|
+
## 代价
|
|
18
|
+
|
|
19
|
+
- 宿主「仅已归档」的规则变化时需要同步。
|
|
20
|
+
|
|
21
|
+
## 重审条件
|
|
22
|
+
|
|
23
|
+
- 宿主把视图筛选或提示通道开放为客户端服务时改用宿主的。
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# D22. 搜索面板:宿主的 Modal、宿主的数据与导航
|
|
2
|
+
|
|
3
|
+
- **状态**:已实施
|
|
4
|
+
- **关联**:D11、D16
|
|
5
|
+
|
|
6
|
+
## 决定
|
|
7
|
+
|
|
8
|
+
- 放置:侧栏搜索框插在宿主品牌行(`[data-slot="sidebar"]` 里的 `_logoRow`)的品牌旁边,只在这一行带宽版品牌时放置。这一行改成网格,品牌与搜索框同占第一格,两者的淡入淡出交给样式表的 `[data-slot="sidebar"]:hover`。
|
|
9
|
+
- 快捷键:宿主的 `session.search` 没有可替换的公开入口,它的效果是展开宿主自己的侧栏搜索并聚焦输入框。宿主的这块搜索因此保持挂载、只从视觉与布局里拿掉;焦点落进它的输入框时搜索面板打开,并经宿主自己的清除按钮把它收回,快捷键改绑后也跟着走。
|
|
10
|
+
- 面板是宿主 ui-primitives 的 `Modal`:遮罩、焦点归还、Esc 与模态层都用宿主的;卡片里的行由皮肤搭。它不套 D16 的弹层外壳,但登记进弹层互斥表。`Modal` 关闭即卸载,所以关闭时先给遮罩层打标记、保持挂载淡出,淡出结束后再卸载,标记在卸载之后才撤(否则重播一帧入场动画)。
|
|
11
|
+
- 数据读宿主的客户端服务:`sessions.list` 与 `workspaces.list`(去掉已归档、子代理与空白占位)、`remote.pluginInventory` 与 `remote.pluginManager`、当前会话的 `remote.skills`、`shortcuts.catalog`。远程命名空间在面板打开时用 `ctx.get('remote.<名字>')` 读(在根上下文直接读 `remote` 的子属性会被 cordis 以「没有 inject」拒绝)。
|
|
12
|
+
- 导航用宿主自己的:`uiWorkspace.openSession` / `startSession`、`pluginNavigation.openBundle`、`layout.selectPanel`;Skill 经会话输入的 `setDraft` 与 `focus`;设置页与快捷键列表经它们在插槽登记里声明的 store(`slots.entries(key)` 条目上的 `store.create()`)打开。快捷键行打开快捷键列表,不代为执行命令(宿主的快捷键命令没有公开的执行入口)。
|
|
13
|
+
- 匹配沿用宿主侧栏搜索的子串规则,排序为:标题开头、标题中的词开头、标题其他位置、第二个键(路径、包名、描述、别名)。
|
|
14
|
+
- 消息内容由宿主半边的 `/session-search` 路由搜(`host/search.js`):经 `sessionQuery.readSession` 读原始日志,只取用户与助手消息里的文本块,匹配照搬 `sessionQuery` 的 `text` 过滤(字面、不分大小写、空白可伸缩)。每个会话的消息文本连同变化标记留在内存里——存档用持久化后端 `list()` 的修订号,开着的会话用日志长度 `seq`——只重读标记变了的会话,子代理会话不读。面板打开时先发一次不带查询的请求预热;每个会话只回最新的一处命中,附摘录与命中位置。
|
|
15
|
+
|
|
16
|
+
## 理由
|
|
17
|
+
|
|
18
|
+
- 面板要做的每件事宿主都已有一条路,借用这些路,行为与宿主各处一致。
|
|
19
|
+
- 内容搜索是唯一的例外:宿主的索引 `sessions.search`(SQLite FTS5)在出厂 Web 组合里关闭,它的 `unicode61` 分词搜不到中文句中的字;读日志与匹配规则仍用宿主的。
|
|
20
|
+
|
|
21
|
+
## 代价
|
|
22
|
+
|
|
23
|
+
- 依赖上面这些服务、store 与品牌行结构的现状;数据与导航要在真实页面核对。
|
|
24
|
+
- 内容搜索在进程启动后第一次要读完全部会话(本机 128 个会话约 16 秒),之后每次查询约 0.1 秒;消息文本常驻宿主进程内存,大小约等于全部对话的文字量。
|
|
25
|
+
|
|
26
|
+
## 重审条件
|
|
27
|
+
|
|
28
|
+
- 宿主提供自己的全局搜索或命令面板时改为打开宿主的;宿主的内容索引能按子串匹配中文、并在出厂组合里打开时,内容搜索改回 `sessions.search`。
|