@deepseek-ai/dsh-client-ui-theme 0.1.1-rc.2 → 0.1.2-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.i18n.yaml CHANGED
@@ -2,5 +2,5 @@
2
2
  # side as of the last confirmed-consistent state. Both languages carry equal authority;
3
3
  # after editing either side, bring the other along and re-record with:
4
4
  # pnpm run verify-translation-pairing --write packages/client/ui-theme/README.md
5
- README.md: a9f0eb428789bc117e2fcbbdd2366066e0b994cc
6
- README.zh.md: 1447536c3e12a415c3ca241e4fe04a636ecaa6fd
5
+ README.md: 32ec60edb39b30afdb9b54804e62302cdc58e531
6
+ README.zh.md: ab17910ab9cec4e1ff519af0922ee27034a6fa7c
package/README.md CHANGED
@@ -1,20 +1,89 @@
1
+ ---
2
+ description: "Theme and content-font-size settings for the dsh web client: --dsw-* token stylesheets, ThemeRuntime state, General settings rows, and the pre-plugin bootstrap."
3
+ kind: "package-reference"
4
+ ---
5
+
1
6
  # @deepseek-ai/dsh-client-ui-theme
2
7
 
3
8
  English | [中文](README.zh.md)
4
9
 
5
- Theme plugin: ThemeRuntime over the --dsw-* token base stylesheets (static scale + alias semantic layers). The service owns the live theme preference (`light`/`dark`/`system`), resolves `system` through `prefers-color-scheme`, and publishes immutable `ThemeSnapshot`s on the `theme/change` event; it never touches the DOM — ui-layout's presenter applies the resolved snapshot (`html { color-scheme }`, `body[data-ds-dark-theme]`, and inline alias tokens). A loopback browser provides the service immediately with `system`, then loads `ui-theme.preference` in the background and writes each built-in selection through the Host settings API, whose local provider stores it in `$DSH_HOME/settings.yaml` by default; pushed settings changes and reconnects refetch it, rapid selections are serialized in gesture order with namespace revisions, and a rejected latest write reloads the durable value. A remote browser cannot access the privileged settings API, so its selection remains process-local. Third-party registered theme ids remain an in-process extension and do not cross the built-in settings schema; removing one never overwrites the last durable built-in preference. The [Host-backed preferences decision](../../../.agents/notes/implemented/bug-fix/2026-08-06-host-backed-web-preferences.md) owns the persistence boundary.
10
+ ## Summary
11
+
12
+ `dsh-client-ui-theme` lets Web GUI users choose `light`, `dark`, or `system` and set conversation content text from 12 to 17 px in Settings. A loopback client stores both values in the `ui-theme` settings namespace, which the local provider persists in `$DSH_HOME/settings.yaml` by default. The plugin resolves `system` through `prefers-color-scheme` and publishes immutable `ThemeSnapshot`s; ui-layout applies each snapshot to the document. The package also ships the `--dsw-*` token stylesheets and injects a synchronous bootstrap so the selected palette and font size apply before the shell loads. Third-party themes can register alias-token overrides through `ctx.theme`.
13
+
14
+ ## Table of Contents
15
+
16
+ - [Use this package](#use-this-package)
17
+ - [Understand the implementation](#understand-the-implementation)
18
+ - [Further Exploration](#further-exploration)
19
+ - [Model Experience](#model-experience)
20
+ - [Known Limitations and Deferred Work](#known-limitations-and-deferred-work)
21
+ - [Dev Note](#dev-note)
22
+
23
+ -----
24
+
25
+ <a id="use-this-package"></a>
26
+ ## Use this package
27
+
28
+ Users switch the color scheme and content font size from two rows in Settings (General section); both choices persist across restarts on a loopback browser. Feature plugins consume the current snapshot through `ctx.theme` and read the `--dsw-*` tokens in CSS; they do not manage theme state themselves.
29
+
30
+ ### Appearance and font size
31
+
32
+ The plugin registers Appearance preference cubes and a font-size stepper in the General section. The stepper accepts integer values from 12 through 17 px and defaults to 14 px. It changes conversation headings and base text by the same increment, including the user bubble and composer draft; flow-row titles, summaries, and tables follow one step under the body size, while small text and code keep fixed sizes. Each accepted change writes through the Host settings API. Rapid changes serialize in gesture order with namespace revisions, and a rejected latest write reloads the durable values. Non-loopback pages keep both choices process-local.
33
+
34
+ ### Registering a theme
35
+
36
+ A composition can register a third-party theme id with alias-token overrides through `ctx.theme`; the override layer folds into the active snapshot's tokens in registration order. Removing one never overwrites the last durable built-in preference. Third-party theme ids remain an in-process extension and do not cross the built-in settings schema.
37
+
38
+ ### Pre-plugin palette
39
+
40
+ When the host composition includes an HTTP server, the host half embeds the registered `ui-theme` settings, or schema defaults, into each index response. Before the loading page renders, the browser sets `color-scheme`, `body[data-ds-dark-theme]`, and `--dsh-content-font-size`, so the first paint uses the selected palette and text size.
41
+
42
+ -----
43
+
44
+ <a id="understand-the-implementation"></a>
45
+ ## Understand the implementation
46
+
47
+ <details>
48
+ <summary>Implementation internals — click to expand</summary>
49
+
50
+ The service owns theme and font-size state and publishes snapshots. The ui-layout presenter applies those snapshots, and the token sheets own the color and conversation text scales.
6
51
 
7
- When the host composition includes an HTTP server, the host half injects a synchronous bootstrap immediately after the opening `<body>` tag. Each index response embeds the registered Host setting for `ui-theme.preference`, or `system` when no settings provider is present; the browser resolves `system` from the OS scheme, then sets `color-scheme` and `body[data-ds-dark-theme]` before the shell loading page renders. Compositions without an HTTP server remain unaffected, and ThemeRuntime and ui-layout remain authoritative for client state and subsequent DOM updates after the plugin tree activates.
52
+ ### Stylesheets
8
53
 
9
- `src/styles/` holds five sheets imported in order by ui-theme's dynamic client entry: `base.css`, `design-platform.css`, `scrollbar.css`, `gradient-shadow-text.css`, and `shiki.css`. The client bundle compiles and injects them as plugin-owned global styles, so unload and HMR remove them with ui-theme instead of leaving theme CSS in the static web shell. `scrollbar.css` is the sole consumer of the `--dsw-alias-scrollbar-*` tokens and must follow `design-platform.css`, which declares them.
54
+ `src/styles/` holds five sheets imported in order by ui-theme's dynamic client entry: `base.css`, `design-platform.css`, `scrollbar.css`, `gradient-shadow-text.css`, and `shiki.css`. The client bundle compiles and injects them as plugin-owned global styles, so unload and HMR remove them with ui-theme. `scrollbar.css` is the sole consumer of the `--dsw-alias-scrollbar-*` tokens and must follow `design-platform.css`, which declares them.
10
55
 
11
- Scrollbar rebinding contract: `scrollbar.css` binds `--dsh-scrollbar-thumb` and `--dsh-scrollbar-thumb-hover` on `body` to the l1 (base-surface) tokens, and both rendering paths read that pair. An elevated surface (menu, popover, dialog) sets `--dsh-scrollbar-thumb: var(--dsw-alias-scrollbar-bg-l2)` and `--dsh-scrollbar-thumb-hover: var(--dsw-alias-scrollbar-hover-l2)` on its own container; one rebind retints whichever path the engine took. The pair's other legal target is `transparent`, which draws no thumb at all — [ui-sidebar](../ui-sidebar/README.md) rebinds its column that way while the pointer is elsewhere. A rebind to the l1 pair is not a rebind; it restates the base-surface default. `--dsh-scrollbar-width` mirrors the WebKit bar's layout width for surfaces that align themselves beside a space-consuming bar — [ui-conversation](../ui-conversation/README.md) reads it for the overlay composer seat's `right` offset — and the scrollbar-styles spec pairs it with the mirrored rule and the consumer.
56
+ `gradient-shadow-text.css` derives `--dsh-content-font-delta` from `--dsh-content-font-size` and shifts the Markdown heading and base-text ladder by that increment. It also derives the secondary tier `--dsh-content-font-size-secondary` (setting −1 at ≤14, setting −2 above; 13px at the default) with its own `--dsh-content-font-delta-secondary` for the table variants and the flow rows one step under the body. Dense small and code variants stay fixed. Outside the ladder, the user bubble and composer draft read the body pair directly, and flow-row titles and summaries read the secondary pair.
12
57
 
13
- The two paths are mutually exclusive by construction. `scrollbar-width`/`scrollbar-color` sit inside `@supports not selector(::-webkit-scrollbar)` because a non-`auto` value of either makes Chromium and Safari discard every `::-webkit-scrollbar*` rule for that element, `::-webkit-scrollbar-thumb:hover` included — declaring both unconditionally leaves `--dsh-scrollbar-thumb-hover` with no rendering anywhere. Firefox therefore takes the standard properties and WebKit-based engines take the pseudo-elements, so the hover token only ever renders through the pseudo-element path. Reasoning and the measured computed values: [the scrollbar Agent Note](../../../.agents/notes/implemented/bug-fix/2026-07-28-themed-scrollbars-and-reserved-gutter.md).
58
+ ### Scrollbar rebinding
14
59
 
60
+ `scrollbar.css` binds `--dsh-scrollbar-thumb` and `--dsh-scrollbar-thumb-hover` on `body` to the l1 base-surface tokens; an elevated surface (menu, popover, dialog) rebinds them to the l2 tokens on its own container, and the pair's other legal target is `transparent` (ui-sidebar rebinds its column that way while the pointer is elsewhere). `--dsh-scrollbar-width` mirrors the WebKit bar's layout width for surfaces that align beside a space-consuming bar. The two rendering paths are mutually exclusive by construction: Firefox takes the standard properties inside `@supports not selector(::-webkit-scrollbar)`, and WebKit-based engines take the pseudo-elements, so the hover token only ever renders through the pseudo-element path ([scrollbar note](../../../.agents/notes/implemented/bug-fix/2026-07-28-themed-scrollbars-and-reserved-gutter.md)).
61
+
62
+ ### Preference persistence
63
+
64
+ The service provides itself immediately with the schema defaults on a loopback browser, then loads the `ui-theme` namespace and writes each accepted theme or font-size change through the Host settings API. Pushed settings changes and reconnects refetch the namespace. Non-loopback pages do not create that Host-backed scope. The persistence boundary is owned by the [Host-backed preferences note](../../../.agents/notes/implemented/bug-fix/2026-08-06-host-backed-web-preferences.md).
65
+
66
+ </details>
67
+
68
+ -----
69
+
70
+ <a id="further-exploration"></a>
71
+ ## Further Exploration
72
+
73
+ These pages cover the layout presenter, the token consumers, and the styling rules.
74
+
75
+ - [ui-layout](../ui-layout/README.md) — the presenter that applies the resolved theme snapshot.
76
+ - [ui-sidebar](../ui-sidebar/README.md) — a consumer of the scrollbar rebinding contract.
77
+ - [ui-conversation](../ui-conversation/README.md) — a consumer of `--dsh-scrollbar-width` for the composer seat.
78
+ - [Web styling](../../../docs/web-styling.md) — the authoritative styling rules for web client components.
79
+ - [Host-backed preferences](../../../.agents/notes/implemented/bug-fix/2026-08-06-host-backed-web-preferences.md) — the persistence boundary decision.
80
+
81
+ -----
82
+
83
+ <a id="model-experience"></a>
15
84
  ## Model Experience
16
85
 
17
- None, as the theme service manages a browser preference; nothing here reaches a model request.
86
+ None, as the package is a browser-side UI plugin layer that registers nothing model-facing.
18
87
 
19
88
  #### KV Cache effect
20
89
 
@@ -22,5 +91,20 @@ None; this package neither assembles nor sends a provider request.
22
91
 
23
92
  ## Known Limitations and Deferred Work
24
93
 
94
+ <a id="known-limitations-and-deferred-work"></a>
95
+
96
+
97
+ These limits define the theme extension surface and the color authority; they are current package constraints.
98
+
25
99
  - **Third-party themes are an extension point, not a product** — registering one means overriding same-named alias variables; no validation exists that an override set is complete.
26
- - **The token sheets are the sole color authority** — values absent from cssdesign (for example the design's #4176E6 tab blue) are deliberately not appended; the nearest semantic token wins. Design-owner-approved additions are the exception and enter as a static step plus a semantic alias in the same change (`--dsw-static-blue-900` / `--dsw-alias-label-primary-bluish`).
100
+ - **The token sheets are the sole color authority** — values absent from the design system are deliberately not appended; the nearest semantic token wins, and design-owner-approved additions enter as a static step plus a semantic alias in the same change.
101
+
102
+ <a id="dev-note"></a>
103
+ ### Dev Note
104
+
105
+ <details>
106
+ <summary>Working context for maintainers — click to expand</summary>
107
+
108
+ None.
109
+
110
+ </details>
package/README.zh.md CHANGED
@@ -1,26 +1,110 @@
1
+ ---
2
+ description: "dsh Web 客户端的主题与正文字号设置:--dsw-* token 样式表、ThemeRuntime 状态、「通用」设置行与插件前引导。"
3
+ kind: "package-reference"
4
+ ---
5
+
1
6
  # @deepseek-ai/dsh-client-ui-theme
2
7
 
3
8
  [English](README.md) | 中文
4
9
 
5
- 主题插件:基于 --dsw-* token 基础样式表(静态尺度 + 别名语义层)的 ThemeRuntime。该服务拥有实时主题偏好(`light`/`dark`/`system`),将 `system` 通过 `prefers-color-scheme` 解析为实际主题,并发布不可变的 `ThemeSnapshot`,通过 `theme/change` 事件通知变化;它绝不接触 DOM:ui-layout 的呈现器会应用解析后的快照(`html { color-scheme }`、`body[data-ds-dark-theme]`,以及主题的别名 token 内联变量)。来自回环地址的浏览器会先以 `system` 立即提供该服务,随后在后台加载 `ui-theme.preference`,并将每次内置主题选择通过 Host settings API 写入;其本地提供方默认将设置存入 `$DSH_HOME/settings.yaml`。收到推送的 settings 变更时或重连后,浏览器都会重新拉取该设置;连续快速选择会按操作顺序携带 namespace revision 串行写入,最新写入被拒时则重新加载持久化值。远程浏览器无法访问特权 settings API,因此它的选择仅保留在进程内。已注册的第三方主题 id 仍是进程内扩展,不会跨越内置 settings schema;移除其中任意一个都绝不会覆盖最后一个持久化的内置偏好。该持久化边界由[Host settings 支撑的偏好决策](../../../.agents/notes/implemented/bug-fix/2026-08-06-host-backed-web-preferences.zh.md)拥有。
10
+ ## 概述
11
+
12
+ `dsh-client-ui-theme` 让 Web GUI 用户在设置中选择 `light`、`dark` 或 `system`,并把会话正文字号设为 12 至 17 px。回环客户端把两个值存入 `ui-theme` 设置命名空间,本地提供方默认将其持久化到 `$DSH_HOME/settings.yaml`。插件通过 `prefers-color-scheme` 解析 `system` 并发布不可变的 `ThemeSnapshot`;ui-layout 把每份快照应用到 document。本包还提供 `--dsw-*` token 样式表,并注入同步引导,使所选调色板与字号在外壳加载前生效。第三方主题可通过 `ctx.theme` 注册别名 token 覆盖。
13
+
14
+ ## 目录
15
+
16
+ - [使用本包](#use-this-package)
17
+ - [理解实现](#understand-the-implementation)
18
+ - [进一步探索](#further-exploration)
19
+ - [模型体验](#model-experience)
20
+ - [已知限制与延期工作](#known-limitations-and-deferred-work)
21
+ - [开发备注](#dev-note)
22
+
23
+ -----
24
+
25
+ <a id="use-this-package"></a>
26
+ ## 使用本包
27
+
28
+ 用户从设置(「通用」分区)的两行中切换配色方案与正文字号;在回环浏览器上,两个选择都会跨重启持久化。功能插件通过 `ctx.theme` 消费当前快照,并在 CSS 中读取 `--dsw-*` token;它们不自行管理主题状态。
29
+
30
+ ### 外观与字号
31
+
32
+ 插件在「通用」分区注册外观偏好方块与字号步进器。步进器接受 12 至 17 px 的整数,默认值为 14 px。它以相同增量调整会话标题与基础文本,包括用户气泡与 composer 草稿;流内行的标题、摘要与表格跟随比正文低一档的字号,小号文本和代码保持固定字号。每次通过的变更都经 Host settings API 写入。连续快速变更按操作顺序携带命名空间 revision 串行写入,最新写入被拒时重新加载持久值。非 loopback 页面把两个选择都保留在进程内。
33
+
34
+ ### 注册主题
35
+
36
+ 组合可以通过 `ctx.theme` 注册带别名 token 覆盖的第三方主题 id;覆盖层按注册顺序折入活动快照的 token 中。移除其中一个绝不会覆盖最后一个持久化的内置偏好。第三方主题 id 仍是进程内扩展,不会跨越内置 settings schema。
37
+
38
+ ### 插件前调色板
39
+
40
+ 当主机组合包含 HTTP 服务器时,宿主侧会把已注册的 `ui-theme` 设置或 schema 默认值嵌入每份 index 响应。浏览器在加载页面渲染前设置 `color-scheme`、`body[data-ds-dark-theme]` 与 `--dsh-content-font-size`,因此首帧绘制就采用所选调色板与字号。
41
+
42
+ -----
43
+
44
+ <a id="understand-the-implementation"></a>
45
+ ## 理解实现
46
+
47
+ <details>
48
+ <summary>实现细节——点击展开</summary>
49
+
50
+ 服务拥有主题与字号状态并发布快照。ui-layout 呈现器应用这些快照,token 样式表则拥有颜色与会话文本尺度。
6
51
 
7
- 当主机组合包含 HTTP 服务器时,主机侧紧接 `<body>` 起始标签注入同步引导代码。每份 index 响应会嵌入已注册的 Host 设置 `ui-theme.preference`,没有 settings provider 时则嵌入 `system`;浏览器按操作系统配色解析 `system`,随后在外壳加载页面渲染前设置 `color-scheme` 和 `body[data-ds-dark-theme]`。不含 HTTP 服务器的组合不受影响,插件树激活后,ThemeRuntime 与 ui-layout 仍分别是客户端状态和后续 DOM 更新的权威来源。
52
+ ### 样式表
8
53
 
9
- `src/styles/` 下有五张样式表,由 ui-theme 的动态客户端 entry 依次导入:`base.css`、`design-platform.css`、`scrollbar.css`、`gradient-shadow-text.css` 与 `shiki.css`。客户端 bundle 将其编译并注入为插件持有的全局样式,因此卸载与 HMR 会随 ui-theme 一同移除这些样式,而不会把主题 CSS 留在静态 Web 外壳中。`scrollbar.css` 是 `--dsw-alias-scrollbar-*` token 的唯一消费方,必须排在声明这些 token 的 `design-platform.css` 之后。
54
+ `src/styles/` 下有五张样式表,由 ui-theme 的动态客户端 entry 依次导入:`base.css`、`design-platform.css`、`scrollbar.css`、`gradient-shadow-text.css` 与 `shiki.css`。客户端 bundle 将其编译并注入为插件持有的全局样式,因此卸载与 HMR 会随 ui-theme 一同移除。`scrollbar.css` 是 `--dsw-alias-scrollbar-*` token 的唯一消费方,必须排在声明这些 token 的 `design-platform.css` 之后。
10
55
 
11
- 滚动条重新绑定约定:`scrollbar.css` `body` 上把 `--dsh-scrollbar-thumb` `--dsh-scrollbar-thumb-hover` 绑定到 l1(基础表面)token,两条渲染路径都读取这一组变量。高层级表面(菜单、浮层、对话框)在自己的容器上设置 `--dsh-scrollbar-thumb: var(--dsw-alias-scrollbar-bg-l2)` `--dsh-scrollbar-thumb-hover: var(--dsw-alias-scrollbar-hover-l2)`;一次重新绑定即可为引擎实际走的那条路径换色。这组变量的另一个合法目标是 `transparent`,即完全不绘制滑块——[ui-sidebar](../ui-sidebar/README.zh.md) 在指针不在栏内时就这样重新绑定自己的列。绑回 l1 那组不算重新绑定,它只是重述基础表面的默认值。`--dsh-scrollbar-width` 镜像 WebKit 滚动条的布局宽度,供需要与占布局宽度的滚动条对齐的表面使用——[ui-conversation](../ui-conversation/README.zh.md) 用它作为覆盖 composer 座位 `right` 偏移——scrollbar-styles 规格把它与镜像规则及消费者配对检查。
56
+ `gradient-shadow-text.css` `--dsh-content-font-size` 派生 `--dsh-content-font-delta`,并以该增量移动 Markdown 标题与基础文本阶梯。它同时派生低一档变量 `--dsh-content-font-size-secondary`(设置 ≤14 时为设置值 −1,>14 时为设置值 −2;默认设置下为 13px)及配套的 `--dsh-content-font-delta-secondary`,供表格变体与比正文低一档的流内行使用。紧凑的小号文本与代码变体保持固定字号。阶梯之外,用户气泡与 composer 草稿直接读取正文档变量对,流内行的标题及摘要读取低一档变量对。
12
57
 
13
- 两条路径在构造上互斥。`scrollbar-width`/`scrollbar-color` 写在 `@supports not selector(::-webkit-scrollbar)` 之内,因为这两个属性中的任一个只要取非 `auto` 值,Chromium 与 Safari 就会丢弃该元素上的全部 `::-webkit-scrollbar*` 规则,`::-webkit-scrollbar-thumb:hover` 也在其中——若无条件地同时声明,`--dsh-scrollbar-thumb-hover` 在任何引擎上都不会被渲染。因此 Firefox 走标准属性,WebKit 系引擎走伪元素,hover token 只经由伪元素这条路径渲染。相关原理与实测计算值见[滚动条 Agent Note](../../../.agents/notes/implemented/bug-fix/2026-07-28-themed-scrollbars-and-reserved-gutter.zh.md)。
58
+ ### 滚动条重新绑定
14
59
 
60
+ `scrollbar.css` 在 `body` 上把 `--dsh-scrollbar-thumb` 与 `--dsh-scrollbar-thumb-hover` 绑定到 l1 基础表面 token;高层级表面(菜单、浮层、对话框)在自己的容器上把它们重新绑定为 l2 token;这组变量的另一个合法目标是 `transparent`(ui-sidebar 在指针不在栏内时就这样重新绑定自己的列)。`--dsh-scrollbar-width` 镜像 WebKit 滚动条的布局宽度,供需要与占布局宽度的滚动条对齐的表面使用。两条渲染路径在构造上互斥:Firefox 走 `@supports not selector(::-webkit-scrollbar)` 内的标准属性,WebKit 系引擎走伪元素,因此 hover token 只经由伪元素这条路径渲染([滚动条笔记](../../../.agents/notes/implemented/bug-fix/2026-07-28-themed-scrollbars-and-reserved-gutter.zh.md))。
61
+
62
+ ### 偏好持久化
63
+
64
+ 在 loopback 浏览器上,服务先以 schema 默认值立即提供自身,随后加载 `ui-theme` 命名空间,并把每次通过的主题或字号变更经 Host settings API 写入。收到推送的设置变更时或重连后都会重新拉取该命名空间。非 loopback 页面不会创建该 Host-backed scope。该持久化边界由 [Host 支撑的偏好笔记](../../../.agents/notes/implemented/bug-fix/2026-08-06-host-backed-web-preferences.zh.md) 拥有。
65
+
66
+ </details>
67
+
68
+ -----
69
+
70
+ <a id="further-exploration"></a>
71
+ ## 进一步探索
72
+
73
+ 以下页面覆盖布局呈现器、token 消费方与样式规则。
74
+
75
+ - [ui-layout](../ui-layout/README.zh.md)——应用解析后主题快照的呈现器。
76
+ - [ui-sidebar](../ui-sidebar/README.zh.md)——滚动条重新绑定约定的消费方。
77
+ - [ui-conversation](../ui-conversation/README.zh.md)——为 composer 席位消费 `--dsh-scrollbar-width` 的消费方。
78
+ - [Web 样式](../../../docs/web-styling.zh.md)——Web 客户端组件的权威样式规则。
79
+ - [Host 支撑的偏好](../../../.agents/notes/implemented/bug-fix/2026-08-06-host-backed-web-preferences.zh.md)——持久化边界决策。
80
+
81
+ -----
82
+
83
+ <a id="model-experience"></a>
15
84
  ## 模型体验
16
85
 
17
- 无。主题服务管理浏览器偏好;这里没有任何内容进入模型请求。
86
+ 无。该包是浏览器端 UI 插件层,不注册任何面向模型的内容。
18
87
 
19
88
  #### KV Cache 影响
20
89
 
21
90
  无;该包既不组装也不发送提供方请求。
22
91
 
23
- ## 已知限制与暂缓事项
92
+ ## 已知限制与延期工作
93
+
94
+ <a id="known-limitations-and-deferred-work"></a>
95
+
96
+
97
+ 这些限制定义主题扩展表面与颜色权威;它们是当前包约束。
98
+
99
+ - **第三方主题是扩展点,不是产品**:注册主题意味着覆盖同名别名变量;目前不会验证一组覆盖是否完整。
100
+ - **token 样式表是颜色值的唯一权威来源**:设计系统中缺失的值会有意不补入;一律采用最接近的语义 token,设计负责人批准的新增值须在同一变更中以一个静态尺度层级与一个语义别名的形式进入。
101
+
102
+ <a id="dev-note"></a>
103
+ ### 开发备注
104
+
105
+ <details>
106
+ <summary>维护者的工作上下文——点击展开</summary>
107
+
108
+ 无。
24
109
 
25
- - **第三方主题是表层,不是产品**:注册主题意味着覆盖同名别名变量;目前不会验证一组覆盖是否完整。
26
- - **token 样式表是颜色值的唯一权威来源**:会有意不补入 cssdesign 中缺失的值(例如设计中的 #4176E6 标签页蓝色);一律采用最接近的语义 token。设计负责人批准的新增值是例外:须在同一变更中以一个静态尺度层级与一个语义别名的形式进入(`--dsw-static-blue-900` / `--dsw-alias-label-primary-bluish`)。
110
+ </details>
package/lib/client.js CHANGED
@@ -6,7 +6,7 @@ window.__ModuleLoader__.load({
6
6
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
7
7
  let react_jsx_runtime = require("react/jsx-runtime");
8
8
  let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
9
- let _deepseek_ai_dsh_client_runtime_client = require("@deepseek-ai/dsh-client-runtime/client");
9
+ let _deepseek_ai_dsh_client_store = require("@deepseek-ai/dsh-client-store");
10
10
  //#region ../../../node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/dist/clsx.mjs
11
11
  function r(e) {
12
12
  var t, f, n = "";
@@ -23,13 +23,13 @@ window.__ModuleLoader__.load({
23
23
  }
24
24
  //#endregion
25
25
  //#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-theme/src/client/AppearanceRow.module.css.mjs
26
- const css = "._8HJdBW_group{border-bottom:1px solid var(--dsw-alias-border-l2);flex-direction:column;gap:8px;padding:16px 0;display:flex}._8HJdBW_title{color:var(--dsw-alias-label-primary);font-size:14px;font-weight:400;line-height:22px}._8HJdBW_cubeRow{flex-wrap:wrap;align-items:stretch;gap:8px;display:flex}._8HJdBW_themeCube{box-sizing:border-box;border:1px solid var(--dsw-alias-border-l2);font:inherit;color:var(--dsw-alias-label-primary);cursor:pointer;background:0 0;border-radius:16px;flex-direction:column;flex:180px;justify-content:center;align-items:center;gap:4px;padding:20px 32px;font-size:14px;line-height:22px;display:flex}._8HJdBW_themeCube:hover:not(._8HJdBW_selected){background:var(--dsw-alias-interactive-bg-hover)}._8HJdBW_selected{background:var(--dsw-alias-bg-module-platform);border-color:var(--dsw-static-neutral-bluish-400)}";
27
- const tagId = "@deepseek-ai/dsh-client-ui-theme/AppearanceRow.module.css";
28
- if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
26
+ const css$1 = "._8HJdBW_group{border-bottom:1px solid var(--dsw-alias-border-l2);flex-direction:column;gap:8px;padding:16px 0;display:flex}._8HJdBW_title{color:var(--dsw-alias-label-primary);font-size:14px;font-weight:400;line-height:22px}._8HJdBW_cubeRow{flex-wrap:wrap;align-items:stretch;gap:8px;display:flex}._8HJdBW_themeCube{box-sizing:border-box;border:1px solid var(--dsw-alias-border-l2);font:inherit;color:var(--dsw-alias-label-primary);cursor:pointer;background:0 0;border-radius:16px;flex-direction:column;flex:180px;justify-content:center;align-items:center;gap:4px;padding:20px 32px;font-size:14px;line-height:22px;display:flex}._8HJdBW_themeCube:hover:not(._8HJdBW_selected){background:var(--dsw-alias-interactive-bg-hover)}._8HJdBW_selected{background:var(--dsw-alias-bg-module-platform);border-color:var(--dsw-static-neutral-bluish-400)}";
27
+ const tagId$1 = "@deepseek-ai/dsh-client-ui-theme/AppearanceRow.module.css";
28
+ if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
29
29
  const tag = document.createElement("style");
30
30
  tag.dataset.plugin = "@deepseek-ai/dsh-client-ui-theme";
31
- tag.dataset.pluginCss = tagId;
32
- tag.textContent = css;
31
+ tag.dataset.pluginCss = tagId$1;
32
+ tag.textContent = css$1;
33
33
  document.head.appendChild(tag);
34
34
  }
35
35
  var AppearanceRow_module_css_default = {
@@ -93,89 +93,6 @@ window.__ModuleLoader__.load({
93
93
  });
94
94
  }
95
95
  //#endregion
96
- //#region lib/types/client/settings-store.js
97
- /**
98
- * Appearance row slot store: a mirror of the theme service snapshot. The
99
- * plugin's apply-world change listener is the only writer; the row component
100
- * reads via props.useStore.
101
- */
102
- /**
103
- * Declares the Appearance row state and write surface.
104
- * @returns the store handle.
105
- */
106
- function createAppearanceRowStore() {
107
- return (0, _deepseek_ai_dsh_client_runtime_client.defineStore)({
108
- init: () => ({
109
- preference: "system",
110
- revision: -1
111
- }),
112
- actions: { sync: (d, preference, revision) => {
113
- if (revision <= d.revision) return;
114
- d.preference = preference;
115
- d.revision = revision;
116
- } }
117
- });
118
- }
119
- //#endregion
120
- //#region \0dsh-inline-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-theme/src/styles/base.css.mjs
121
- var base_css_default = ":root{--dsw-font-family:-apple-system, BlinkMacSystemFont, \"Segoe UI\", \"PingFang SC\", \"Hiragino Sans GB\", \"Microsoft YaHei\", \"Helvetica Neue\", Helvetica, Arial, sans-serif;--ds-font-family-code:\"SF Mono\", \"JetBrains Mono\", \"Fira Code\", Consolas, \"Liberation Mono\", Menlo, Courier, \"PingFang SC\", \"Microsoft YaHei\";--ds-ease-in-out:cubic-bezier(.4, 0, .2, 1);--ds-transition-duration:.2s;--ds-transition-duration-fast:.1s;--ds-transition-duration-slow:.3s}";
122
- //#endregion
123
- //#region \0dsh-inline-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-theme/src/styles/design-platform.css.mjs
124
- var design_platform_css_default = "body{--dsw-static-amber-100:#fef5e7;--dsw-static-amber-400:#f7ad31;--dsw-static-amber-500:#f59e0b;--dsw-static-amber-600:#dd8629;--dsw-static-amber-900:#27241f;--dsw-static-blue-100:#dbeafe;--dsw-static-blue-300:#93c5fd;--dsw-static-blue-400:#60a5fa;--dsw-static-blue-450:#4d93f8;--dsw-static-blue-500:#3b82f6;--dsw-static-blue-50:#eff6ff;--dsw-static-blue-50p:#eaf3ff;--dsw-static-blue-600:#2563eb;--dsw-static-blue-75:#e5f0ff;--dsw-static-blue-800:#1e40af;--dsw-static-blue-900:#0e3074;--dsw-static-blue-950:#172554;--dsw-static-deepseek-100:#e4edfd;--dsw-static-deepseek-200:#d3e2ff;--dsw-static-deepseek-300:#b7c8fe;--dsw-static-deepseek-400:#679efe;--dsw-static-deepseek-450:#5686fe;--dsw-static-deepseek-500:#4176e6;--dsw-static-deepseek-50:#edf3fe;--dsw-static-deepseek-600:#4868b2;--dsw-static-deepseek-700-delete:#2f4c8f;--dsw-static-deepseek-800:#34415b;--dsw-static-deepseek-900:#283142;--dsw-static-green-100:#e6faed;--dsw-static-green-400:#4ed17e;--dsw-static-green-500:#22c55e;--dsw-static-green-900:#233c2c;--dsw-static-neutral-00:#fff;--dsw-static-neutral-1000:#000;--dsw-static-neutral-100:#f5f5f5;--dsw-static-neutral-150:#ededed;--dsw-static-neutral-200:#e5e5e5;--dsw-static-neutral-250:#dcdcdc;--dsw-static-neutral-300:#d4d4d4;--dsw-static-neutral-400:#a2a4a6;--dsw-static-neutral-500:#7f8287;--dsw-static-neutral-50:#fafafa;--dsw-static-neutral-550:#65676b;--dsw-static-neutral-600:#545557;--dsw-static-neutral-700:#3c3c3d;--dsw-static-neutral-800:#292929;--dsw-static-neutral-850:#212123;--dsw-static-neutral-900:#0f0f0f;--dsw-static-neutral-bluish-00:#fff;--dsw-static-neutral-bluish-1000:#0f1115;--dsw-static-neutral-bluish-100:#ebeef2;--dsw-static-neutral-bluish-150:#e9ecf2;--dsw-static-neutral-bluish-200:#e1e5ee;--dsw-static-neutral-bluish-300:#cfd3d6;--dsw-static-neutral-bluish-400:#adb2b8;--dsw-static-neutral-bluish-500:#979da6;--dsw-static-neutral-bluish-50:#f9fafb;--dsw-static-neutral-bluish-600:#81858c;--dsw-static-neutral-bluish-60:#f5f6f7;--dsw-static-neutral-bluish-700:#61666b;--dsw-static-neutral-bluish-750:#43454a;--dsw-static-neutral-bluish-75:#f1f3f5;--dsw-static-neutral-bluish-800:#353638;--dsw-static-neutral-bluish-850:#2c2c2e;--dsw-static-neutral-bluish-875:#232324;--dsw-static-neutral-bluish-900:#1b1b1c;--dsw-static-neutral-bluish-950:#151517;--dsw-static-red-100:#fee2e2;--dsw-static-red-400:#f25a5a;--dsw-static-red-500:#ef4444;--dsw-static-red-50:#fef2f2;--dsw-static-red-600:#ec1313;--dsw-static-red-900:#570c0c}body[data-ds-dark-theme]{--dsw-static-amber-100:#fef5e7;--dsw-static-amber-400:#f7ad31;--dsw-static-amber-500:#f59e0b;--dsw-static-amber-600:#dd8629;--dsw-static-amber-900:#27241f;--dsw-static-blue-100:#dbeafe;--dsw-static-blue-300:#93c5fd;--dsw-static-blue-400:#60a5fa;--dsw-static-blue-450:#4d93f8;--dsw-static-blue-500:#3b82f6;--dsw-static-blue-50:#eff6ff;--dsw-static-blue-50p:#eaf3ff;--dsw-static-blue-600:#2563eb;--dsw-static-blue-75:#e5f0ff;--dsw-static-blue-800:#1e40af;--dsw-static-blue-900:#0e3074;--dsw-static-blue-950:#172554;--dsw-static-deepseek-100:#e4edfd;--dsw-static-deepseek-200:#d3e2ff;--dsw-static-deepseek-300:#b7c8fe;--dsw-static-deepseek-400:#679efe;--dsw-static-deepseek-450:#5686fe;--dsw-static-deepseek-500:#4176e6;--dsw-static-deepseek-50:#edf3fe;--dsw-static-deepseek-600:#4868b2;--dsw-static-deepseek-700-delete:#2f4c8f;--dsw-static-deepseek-800:#34415b;--dsw-static-deepseek-900:#283142;--dsw-static-green-100:#e6faed;--dsw-static-green-400:#4ed17e;--dsw-static-green-500:#22c55e;--dsw-static-green-900:#233c2c;--dsw-static-neutral-00:#fff;--dsw-static-neutral-1000:#000;--dsw-static-neutral-100:#f5f5f5;--dsw-static-neutral-150:#ededed;--dsw-static-neutral-200:#e5e5e5;--dsw-static-neutral-250:#dcdcdc;--dsw-static-neutral-300:#d4d4d4;--dsw-static-neutral-400:#a2a4a6;--dsw-static-neutral-500:#7f8287;--dsw-static-neutral-50:#fafafa;--dsw-static-neutral-550:#65676b;--dsw-static-neutral-600:#545557;--dsw-static-neutral-700:#3c3c3d;--dsw-static-neutral-800:#292929;--dsw-static-neutral-850:#212123;--dsw-static-neutral-900:#0f0f0f;--dsw-static-neutral-bluish-00:#fff;--dsw-static-neutral-bluish-1000:#0f1115;--dsw-static-neutral-bluish-100:#ebeef2;--dsw-static-neutral-bluish-150:#e9ecf2;--dsw-static-neutral-bluish-200:#e1e5ee;--dsw-static-neutral-bluish-300:#cfd3d6;--dsw-static-neutral-bluish-400:#adb2b8;--dsw-static-neutral-bluish-500:#979da6;--dsw-static-neutral-bluish-50:#f9fafb;--dsw-static-neutral-bluish-600:#81858c;--dsw-static-neutral-bluish-60:#f9fafb;--dsw-static-neutral-bluish-700:#61666b;--dsw-static-neutral-bluish-750:#43454a;--dsw-static-neutral-bluish-75:#f1f3f5;--dsw-static-neutral-bluish-800:#353638;--dsw-static-neutral-bluish-850:#2c2c2e;--dsw-static-neutral-bluish-875:#232324;--dsw-static-neutral-bluish-900:#1b1b1c;--dsw-static-neutral-bluish-950:#151517;--dsw-static-red-100:#fee2e2;--dsw-static-red-400:#f25a5a;--dsw-static-red-500:#ef4444;--dsw-static-red-50:#fef2f2;--dsw-static-red-600:#ec1313;--dsw-static-red-900:#570c0c}body{--dsw-alias-bg-base:var(--dsw-static-neutral-bluish-00);--dsw-alias-bg-layer-1:var(--dsw-static-neutral-bluish-00);--dsw-alias-bg-layer-2:var(--dsw-static-neutral-bluish-00);--dsw-alias-bg-layer-3:var(--dsw-static-neutral-bluish-00);--dsw-alias-bg-mask-1:#0000003d;--dsw-alias-bg-mask-2:#0000001f;--dsw-alias-bg-mask-3:#0000007a;--dsw-alias-bg-mask-photo:#000000e0;--dsw-alias-bg-mask-drop:#ffffffb3;--dsw-alias-bg-module-platform:var(--dsw-static-neutral-bluish-60);--dsw-alias-bg-multi-select:var(--dsw-static-neutral-bluish-60);--dsw-alias-bg-overlay:var(--dsw-static-neutral-bluish-150);--dsw-alias-bg-skeleton:#0000000a;--dsw-alias-border-inverted2:#0000;--dsw-alias-border-inverted:#0000;--dsw-alias-border-l1:#0000000a;--dsw-alias-border-l2-darkmode-thin:#0000001a;--dsw-alias-border-l2:#0000001a;--dsw-alias-border-l3:#0000001f;--dsw-alias-border-l4:#00000029;--dsw-alias-brand-primary-invert:var(--dsw-static-neutral-bluish-1000);--dsw-alias-brand-primary-new-colorprimary-new-color:#4176e6;--dsw-alias-brand-primary:var(--dsw-static-neutral-bluish-1000);--dsw-alias-brand-text:var(--dsw-static-neutral-bluish-1000);--dsw-alias-button-contrast-fill:var(--dsw-static-neutral-bluish-700);--dsw-alias-button-elevated-fill:var(--dsw-static-neutral-bluish-00);--dsw-alias-button-floating-fill:var(--dsw-static-neutral-bluish-00);--dsw-alias-button-floating-hover:var(--dsw-static-neutral-bluish-75);--dsw-alias-button-ghost-active-border:var(--dsw-static-neutral-bluish-500);--dsw-alias-button-ghost-active-fill:var(--dsw-static-neutral-bluish-100);--dsw-alias-button-ghost-active-hover:var(--dsw-static-neutral-bluish-150);--dsw-alias-button-info-fill:var(--dsw-static-deepseek-500);--dsw-alias-button-info-hover:var(--dsw-static-deepseek-400);--dsw-alias-button-primary-dimmed:var(--dsw-static-neutral-bluish-100);--dsw-alias-button-primary-fill:var(--dsw-alias-brand-primary);--dsw-alias-button-primary-hover:var(--dsw-static-neutral-bluish-750);--dsw-alias-button-tool-bar-fill-invisible:#1f1f1f5c;--dsw-alias-button-tool-bar-fill:#54555780;--dsw-alias-button-tool-bar-hover:#54555799;--dsw-alias-interactive-bg-active:#2631481a;--dsw-alias-interactive-bg-hover-accent:#26314824;--dsw-alias-interactive-bg-hover-danger:#ec13130d;--dsw-alias-interactive-bg-hover-solid:var(--dsw-static-neutral-bluish-75);--dsw-alias-interactive-bg-hover:#2631480f;--dsw-alias-label-caption:var(--dsw-static-neutral-bluish-400);--dsw-alias-label-dimmed:var(--dsw-static-neutral-bluish-200);--dsw-alias-label-primary-bluish:var(--dsw-static-blue-900);--dsw-alias-label-primary-dimmed:var(--dsw-static-neutral-bluish-950);--dsw-alias-label-primary-foreground:var(--dsw-static-neutral-bluish-00);--dsw-alias-label-primary-inverted:var(--dsw-static-neutral-bluish-00);--dsw-alias-label-primary:var(--dsw-static-neutral-bluish-1000);--dsw-alias-label-secondary:var(--dsw-static-neutral-bluish-700);--dsw-alias-label-tertiary:var(--dsw-static-neutral-bluish-600);--dsw-alias-markdown-citation:var(--dsw-static-neutral-bluish-100);--dsw-alias-markdown-code-block-banner:var(--dsw-static-neutral-bluish-50);--dsw-alias-markdown-code-block:var(--dsw-static-neutral-bluish-50);--dsw-alias-markdown-code-segment-selected:var(--dsw-static-neutral-bluish-00);--dsw-alias-markdown-code-segment-unselected:var(--dsw-static-neutral-bluish-75);--dsw-alias-markdown-inline-code:var(--dsw-static-neutral-bluish-100);--dsw-alias-markdown-placeholder:var(--dsw-static-neutral-bluish-60);--dsw-alias-markdown-tag:var(--dsw-static-neutral-bluish-75);--dsw-alias-scrollbar-bg-l1:var(--dsw-static-neutral-200);--dsw-alias-scrollbar-bg-l2:var(--dsw-static-neutral-200);--dsw-alias-scrollbar-hover-l1:var(--dsw-static-neutral-300);--dsw-alias-scrollbar-hover-l2:var(--dsw-static-neutral-300);--dsw-alias-state-business-primary:var(--dsw-static-deepseek-500);--dsw-alias-state-business-tertiary:var(--dsw-static-deepseek-100);--dsw-alias-state-error-primary:var(--dsw-static-red-600);--dsw-alias-state-error-secondary:var(--dsw-static-red-400);--dsw-alias-state-success-primary:var(--dsw-static-green-500);--dsw-alias-state-success-secondary:var(--dsw-static-green-400);--dsw-alias-state-success-tertiary:var(--dsw-static-green-100);--dsw-alias-state-warn-label:var(--dsw-static-amber-600);--dsw-alias-state-warn-primary:var(--dsw-static-amber-500);--dsw-alias-state-warn-secondary:var(--dsw-static-amber-400);--dsw-alias-state-warn-tertiary:var(--dsw-static-amber-100);--dsw-alias-toast-bg:var(--dsw-static-neutral-bluish-800);--dsw-alias-tooltip-bg:var(--dsw-static-neutral-bluish-850);--dsw-specific-bubble-highlight:var(--dsw-static-deepseek-200);--dsw-specific-bubble:var(--dsw-static-deepseek-50);--dsw-specific-input-major:var(--dsw-static-neutral-bluish-00);--dsw-specific-login-input:var(--dsw-static-neutral-bluish-50);--dsw-specific-menu:var(--dsw-alias-bg-layer-3);--dsw-specific-selector:var(--dsw-static-neutral-bluish-60);--dsw-specific-sidebar-fill:var(--dsw-static-neutral-bluish-50);--dsw-specific-sidebar-nav-item-active-accent:var(--dsw-static-deepseek-100);--dsw-specific-sidebar-nav-item-active:var(--dsw-static-neutral-bluish-100);--dsw-specific-sidebar-nav-item-hover:var(--dsw-static-neutral-bluish-75);--dsw-specific-tip:var(--dsw-static-neutral-bluish-60)}body[data-ds-dark-theme]{--dsw-alias-bg-base:var(--dsw-static-neutral-bluish-950);--dsw-alias-bg-layer-1:var(--dsw-static-neutral-bluish-875);--dsw-alias-bg-layer-2:var(--dsw-static-neutral-bluish-850);--dsw-alias-bg-layer-3:var(--dsw-static-neutral-bluish-800);--dsw-alias-bg-mask-1:#00000080;--dsw-alias-bg-mask-2:#0003;--dsw-alias-bg-mask-3:#0000007a;--dsw-alias-bg-mask-photo:#000000e0;--dsw-alias-bg-mask-drop:#272730b3;--dsw-alias-bg-module-platform:var(--dsw-static-neutral-bluish-800);--dsw-alias-bg-multi-select:var(--dsw-static-neutral-850);--dsw-alias-bg-overlay:var(--dsw-static-neutral-bluish-700);--dsw-alias-bg-skeleton:#ffffff14;--dsw-alias-border-inverted2:#ffffff14;--dsw-alias-border-inverted:#ffffff0f;--dsw-alias-border-l1:#ffffff0f;--dsw-alias-border-l2-darkmode-thin:#ffffff0f;--dsw-alias-border-l2:#ffffff1f;--dsw-alias-border-l3:#ffffff29;--dsw-alias-border-l4:#fff3;--dsw-alias-brand-primary-invert:var(--dsw-static-neutral-bluish-50);--dsw-alias-brand-primary-new-colorprimary-new-color:var(--dsw-static-deepseek-450);--dsw-alias-brand-primary:var(--dsw-static-neutral-bluish-50);--dsw-alias-brand-text:var(--dsw-static-neutral-bluish-50);--dsw-alias-button-contrast-fill:var(--dsw-static-neutral-bluish-50);--dsw-alias-button-elevated-fill:var(--dsw-static-neutral-bluish-750);--dsw-alias-button-floating-fill:var(--dsw-static-neutral-bluish-850);--dsw-alias-button-floating-hover:var(--dsw-static-neutral-bluish-800);--dsw-alias-button-ghost-active-border:var(--dsw-static-neutral-bluish-600);--dsw-alias-button-ghost-active-fill:var(--dsw-static-neutral-bluish-750);--dsw-alias-button-ghost-active-hover:var(--dsw-static-neutral-bluish-700);--dsw-alias-button-info-fill:var(--dsw-static-deepseek-400);--dsw-alias-button-info-hover:var(--dsw-static-deepseek-500);--dsw-alias-button-primary-dimmed:var(--dsw-static-neutral-bluish-750);--dsw-alias-button-primary-fill:var(--dsw-alias-brand-primary);--dsw-alias-button-primary-hover:var(--dsw-static-neutral-bluish-100);--dsw-alias-button-tool-bar-fill-invisible:#1f1f1f5c;--dsw-alias-button-tool-bar-fill:#54555780;--dsw-alias-button-tool-bar-hover:#54555799;--dsw-alias-interactive-bg-active:#ffffff24;--dsw-alias-interactive-bg-hover-accent:#ffffff3d;--dsw-alias-interactive-bg-hover-danger:#f25a5a26;--dsw-alias-interactive-bg-hover-solid:var(--dsw-static-neutral-bluish-800);--dsw-alias-interactive-bg-hover:#ffffff14;--dsw-alias-label-caption:var(--dsw-static-neutral-bluish-600);--dsw-alias-label-dimmed:var(--dsw-static-neutral-bluish-750);--dsw-alias-label-primary-bluish:var(--dsw-static-neutral-bluish-50);--dsw-alias-label-primary-dimmed:var(--dsw-static-neutral-bluish-100);--dsw-alias-label-primary-foreground:var(--dsw-static-neutral-bluish-1000);--dsw-alias-label-primary-inverted:var(--dsw-static-neutral-bluish-800);--dsw-alias-label-primary:var(--dsw-static-neutral-bluish-50);--dsw-alias-label-secondary:var(--dsw-static-neutral-bluish-300);--dsw-alias-label-tertiary:var(--dsw-static-neutral-bluish-400);--dsw-alias-markdown-citation:var(--dsw-static-neutral-bluish-800);--dsw-alias-markdown-code-block-banner:var(--dsw-static-neutral-bluish-850);--dsw-alias-markdown-code-block:var(--dsw-static-neutral-bluish-900);--dsw-alias-markdown-code-segment-selected:var(--dsw-static-neutral-bluish-800);--dsw-alias-markdown-code-segment-unselected:var(--dsw-static-neutral-bluish-900);--dsw-alias-markdown-inline-code:var(--dsw-static-neutral-bluish-850);--dsw-alias-markdown-placeholder:var(--dsw-static-neutral-bluish-850);--dsw-alias-markdown-tag:var(--dsw-static-neutral-bluish-850);--dsw-alias-scrollbar-bg-l1:var(--dsw-static-neutral-700);--dsw-alias-scrollbar-bg-l2:var(--dsw-static-neutral-600);--dsw-alias-scrollbar-hover-l1:var(--dsw-static-neutral-600);--dsw-alias-scrollbar-hover-l2:var(--dsw-static-neutral-550);--dsw-alias-state-business-primary:var(--dsw-static-deepseek-400);--dsw-alias-state-business-tertiary:var(--dsw-static-deepseek-800);--dsw-alias-state-error-primary:var(--dsw-static-red-400);--dsw-alias-state-error-secondary:var(--dsw-static-red-400);--dsw-alias-state-success-primary:var(--dsw-static-green-500);--dsw-alias-state-success-secondary:var(--dsw-static-green-400);--dsw-alias-state-success-tertiary:var(--dsw-static-green-900);--dsw-alias-state-warn-label:var(--dsw-static-amber-600);--dsw-alias-state-warn-primary:var(--dsw-static-amber-500);--dsw-alias-state-warn-secondary:var(--dsw-static-amber-400);--dsw-alias-state-warn-tertiary:var(--dsw-static-amber-900);--dsw-alias-toast-bg:var(--dsw-static-neutral-bluish-750);--dsw-alias-tooltip-bg:var(--dsw-static-neutral-bluish-750);--dsw-specific-bubble-highlight:var(--dsw-static-neutral-bluish-750);--dsw-specific-bubble:var(--dsw-static-neutral-bluish-850);--dsw-specific-input-major:var(--dsw-static-neutral-bluish-850);--dsw-specific-login-input:var(--dsw-static-neutral-bluish-900);--dsw-specific-menu:var(--dsw-alias-bg-layer-3);--dsw-specific-selector:var(--dsw-static-neutral-bluish-800);--dsw-specific-sidebar-fill:var(--dsw-static-neutral-bluish-900);--dsw-specific-sidebar-nav-item-active-accent:var(--dsw-static-neutral-bluish-800);--dsw-specific-sidebar-nav-item-active:var(--dsw-static-neutral-bluish-750);--dsw-specific-sidebar-nav-item-hover:var(--dsw-static-neutral-bluish-850);--dsw-specific-tip:var(--dsw-static-neutral-bluish-800)}";
125
- //#endregion
126
- //#region \0dsh-inline-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-theme/src/styles/scrollbar.css.mjs
127
- var scrollbar_css_default = "body{--dsh-scrollbar-thumb:var(--dsw-alias-scrollbar-bg-l1);--dsh-scrollbar-thumb-hover:var(--dsw-alias-scrollbar-hover-l1);--dsh-scrollbar-width:8px}@supports not selector(::-webkit-scrollbar){body,body *{scrollbar-width:thin;scrollbar-color:var(--dsh-scrollbar-thumb) transparent}}::-webkit-scrollbar{width:8px;height:8px}::-webkit-scrollbar-track{background:0 0}::-webkit-scrollbar-thumb{background:var(--dsh-scrollbar-thumb);border-radius:4px}::-webkit-scrollbar-thumb:hover{background:var(--dsh-scrollbar-thumb-hover)}::-webkit-scrollbar-corner{background:0 0}";
128
- //#endregion
129
- //#region \0dsh-inline-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-theme/src/styles/gradient-shadow-text.css.mjs
130
- var gradient_shadow_text_css_default = "body{--dsw-linear-gradient-think:linear-gradient(180deg, #fff 20.19%, #fff0 100%);--dsw-linear-think-select:linear-gradient(180deg, #f5f6f7 20.19%, #f5f6f700 100%);--dsw-shadow-lv1:0 2px 4px 0 #0000000d;--dsw-shadow-lv1-blur:0 4px 12px 0 #00000005;--dsw-shadow-lv2:0 4px 12px 0 #00000005, 0 2px 8px 0 #0000000a;--dsw-shadow-lv3:0 0 1px 0 #0003, 0 0 4px 0 #00000005, 0 12px 32px 0 #00000014;--dsw-mask-blur:blur(2px)}body[data-ds-dark-theme]{--dsw-linear-gradient-think:linear-gradient(180deg, #151517 20.19%, #15151700 100%);--dsw-linear-think-select:linear-gradient(180deg, #232325 20.19%, #23232500 100%)}body{--dsw-font-markdown-h1:700 24px/34px var(--dsw-font-family);--dsw-font-markdown-h1-font-family:var(--dsw-font-family);--dsw-font-markdown-h1-font-weight:700;--dsw-font-markdown-h1-line-height:34px;--dsw-font-markdown-h1-font-size:24px;--dsw-font-markdown-h1-font-style:normal;--dsw-font-markdown-h2:700 22px/32px var(--dsw-font-family);--dsw-font-markdown-h2-font-family:var(--dsw-font-family);--dsw-font-markdown-h2-font-weight:700;--dsw-font-markdown-h2-line-height:32px;--dsw-font-markdown-h2-font-size:22px;--dsw-font-markdown-h2-font-style:normal;--dsw-font-markdown-h3:700 20px/30px var(--dsw-font-family);--dsw-font-markdown-h3-font-family:var(--dsw-font-family);--dsw-font-markdown-h3-font-weight:700;--dsw-font-markdown-h3-line-height:30px;--dsw-font-markdown-h3-font-size:20px;--dsw-font-markdown-h3-font-style:normal;--dsw-font-markdown-h4:600 16px/28px var(--dsw-font-family);--dsw-font-markdown-h4-font-family:var(--dsw-font-family);--dsw-font-markdown-h4-font-weight:600;--dsw-font-markdown-h4-line-height:28px;--dsw-font-markdown-h4-font-size:16px;--dsw-font-markdown-h4-font-style:normal;--dsw-font-markdown-base:16px/28px var(--dsw-font-family);--dsw-font-markdown-base-font-family:var(--dsw-font-family);--dsw-font-markdown-base-font-weight:400;--dsw-font-markdown-base-line-height:28px;--dsw-font-markdown-base-font-size:16px;--dsw-font-markdown-base-font-style:normal;--dsw-font-markdown-base-strong:600 16px/28px var(--dsw-font-family);--dsw-font-markdown-base-strong-font-family:var(--dsw-font-family);--dsw-font-markdown-base-strong-font-weight:600;--dsw-font-markdown-base-strong-line-height:28px;--dsw-font-markdown-base-strong-font-size:16px;--dsw-font-markdown-base-strong-font-style:normal;--dsw-font-markdown-base-italic:italic 16px/28px var(--dsw-font-family);--dsw-font-markdown-base-italic-font-family:var(--dsw-font-family);--dsw-font-markdown-base-italic-font-weight:400;--dsw-font-markdown-base-italic-line-height:28px;--dsw-font-markdown-base-italic-font-size:16px;--dsw-font-markdown-base-italic-font-style:italic;--dsw-font-markdown-base-strong-italic:italic 600 16px/28px var(--dsw-font-family);--dsw-font-markdown-base-strong-italic-font-family:var(--dsw-font-family);--dsw-font-markdown-base-strong-italic-font-weight:600;--dsw-font-markdown-base-strong-italic-line-height:28px;--dsw-font-markdown-base-strong-italic-font-size:16px;--dsw-font-markdown-base-strong-italic-font-style:italic;--dsw-font-markdown-table:15px/25px var(--dsw-font-family);--dsw-font-markdown-table-font-family:var(--dsw-font-family);--dsw-font-markdown-table-font-weight:400;--dsw-font-markdown-table-line-height:25px;--dsw-font-markdown-table-font-size:15px;--dsw-font-markdown-table-font-style:normal;--dsw-font-markdown-table-head:500 15px/25px var(--dsw-font-family);--dsw-font-markdown-table-head-font-family:var(--dsw-font-family);--dsw-font-markdown-table-head-font-weight:500;--dsw-font-markdown-table-head-line-height:25px;--dsw-font-markdown-table-head-font-size:15px;--dsw-font-markdown-table-head-font-style:normal;--dsw-font-markdown-small:14px/24px var(--dsw-font-family);--dsw-font-markdown-small-font-family:var(--dsw-font-family);--dsw-font-markdown-small-font-weight:400;--dsw-font-markdown-small-line-height:24px;--dsw-font-markdown-small-font-size:14px;--dsw-font-markdown-small-font-style:normal;--dsw-font-markdown-small-strong:600 14px/24px var(--dsw-font-family);--dsw-font-markdown-small-strong-font-family:var(--dsw-font-family);--dsw-font-markdown-small-strong-font-weight:600;--dsw-font-markdown-small-strong-line-height:24px;--dsw-font-markdown-small-strong-font-size:14px;--dsw-font-markdown-small-strong-font-style:normal;--dsw-font-markdown-small-italic:italic 14px/24px var(--dsw-font-family);--dsw-font-markdown-small-italic-font-family:var(--dsw-font-family);--dsw-font-markdown-small-italic-font-weight:400;--dsw-font-markdown-small-italic-line-height:24px;--dsw-font-markdown-small-italic-font-size:14px;--dsw-font-markdown-small-italic-font-style:italic;--dsw-font-markdown-small-strong-italic:italic 600 14px/24px var(--dsw-font-family);--dsw-font-markdown-small-strong-italic-font-family:var(--dsw-font-family);--dsw-font-markdown-small-strong-italic-font-weight:600;--dsw-font-markdown-small-strong-italic-line-height:24px;--dsw-font-markdown-small-strong-italic-font-size:14px;--dsw-font-markdown-small-strong-italic-font-style:italic;--dsw-font-markdown-code:14px/22px var(--ds-font-family-code);--dsw-font-markdown-code-font-family:var(--ds-font-family-code);--dsw-font-markdown-code-font-weight:400;--dsw-font-markdown-code-line-height:22px;--dsw-font-markdown-code-font-size:14px;--dsw-font-markdown-code-font-style:normal;--dsw-font-markdown-code-block:13px/22px var(--ds-font-family-code);--dsw-font-markdown-code-block-font-family:var(--ds-font-family-code);--dsw-font-markdown-code-block-font-weight:400;--dsw-font-markdown-code-block-line-height:22px;--dsw-font-markdown-code-block-font-size:13px;--dsw-font-markdown-code-block-font-style:normal;--dsw-font-markdown-code-block-small:12px/18px var(--ds-font-family-code);--dsw-font-markdown-code-block-small-font-family:var(--ds-font-family-code);--dsw-font-markdown-code-block-small-font-weight:400;--dsw-font-markdown-code-block-small-line-height:18px;--dsw-font-markdown-code-block-small-font-size:12px;--dsw-font-markdown-code-block-small-font-style:normal;--dsw-font-xl-24:600 24px/32px var(--dsw-font-family);--dsw-font-xl-24-font-family:var(--dsw-font-family);--dsw-font-xl-24-font-weight:600;--dsw-font-xl-24-line-height:32px;--dsw-font-xl-24-font-size:24px;--dsw-font-xl-24-font-style:normal;--dsw-font-l-20:500 20px/28px var(--dsw-font-family);--dsw-font-l-20-font-family:var(--dsw-font-family);--dsw-font-l-20-font-weight:500;--dsw-font-l-20-line-height:28px;--dsw-font-l-20-font-size:20px;--dsw-font-l-20-font-style:normal;--dsw-font-m-18:500 16px/28px var(--dsw-font-family);--dsw-font-m-18-font-family:var(--dsw-font-family);--dsw-font-m-18-font-weight:500;--dsw-font-m-18-line-height:28px;--dsw-font-m-18-font-size:16px;--dsw-font-m-18-font-style:normal;--dsw-font-base-16:16px/24px var(--dsw-font-family);--dsw-font-base-16-font-family:var(--dsw-font-family);--dsw-font-base-16-font-weight:400;--dsw-font-base-16-line-height:24px;--dsw-font-base-16-font-size:16px;--dsw-font-base-16-font-style:normal;--dsw-font-base-strong-16:500 16px/24px var(--dsw-font-family);--dsw-font-base-strong-16-font-family:var(--dsw-font-family);--dsw-font-base-strong-16-font-weight:500;--dsw-font-base-strong-16-line-height:24px;--dsw-font-base-strong-16-font-size:16px;--dsw-font-base-strong-16-font-style:normal;--dsw-font-s-14:14px/22px var(--dsw-font-family);--dsw-font-s-14-font-family:var(--dsw-font-family);--dsw-font-s-14-font-weight:400;--dsw-font-s-14-line-height:22px;--dsw-font-s-14-font-size:14px;--dsw-font-s-14-font-style:normal;--dsw-font-s-strong-14:500 14px/22px var(--dsw-font-family);--dsw-font-s-strong-14-font-family:var(--dsw-font-family);--dsw-font-s-strong-14-font-weight:500;--dsw-font-s-strong-14-line-height:22px;--dsw-font-s-strong-14-font-size:14px;--dsw-font-s-strong-14-font-style:normal;--dsw-font-xs-13:13px/20px var(--dsw-font-family);--dsw-font-xs-13-font-family:var(--dsw-font-family);--dsw-font-xs-13-font-weight:400;--dsw-font-xs-13-line-height:20px;--dsw-font-xs-13-font-size:13px;--dsw-font-xs-13-font-style:normal;--dsw-font-xs-strong-13:500 13px/20px var(--dsw-font-family);--dsw-font-xs-strong-13-font-family:var(--dsw-font-family);--dsw-font-xs-strong-13-font-weight:500;--dsw-font-xs-strong-13-line-height:20px;--dsw-font-xs-strong-13-font-size:13px;--dsw-font-xs-strong-13-font-style:normal;--dsw-font-xxs-12:12px/18px var(--dsw-font-family);--dsw-font-xxs-12-font-family:var(--dsw-font-family);--dsw-font-xxs-12-font-weight:400;--dsw-font-xxs-12-line-height:18px;--dsw-font-xxs-12-font-size:12px;--dsw-font-xxs-12-font-style:normal;--dsw-font-xxs-strong-12:500 12px/18px var(--dsw-font-family);--dsw-font-xxs-strong-12-font-family:var(--dsw-font-family);--dsw-font-xxs-strong-12-font-weight:500;--dsw-font-xxs-strong-12-line-height:18px;--dsw-font-xxs-strong-12-font-size:12px;--dsw-font-xxs-strong-12-font-style:normal;--dsw-font-xxxs-11:11px/14px var(--dsw-font-family);--dsw-font-xxxs-11-font-family:var(--dsw-font-family);--dsw-font-xxxs-11-font-weight:400;--dsw-font-xxxs-11-line-height:14px;--dsw-font-xxxs-11-font-size:11px;--dsw-font-xxxs-11-font-style:normal;--dsw-font-xxxs-strong-11:500 11px/14px var(--dsw-font-family);--dsw-font-xxxs-strong-11-font-family:var(--dsw-font-family);--dsw-font-xxxs-strong-11-font-weight:500;--dsw-font-xxxs-strong-11-line-height:14px;--dsw-font-xxxs-strong-11-font-size:11px;--dsw-font-xxxs-strong-11-font-style:normal}";
131
- //#endregion
132
- //#region \0dsh-inline-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-theme/src/styles/shiki.css.mjs
133
- var shiki_css_default = ":root{--shiki-foreground:var(--dsw-alias-label-primary);--shiki-background:var(--dsw-alias-markdown-code-block);--shiki-token-constant:#1c7ed6;--shiki-token-string:#2f9e44;--shiki-token-comment:#868e96;--shiki-token-keyword:#d6336c;--shiki-token-parameter:#e8590c;--shiki-token-function:#6741d9;--shiki-token-string-expression:#2b8a3e;--shiki-token-punctuation:#495057;--shiki-token-link:#1971c2}body[data-ds-dark-theme]{--shiki-token-constant:#4dabf7;--shiki-token-string:#69db7c;--shiki-token-comment:#adb5bd;--shiki-token-keyword:#faa2c1;--shiki-token-parameter:#ffa94d;--shiki-token-function:#b197fc;--shiki-token-string-expression:#8ce99a;--shiki-token-punctuation:#ced4da;--shiki-token-link:#74c0fc}";
134
- //#endregion
135
- //#region lib/types/client/styles.js
136
- const PLUGIN_ID = "@deepseek-ai/dsh-client-ui-theme";
137
- const STYLES = [
138
- ["base.css", base_css_default],
139
- ["design-platform.css", design_platform_css_default],
140
- ["scrollbar.css", scrollbar_css_default],
141
- ["gradient-shadow-text.css", gradient_shadow_text_css_default],
142
- ["shiki.css", shiki_css_default]
143
- ];
144
- /**
145
- * Mount the global theme sheets for exactly the owning plugin lifetime.
146
- * @param ctx - Owning plugin context.
147
- */
148
- function installThemeStyles(ctx) {
149
- if (typeof document === "undefined") return;
150
- for (const [name, css] of STYLES) ctx.effect(() => {
151
- const tag = document.createElement("style");
152
- tag.dataset.plugin = PLUGIN_ID;
153
- tag.dataset.pluginCss = `${PLUGIN_ID}/${name}`;
154
- tag.textContent = css;
155
- document.head.appendChild(tag);
156
- return () => {
157
- tag.remove();
158
- };
159
- }, `ui-theme: ${name} stylesheet`);
160
- }
161
- //#endregion
162
- //#region lib/types/client/locales.js
163
- /** `settings.theme` namespace dictionaries (the Appearance row's copy). */
164
- /** Simplified Chinese dictionary (the key-set source of truth). */
165
- const zh = {
166
- "appearance.title": "外观",
167
- "appearance.light": "浅色",
168
- "appearance.dark": "深色",
169
- "appearance.system": "跟随系统"
170
- };
171
- /** English dictionary, checked complete against the zh key set. */
172
- const en = {
173
- "appearance.title": "Appearance",
174
- "appearance.light": "Light",
175
- "appearance.dark": "Dark",
176
- "appearance.system": "System"
177
- };
178
- //#endregion
179
96
  //#region ../../../vendor/cosmokit/src/misc.ts
180
97
  /** Return true when a value is `null` or `undefined`. */
181
98
  function isNullable(value) {
@@ -980,9 +897,14 @@ window.__ModuleLoader__.load({
980
897
  const THEME_SETTINGS_NAMESPACE = "ui-theme";
981
898
  /** Field carrying the selected built-in theme preference. */
982
899
  const THEME_PREFERENCE_FIELD = "preference";
900
+ /** Field carrying the conversation content font size. */
901
+ const FONT_SIZE_FIELD = "fontSize";
983
902
  /** Default preference when the user-settings document has no override. */
984
903
  const DEFAULT_PREFERENCE = "system";
985
- Schema.object({ [THEME_PREFERENCE_FIELD]: Schema.union([...THEME_PREFERENCES]).default(DEFAULT_PREFERENCE) });
904
+ Schema.object({
905
+ [THEME_PREFERENCE_FIELD]: Schema.union([...THEME_PREFERENCES]).default(DEFAULT_PREFERENCE),
906
+ [FONT_SIZE_FIELD]: Schema.number().step(1).min(12).max(17).default(14)
907
+ });
986
908
  /**
987
909
  * Narrow one wire or registry value to a persistable preference.
988
910
  * @param value - value crossing the settings or registry boundary.
@@ -992,6 +914,204 @@ window.__ModuleLoader__.load({
992
914
  return THEME_PREFERENCES.some((preference) => preference === value);
993
915
  }
994
916
  //#endregion
917
+ //#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-theme/src/client/FontSizeRow.module.css.mjs
918
+ const css = ".bVCLcG_row{border-bottom:1px solid var(--dsw-alias-border-l2);align-items:center;gap:8px;padding:16px 0;display:flex}.bVCLcG_rowText{flex-direction:column;flex:1;gap:4px;min-width:0;padding-right:48px;display:flex}.bVCLcG_title{color:var(--dsw-alias-label-primary);font-size:14px;font-weight:400;line-height:22px}.bVCLcG_desc{color:var(--dsw-alias-label-tertiary);font-size:12px;font-weight:400;line-height:18px}.bVCLcG_control{align-items:center;gap:8px;display:inline-flex}.bVCLcG_stepper{background:var(--dsw-alias-bg-module-platform);border-radius:18px;justify-content:center;align-items:center;min-width:72px;height:36px;display:inline-flex;position:relative}.bVCLcG_value{text-align:center;font-variant-numeric:tabular-nums;min-width:18px;color:var(--dsw-alias-label-primary);font-size:14px;line-height:22px}.bVCLcG_unit{color:var(--dsw-alias-label-secondary);font-size:14px;line-height:22px}.bVCLcG_arrows{opacity:0;flex-direction:column;gap:2px;display:flex;position:absolute;right:8px}.bVCLcG_stepper:hover .bVCLcG_arrows,.bVCLcG_stepper:focus-within .bVCLcG_arrows{opacity:1}.bVCLcG_arrow{background:color-mix(in srgb, var(--dsw-alias-bg-layer-1) 75%, transparent);width:17px;height:12px;color:var(--dsw-alias-label-primary);cursor:pointer;border:none;border-radius:3px;justify-content:center;align-items:center;padding:0;display:inline-flex}.bVCLcG_arrow:hover:not(:disabled){background:var(--dsw-alias-bg-layer-1)}.bVCLcG_arrow:disabled{color:var(--dsw-alias-label-caption);cursor:default}";
919
+ const tagId = "@deepseek-ai/dsh-client-ui-theme/FontSizeRow.module.css";
920
+ if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
921
+ const tag = document.createElement("style");
922
+ tag.dataset.plugin = "@deepseek-ai/dsh-client-ui-theme";
923
+ tag.dataset.pluginCss = tagId;
924
+ tag.textContent = css;
925
+ document.head.appendChild(tag);
926
+ }
927
+ var FontSizeRow_module_css_default = {
928
+ "arrow": "bVCLcG_arrow",
929
+ "arrows": "bVCLcG_arrows",
930
+ "control": "bVCLcG_control",
931
+ "desc": "bVCLcG_desc",
932
+ "row": "bVCLcG_row",
933
+ "rowText": "bVCLcG_rowText",
934
+ "stepper": "bVCLcG_stepper",
935
+ "title": "bVCLcG_title",
936
+ "unit": "bVCLcG_unit",
937
+ "value": "bVCLcG_value"
938
+ };
939
+ //#endregion
940
+ //#region lib/types/client/FontSizeRow.js
941
+ /**
942
+ * Font-size preference row registered into the General section item slot:
943
+ * title + body-text-only description + stepper pill (centered value; hover
944
+ * reveals the up/down arrow column anchored to the pill's right edge) + a px
945
+ * unit label after the pill. Registered by this package — the theme feature
946
+ * owns the content font-size setting the same way it owns the appearance
947
+ * preference. The displayed value follows the persisted setting, never the
948
+ * click echo.
949
+ */
950
+ /**
951
+ * Render the font-size row.
952
+ * @param props - composed slot props.
953
+ * @returns the row element tree.
954
+ */
955
+ function FontSizeRow({ t, setFontSize, useStore }) {
956
+ const fontSize = useStore((s) => s.fontSize);
957
+ return (0, react_jsx_runtime.jsxs)("div", {
958
+ className: FontSizeRow_module_css_default.row,
959
+ children: [(0, react_jsx_runtime.jsxs)("div", {
960
+ className: FontSizeRow_module_css_default.rowText,
961
+ children: [(0, react_jsx_runtime.jsx)("div", {
962
+ className: FontSizeRow_module_css_default.title,
963
+ children: t("fontSize.title")
964
+ }), (0, react_jsx_runtime.jsx)("div", {
965
+ className: FontSizeRow_module_css_default.desc,
966
+ children: t("fontSize.description")
967
+ })]
968
+ }), (0, react_jsx_runtime.jsxs)("div", {
969
+ className: FontSizeRow_module_css_default.control,
970
+ children: [(0, react_jsx_runtime.jsxs)("div", {
971
+ className: FontSizeRow_module_css_default.stepper,
972
+ children: [(0, react_jsx_runtime.jsx)("span", {
973
+ className: FontSizeRow_module_css_default.value,
974
+ children: fontSize
975
+ }), (0, react_jsx_runtime.jsxs)("span", {
976
+ className: FontSizeRow_module_css_default.arrows,
977
+ children: [(0, react_jsx_runtime.jsx)("button", {
978
+ type: "button",
979
+ className: FontSizeRow_module_css_default.arrow,
980
+ "aria-label": t("fontSize.increase"),
981
+ disabled: fontSize >= 17,
982
+ onClick: () => {
983
+ setFontSize(fontSize + 1);
984
+ },
985
+ children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronUpOutline14, { size: 9 })
986
+ }), (0, react_jsx_runtime.jsx)("button", {
987
+ type: "button",
988
+ className: FontSizeRow_module_css_default.arrow,
989
+ "aria-label": t("fontSize.decrease"),
990
+ disabled: fontSize <= 12,
991
+ onClick: () => {
992
+ setFontSize(fontSize - 1);
993
+ },
994
+ children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutline14, { size: 9 })
995
+ })]
996
+ })]
997
+ }), (0, react_jsx_runtime.jsx)("span", {
998
+ className: FontSizeRow_module_css_default.unit,
999
+ children: t("fontSize.unit")
1000
+ })]
1001
+ })]
1002
+ });
1003
+ }
1004
+ //#endregion
1005
+ //#region lib/types/client/settings-store.js
1006
+ /**
1007
+ * Appearance and font-size row slot stores: mirrors of the theme service
1008
+ * snapshot. The plugin's apply-world change listener is the only writer; the
1009
+ * row components read via props.useStore.
1010
+ */
1011
+ /**
1012
+ * Declares the Appearance row state and write surface.
1013
+ * @returns the store handle.
1014
+ */
1015
+ function createAppearanceRowStore() {
1016
+ return (0, _deepseek_ai_dsh_client_store.defineStore)({
1017
+ init: () => ({
1018
+ preference: "system",
1019
+ revision: -1
1020
+ }),
1021
+ actions: { sync: (d, preference, revision) => {
1022
+ if (revision <= d.revision) return;
1023
+ d.preference = preference;
1024
+ d.revision = revision;
1025
+ } }
1026
+ });
1027
+ }
1028
+ /**
1029
+ * Declares the font-size row state and write surface.
1030
+ * @returns the store handle.
1031
+ */
1032
+ function createFontSizeRowStore() {
1033
+ return (0, _deepseek_ai_dsh_client_store.defineStore)({
1034
+ init: () => ({
1035
+ fontSize: 14,
1036
+ revision: -1
1037
+ }),
1038
+ actions: { sync: (d, fontSize, revision) => {
1039
+ if (revision <= d.revision) return;
1040
+ d.fontSize = fontSize;
1041
+ d.revision = revision;
1042
+ } }
1043
+ });
1044
+ }
1045
+ //#endregion
1046
+ //#region \0dsh-inline-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-theme/src/styles/base.css.mjs
1047
+ var base_css_default = ":root{--dsw-font-family:-apple-system, BlinkMacSystemFont, \"Segoe UI\", \"PingFang SC\", \"Hiragino Sans GB\", \"Microsoft YaHei\", \"Helvetica Neue\", Helvetica, Arial, sans-serif;--ds-font-family-code:\"SF Mono\", \"JetBrains Mono\", \"Fira Code\", Consolas, \"Liberation Mono\", Menlo, Courier, \"PingFang SC\", \"Microsoft YaHei\";--ds-ease-in-out:cubic-bezier(.4, 0, .2, 1);--ds-transition-duration:.2s;--ds-transition-duration-fast:.1s;--ds-transition-duration-slow:.3s}";
1048
+ //#endregion
1049
+ //#region \0dsh-inline-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-theme/src/styles/design-platform.css.mjs
1050
+ var design_platform_css_default = "body{--dsw-static-amber-100:#fef5e7;--dsw-static-amber-400:#f7ad31;--dsw-static-amber-500:#f59e0b;--dsw-static-amber-600:#dd8629;--dsw-static-amber-900:#27241f;--dsw-static-blue-100:#dbeafe;--dsw-static-blue-300:#93c5fd;--dsw-static-blue-400:#60a5fa;--dsw-static-blue-450:#4d93f8;--dsw-static-blue-500:#3b82f6;--dsw-static-blue-50:#eff6ff;--dsw-static-blue-50p:#eaf3ff;--dsw-static-blue-600:#2563eb;--dsw-static-blue-75:#e5f0ff;--dsw-static-blue-800:#1e40af;--dsw-static-blue-900:#0e3074;--dsw-static-blue-950:#172554;--dsw-static-deepseek-100:#e4edfd;--dsw-static-deepseek-200:#d3e2ff;--dsw-static-deepseek-300:#b7c8fe;--dsw-static-deepseek-400:#679efe;--dsw-static-deepseek-450:#5686fe;--dsw-static-deepseek-500:#4176e6;--dsw-static-deepseek-50:#edf3fe;--dsw-static-deepseek-600:#4868b2;--dsw-static-deepseek-700-delete:#2f4c8f;--dsw-static-deepseek-800:#34415b;--dsw-static-deepseek-900:#283142;--dsw-static-green-100:#e6faed;--dsw-static-green-400:#4ed17e;--dsw-static-green-500:#22c55e;--dsw-static-green-900:#233c2c;--dsw-static-neutral-00:#fff;--dsw-static-neutral-1000:#000;--dsw-static-neutral-100:#f5f5f5;--dsw-static-neutral-150:#ededed;--dsw-static-neutral-200:#e5e5e5;--dsw-static-neutral-250:#dcdcdc;--dsw-static-neutral-300:#d4d4d4;--dsw-static-neutral-400:#a2a4a6;--dsw-static-neutral-500:#7f8287;--dsw-static-neutral-50:#fafafa;--dsw-static-neutral-550:#65676b;--dsw-static-neutral-600:#545557;--dsw-static-neutral-700:#3c3c3d;--dsw-static-neutral-800:#292929;--dsw-static-neutral-850:#212123;--dsw-static-neutral-900:#0f0f0f;--dsw-static-neutral-bluish-00:#fff;--dsw-static-neutral-bluish-1000:#0f1115;--dsw-static-neutral-bluish-100:#ebeef2;--dsw-static-neutral-bluish-150:#e9ecf2;--dsw-static-neutral-bluish-200:#e1e5ee;--dsw-static-neutral-bluish-300:#cfd3d6;--dsw-static-neutral-bluish-400:#adb2b8;--dsw-static-neutral-bluish-500:#979da6;--dsw-static-neutral-bluish-50:#f9fafb;--dsw-static-neutral-bluish-600:#81858c;--dsw-static-neutral-bluish-60:#f5f6f7;--dsw-static-neutral-bluish-700:#61666b;--dsw-static-neutral-bluish-750:#43454a;--dsw-static-neutral-bluish-75:#f1f3f5;--dsw-static-neutral-bluish-800:#353638;--dsw-static-neutral-bluish-850:#2c2c2e;--dsw-static-neutral-bluish-875:#232324;--dsw-static-neutral-bluish-900:#1b1b1c;--dsw-static-neutral-bluish-950:#151517;--dsw-static-red-100:#fee2e2;--dsw-static-red-400:#f25a5a;--dsw-static-red-500:#ef4444;--dsw-static-red-50:#fef2f2;--dsw-static-red-600:#ec1313;--dsw-static-red-900:#570c0c}body[data-ds-dark-theme]{--dsw-static-amber-100:#fef5e7;--dsw-static-amber-400:#f7ad31;--dsw-static-amber-500:#f59e0b;--dsw-static-amber-600:#dd8629;--dsw-static-amber-900:#27241f;--dsw-static-blue-100:#dbeafe;--dsw-static-blue-300:#93c5fd;--dsw-static-blue-400:#60a5fa;--dsw-static-blue-450:#4d93f8;--dsw-static-blue-500:#3b82f6;--dsw-static-blue-50:#eff6ff;--dsw-static-blue-50p:#eaf3ff;--dsw-static-blue-600:#2563eb;--dsw-static-blue-75:#e5f0ff;--dsw-static-blue-800:#1e40af;--dsw-static-blue-900:#0e3074;--dsw-static-blue-950:#172554;--dsw-static-deepseek-100:#e4edfd;--dsw-static-deepseek-200:#d3e2ff;--dsw-static-deepseek-300:#b7c8fe;--dsw-static-deepseek-400:#679efe;--dsw-static-deepseek-450:#5686fe;--dsw-static-deepseek-500:#4176e6;--dsw-static-deepseek-50:#edf3fe;--dsw-static-deepseek-600:#4868b2;--dsw-static-deepseek-700-delete:#2f4c8f;--dsw-static-deepseek-800:#34415b;--dsw-static-deepseek-900:#283142;--dsw-static-green-100:#e6faed;--dsw-static-green-400:#4ed17e;--dsw-static-green-500:#22c55e;--dsw-static-green-900:#233c2c;--dsw-static-neutral-00:#fff;--dsw-static-neutral-1000:#000;--dsw-static-neutral-100:#f5f5f5;--dsw-static-neutral-150:#ededed;--dsw-static-neutral-200:#e5e5e5;--dsw-static-neutral-250:#dcdcdc;--dsw-static-neutral-300:#d4d4d4;--dsw-static-neutral-400:#a2a4a6;--dsw-static-neutral-500:#7f8287;--dsw-static-neutral-50:#fafafa;--dsw-static-neutral-550:#65676b;--dsw-static-neutral-600:#545557;--dsw-static-neutral-700:#3c3c3d;--dsw-static-neutral-800:#292929;--dsw-static-neutral-850:#212123;--dsw-static-neutral-900:#0f0f0f;--dsw-static-neutral-bluish-00:#fff;--dsw-static-neutral-bluish-1000:#0f1115;--dsw-static-neutral-bluish-100:#ebeef2;--dsw-static-neutral-bluish-150:#e9ecf2;--dsw-static-neutral-bluish-200:#e1e5ee;--dsw-static-neutral-bluish-300:#cfd3d6;--dsw-static-neutral-bluish-400:#adb2b8;--dsw-static-neutral-bluish-500:#979da6;--dsw-static-neutral-bluish-50:#f9fafb;--dsw-static-neutral-bluish-600:#81858c;--dsw-static-neutral-bluish-60:#f9fafb;--dsw-static-neutral-bluish-700:#61666b;--dsw-static-neutral-bluish-750:#43454a;--dsw-static-neutral-bluish-75:#f1f3f5;--dsw-static-neutral-bluish-800:#353638;--dsw-static-neutral-bluish-850:#2c2c2e;--dsw-static-neutral-bluish-875:#232324;--dsw-static-neutral-bluish-900:#1b1b1c;--dsw-static-neutral-bluish-950:#151517;--dsw-static-red-100:#fee2e2;--dsw-static-red-400:#f25a5a;--dsw-static-red-500:#ef4444;--dsw-static-red-50:#fef2f2;--dsw-static-red-600:#ec1313;--dsw-static-red-900:#570c0c}body{--dsw-alias-bg-base:var(--dsw-static-neutral-bluish-00);--dsw-alias-bg-layer-1:var(--dsw-static-neutral-bluish-00);--dsw-alias-bg-layer-2:var(--dsw-static-neutral-bluish-00);--dsw-alias-bg-layer-3:var(--dsw-static-neutral-bluish-00);--dsw-alias-bg-mask-1:#0000003d;--dsw-alias-bg-mask-2:#0000001f;--dsw-alias-bg-mask-3:#0000007a;--dsw-alias-bg-mask-photo:#000000e0;--dsw-alias-bg-mask-drop:#ffffffb3;--dsw-alias-bg-module-platform:var(--dsw-static-neutral-bluish-60);--dsw-alias-bg-multi-select:var(--dsw-static-neutral-bluish-60);--dsw-alias-bg-overlay:var(--dsw-static-neutral-bluish-150);--dsw-alias-bg-skeleton:#0000000a;--dsw-alias-border-inverted2:#0000;--dsw-alias-border-inverted:#0000;--dsw-alias-border-l1:#0000000a;--dsw-alias-border-l2-darkmode-thin:#0000001a;--dsw-alias-border-l2:#0000001a;--dsw-alias-border-l3:#0000001f;--dsw-alias-border-l4:#00000029;--dsw-alias-brand-primary-invert:var(--dsw-static-neutral-bluish-1000);--dsw-alias-brand-primary-new-colorprimary-new-color:#4176e6;--dsw-alias-brand-primary:var(--dsw-static-neutral-bluish-1000);--dsw-alias-brand-text:var(--dsw-static-neutral-bluish-1000);--dsw-alias-button-contrast-fill:var(--dsw-static-neutral-bluish-700);--dsw-alias-button-elevated-fill:var(--dsw-static-neutral-bluish-00);--dsw-alias-button-floating-fill:var(--dsw-static-neutral-bluish-00);--dsw-alias-button-floating-hover:var(--dsw-static-neutral-bluish-75);--dsw-alias-button-ghost-active-border:var(--dsw-static-neutral-bluish-500);--dsw-alias-button-ghost-active-fill:var(--dsw-static-neutral-bluish-100);--dsw-alias-button-ghost-active-hover:var(--dsw-static-neutral-bluish-150);--dsw-alias-button-info-fill:var(--dsw-static-deepseek-500);--dsw-alias-button-info-hover:var(--dsw-static-deepseek-400);--dsw-alias-button-primary-dimmed:var(--dsw-static-neutral-bluish-100);--dsw-alias-button-primary-fill:var(--dsw-alias-brand-primary);--dsw-alias-button-primary-hover:var(--dsw-static-neutral-bluish-750);--dsw-alias-button-tool-bar-fill-invisible:#1f1f1f5c;--dsw-alias-button-tool-bar-fill:#54555780;--dsw-alias-button-tool-bar-hover:#54555799;--dsw-alias-interactive-bg-active:#2631481a;--dsw-alias-interactive-bg-hover-accent:#26314824;--dsw-alias-interactive-bg-hover-danger:#ec13130d;--dsw-alias-interactive-bg-hover-solid:var(--dsw-static-neutral-bluish-75);--dsw-alias-interactive-bg-hover:#2631480f;--dsw-alias-label-caption:var(--dsw-static-neutral-bluish-400);--dsw-alias-label-dimmed:var(--dsw-static-neutral-bluish-200);--dsw-alias-label-primary-bluish:var(--dsw-static-blue-900);--dsw-alias-label-primary-dimmed:var(--dsw-static-neutral-bluish-950);--dsw-alias-label-primary-foreground:var(--dsw-static-neutral-bluish-00);--dsw-alias-label-primary-inverted:var(--dsw-static-neutral-bluish-00);--dsw-alias-label-primary:var(--dsw-static-neutral-bluish-1000);--dsw-alias-label-secondary:var(--dsw-static-neutral-bluish-700);--dsw-alias-label-tertiary:var(--dsw-static-neutral-bluish-600);--dsw-alias-markdown-citation:var(--dsw-static-neutral-bluish-100);--dsw-alias-markdown-code-block-banner:var(--dsw-static-neutral-bluish-50);--dsw-alias-markdown-code-block:var(--dsw-static-neutral-bluish-50);--dsw-alias-markdown-code-segment-selected:var(--dsw-static-neutral-bluish-00);--dsw-alias-markdown-code-segment-unselected:var(--dsw-static-neutral-bluish-75);--dsw-alias-markdown-inline-code:var(--dsw-static-neutral-bluish-100);--dsw-alias-markdown-placeholder:var(--dsw-static-neutral-bluish-60);--dsw-alias-markdown-tag:var(--dsw-static-neutral-bluish-75);--dsw-alias-scrollbar-bg-l1:var(--dsw-static-neutral-200);--dsw-alias-scrollbar-bg-l2:var(--dsw-static-neutral-200);--dsw-alias-scrollbar-hover-l1:var(--dsw-static-neutral-300);--dsw-alias-scrollbar-hover-l2:var(--dsw-static-neutral-300);--dsw-alias-state-business-primary:var(--dsw-static-deepseek-500);--dsw-alias-state-business-tertiary:var(--dsw-static-deepseek-100);--dsw-alias-state-error-primary:var(--dsw-static-red-600);--dsw-alias-state-error-secondary:var(--dsw-static-red-400);--dsw-alias-state-success-primary:var(--dsw-static-green-500);--dsw-alias-state-success-secondary:var(--dsw-static-green-400);--dsw-alias-state-success-tertiary:var(--dsw-static-green-100);--dsw-alias-state-warn-label:var(--dsw-static-amber-600);--dsw-alias-state-warn-primary:var(--dsw-static-amber-500);--dsw-alias-state-warn-secondary:var(--dsw-static-amber-400);--dsw-alias-state-warn-tertiary:var(--dsw-static-amber-100);--dsw-alias-toast-bg:var(--dsw-static-neutral-bluish-800);--dsw-alias-tooltip-bg:var(--dsw-static-neutral-bluish-850);--dsw-specific-bubble-highlight:var(--dsw-static-deepseek-200);--dsw-specific-bubble:var(--dsw-static-deepseek-50);--dsw-specific-input-major:var(--dsw-static-neutral-bluish-00);--dsw-specific-login-input:var(--dsw-static-neutral-bluish-50);--dsw-specific-menu:var(--dsw-alias-bg-layer-3);--dsw-specific-selector:var(--dsw-static-neutral-bluish-60);--dsw-specific-sidebar-fill:var(--dsw-static-neutral-bluish-50);--dsw-specific-sidebar-nav-item-active-accent:var(--dsw-static-deepseek-100);--dsw-specific-sidebar-nav-item-active:var(--dsw-static-neutral-bluish-100);--dsw-specific-sidebar-nav-item-hover:var(--dsw-static-neutral-bluish-75);--dsw-specific-tip:var(--dsw-static-neutral-bluish-60)}body[data-ds-dark-theme]{--dsw-alias-bg-base:var(--dsw-static-neutral-bluish-950);--dsw-alias-bg-layer-1:var(--dsw-static-neutral-bluish-875);--dsw-alias-bg-layer-2:var(--dsw-static-neutral-bluish-850);--dsw-alias-bg-layer-3:var(--dsw-static-neutral-bluish-800);--dsw-alias-bg-mask-1:#00000080;--dsw-alias-bg-mask-2:#0003;--dsw-alias-bg-mask-3:#0000007a;--dsw-alias-bg-mask-photo:#000000e0;--dsw-alias-bg-mask-drop:#272730b3;--dsw-alias-bg-module-platform:var(--dsw-static-neutral-bluish-800);--dsw-alias-bg-multi-select:var(--dsw-static-neutral-850);--dsw-alias-bg-overlay:var(--dsw-static-neutral-bluish-700);--dsw-alias-bg-skeleton:#ffffff14;--dsw-alias-border-inverted2:#ffffff14;--dsw-alias-border-inverted:#ffffff0f;--dsw-alias-border-l1:#ffffff0f;--dsw-alias-border-l2-darkmode-thin:#ffffff0f;--dsw-alias-border-l2:#ffffff1f;--dsw-alias-border-l3:#ffffff29;--dsw-alias-border-l4:#fff3;--dsw-alias-brand-primary-invert:var(--dsw-static-neutral-bluish-50);--dsw-alias-brand-primary-new-colorprimary-new-color:var(--dsw-static-deepseek-450);--dsw-alias-brand-primary:var(--dsw-static-neutral-bluish-50);--dsw-alias-brand-text:var(--dsw-static-neutral-bluish-50);--dsw-alias-button-contrast-fill:var(--dsw-static-neutral-bluish-50);--dsw-alias-button-elevated-fill:var(--dsw-static-neutral-bluish-750);--dsw-alias-button-floating-fill:var(--dsw-static-neutral-bluish-850);--dsw-alias-button-floating-hover:var(--dsw-static-neutral-bluish-800);--dsw-alias-button-ghost-active-border:var(--dsw-static-neutral-bluish-600);--dsw-alias-button-ghost-active-fill:var(--dsw-static-neutral-bluish-750);--dsw-alias-button-ghost-active-hover:var(--dsw-static-neutral-bluish-700);--dsw-alias-button-info-fill:var(--dsw-static-deepseek-400);--dsw-alias-button-info-hover:var(--dsw-static-deepseek-500);--dsw-alias-button-primary-dimmed:var(--dsw-static-neutral-bluish-750);--dsw-alias-button-primary-fill:var(--dsw-alias-brand-primary);--dsw-alias-button-primary-hover:var(--dsw-static-neutral-bluish-100);--dsw-alias-button-tool-bar-fill-invisible:#1f1f1f5c;--dsw-alias-button-tool-bar-fill:#54555780;--dsw-alias-button-tool-bar-hover:#54555799;--dsw-alias-interactive-bg-active:#ffffff24;--dsw-alias-interactive-bg-hover-accent:#ffffff3d;--dsw-alias-interactive-bg-hover-danger:#f25a5a26;--dsw-alias-interactive-bg-hover-solid:var(--dsw-static-neutral-bluish-800);--dsw-alias-interactive-bg-hover:#ffffff14;--dsw-alias-label-caption:var(--dsw-static-neutral-bluish-600);--dsw-alias-label-dimmed:var(--dsw-static-neutral-bluish-750);--dsw-alias-label-primary-bluish:var(--dsw-static-neutral-bluish-50);--dsw-alias-label-primary-dimmed:var(--dsw-static-neutral-bluish-100);--dsw-alias-label-primary-foreground:var(--dsw-static-neutral-bluish-1000);--dsw-alias-label-primary-inverted:var(--dsw-static-neutral-bluish-800);--dsw-alias-label-primary:var(--dsw-static-neutral-bluish-50);--dsw-alias-label-secondary:var(--dsw-static-neutral-bluish-300);--dsw-alias-label-tertiary:var(--dsw-static-neutral-bluish-400);--dsw-alias-markdown-citation:var(--dsw-static-neutral-bluish-800);--dsw-alias-markdown-code-block-banner:var(--dsw-static-neutral-bluish-850);--dsw-alias-markdown-code-block:var(--dsw-static-neutral-bluish-900);--dsw-alias-markdown-code-segment-selected:var(--dsw-static-neutral-bluish-800);--dsw-alias-markdown-code-segment-unselected:var(--dsw-static-neutral-bluish-900);--dsw-alias-markdown-inline-code:var(--dsw-static-neutral-bluish-850);--dsw-alias-markdown-placeholder:var(--dsw-static-neutral-bluish-850);--dsw-alias-markdown-tag:var(--dsw-static-neutral-bluish-850);--dsw-alias-scrollbar-bg-l1:var(--dsw-static-neutral-700);--dsw-alias-scrollbar-bg-l2:var(--dsw-static-neutral-600);--dsw-alias-scrollbar-hover-l1:var(--dsw-static-neutral-600);--dsw-alias-scrollbar-hover-l2:var(--dsw-static-neutral-550);--dsw-alias-state-business-primary:var(--dsw-static-deepseek-400);--dsw-alias-state-business-tertiary:var(--dsw-static-deepseek-800);--dsw-alias-state-error-primary:var(--dsw-static-red-400);--dsw-alias-state-error-secondary:var(--dsw-static-red-400);--dsw-alias-state-success-primary:var(--dsw-static-green-500);--dsw-alias-state-success-secondary:var(--dsw-static-green-400);--dsw-alias-state-success-tertiary:var(--dsw-static-green-900);--dsw-alias-state-warn-label:var(--dsw-static-amber-600);--dsw-alias-state-warn-primary:var(--dsw-static-amber-500);--dsw-alias-state-warn-secondary:var(--dsw-static-amber-400);--dsw-alias-state-warn-tertiary:var(--dsw-static-amber-900);--dsw-alias-toast-bg:var(--dsw-static-neutral-bluish-750);--dsw-alias-tooltip-bg:var(--dsw-static-neutral-bluish-750);--dsw-specific-bubble-highlight:var(--dsw-static-neutral-bluish-750);--dsw-specific-bubble:var(--dsw-static-neutral-bluish-850);--dsw-specific-input-major:var(--dsw-static-neutral-bluish-850);--dsw-specific-login-input:var(--dsw-static-neutral-bluish-900);--dsw-specific-menu:var(--dsw-alias-bg-layer-3);--dsw-specific-selector:var(--dsw-static-neutral-bluish-800);--dsw-specific-sidebar-fill:var(--dsw-static-neutral-bluish-900);--dsw-specific-sidebar-nav-item-active-accent:var(--dsw-static-neutral-bluish-800);--dsw-specific-sidebar-nav-item-active:var(--dsw-static-neutral-bluish-750);--dsw-specific-sidebar-nav-item-hover:var(--dsw-static-neutral-bluish-850);--dsw-specific-tip:var(--dsw-static-neutral-bluish-800)}";
1051
+ //#endregion
1052
+ //#region \0dsh-inline-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-theme/src/styles/scrollbar.css.mjs
1053
+ var scrollbar_css_default = "body{--dsh-scrollbar-thumb:var(--dsw-alias-scrollbar-bg-l1);--dsh-scrollbar-thumb-hover:var(--dsw-alias-scrollbar-hover-l1);--dsh-scrollbar-width:8px}@supports not selector(::-webkit-scrollbar){body,body *{scrollbar-width:thin;scrollbar-color:var(--dsh-scrollbar-thumb) transparent}}::-webkit-scrollbar{width:8px;height:8px}::-webkit-scrollbar-track{background:0 0}::-webkit-scrollbar-thumb{background:var(--dsh-scrollbar-thumb);border-radius:4px}::-webkit-scrollbar-thumb:hover{background:var(--dsh-scrollbar-thumb-hover)}::-webkit-scrollbar-corner{background:0 0}";
1054
+ //#endregion
1055
+ //#region \0dsh-inline-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-theme/src/styles/gradient-shadow-text.css.mjs
1056
+ var gradient_shadow_text_css_default = "body{--dsw-linear-gradient-think:linear-gradient(180deg, #fff 20.19%, #fff0 100%);--dsw-linear-think-select:linear-gradient(180deg, #f5f6f7 20.19%, #f5f6f700 100%);--dsw-shadow-lv1:0 2px 4px 0 #0000000d;--dsw-shadow-lv1-blur:0 4px 12px 0 #00000005;--dsw-shadow-lv2:0 4px 12px 0 #00000005, 0 2px 8px 0 #0000000a;--dsw-shadow-lv3:0 0 1px 0 #0003, 0 0 4px 0 #00000005, 0 12px 32px 0 #00000014;--dsw-mask-blur:blur(2px)}body[data-ds-dark-theme]{--dsw-linear-gradient-think:linear-gradient(180deg, #151517 20.19%, #15151700 100%);--dsw-linear-think-select:linear-gradient(180deg, #232325 20.19%, #23232500 100%)}body{--dsh-content-font-delta:calc(var(--dsh-content-font-size,14px) - 14px);--dsh-content-font-size-secondary:min(calc(var(--dsh-content-font-size,14px) - 1px), max(13px, calc(var(--dsh-content-font-size,14px) - 2px)));--dsh-content-font-delta-secondary:calc(var(--dsh-content-font-size-secondary) - 13px);--dsw-font-markdown-h1:700 calc(21px + var(--dsh-content-font-delta)) / calc(30px + var(--dsh-content-font-delta)) var(--dsw-font-family);--dsw-font-markdown-h1-font-family:var(--dsw-font-family);--dsw-font-markdown-h1-font-weight:700;--dsw-font-markdown-h1-line-height:calc(30px + var(--dsh-content-font-delta));--dsw-font-markdown-h1-font-size:calc(21px + var(--dsh-content-font-delta));--dsw-font-markdown-h1-font-style:normal;--dsw-font-markdown-h2:700 calc(19px + var(--dsh-content-font-delta)) / calc(28px + var(--dsh-content-font-delta)) var(--dsw-font-family);--dsw-font-markdown-h2-font-family:var(--dsw-font-family);--dsw-font-markdown-h2-font-weight:700;--dsw-font-markdown-h2-line-height:calc(28px + var(--dsh-content-font-delta));--dsw-font-markdown-h2-font-size:calc(19px + var(--dsh-content-font-delta));--dsw-font-markdown-h2-font-style:normal;--dsw-font-markdown-h3:700 calc(18px + var(--dsh-content-font-delta)) / calc(26px + var(--dsh-content-font-delta)) var(--dsw-font-family);--dsw-font-markdown-h3-font-family:var(--dsw-font-family);--dsw-font-markdown-h3-font-weight:700;--dsw-font-markdown-h3-line-height:calc(26px + var(--dsh-content-font-delta));--dsw-font-markdown-h3-font-size:calc(18px + var(--dsh-content-font-delta));--dsw-font-markdown-h3-font-style:normal;--dsw-font-markdown-h4:600 var(--dsh-content-font-size,14px) / calc(24px + var(--dsh-content-font-delta)) var(--dsw-font-family);--dsw-font-markdown-h4-font-family:var(--dsw-font-family);--dsw-font-markdown-h4-font-weight:600;--dsw-font-markdown-h4-line-height:calc(24px + var(--dsh-content-font-delta));--dsw-font-markdown-h4-font-size:var(--dsh-content-font-size,14px);--dsw-font-markdown-h4-font-style:normal;--dsw-font-markdown-base:var(--dsh-content-font-size,14px) / calc(24px + var(--dsh-content-font-delta)) var(--dsw-font-family);--dsw-font-markdown-base-font-family:var(--dsw-font-family);--dsw-font-markdown-base-font-weight:400;--dsw-font-markdown-base-line-height:calc(24px + var(--dsh-content-font-delta));--dsw-font-markdown-base-font-size:var(--dsh-content-font-size,14px);--dsw-font-markdown-base-font-style:normal;--dsw-font-markdown-base-strong:600 var(--dsh-content-font-size,14px) / calc(24px + var(--dsh-content-font-delta)) var(--dsw-font-family);--dsw-font-markdown-base-strong-font-family:var(--dsw-font-family);--dsw-font-markdown-base-strong-font-weight:600;--dsw-font-markdown-base-strong-line-height:calc(24px + var(--dsh-content-font-delta));--dsw-font-markdown-base-strong-font-size:var(--dsh-content-font-size,14px);--dsw-font-markdown-base-strong-font-style:normal;--dsw-font-markdown-base-italic:italic var(--dsh-content-font-size,14px) / calc(24px + var(--dsh-content-font-delta)) var(--dsw-font-family);--dsw-font-markdown-base-italic-font-family:var(--dsw-font-family);--dsw-font-markdown-base-italic-font-weight:400;--dsw-font-markdown-base-italic-line-height:calc(24px + var(--dsh-content-font-delta));--dsw-font-markdown-base-italic-font-size:var(--dsh-content-font-size,14px);--dsw-font-markdown-base-italic-font-style:italic;--dsw-font-markdown-base-strong-italic:italic 600 var(--dsh-content-font-size,14px) / calc(24px + var(--dsh-content-font-delta)) var(--dsw-font-family);--dsw-font-markdown-base-strong-italic-font-family:var(--dsw-font-family);--dsw-font-markdown-base-strong-italic-font-weight:600;--dsw-font-markdown-base-strong-italic-line-height:calc(24px + var(--dsh-content-font-delta));--dsw-font-markdown-base-strong-italic-font-size:var(--dsh-content-font-size,14px);--dsw-font-markdown-base-strong-italic-font-style:italic;--dsw-font-markdown-table:var(--dsh-content-font-size-secondary,13px)/calc(22px + var(--dsh-content-font-delta-secondary,0px)) var(--dsw-font-family);--dsw-font-markdown-table-font-family:var(--dsw-font-family);--dsw-font-markdown-table-font-weight:400;--dsw-font-markdown-table-line-height:calc(22px + var(--dsh-content-font-delta-secondary,0px));--dsw-font-markdown-table-font-size:var(--dsh-content-font-size-secondary,13px);--dsw-font-markdown-table-font-style:normal;--dsw-font-markdown-table-head:500 var(--dsh-content-font-size-secondary,13px)/calc(22px + var(--dsh-content-font-delta-secondary,0px)) var(--dsw-font-family);--dsw-font-markdown-table-head-font-family:var(--dsw-font-family);--dsw-font-markdown-table-head-font-weight:500;--dsw-font-markdown-table-head-line-height:calc(22px + var(--dsh-content-font-delta-secondary,0px));--dsw-font-markdown-table-head-font-size:var(--dsh-content-font-size-secondary,13px);--dsw-font-markdown-table-head-font-style:normal;--dsw-font-markdown-small:12px/20px var(--dsw-font-family);--dsw-font-markdown-small-font-family:var(--dsw-font-family);--dsw-font-markdown-small-font-weight:400;--dsw-font-markdown-small-line-height:20px;--dsw-font-markdown-small-font-size:12px;--dsw-font-markdown-small-font-style:normal;--dsw-font-markdown-small-strong:600 12px/20px var(--dsw-font-family);--dsw-font-markdown-small-strong-font-family:var(--dsw-font-family);--dsw-font-markdown-small-strong-font-weight:600;--dsw-font-markdown-small-strong-line-height:20px;--dsw-font-markdown-small-strong-font-size:12px;--dsw-font-markdown-small-strong-font-style:normal;--dsw-font-markdown-small-italic:italic 12px/20px var(--dsw-font-family);--dsw-font-markdown-small-italic-font-family:var(--dsw-font-family);--dsw-font-markdown-small-italic-font-weight:400;--dsw-font-markdown-small-italic-line-height:20px;--dsw-font-markdown-small-italic-font-size:12px;--dsw-font-markdown-small-italic-font-style:italic;--dsw-font-markdown-small-strong-italic:italic 600 12px/20px var(--dsw-font-family);--dsw-font-markdown-small-strong-italic-font-family:var(--dsw-font-family);--dsw-font-markdown-small-strong-italic-font-weight:600;--dsw-font-markdown-small-strong-italic-line-height:20px;--dsw-font-markdown-small-strong-italic-font-size:12px;--dsw-font-markdown-small-strong-italic-font-style:italic;--dsw-font-markdown-code:12px/19px var(--ds-font-family-code);--dsw-font-markdown-code-font-family:var(--ds-font-family-code);--dsw-font-markdown-code-font-weight:400;--dsw-font-markdown-code-line-height:19px;--dsw-font-markdown-code-font-size:12px;--dsw-font-markdown-code-font-style:normal;--dsw-font-markdown-code-block:11px/19px var(--ds-font-family-code);--dsw-font-markdown-code-block-font-family:var(--ds-font-family-code);--dsw-font-markdown-code-block-font-weight:400;--dsw-font-markdown-code-block-line-height:19px;--dsw-font-markdown-code-block-font-size:11px;--dsw-font-markdown-code-block-font-style:normal;--dsw-font-markdown-code-block-small:11px/16px var(--ds-font-family-code);--dsw-font-markdown-code-block-small-font-family:var(--ds-font-family-code);--dsw-font-markdown-code-block-small-font-weight:400;--dsw-font-markdown-code-block-small-line-height:16px;--dsw-font-markdown-code-block-small-font-size:11px;--dsw-font-markdown-code-block-small-font-style:normal;--dsw-font-xl-24:600 24px/32px var(--dsw-font-family);--dsw-font-xl-24-font-family:var(--dsw-font-family);--dsw-font-xl-24-font-weight:600;--dsw-font-xl-24-line-height:32px;--dsw-font-xl-24-font-size:24px;--dsw-font-xl-24-font-style:normal;--dsw-font-l-20:500 20px/28px var(--dsw-font-family);--dsw-font-l-20-font-family:var(--dsw-font-family);--dsw-font-l-20-font-weight:500;--dsw-font-l-20-line-height:28px;--dsw-font-l-20-font-size:20px;--dsw-font-l-20-font-style:normal;--dsw-font-m-18:500 16px/28px var(--dsw-font-family);--dsw-font-m-18-font-family:var(--dsw-font-family);--dsw-font-m-18-font-weight:500;--dsw-font-m-18-line-height:28px;--dsw-font-m-18-font-size:16px;--dsw-font-m-18-font-style:normal;--dsw-font-base-16:16px/24px var(--dsw-font-family);--dsw-font-base-16-font-family:var(--dsw-font-family);--dsw-font-base-16-font-weight:400;--dsw-font-base-16-line-height:24px;--dsw-font-base-16-font-size:16px;--dsw-font-base-16-font-style:normal;--dsw-font-base-strong-16:500 16px/24px var(--dsw-font-family);--dsw-font-base-strong-16-font-family:var(--dsw-font-family);--dsw-font-base-strong-16-font-weight:500;--dsw-font-base-strong-16-line-height:24px;--dsw-font-base-strong-16-font-size:16px;--dsw-font-base-strong-16-font-style:normal;--dsw-font-s-14:14px/22px var(--dsw-font-family);--dsw-font-s-14-font-family:var(--dsw-font-family);--dsw-font-s-14-font-weight:400;--dsw-font-s-14-line-height:22px;--dsw-font-s-14-font-size:14px;--dsw-font-s-14-font-style:normal;--dsw-font-s-strong-14:500 14px/22px var(--dsw-font-family);--dsw-font-s-strong-14-font-family:var(--dsw-font-family);--dsw-font-s-strong-14-font-weight:500;--dsw-font-s-strong-14-line-height:22px;--dsw-font-s-strong-14-font-size:14px;--dsw-font-s-strong-14-font-style:normal;--dsw-font-xs-13:13px/20px var(--dsw-font-family);--dsw-font-xs-13-font-family:var(--dsw-font-family);--dsw-font-xs-13-font-weight:400;--dsw-font-xs-13-line-height:20px;--dsw-font-xs-13-font-size:13px;--dsw-font-xs-13-font-style:normal;--dsw-font-xs-strong-13:500 13px/20px var(--dsw-font-family);--dsw-font-xs-strong-13-font-family:var(--dsw-font-family);--dsw-font-xs-strong-13-font-weight:500;--dsw-font-xs-strong-13-line-height:20px;--dsw-font-xs-strong-13-font-size:13px;--dsw-font-xs-strong-13-font-style:normal;--dsw-font-xxs-12:12px/18px var(--dsw-font-family);--dsw-font-xxs-12-font-family:var(--dsw-font-family);--dsw-font-xxs-12-font-weight:400;--dsw-font-xxs-12-line-height:18px;--dsw-font-xxs-12-font-size:12px;--dsw-font-xxs-12-font-style:normal;--dsw-font-xxs-strong-12:500 12px/18px var(--dsw-font-family);--dsw-font-xxs-strong-12-font-family:var(--dsw-font-family);--dsw-font-xxs-strong-12-font-weight:500;--dsw-font-xxs-strong-12-line-height:18px;--dsw-font-xxs-strong-12-font-size:12px;--dsw-font-xxs-strong-12-font-style:normal;--dsw-font-xxxs-11:11px/14px var(--dsw-font-family);--dsw-font-xxxs-11-font-family:var(--dsw-font-family);--dsw-font-xxxs-11-font-weight:400;--dsw-font-xxxs-11-line-height:14px;--dsw-font-xxxs-11-font-size:11px;--dsw-font-xxxs-11-font-style:normal;--dsw-font-xxxs-strong-11:500 11px/14px var(--dsw-font-family);--dsw-font-xxxs-strong-11-font-family:var(--dsw-font-family);--dsw-font-xxxs-strong-11-font-weight:500;--dsw-font-xxxs-strong-11-line-height:14px;--dsw-font-xxxs-strong-11-font-size:11px;--dsw-font-xxxs-strong-11-font-style:normal}";
1057
+ //#endregion
1058
+ //#region \0dsh-inline-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-theme/src/styles/shiki.css.mjs
1059
+ var shiki_css_default = ":root{--shiki-foreground:var(--dsw-alias-label-primary);--shiki-background:var(--dsw-alias-markdown-code-block);--shiki-token-constant:#1c7ed6;--shiki-token-string:#2f9e44;--shiki-token-comment:#868e96;--shiki-token-keyword:#d6336c;--shiki-token-parameter:#e8590c;--shiki-token-function:#6741d9;--shiki-token-string-expression:#2b8a3e;--shiki-token-punctuation:#495057;--shiki-token-link:#1971c2}body[data-ds-dark-theme]{--shiki-token-constant:#4dabf7;--shiki-token-string:#69db7c;--shiki-token-comment:#adb5bd;--shiki-token-keyword:#faa2c1;--shiki-token-parameter:#ffa94d;--shiki-token-function:#b197fc;--shiki-token-string-expression:#8ce99a;--shiki-token-punctuation:#ced4da;--shiki-token-link:#74c0fc}";
1060
+ //#endregion
1061
+ //#region lib/types/client/styles.js
1062
+ const PLUGIN_ID = "@deepseek-ai/dsh-client-ui-theme";
1063
+ const STYLES = [
1064
+ ["base.css", base_css_default],
1065
+ ["design-platform.css", design_platform_css_default],
1066
+ ["scrollbar.css", scrollbar_css_default],
1067
+ ["gradient-shadow-text.css", gradient_shadow_text_css_default],
1068
+ ["shiki.css", shiki_css_default]
1069
+ ];
1070
+ /**
1071
+ * Mount the global theme sheets for exactly the owning plugin lifetime.
1072
+ * @param ctx - Owning plugin context.
1073
+ */
1074
+ function installThemeStyles(ctx) {
1075
+ if (typeof document === "undefined") return;
1076
+ for (const [name, css] of STYLES) ctx.effect(() => {
1077
+ const tag = document.createElement("style");
1078
+ tag.dataset.plugin = PLUGIN_ID;
1079
+ tag.dataset.pluginCss = `${PLUGIN_ID}/${name}`;
1080
+ tag.textContent = css;
1081
+ document.head.appendChild(tag);
1082
+ return () => {
1083
+ tag.remove();
1084
+ };
1085
+ }, `ui-theme: ${name} stylesheet`);
1086
+ }
1087
+ //#endregion
1088
+ //#region lib/types/client/locales.js
1089
+ /** `settings.theme` namespace dictionaries (the Appearance and font-size rows' copy). */
1090
+ /** Simplified Chinese dictionary (the key-set source of truth). */
1091
+ const zh = {
1092
+ "appearance.title": "外观",
1093
+ "appearance.light": "浅色",
1094
+ "appearance.dark": "深色",
1095
+ "appearance.system": "跟随系统",
1096
+ "fontSize.title": "字号大小",
1097
+ "fontSize.description": "仅影响会话内容的字号",
1098
+ "fontSize.unit": "px",
1099
+ "fontSize.increase": "增大字号",
1100
+ "fontSize.decrease": "减小字号"
1101
+ };
1102
+ /** English dictionary, checked complete against the zh key set. */
1103
+ const en = {
1104
+ "appearance.title": "Appearance",
1105
+ "appearance.light": "Light",
1106
+ "appearance.dark": "Dark",
1107
+ "appearance.system": "System",
1108
+ "fontSize.title": "Font size",
1109
+ "fontSize.description": "Only affects conversation content",
1110
+ "fontSize.unit": "px",
1111
+ "fontSize.increase": "Increase font size",
1112
+ "fontSize.decrease": "Decrease font size"
1113
+ };
1114
+ //#endregion
995
1115
  //#region lib/types/client/index.js
996
1116
  /** Namespace owning this feature's settings-row copy. */
997
1117
  const SETTINGS_NS = "settings.theme";
@@ -1113,6 +1233,7 @@ window.__ModuleLoader__.load({
1113
1233
  host;
1114
1234
  themes = [...BUILTIN_THEMES];
1115
1235
  preference;
1236
+ fontSize = bootstrapFontSize();
1116
1237
  revision = 0;
1117
1238
  snapshot;
1118
1239
  media;
@@ -1178,11 +1299,26 @@ window.__ModuleLoader__.load({
1178
1299
  if (isThemePreference(id)) this.host.set(THEME_PREFERENCE_FIELD, id);
1179
1300
  this.publish();
1180
1301
  }
1302
+ /**
1303
+ * Change the conversation content font size — the only font-size write
1304
+ * entry. Accepted values are written through the settings scope and emit
1305
+ * `theme/change`.
1306
+ * @param px - integer px within FONT_SIZE_MIN..FONT_SIZE_MAX; out-of-range or fractional values throw.
1307
+ */
1308
+ setFontSize(px) {
1309
+ if (!Number.isInteger(px) || px < 12 || px > 17) throw new Error(`font size ${px} is outside 12..17`);
1310
+ if (this.fontSize === px) return;
1311
+ this.fontSize = px;
1312
+ this.host.set(FONT_SIZE_FIELD, px);
1313
+ this.publish();
1314
+ }
1181
1315
  /** Adopt the scope's accepted durable preference without writing it back. */
1182
1316
  adopt() {
1183
1317
  const section = this.host.getSnapshot().value;
1184
- if (section === void 0 || this.preference === section.preference) return;
1318
+ if (section === void 0) return;
1319
+ if (this.preference === section.preference && this.fontSize === section.fontSize) return;
1185
1320
  this.preference = section.preference;
1321
+ this.fontSize = section.fontSize;
1186
1322
  this.publish();
1187
1323
  }
1188
1324
  /**
@@ -1241,6 +1377,7 @@ window.__ModuleLoader__.load({
1241
1377
  if (active === void 0) throw new Error(`theme registry lost "${resolvedId}"`);
1242
1378
  return Object.freeze({
1243
1379
  preference: this.preference,
1380
+ fontSize: this.fontSize,
1244
1381
  active: this.composeActive(active),
1245
1382
  themes: Object.freeze([...this.themes]),
1246
1383
  revision: this.revision
@@ -1268,12 +1405,25 @@ window.__ModuleLoader__.load({
1268
1405
  }
1269
1406
  };
1270
1407
  /**
1408
+ * Read the font size the Host boot script wrote on `body` before any plugin
1409
+ * ran, so the initial snapshot matches first paint and ui-layout's presenter
1410
+ * does not flash the schema default while the settings read is in flight.
1411
+ * Non-browser runs and mounts without the boot script fall back to the
1412
+ * schema default; the durable settings adoption still lands afterwards.
1413
+ */
1414
+ function bootstrapFontSize() {
1415
+ /* v8 ignore next -- needs a documentless run (node e2e booting the client tree), not constructible under jsdom */
1416
+ if (typeof document === "undefined") return 14;
1417
+ const raw = document.body.style.getPropertyValue("--dsh-content-font-size");
1418
+ const parsed = Number.parseInt(raw, 10);
1419
+ return Number.isInteger(parsed) && parsed >= 12 && parsed <= 17 ? parsed : 14;
1420
+ }
1421
+ /**
1271
1422
  * Runtime shape check for one override layer (model-authored callers pass
1272
1423
  * untyped JS through the dynamic-package façade, so the static type cannot
1273
1424
  * enforce the pair shape there). Returns a defensive per-token copy so later
1274
1425
  * caller mutation cannot reach the stored layer.
1275
- */
1276
- function validateOverrides(source, tokens) {
1426
+ */ function validateOverrides(source, tokens) {
1277
1427
  const validated = {};
1278
1428
  for (const [name, value] of Object.entries(tokens)) {
1279
1429
  if (typeof value === "string") throw new TypeError(`theme override "${name}" from "${source}" is a bare string — pass { light: ${JSON.stringify(value)}, dark: ${JSON.stringify(value)} } (repeat the value when it is the same in both palettes); a single value goes illegible when the user switches color scheme`);
@@ -1303,7 +1453,6 @@ window.__ModuleLoader__.load({
1303
1453
  const inject = [
1304
1454
  "slots",
1305
1455
  "locale",
1306
- "connection",
1307
1456
  "remote",
1308
1457
  "settingsScope"
1309
1458
  ];
@@ -1323,8 +1472,11 @@ window.__ModuleLoader__.load({
1323
1472
  }), "ui-theme: settings row dictionaries");
1324
1473
  const store = createAppearanceRowStore();
1325
1474
  let bound;
1475
+ const fontSizeStore = createFontSizeRowStore();
1476
+ let fontSizeBound;
1326
1477
  const sync = (snapshot) => {
1327
1478
  bound?.sync(snapshot.preference, snapshot.revision);
1479
+ fontSizeBound?.sync(snapshot.fontSize, snapshot.revision);
1328
1480
  };
1329
1481
  ctx.on("theme/change", sync);
1330
1482
  const injected = (actions) => {
@@ -1342,6 +1494,21 @@ window.__ModuleLoader__.load({
1342
1494
  locale: SETTINGS_NS,
1343
1495
  inject: injected
1344
1496
  }, AppearanceRow));
1497
+ const fontSizeInjected = (actions) => {
1498
+ fontSizeBound = actions;
1499
+ sync(theme.getTheme());
1500
+ return { setFontSize: (px) => {
1501
+ theme.setFontSize(px);
1502
+ } };
1503
+ };
1504
+ ctx.slots.inject("settings.general.item", () => ctx.slots.register({
1505
+ name: "settings.general.item",
1506
+ id: "font-size",
1507
+ order: 11,
1508
+ store: fontSizeStore,
1509
+ locale: SETTINGS_NS,
1510
+ inject: fontSizeInjected
1511
+ }, FontSizeRow));
1345
1512
  }
1346
1513
  //#endregion
1347
1514
  exports.SETTINGS_NS = SETTINGS_NS;
package/lib/index.js CHANGED
@@ -1,4 +1,3 @@
1
- import { settingsNamespace } from "@deepseek-ai/dsh-settings";
2
1
  import z from "@deepseek-ai/schemastery";
3
2
  //#region lib/types/theme-settings.js
4
3
  /** Theme preferences stored in the Host user-settings document. */
@@ -12,20 +11,31 @@ const THEME_PREFERENCES = [
12
11
  const THEME_SETTINGS_NAMESPACE = "ui-theme";
13
12
  /** Field carrying the selected built-in theme preference. */
14
13
  const THEME_PREFERENCE_FIELD = "preference";
14
+ /** Field carrying the conversation content font size. */
15
+ const FONT_SIZE_FIELD = "fontSize";
15
16
  /** Default preference when the user-settings document has no override. */
16
17
  const DEFAULT_PREFERENCE = "system";
18
+ /** Smallest accepted content font size (px). */
19
+ const FONT_SIZE_MIN = 12;
20
+ /** Largest accepted content font size (px). */
21
+ const FONT_SIZE_MAX = 17;
22
+ /** Content font size when the user-settings document has no override (px). */
23
+ const DEFAULT_FONT_SIZE = 14;
17
24
  /** Durable theme schema; also the wire envelope the browser scope validates against. */
18
- const ThemeSettingsSchema = z.object({ [THEME_PREFERENCE_FIELD]: z.union([...THEME_PREFERENCES]).default(DEFAULT_PREFERENCE) });
25
+ const ThemeSettingsSchema = z.object({
26
+ [THEME_PREFERENCE_FIELD]: z.union([...THEME_PREFERENCES]).default(DEFAULT_PREFERENCE),
27
+ [FONT_SIZE_FIELD]: z.number().step(1).min(12).max(17).default(14)
28
+ });
19
29
  //#endregion
20
30
  //#region lib/types/boot-theme.js
21
31
  /**
22
32
  * Theme bootstrap row for the browser's pre-plugin interval. Each index
23
- * render embeds the current durable built-in preference; the browser resolves
24
- * only `system`, then writes the same DOM fields ui-layout's ThemePresenter
25
- * owns after the client plugin tree activates.
33
+ * render embeds the current durable built-in preference and content font size;
34
+ * the browser resolves only `system`, then writes the same DOM fields
35
+ * ui-layout's ThemePresenter owns after the client plugin tree activates.
26
36
  */
27
- /** Build the inline script body for one schema-validated built-in preference. */
28
- function bootThemeScript(preference) {
37
+ /** Build the inline script body for one schema-validated durable theme section. */
38
+ function bootThemeScript(preference, fontSize) {
29
39
  return `(() => {
30
40
  const preference = ${JSON.stringify(preference)}
31
41
  const systemDark = preference === 'system'
@@ -34,32 +44,38 @@ function bootThemeScript(preference) {
34
44
  const dark = preference === 'dark' || systemDark
35
45
  document.documentElement.style.colorScheme = dark ? 'dark' : 'light'
36
46
  document.body.toggleAttribute('data-ds-dark-theme', dark)
47
+ document.body.style.setProperty('--dsh-content-font-size', ${JSON.stringify(`${fontSize}px`)})
37
48
  })()`;
38
49
  }
39
50
  /**
40
51
  * The theme bootstrap as an injection row: an inline script immediately after
41
52
  * the opening body tag, before the shell mount and module script.
42
53
  * @param preference - Current Host-backed built-in preference.
54
+ * @param fontSize - Current Host-backed content font size in px.
43
55
  * @returns the body script row.
44
56
  */
45
- function bootThemeInjection(preference = DEFAULT_PREFERENCE) {
57
+ function bootThemeInjection(preference = DEFAULT_PREFERENCE, fontSize = 14) {
46
58
  return {
47
59
  kind: "script",
48
60
  placement: "body",
49
- text: bootThemeScript(preference)
61
+ text: bootThemeScript(preference, fontSize)
50
62
  };
51
63
  }
52
64
  //#endregion
53
65
  //#region lib/types/index.js
54
66
  /** Host registration for the browser theme preference and pre-plugin palette. */
55
- const THEME_NAMESPACE = settingsNamespace(THEME_SETTINGS_NAMESPACE);
56
- /** Read the registered preference or use the schema default without a settings provider. */
57
- function readPreference(ctx) {
67
+ const THEME_NAMESPACE = THEME_SETTINGS_NAMESPACE;
68
+ /** Read the registered theme section or the schema defaults without a settings provider. */
69
+ function readSection(ctx) {
70
+ const fallback = {
71
+ preference: DEFAULT_PREFERENCE,
72
+ fontSize: 14
73
+ };
58
74
  const settings = ctx.get("settings");
59
- if (settings === void 0) return DEFAULT_PREFERENCE;
75
+ if (settings === void 0) return fallback;
60
76
  const section = settings.get(THEME_NAMESPACE);
61
- if (section === void 0) return DEFAULT_PREFERENCE;
62
- return section.preference;
77
+ if (section === void 0) return fallback;
78
+ return section;
63
79
  }
64
80
  /**
65
81
  * Register the durable theme section when the optional settings service is
@@ -72,8 +88,9 @@ function apply(ctx) {
72
88
  settingsCtx.settings.register(THEME_NAMESPACE, ThemeSettingsSchema);
73
89
  });
74
90
  ctx.on("webserver/index-inject", (table) => {
75
- table.push(bootThemeInjection(readPreference(ctx)));
91
+ const section = readSection(ctx);
92
+ table.push(bootThemeInjection(section.preference, section.fontSize));
76
93
  });
77
94
  }
78
95
  //#endregion
79
- export { DEFAULT_PREFERENCE, THEME_PREFERENCES, THEME_PREFERENCE_FIELD, THEME_SETTINGS_NAMESPACE, apply };
96
+ export { DEFAULT_FONT_SIZE, DEFAULT_PREFERENCE, FONT_SIZE_FIELD, FONT_SIZE_MAX, FONT_SIZE_MIN, THEME_PREFERENCES, THEME_PREFERENCE_FIELD, THEME_SETTINGS_NAMESPACE, apply };
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * Theme bootstrap row for the browser's pre-plugin interval. Each index
3
- * render embeds the current durable built-in preference; the browser resolves
4
- * only `system`, then writes the same DOM fields ui-layout's ThemePresenter
5
- * owns after the client plugin tree activates.
3
+ * render embeds the current durable built-in preference and content font size;
4
+ * the browser resolves only `system`, then writes the same DOM fields
5
+ * ui-layout's ThemePresenter owns after the client plugin tree activates.
6
6
  */
7
7
  import type { IndexInjection } from '@deepseek-ai/dsh-host-webserver';
8
8
  import { type ThemePreference } from './theme-settings.ts';
@@ -10,7 +10,8 @@ import { type ThemePreference } from './theme-settings.ts';
10
10
  * The theme bootstrap as an injection row: an inline script immediately after
11
11
  * the opening body tag, before the shell mount and module script.
12
12
  * @param preference - Current Host-backed built-in preference.
13
+ * @param fontSize - Current Host-backed content font size in px.
13
14
  * @returns the body script row.
14
15
  */
15
- export declare function bootThemeInjection(preference?: ThemePreference): IndexInjection;
16
+ export declare function bootThemeInjection(preference?: ThemePreference, fontSize?: number): IndexInjection;
16
17
  //# sourceMappingURL=boot-theme.d.ts.map
@@ -0,0 +1,16 @@
1
+ import type { PropsLocale, PropsRuntime, PropsStore } from '@deepseek-ai/dsh-client-ui-slots';
2
+ import type { createFontSizeRowStore } from './settings-store.ts';
3
+ /** Injected business face: the preference write (t rides the standard locale seat). */
4
+ export interface FontSizeRowInjected {
5
+ /** Change the content font size (integer px within FONT_SIZE_MIN..FONT_SIZE_MAX). */
6
+ setFontSize: (px: number) => void;
7
+ }
8
+ /** Full component props: runtime share + store share + locale seat + injected face. */
9
+ export type FontSizeRowComponentProps = PropsRuntime<'settings.general.item'> & PropsStore<ReturnType<typeof createFontSizeRowStore>> & PropsLocale<'settings.theme'> & FontSizeRowInjected;
10
+ /**
11
+ * Render the font-size row.
12
+ * @param props - composed slot props.
13
+ * @returns the row element tree.
14
+ */
15
+ export declare function FontSizeRow({ t, setFontSize, useStore }: FontSizeRowComponentProps): import("react").JSX.Element;
16
+ //# sourceMappingURL=FontSizeRow.d.ts.map
@@ -7,12 +7,13 @@
7
7
  * document. The plugin also registers the Appearance preference row into the
8
8
  * settings General section — the theme feature owns its own settings surface.
9
9
  */
10
- import type { Context } from '@deepseek-ai/cordis';
11
- import type { ClientContext, SettingsScope } from '@deepseek-ai/dsh-client-runtime/client';
10
+ import type { Context as ClientContext } from '@deepseek-ai/cordis';
11
+ import type { SettingsScope } from '@deepseek-ai/dsh-client-ui-settings/client';
12
12
  import { type ThemeKey } from './locales.ts';
13
13
  import { type ThemePreference, type ThemeSettings } from '../theme-settings.ts';
14
14
  export type { AppearanceRowComponentProps, AppearanceRowInjected } from './AppearanceRow.tsx';
15
- export type { AppearanceRowState } from './settings-store.ts';
15
+ export type { FontSizeRowComponentProps, FontSizeRowInjected } from './FontSizeRow.tsx';
16
+ export type { AppearanceRowState, FontSizeRowState } from './settings-store.ts';
16
17
  export type { ThemeKey } from './locales.ts';
17
18
  export type { ThemePreference, ThemeSettings } from '../theme-settings.ts';
18
19
  /** Namespace owning this feature's settings-row copy. */
@@ -54,6 +55,8 @@ export interface ThemeDefinition {
54
55
  export interface ThemeSnapshot {
55
56
  /** The persisted preference (may be `system`). */
56
57
  preference: ThemePreference;
58
+ /** Conversation content font size in px (integer within FONT_SIZE_MIN..FONT_SIZE_MAX). */
59
+ fontSize: number;
57
60
  /**
58
61
  * The resolved active theme (`system` resolved via prefers-color-scheme)
59
62
  * with override layers folded into its tokens (seq order, later layers win
@@ -108,6 +111,7 @@ export declare class ThemeRuntime {
108
111
  private readonly host;
109
112
  private themes;
110
113
  private preference;
114
+ private fontSize;
111
115
  private revision;
112
116
  private snapshot;
113
117
  private readonly media;
@@ -119,7 +123,7 @@ export declare class ThemeRuntime {
119
123
  * media-query and scope listeners are released through ctx.effect on dispose).
120
124
  * @param host - durable preference scope owned by the same plugin.
121
125
  */
122
- constructor(ctx: Context, host: SettingsScope<ThemeSettings>);
126
+ constructor(ctx: ClientContext, host: SettingsScope<ThemeSettings>);
123
127
  /**
124
128
  * Read the current immutable theme snapshot.
125
129
  * @returns the current snapshot (stable reference until the next change).
@@ -137,6 +141,13 @@ export declare class ThemeRuntime {
137
141
  * @param id - a registered theme id or `system`; unknown ids throw.
138
142
  */
139
143
  setTheme(id: string): void;
144
+ /**
145
+ * Change the conversation content font size — the only font-size write
146
+ * entry. Accepted values are written through the settings scope and emit
147
+ * `theme/change`.
148
+ * @param px - integer px within FONT_SIZE_MIN..FONT_SIZE_MAX; out-of-range or fractional values throw.
149
+ */
150
+ setFontSize(px: number): void;
140
151
  /** Adopt the scope's accepted durable preference without writing it back. */
141
152
  private adopt;
142
153
  /**
@@ -1,10 +1,15 @@
1
- /** `settings.theme` namespace dictionaries (the Appearance row's copy). */
1
+ /** `settings.theme` namespace dictionaries (the Appearance and font-size rows' copy). */
2
2
  /** Simplified Chinese dictionary (the key-set source of truth). */
3
3
  export declare const zh: {
4
4
  'appearance.title': string;
5
5
  'appearance.light': string;
6
6
  'appearance.dark': string;
7
7
  'appearance.system': string;
8
+ 'fontSize.title': string;
9
+ 'fontSize.description': string;
10
+ 'fontSize.unit': string;
11
+ 'fontSize.increase': string;
12
+ 'fontSize.decrease': string;
8
13
  };
9
14
  /** The settings.theme namespace key union. */
10
15
  export type ThemeKey = keyof typeof zh;
@@ -14,5 +19,10 @@ export declare const en: {
14
19
  'appearance.light': string;
15
20
  'appearance.dark': string;
16
21
  'appearance.system': string;
22
+ 'fontSize.title': string;
23
+ 'fontSize.description': string;
24
+ 'fontSize.unit': string;
25
+ 'fontSize.increase': string;
26
+ 'fontSize.decrease': string;
17
27
  };
18
28
  //# sourceMappingURL=locales.d.ts.map
@@ -1,10 +1,10 @@
1
1
  /**
2
- * Appearance row slot store: a mirror of the theme service snapshot. The
3
- * plugin's apply-world change listener is the only writer; the row component
4
- * reads via props.useStore.
2
+ * Appearance and font-size row slot stores: mirrors of the theme service
3
+ * snapshot. The plugin's apply-world change listener is the only writer; the
4
+ * row components read via props.useStore.
5
5
  */
6
- import { type EngineStoreHandle } from '@deepseek-ai/dsh-client-runtime/client';
7
- import type { ThemePreference } from '../theme-settings.ts';
6
+ import { type EngineStoreHandle } from '@deepseek-ai/dsh-client-store';
7
+ import { type ThemePreference } from '../theme-settings.ts';
8
8
  /** Store state mirrored from the theme snapshot. */
9
9
  export interface AppearanceRowState {
10
10
  /** Persisted preference (selection state reads this, never the resolved active theme). */
@@ -21,5 +21,21 @@ type AppearanceRowActions = {
21
21
  * @returns the store handle.
22
22
  */
23
23
  export declare function createAppearanceRowStore(): EngineStoreHandle<AppearanceRowState, AppearanceRowActions>;
24
+ /** Store state mirrored from the theme snapshot's font size. */
25
+ export interface FontSizeRowState {
26
+ /** Persisted content font size in px. */
27
+ fontSize: number;
28
+ /** Service revision; -1 until first sync so revision 0 lands as a change. */
29
+ revision: number;
30
+ }
31
+ /** Declared action shape giving the exported factory a stable return type. */
32
+ type FontSizeRowActions = {
33
+ sync: (draft: FontSizeRowState, fontSize: number, revision: number) => void;
34
+ };
35
+ /**
36
+ * Declares the font-size row state and write surface.
37
+ * @returns the store handle.
38
+ */
39
+ export declare function createFontSizeRowStore(): EngineStoreHandle<FontSizeRowState, FontSizeRowActions>;
24
40
  export {};
25
41
  //# sourceMappingURL=settings-store.d.ts.map
@@ -1,6 +1,6 @@
1
1
  /** Host registration for the browser theme preference and pre-plugin palette. */
2
2
  import type { Context } from '@deepseek-ai/cordis';
3
- export { DEFAULT_PREFERENCE, THEME_PREFERENCE_FIELD, THEME_PREFERENCES, THEME_SETTINGS_NAMESPACE, type ThemePreference, type ThemeSettings, } from './theme-settings.ts';
3
+ export { DEFAULT_FONT_SIZE, DEFAULT_PREFERENCE, FONT_SIZE_FIELD, FONT_SIZE_MAX, FONT_SIZE_MIN, THEME_PREFERENCE_FIELD, THEME_PREFERENCES, THEME_SETTINGS_NAMESPACE, type ThemePreference, type ThemeSettings, } from './theme-settings.ts';
4
4
  /**
5
5
  * Register the durable theme section when the optional settings service is
6
6
  * composed, and answer every index injection collection with the current
@@ -6,14 +6,24 @@ export declare const THEME_PREFERENCES: readonly ["light", "dark", "system"];
6
6
  export declare const THEME_SETTINGS_NAMESPACE = "ui-theme";
7
7
  /** Field carrying the selected built-in theme preference. */
8
8
  export declare const THEME_PREFERENCE_FIELD = "preference";
9
+ /** Field carrying the conversation content font size. */
10
+ export declare const FONT_SIZE_FIELD = "fontSize";
9
11
  /** Theme preference persisted by the product Appearance row. */
10
12
  export type ThemePreference = typeof THEME_PREFERENCES[number];
11
13
  /** Default preference when the user-settings document has no override. */
12
14
  export declare const DEFAULT_PREFERENCE: ThemePreference;
15
+ /** Smallest accepted content font size (px). */
16
+ export declare const FONT_SIZE_MIN = 12;
17
+ /** Largest accepted content font size (px). */
18
+ export declare const FONT_SIZE_MAX = 17;
19
+ /** Content font size when the user-settings document has no override (px). */
20
+ export declare const DEFAULT_FONT_SIZE = 14;
13
21
  /** Durable theme section shared by the Host schema and the browser scope. */
14
22
  export interface ThemeSettings {
15
23
  /** Selected built-in preference. */
16
24
  preference: ThemePreference;
25
+ /** Conversation content font size in px (integer within {@link FONT_SIZE_MIN}..{@link FONT_SIZE_MAX}). */
26
+ fontSize: number;
17
27
  }
18
28
  /** Durable theme schema; also the wire envelope the browser scope validates against. */
19
29
  export declare const ThemeSettingsSchema: z<ThemeSettings>;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@deepseek-ai/dsh-client-ui-theme",
3
3
  "description": "Theme plugin: Host bootstrap for the pre-plugin palette; DOM-free ThemeRuntime for light/dark/system state; --dsw-* token styles and Appearance settings row",
4
- "version": "0.1.1-rc.2",
4
+ "version": "0.1.2-alpha.2",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -33,8 +33,8 @@
33
33
  "client": {
34
34
  "inject": [
35
35
  "@deepseek-ai/dsh-client-connection",
36
- "@deepseek-ai/dsh-client-runtime",
37
36
  "@deepseek-ai/dsh-client-locale",
37
+ "@deepseek-ai/dsh-client-ui-renderer",
38
38
  "@deepseek-ai/dsh-client-ui-settings",
39
39
  "@deepseek-ai/dsh-api-remotes"
40
40
  ],
@@ -44,31 +44,24 @@
44
44
  },
45
45
  "license": "MIT",
46
46
  "peerDependencies": {
47
- "@deepseek-ai/cordis": "^4.0.1",
48
- "@deepseek-ai/dsh-api-remotes": "^0.1.1-rc.2",
49
- "@deepseek-ai/dsh-client-connection": "^0.1.1-rc.2",
50
- "@deepseek-ai/dsh-client-locale": "^0.1.1-rc.2",
51
- "@deepseek-ai/dsh-client-runtime": "^0.1.1-rc.2",
52
- "@deepseek-ai/dsh-client-ui-settings": "^0.1.1-rc.2",
53
- "@deepseek-ai/dsh-invariants": "^0.1.1-rc.2",
54
- "@deepseek-ai/dsh-host-webserver": "^0.1.1-rc.2",
55
- "@deepseek-ai/dsh-settings": "^0.1.1-rc.2"
47
+ "@deepseek-ai/cordis": "^4.0.2"
56
48
  },
57
49
  "devDependencies": {
58
50
  "@types/react": "~18.3.1",
59
51
  "react": "^18.2.0",
60
- "@deepseek-ai/cordis": "^4.0.1",
61
- "@deepseek-ai/dsh-api-remotes": "^0.1.1-rc.2",
62
- "@deepseek-ai/dsh-client-connection": "^0.1.1-rc.2",
63
- "@deepseek-ai/dsh-client-locale": "^0.1.1-rc.2",
64
- "@deepseek-ai/dsh-client-runtime": "^0.1.1-rc.2",
65
- "@deepseek-ai/dsh-client-test-runtime": "^0.1.1-rc.2",
66
- "@deepseek-ai/dsh-client-ui-primitives": "^0.1.1-rc.2",
67
- "@deepseek-ai/dsh-client-ui-settings": "^0.1.1-rc.2",
68
- "@deepseek-ai/dsh-client-ui-slots": "^0.1.1-rc.2",
69
- "@deepseek-ai/dsh-host-webserver": "^0.1.1-rc.2",
70
- "@deepseek-ai/dsh-invariants": "^0.1.1-rc.2",
71
- "@deepseek-ai/dsh-settings": "^0.1.1-rc.2"
52
+ "@deepseek-ai/cordis": "^4.0.2",
53
+ "@deepseek-ai/dsh-api-remotes": "^0.1.2-alpha.2",
54
+ "@deepseek-ai/dsh-client-connection": "^0.1.2-alpha.2",
55
+ "@deepseek-ai/dsh-client-locale": "^0.1.2-alpha.2",
56
+ "@deepseek-ai/dsh-client-store": "^0.1.2-alpha.2",
57
+ "@deepseek-ai/dsh-client-test-runtime": "^0.1.2-alpha.2",
58
+ "@deepseek-ai/dsh-client-ui-primitives": "^0.1.2-alpha.2",
59
+ "@deepseek-ai/dsh-client-ui-renderer": "^0.1.2-alpha.2",
60
+ "@deepseek-ai/dsh-client-ui-settings": "^0.1.2-alpha.2",
61
+ "@deepseek-ai/dsh-client-ui-slots": "^0.1.2-alpha.2",
62
+ "@deepseek-ai/dsh-host-webserver": "^0.1.2-alpha.2",
63
+ "@deepseek-ai/dsh-invariants": "^0.1.2-alpha.2",
64
+ "@deepseek-ai/dsh-settings": "^0.1.2-alpha.2"
72
65
  },
73
66
  "files": [
74
67
  "lib/index.js",
@@ -79,7 +72,7 @@
79
72
  ],
80
73
  "dependencies": {
81
74
  "clsx": "^2.0.0",
82
- "@deepseek-ai/schemastery": "^3.18.1"
75
+ "@deepseek-ai/schemastery": "^3.18.2"
83
76
  },
84
77
  "scripts": {
85
78
  "bundle": "tsdown",