dsh-style-tweaks 0.1.0 → 0.1.1
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/README.en.md +6 -0
- package/README.md +6 -0
- package/lib/client.js +671 -1
- package/lib/client.js.map +1 -1
- package/lib/config.js +8 -0
- package/lib/config.js.map +1 -1
- package/lib/types/client/index.d.ts +39 -0
- package/lib/types/client/index.d.ts.map +1 -1
- package/lib/types/client/tweak-config.d.ts +4 -0
- package/lib/types/client/tweak-config.d.ts.map +1 -1
- package/lib/types/client/tweak-types.d.ts +4 -0
- package/lib/types/client/tweak-types.d.ts.map +1 -1
- package/lib/types/client/tweaks/legacy-stats-line.d.ts +59 -0
- package/lib/types/client/tweaks/legacy-stats-line.d.ts.map +1 -0
- package/lib/types/client/tweaks/pills-cache-hit-decimals.d.ts +57 -0
- package/lib/types/client/tweaks/pills-cache-hit-decimals.d.ts.map +1 -0
- package/lib/types/client/tweaks/registry.d.ts.map +1 -1
- package/lib/types/client/tweaks/stats-cache-hit.d.ts +30 -0
- package/lib/types/client/tweaks/stats-cache-hit.d.ts.map +1 -0
- package/lib/types/config.d.ts +29 -0
- package/lib/types/config.d.ts.map +1 -1
- package/package.json +5 -1
package/README.en.md
CHANGED
|
@@ -20,6 +20,8 @@ A [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) (DSH) web
|
|
|
20
20
|
- **Project running indicator (default on)** — shows the conversation title's animated running dot on the right side of each project directory in the sidebar, so a running conversation stays visible even when its group is collapsed.
|
|
21
21
|
- **Locate current session (default on)** — adds a "locate" button to the left of the native search button in the sidebar's "Workspaces" section header. Clicking it expands the current session's workspace directory (if collapsed) and its "Show {n} more sessions" overflow, then scrolls the session into the sidebar's visible area. Disabled with the tooltip "Open a session first" when no session is open.
|
|
22
22
|
- **Scrollable settings nav (default on)** — lets the settings dialog's left menu scroll when its entries outgrow the panel, instead of silently clipping the ones at the bottom (the panel has a fixed height and `overflow: hidden`; stock CSS only gave the right content column a scroll treatment). The scrollbar is an overlay-style thin strip: parked in the rail's spare right padding so it never squeezes the menu, and visible only while the list is actually scrolling, fading out ~0.8 s after scrolling stops.
|
|
23
|
+
- **Legacy stats line (default off)** — since DSH 0.1.5 the stats under the input box are two icon pills that open dialogs; this tweak brings back the pre-0.1.5 centered text line (turns/steps · timings · speed · cache hit · tokens). It reads the same durable projections (`sessionStats` / `tokenUsage`) so every figure matches the pills; an overlong line truncates with an ellipsis and reveals itself on hover, and turning the tweak off hands the row straight back to the pills.
|
|
24
|
+
- **Cache hit with two decimals (pills, default off)** — shows the new stats pills' cache-hit share with two decimal places (e.g. `87.35%`) instead of integer rounding; the token-usage dialog follows. Hidden in Settings while the legacy stats line is on (that line replaces the pills outright); with both toggles on, the legacy line wins.
|
|
23
25
|
|
|
24
26
|
```yaml
|
|
25
27
|
style-tweaks:
|
|
@@ -34,6 +36,8 @@ style-tweaks:
|
|
|
34
36
|
projectRunningIndicator: true # default true; false disables the tweak
|
|
35
37
|
locateCurrentSession: true # default true; false hides the sidebar locate button
|
|
36
38
|
settingsNavScroll: true # default true; false disables the settings-nav scrolling
|
|
39
|
+
legacyStatsLine: false # default false; true swaps the pills for the 0.1.2 text line
|
|
40
|
+
pillsCacheHitDecimals: false # default false; true shows the pills' cache hit with two decimals
|
|
37
41
|
```
|
|
38
42
|
|
|
39
43
|
Settings entry: **Settings → Style tweaks**.
|
|
@@ -104,6 +108,8 @@ Only client plugins (`client.js`) support hot reloading. Changes to the `apps/we
|
|
|
104
108
|
- **Project running indicator** (`src/client/tweaks/project-running-indicator.ts`) reads session running state and directory membership from `ctx.get('sessions')` / `ctx.get('workspaces')`, and uses a MutationObserver to mount the app's own `StateDot` (re-using `@deepseek-ai/dsh-client-ui-primitives` so the animation keyframes and style tokens are byte-identical to the conversation title's dot) inside each project directory header row (`role="treeitem"[aria-expanded]`, a stable hand-written attribute).
|
|
105
109
|
- **Locate current session** (`src/client/tweaks/locate-current-session.ts`) injects a new button into the sidebar's workspaces section header, to the left of the native search button. All anchors are i18n-safe: the search button's aria-label and the breadcrumb nav's aria-label are resolved through `ctx.locale.bind()` (the `workspace` / `conversation` namespace keys DSH itself uses), with structural class-fragment fallbacks (`searchButton`, `crumbs`) when the locale service is unavailable. Clicking it reads the current session title from the breadcrumb's disabled crumb, resolves the parent workspace via `ctx.get('sessions')` / `ctx.get('workspaces')` app stores (works even when the workspace's sidebar group is collapsed), finds the workspace row by exact title match, then pierces both collapse layers — clicking the collapsed workspace row to expand it, and auto-clicking the "Show {n} more sessions" overflow button (`[class*="sessionOverflowButton"][aria-expanded="false"]`) when the target row hides behind it — before `scrollIntoView({ block: 'center' })`. The hover tooltip replicates DSH's native `<Tooltip>` primitive (fixed-position bubble, theme tokens, 500 ms delay, viewport flip) instead of the browser-native `title`. A MutationObserver watches `aria-selected` / `aria-expanded` attribute changes to keep the button's enabled state and mount in sync.
|
|
106
110
|
- **Scrollable settings nav** (`src/client/tweaks/settings-nav-scroll.ts`) turns the settings dialog's left nav list into the scroll container of the nav rail: DSH's settings panel (`SettingsRoot`) has one fixed height with `overflow: hidden` and only gave the right content column (`.options`) an `overflow-y: auto`; the left `.navList` has neither `min-height: 0` nor an overflow treatment, so extra entries spill out and get clipped. Two CSS rules plus a small JS driver do it: the base rule `flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding-bottom: 12px; margin-inline-end: -12px` makes the list scrollable and parks the classic scrollbar in the nav rail's full 12px right padding gutter (8px gap + 4px strip), so the thumb floats over the spare padding 8px clear of the entries; a cell cap `max-width: 164px` (DSH's stock 188 nav − 2×12 padding) pins the entries to stock width in every state — bar present or not, hovering or scrolling — and `::-webkit-scrollbar { width: 4px }` is two notches thinner than DSH's global skin. The show timing is JS-driven: the first cut used `:not(:hover)` to blank the thumb, but Chromium does not reliably repaint custom scrollbar pseudo-elements when only the host's `:hover` state changes (in practice the bar appeared when clicking a nav cell — the React re-render forced the repaint), so the driver listens for `scroll` events on the list instead: scrolling adds a `cst-nav-scroll-show` class that reveals the thumb (coloured from the panel's inherited l2 tokens), and the class is removed ~0.8 s after scrolling stops; a MutationObserver re-attaches the listener whenever the dialog unmounts and reopens. The selector pairs the modal structure with a CSS Modules class fragment (DSH hashes classes as `[hash]_[local]`; the `navList` local name is unique across DSH), and needs no `!important`.
|
|
111
|
+
- **Legacy stats line** (`src/client/tweaks/legacy-stats-line.tsx`): 0.1.5 replaced the composer stats line (the old `StatsLine`) with icon pills (the new `StatsPills`); both mount the same way — a `list` entry with id `stats` on the `conversation.composer.dock` slot. A list cell renders its lowest-priority live entry (see `SlotCore.register`), so while the tweak is on, the plugin shadows the shipped entry with `id: 'stats'` + `priority: -2` (one step below the pills-decimals row, which it outranks when both are on) — the slot system's own shadowing mechanism, no CSS hiding or DOM patching — and disposing the registration hands the cell straight back; a crashed entry retires itself, restoring the pills. The data plane matches the pills: the durable `sessionStats` (whole-log counts and wall times) and `tokenUsage` (billing buckets) projections, without the old whole-window fallback fold (no projection → no row, matching the old line's "no data, no row" rule). Copy lives in the plugin's own `style-tweaks` namespace (`legacyStats.*` keys) — DSH removed the old `stats.llm` family from its dictionaries in 0.1.5, so the plugin carries its own en/zh strings; the row skin (centered, tertiary text, ellipsis truncation) is ported from 0.1.2's `StatsLine.module.css` with the original tokens plus fallbacks. The row root carries the `data-composer-stats` marker: the host InputBar tightens its own 8px bottom clearance to 4px around any mounted stats row (`.root:has([data-composer-stats])`), and the row adds 2px of bottom padding so its total matches the pills row (26px row + 4px host clearance on both presentations) — toggling the tweak no longer shifts the conversation.
|
|
112
|
+
- **Cache hit with two decimals** (`src/client/tweaks/pills-cache-hit-decimals.tsx`): the pills' percent rounding happens inside a module-internal formatter in dsh-client-ui-chat that a plugin cannot reach, so while the tweak is on, it shadows the same `stats` slot cell (`priority: -1`) with its own render of the whole row — both pills and their click-open dialogs ported style-for-style from 0.1.5's `StatsPills` / `stat-dialog` (placement and outside-close ride the host primitives' own `useAnchoredPosition` / `useDismissOnOutsidePointer`), with the cache hit routed through the plugin's shared `formatCacheHitPercent(…, 2)` (two-decimal rounding; a hit that would read `100%` keeps its honest extra-precision tail, e.g. `99.97`). The dialog rows and pill labels follow. The data plane is the same `sessionStats` / `tokenUsage` projections (no window fold), and the root carries `data-composer-stats` as well. One icon note: the pills' gauge icon only exists in primitives 0.1.3+, while the plugin typechecks against 0.1.2-rc.1 — at runtime the host's `IconGaugeOutline16` is used when present, falling back to a clock icon. Layering with the legacy line: both tweaks write the same slot cell; the legacy line registers at `priority: -2` and renders instead, leaving this row shadowed (unrendered, zero cost) until the legacy line is turned off, and the shipped pills return only when both tweaks are off. Settings hides this toggle while the legacy line is on.
|
|
107
113
|
|
|
108
114
|
## Acknowledgements
|
|
109
115
|
|
package/README.md
CHANGED
|
@@ -20,6 +20,8 @@
|
|
|
20
20
|
- **项目目录运行指示(默认开启)**:在侧边栏项目目录右侧显示与对话标题一致的运行动画圆点,目录收起时也能一眼看出里面有对话正在进行。
|
|
21
21
|
- **定位当前会话(默认开启)**:在侧边栏"工作区"段头部的搜索按钮左边新增一个定位按钮;点击后自动展开当前会话所属的工作区目录(包括"展开其余 x 个会话"的折叠层),将该会话滚动到侧边栏视口中央。无当前会话时按钮禁用并提示"请先打开一个会话"。
|
|
22
22
|
- **设置菜单可滚动(默认开启)**:设置项较多时,让设置面板左侧菜单可以上下滚动,而不是把放不下的项直接裁掉(面板高度固定且 `overflow: hidden`,原生样式只给右侧内容列加了滚动)。滚动条为悬浮式细条:停靠在菜单右侧的留白里、不挤压菜单宽度,只在列表实际滚动时出现,停止滚动约 0.8 秒后淡出。
|
|
23
|
+
- **经典统计行(默认关闭)**:DSH 0.1.5 起,输入框下方的统计信息从一行居中文本(轮数/步数 · 耗时 · 速度 · 缓存命中 · Token 用量)改成了两个图标胶囊(点开弹窗查看)。开启本项可恢复 0.1.2 的文本行样式:数据仍读同一批持久化投影(`sessionStats` / `tokenUsage`),数值与胶囊一致,超宽时省略号截断、悬停显示完整内容;关闭后立即恢复新版胶囊。
|
|
24
|
+
- **缓存命中两位小数(胶囊,默认关闭)**:新版统计胶囊的缓存命中率按两位小数显示(如 87.35%),不再取整;点开的 Token 用量弹窗同步生效。经典统计行开启时本项在设置面板中隐藏(该行已整体替换胶囊);两个开关同时为开时由经典统计行生效。
|
|
23
25
|
|
|
24
26
|
```yaml
|
|
25
27
|
style-tweaks:
|
|
@@ -34,6 +36,8 @@ style-tweaks:
|
|
|
34
36
|
projectRunningIndicator: true # 默认 true;false 则关闭
|
|
35
37
|
locateCurrentSession: true # 默认 true;false 则隐藏侧边栏定位按钮
|
|
36
38
|
settingsNavScroll: true # 默认 true;false 则关闭设置左侧菜单滚动
|
|
39
|
+
legacyStatsLine: false # 默认 false;true 则用 0.1.2 的文本统计行替换新版胶囊
|
|
40
|
+
pillsCacheHitDecimals: false # 默认 false;true 则新版胶囊的缓存命中率显示两位小数
|
|
37
41
|
```
|
|
38
42
|
|
|
39
43
|
设置入口:**设置 → 样式调整**。
|
|
@@ -103,6 +107,8 @@ npx -y @deepseek-ai/dsh plugin --profile web add . # 从本目录作为 b
|
|
|
103
107
|
- **项目目录运行指示**(`src/client/tweaks/project-running-indicator.ts`):从 `ctx.get('sessions')` / `ctx.get('workspaces')` 读取会话运行状态与目录归属,用 MutationObserver 在项目目录头行(`role="treeitem"[aria-expanded]`,稳定手写属性)内挂载应用自身的 `StateDot`(复用 `@deepseek-ai/dsh-client-ui-primitives` 的同一份模块,动画 keyframes 与样式 token 与对话标题处完全一致)。
|
|
104
108
|
- **定位当前会话**(`src/client/tweaks/locate-current-session.ts`):在 DSH 侧边栏"工作区"段头部的搜索按钮左边注入一个新按钮。锚点全部走 i18n 与语义片段:通过 `ctx.locale.bind()` 解析当前语言的搜索按钮 aria-label(`workspace` 命名空间的 `search.sessions.aria` 键)与顶部面包屑的 aria-label(`conversation` 命名空间的 `session.hierarchy` 键),locale 服务不可用时退回 `[class*="searchButton"]` / `[class*="crumbs"]` 语义片段兜底。点击后从面包屑(`button[disabled]` 的当前项)读出会话标题,用 `ctx.get('sessions')` 与 `ctx.get('workspaces')` 两个应用级 store 反查所在工作区标题(即使其工作区目录收起也能定位),再按标题匹配工作区行;依次穿透两级折叠——工作区收起时 click 展开、"展开其余 x 个会话"溢出按钮(`[class*="sessionOverflowButton"][aria-expanded="false"]`)挡住目标行时自动点开——然后 `scrollIntoView({ block: 'center' })` 滚动居中。悬停提示复刻了 DSH 原生 `<Tooltip>` 的自研气泡(fixed 定位 + 主题 token + 500ms 延迟 + 视口翻转),而非浏览器原生 `title`。MutationObserver 监听 `aria-selected` / `aria-expanded` 属性变化同步按钮可用性与挂载状态。
|
|
105
109
|
- **设置菜单可滚动**(`src/client/tweaks/settings-nav-scroll.ts`):DSH 设置面板(`SettingsRoot`)高度固定且 `overflow: hidden`,原生样式只让右侧内容列(`.options`)滚动;左侧菜单列表 `.navList` 没有 `min-height: 0` 与 overflow 处理,条目多时被面板直接裁掉。本调整项用"两条 CSS 规则 + 一个小型 JS 驱动"实现:基础规则 `flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding-bottom: 12px; margin-inline-end: -12px` 让列表成为滚动容器,并把滚动条"停靠"进导航栏右侧的 12px 留白里(8px 间距 + 4px 条位,恰好占满留白),滑块悬浮在留白上、与菜单项保持 8px 间距;菜单项上限 `max-width: 164px`(DSH 原生 188 导航 − 2×12 padding)钉住原生宽度,无论滚动条出现与否、悬停还是滚动,菜单项都与原生完全同宽;`::-webkit-scrollbar { width: 4px }` 比全局皮肤细两档。显示时机由 JS 驱动:第一版用 `:not(:hover)` 隐藏滑块,但 Chromium 在宿主 `:hover` 变化时不会可靠重绘自定义滚动条伪元素(实测表现为"点击菜单才出现"),因此改为监听列表 `scroll` 事件——滚动时给列表加 `cst-nav-scroll-show` 类显示滑块(颜色沿用面板继承的 l2 主题 token),停止滚动约 0.8 秒后移除类淡出;MutationObserver 在设置弹窗卸载/重开时保持监听器挂在当前列表上。选择器用"弹窗结构 + CSS Modules 语义片段"双保险(DSH 类名按 `[hash]_[local]` 哈希,`navList` 局部名全 DSH 唯一),无需 `!important`。
|
|
110
|
+
- **经典统计行**(`src/client/tweaks/legacy-stats-line.tsx`):0.1.5 起 DSH 把输入框下方的统计行(旧 `StatsLine`)换成了图标胶囊(新 `StatsPills`),两者挂载方式相同——`conversation.composer.dock` 列表槽位上 id 为 `stats` 的条目。列表槽位的规则是同一 id(同一"格")里 priority 最低的存活条目渲染,因此本调整项在开关打开时用 `id: 'stats'` + `priority: -1` 影子覆盖原生条目(走槽位系统自己的遮蔽机制,无需 CSS 隐藏或 DOM 修补;与"缓存命中两位小数"并存时本项注册在 `priority: -2` 优先,见下条),销毁注册即把格子还给原生胶囊;若条目渲染崩溃会自动退位,胶囊原样回来。数据面与新胶囊一致:读 `sessionStats`(整段日志的轮数/步数/耗时)与 `tokenUsage`(计费桶)两个持久化投影,不再做旧版"可见窗口折叠"的兜底(无投影时整行不渲染,符合旧行"无数据不出行"的规则)。文案走插件自己的 `style-tweaks` 命名空间(`legacyStats.*` 键)——旧版 `stats.llm` 系列键在 0.1.5 的词典里已被删除,插件自带中英文案;行样式(居中、三级文字色、省略号截断)按 0.1.2 的 `StatsLine.module.css` 移植,token 全部沿用原值并带兜底。行根元素带 `data-composer-stats` 标记:宿主 InputBar 会围绕任何挂载的统计行把自己的 8px 底距收紧到 4px(`.root:has([data-composer-stats])`),行本身底部补 2px 使总高与胶囊行(26px 行 + 4px 宿主底距)一致——开关切换时对话内容不再上下位移。
|
|
111
|
+
- **缓存命中两位小数**(`src/client/tweaks/pills-cache-hit-decimals.tsx`):新胶囊的命中率取整发生在 dsh-client-ui-chat 模块内部的格式化函数里,插件无法触及,因此本调整项在开关打开时对同一个 `stats` 槽位格做影子替换(`priority: -1`),由插件自绘整行——两个胶囊与点开弹窗按 0.1.5 的 `StatsPills` / `stat-dialog` 逐样式移植(定位与外点关闭直接复用宿主 primitives 的 `useAnchoredPosition` / `useDismissOnOutsidePointer`),缓存命中率改走插件共享的 `formatCacheHitPercent(…, 2)`(按两位小数取整,靠近 100% 时仍按"诚实尾数"多显示一位,如 `99.97`),弹窗各行与胶囊标签同步生效。数据面同样是 `sessionStats` / `tokenUsage` 两个投影(不做窗口折叠兜底);根元素同样带 `data-composer-stats`。图标方面,胶囊的 gauge 图标在 0.1.3+ 的 primitives 里才存在,插件按 rc.1 类型编译,故运行时优先从宿主 primitives 取 `IconGaugeOutline16`,取不到则回退为时钟图标。与"经典统计行"的层叠关系:两项同写一个槽位格,经典统计行注册在 `priority: -2` 优先渲染,本项在其下被遮蔽(不渲染、零开销);经典统计行关闭后本项若仍为开则自动接管格子,两者都关时恢复原生胶囊。设置面板在经典统计行开启时隐藏本项开关。
|
|
106
112
|
|
|
107
113
|
## 致谢
|
|
108
114
|
|