@lemoncat7/dsh-theme-xiaohei 0.3.4 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -4
- package/docs/releases/0.3.5.md +7 -0
- package/docs/releases/0.4.0.md +20 -0
- package/lib/bloub-heixiu/signals.js +3 -1
- package/lib/chrome/conversation-messages.js +22 -0
- package/lib/chrome/sidebar.d.ts +1 -1
- package/lib/chrome/sidebar.js +9 -0
- package/lib/client.js +35 -1
- package/lib/current-session.d.ts +6 -0
- package/lib/current-session.js +5 -0
- package/lib/state.js +3 -2
- package/package.json +15 -12
package/README.md
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
# Xiaohei Night for DSH
|
|
2
2
|
|
|
3
|
+
> 当前正式版 **0.4.0**,适配并验证 **DSH 0.1.7-rc.2**。插件为正式版,宿主仍为 RC;不支持直接用于旧宿主。Node.js **^22.19.0 或 >=24.0.0**。旧版源码保留于 `pre-dsh-0.1.7-rc.2`;详见 [0.4.0 发布说明](docs/releases/0.4.0.md)。
|
|
4
|
+
|
|
3
5
|
`Xiaohei Night` 是一个基于 DeepSeek Harness 官方主题注册接口开发的非官方粉丝主题插件。主题以低饱和天空、日夜光线和坐在小平台上的人形小黑表达陪伴感,保留原生工作台布局。
|
|
4
6
|
|
|
5
7
|
## 兼容性
|
|
6
8
|
|
|
7
|
-
正式版 `0.
|
|
9
|
+
正式版 `0.4.0` 适配并验证 DeepSeek Harness `0.1.7-rc.2`,开发依赖锁定该宿主版本,需要 Node.js `^22.19.0` 或 `>=24.0.0`。旧宿主请保留 `0.3.5`。保留侧栏操作与仅思考消息显示修复,不修改官方核心代码。“跟随系统”读取当前设备/浏览器配色偏好,不按服务器时间切换。
|
|
8
10
|
|
|
9
11
|
## 当前范围
|
|
10
12
|
|
|
@@ -33,13 +35,13 @@
|
|
|
33
35
|
通过 npm 安装正式版:
|
|
34
36
|
|
|
35
37
|
```bash
|
|
36
|
-
dsh plugin --profile web add @lemoncat7/dsh-theme-xiaohei@0.3.
|
|
38
|
+
dsh plugin --profile web add @lemoncat7/dsh-theme-xiaohei@0.3.5
|
|
37
39
|
```
|
|
38
40
|
|
|
39
|
-
|
|
41
|
+
也可在源码目录运行 `npm pack` 生成完整包后安装:
|
|
40
42
|
|
|
41
43
|
```bash
|
|
42
|
-
dsh plugin --profile web add ./lemoncat7-dsh-theme-xiaohei-0.3.
|
|
44
|
+
dsh plugin --profile web add ./lemoncat7-dsh-theme-xiaohei-0.3.5.tgz
|
|
43
45
|
```
|
|
44
46
|
|
|
45
47
|
卸载:
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# 0.3.5 · 侧栏按钮与思考气泡修复
|
|
2
|
+
|
|
3
|
+
延续 0.3.4 的 DSH 0.1.5-rc.1 兼容基线,Node.js ^22.19.0 或 >=24.0.0。本次浏览器回归使用桌面及移动端模拟 DOM,未重新完成其他宿主版本的端到端验证。
|
|
4
|
+
|
|
5
|
+
- 按中英文 aria-label 定位原生收起侧栏按钮,恢复显示和点击,不依赖按钮排列位置,不覆盖宿主明确隐藏或禁用的控件。
|
|
6
|
+
- 仅思考内容的助手节点移除气泡背景、边框、留白与头像,恢复普通过程行;混合正文仍保留聊天气泡。
|
|
7
|
+
- 不修改 DSH 官方核心代码,不增加运行时轮询。
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# 0.4.0 · 适配 DSH 0.1.7-rc.2
|
|
2
|
+
|
|
3
|
+
插件正式版(非 prerelease),已验证宿主:**DSH 0.1.7-rc.2**。宿主本身仍是 RC,不代表已验证所有未来版本。Node.js:**^22.19.0 或 >=24.0.0**。
|
|
4
|
+
|
|
5
|
+
## 更新
|
|
6
|
+
|
|
7
|
+
适配主视图当前会话和 pendingSubmissions,保留侧栏操作与对话显示,不改动既有角色资产。
|
|
8
|
+
|
|
9
|
+
## 升级与回退
|
|
10
|
+
|
|
11
|
+
- 本版面向 DSH 0.1.7-rc.2,不应直接安装到 DSH 0.1.5 或更早宿主。
|
|
12
|
+
- 升级前源码快照:`pre-dsh-0.1.7-rc.2`(提交 dfea01f,插件源码版本 0.3.5)。历史正式标签保留,不移动或覆盖。
|
|
13
|
+
- 旧版 npm 安装参考:`npm install @lemoncat7/dsh-theme-xiaohei@0.3.5`;升级宿主前先备份配置、数据库及工作目录。
|
|
14
|
+
- 新版安装:`npm install @lemoncat7/dsh-theme-xiaohei@0.4.0`。
|
|
15
|
+
|
|
16
|
+
## 验证边界
|
|
17
|
+
|
|
18
|
+
本地构建和自动化测试通过;DSH 0.1.7-rc.2 隔离容器已验证插件启动、适用的设置页面和接口。正式容器已经部署对应兼容代码并完成页面/API 冒烟检查。
|
|
19
|
+
|
|
20
|
+
未穷举 Windows/macOS 桌面桥、真实远端 SSH/FTP、所有渠道端到端附件投递及付费模型提供方。没有把本次验证扩大为对所有外部服务的保证。
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { currentSession } from '../current-session.js';
|
|
1
2
|
/** Small local read model. No messages, RPCs, history scans or persisted state. */
|
|
2
3
|
export function createHeixiuSignals() {
|
|
3
4
|
let value = { running: false, notice: null, revision: 0 };
|
|
@@ -32,7 +33,8 @@ export function bindHeixiuSessions(sessions, signals) {
|
|
|
32
33
|
previous = next;
|
|
33
34
|
};
|
|
34
35
|
const select = () => {
|
|
35
|
-
const
|
|
36
|
+
const snapshot = sessions.list.getSnapshot();
|
|
37
|
+
const id = currentSession(snapshot);
|
|
36
38
|
const next = id ? sessions.binding(id)?.session : undefined;
|
|
37
39
|
if (next === face)
|
|
38
40
|
return;
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import { XIAOHEI_AVATAR_2D_FRONT } from '../generated-keyart.js';
|
|
2
|
+
// AssistantMarkdown > body > ProcessReasoning > ReasoningRow. Require the
|
|
3
|
+
// reasoning wrapper to be the only body child: mixed replies/images/interrupted
|
|
4
|
+
// messages keep their bubble. No hashed classes or nested :has selectors.
|
|
5
|
+
const thinkingOnlyRow = `#root [data-chat-flow-kind='assistant-step']:has(> [data-slot='conversation.chat.node'] > div:first-child > div:only-child > div:only-child > [data-variant='think']:only-child)`;
|
|
2
6
|
/** Native conversation messages restyled without changing their DOM contract. */
|
|
3
7
|
export const XIAOHEI_CONVERSATION_MESSAGES_CSS = `
|
|
4
8
|
/* Keep DSH's native max width; only tune vertical reading rhythm. */
|
|
@@ -10,6 +14,24 @@ export const XIAOHEI_CONVERSATION_MESSAGES_CSS = `
|
|
|
10
14
|
color: var(--xiaohei-conversation-text);
|
|
11
15
|
}
|
|
12
16
|
|
|
17
|
+
${thinkingOnlyRow} {
|
|
18
|
+
padding-inline: 0 !important;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
${thinkingOnlyRow}::before {
|
|
22
|
+
content: none !important;
|
|
23
|
+
display: none !important;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
${thinkingOnlyRow} > [data-slot='conversation.chat.node'] > div:first-child {
|
|
27
|
+
inline-size: 100% !important;
|
|
28
|
+
padding: 0 !important;
|
|
29
|
+
border: 0 !important;
|
|
30
|
+
border-radius: 0 !important;
|
|
31
|
+
background: transparent !important;
|
|
32
|
+
box-shadow: none !important;
|
|
33
|
+
}
|
|
34
|
+
|
|
13
35
|
/* Message portraits are deliberately static and only identify the speaker. */
|
|
14
36
|
#root [data-chat-flow-kind='assistant-step'],
|
|
15
37
|
#root [data-chat-flow-kind='user'] {
|
package/lib/chrome/sidebar.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
/** One glass surface over DSH's native sidebar geometry and controls. */
|
|
2
|
-
export declare const XIAOHEI_SIDEBAR_CSS = "\n/* The layout column and SidebarRoot both consume the native sidebar fill.\n * The theme token makes those surfaces transparent; this stable slot\n * relationship removes the layout column's remaining straight divider. */\n#root :has(> [data-slot='sidebar']) {\n background: transparent !important;\n border-right-color: transparent !important;\n}\n\n#root [data-slot='sidebar'] {\n position: relative;\n}\n\n/* Reveal wide navigation only after its column has reached the target width.\n * Keep the toggle itself native. Opacity is applied to content, never the shell\n * (which also hosts fixed-position settings dialogs). */\n@media (prefers-reduced-motion: no-preference) {\n #root [data-xiaohei-sidebar-reveal] [data-xiaohei-sidebar-brand] {\n transition: opacity 100ms ease-out;\n }\n #root [data-xiaohei-sidebar-reveal='waiting'] [data-xiaohei-sidebar-brand] {\n opacity: 0 !important;\n visibility: hidden;\n transition: none;\n }\n}\n\n/* Hide the tree scrollbar's paint, retaining its gutter so rows do not grow\n * into the glass edge. Wheel, touch and keyboard remain native; dialogs and\n * other plugin panels keep their normal scrollbar affordance. */\n#root [data-slot='sidebar.workspaces'] [role='tree'] {\n scrollbar-color: transparent transparent !important;\n}\n\n#root [data-slot='sidebar.workspaces'] [role='tree']::-webkit-scrollbar,\n#root [data-slot='sidebar.workspaces'] [role='tree']::-webkit-scrollbar-thumb,\n#root [data-slot='sidebar.workspaces'] [role='tree']::-webkit-scrollbar-track {\n background: transparent !important;\n border-color: transparent !important;\n box-shadow: none !important;\n}\n\n/* The host shell remains paint- and filter-free because Settings is a fixed\n * descendant. The glass itself lives outside #root in the scene layer. */\n#root [data-slot='sidebar'] > div {\n --dsh-sidebar-inline-padding: 18px;\n position: relative;\n background: transparent !important;\n border-right: 0;\n box-shadow: none;\n}\n\n#dsh-theme-xiaohei\\/sidebar-glass {\n position: absolute;\n box-sizing: border-box;\n left: var(--xiaohei-sidebar-glass-left, 7px);\n top: var(--xiaohei-sidebar-glass-top, 8px);\n width: var(--xiaohei-sidebar-glass-width, 0px);\n height: var(--xiaohei-sidebar-glass-height, 0px);\n pointer-events: none;\n overflow: hidden;\n border: 1px solid var(--xiaohei-sidebar-glass-edge);\n border-radius: var(--xiaohei-sidebar-glass-radius);\n background: var(--xiaohei-sidebar-glass-fill);\n box-shadow:\n inset 0 1px var(--xiaohei-sidebar-glass-highlight),\n inset 1px 0 var(--xiaohei-sidebar-glass-refraction),\n 0 18px 50px -32px var(--xiaohei-sidebar-shadow);\n -webkit-backdrop-filter:\n blur(var(--xiaohei-sidebar-glass-blur))\n saturate(var(--xiaohei-sidebar-glass-saturation));\n backdrop-filter:\n blur(var(--xiaohei-sidebar-glass-blur))\n saturate(var(--xiaohei-sidebar-glass-saturation));\n}\n\n/* Width dragging changes the full-height glass raster every frame. Suspend\n * only the filters while geometry is moving; the translucent surface remains\n * visible and the settled glass returns after the resize gesture ends. */\nhtml[data-xiaohei-sidebar-resizing] #dsh-theme-xiaohei\\/sidebar-glass {\n -webkit-backdrop-filter: none;\n backdrop-filter: none;\n}\n\n/* One restrained inner rim completes the glass edge without tinting content. */\n#dsh-theme-xiaohei\\/sidebar-glass::after {\n content: '';\n position: absolute;\n pointer-events: none;\n inset: 1px;\n border-radius: calc(var(--xiaohei-sidebar-glass-radius) - 1px);\n box-shadow:\n inset 0 1px var(--xiaohei-sidebar-glass-refraction),\n inset 0 -20px 28px -32px var(--xiaohei-sidebar-shadow-soft);\n}\n\n/* The official brand slot owns geometry in both the wide sidebar and rail.\n * The bitmap remains visible as a no-WebGL fallback while the compact\n * MetallicPaint canvas adds a restrained liquid-metal pass above it. */\n.xiaohei-brand-mark {\n position: relative;\n display: inline-grid;\n flex: none;\n place-items: center;\n width: var(--xiaohei-brand-mark-size);\n height: var(--xiaohei-brand-mark-size);\n margin: -2px;\n overflow: visible;\n pointer-events: none;\n filter: drop-shadow(0 2px 3px rgb(8 13 15 / 18%));\n transform: translateY(-1px);\n}\n\n.xiaohei-brand-mark__fallback,\n.xiaohei-brand-mark__metal {\n position: absolute;\n inset: 0;\n display: block;\n width: 100%;\n height: 100%;\n object-fit: contain;\n}\n\n.xiaohei-brand-mark__fallback {\n opacity: .94;\n transition: opacity var(--xiaohei-motion-base) ease;\n}\n\n.xiaohei-brand-mark__metal {\n opacity: 0;\n transition:\n opacity var(--xiaohei-motion-base) ease,\n filter var(--xiaohei-motion-base) ease;\n}\n\n.xiaohei-brand-mark[data-metallic-ready='true'] .xiaohei-brand-mark__fallback {\n opacity: .28;\n}\n\n.xiaohei-brand-mark[data-metallic-ready='true'] .xiaohei-brand-mark__metal {\n opacity: .92;\n}\n\n.xiaohei-brand-name {\n white-space: nowrap;\n letter-spacing: .025em;\n font-size: 17px;\n font-weight: 600;\n}\n\n/* ui-conversation currently exposes the Hero mark but not its headline as a\n * slot. Anchor the visual copy to that official mark occupant so hashed Host\n * class names and unrelated headings remain untouched. */\n#root span:has(> .xiaohei-brand-mark[data-brand-context='hero']) + span {\n font-size: 0;\n}\n\n#root span:has(> .xiaohei-brand-mark[data-brand-context='hero']) + span::after {\n content: '\u4E07\u7269\u6709\u7075\uFF0C\u81EA\u5728\u540C\u884C';\n font-size: 26px;\n font-weight: 500;\n line-height: 32px;\n}\n\n#root [data-slot='sidebar'] button:hover .xiaohei-brand-mark__metal {\n filter: brightness(1.12) contrast(1.04);\n}\n\n/* Keep native rail/wide geometry and one consistent control material. */\n#root [data-slot='sidebar'] button:is([aria-label='Collapse sidebar'], [aria-label='\u6536\u8D77\u4FA7\u8FB9\u680F']),\n#root [data-slot='sidebar'] > div:has(button:is([aria-label='Collapse sidebar'], [aria-label='\u6536\u8D77\u4FA7\u8FB9\u680F'])) > button[aria-label='\u65B0\u5EFA\u4F1A\u8BDD'],\n#root [data-slot='sidebar'] > div:has(button:is([aria-label='Collapse sidebar'], [aria-label='\u6536\u8D77\u4FA7\u8FB9\u680F'])) > button[aria-label='New session'] {\n color: var(--xiaohei-sidebar-emphasis);\n transition:\n background-color var(--xiaohei-motion-fast) ease,\n border-color var(--xiaohei-motion-fast) ease,\n transform var(--xiaohei-motion-fast) var(--xiaohei-motion-curve);\n}\n\n#root [data-slot='sidebar'] button:is([aria-label='Collapse sidebar'], [aria-label='\u6536\u8D77\u4FA7\u8FB9\u680F']):hover {\n background: var(--xiaohei-sidebar-hover);\n}\n\n#root [data-slot='sidebar'] > div:has(button:is([aria-label='Collapse sidebar'], [aria-label='\u6536\u8D77\u4FA7\u8FB9\u680F'])) > button[aria-label='\u65B0\u5EFA\u4F1A\u8BDD'],\n#root [data-slot='sidebar'] > div:has(button:is([aria-label='Collapse sidebar'], [aria-label='\u6536\u8D77\u4FA7\u8FB9\u680F'])) > button[aria-label='New session'] {\n border: 1px solid var(--xiaohei-sidebar-control-edge);\n border-radius: var(--xiaohei-radius-control);\n background: var(--xiaohei-sidebar-control);\n box-shadow: inset 0 1px var(--xiaohei-sidebar-control-highlight);\n justify-content: flex-start;\n gap: 8px;\n padding-inline: 12px;\n text-align: start;\n}\n\n#root [data-slot='sidebar'] > div:has(button:is([aria-label='Collapse sidebar'], [aria-label='\u6536\u8D77\u4FA7\u8FB9\u680F'])) > button[aria-label='\u65B0\u5EFA\u4F1A\u8BDD']:hover,\n#root [data-slot='sidebar'] > div:has(button:is([aria-label='Collapse sidebar'], [aria-label='\u6536\u8D77\u4FA7\u8FB9\u680F'])) > button[aria-label='New session']:hover {\n border-color: var(--xiaohei-sidebar-control-edge-hover);\n background: var(--xiaohei-sidebar-hover);\n}\n\n/* The footer uses a divider instead of another framed card. */\n#root [data-slot='sidebar'] > div:has(button:is([aria-label='Collapse sidebar'], [aria-label='\u6536\u8D77\u4FA7\u8FB9\u680F']))\n > :has(> div > [data-slot='sidebar.footer.action']) {\n box-sizing: border-box;\n gap: 2px;\n margin-top: 8px;\n padding-top: 8px;\n border-top: 1px solid var(--xiaohei-sidebar-control-edge);\n}\n\n#root [data-slot='sidebar.footer.action'] > button,\n#root [data-slot='sidebar.settings'] > button {\n color: var(--dsw-alias-label-secondary);\n border-radius: var(--xiaohei-radius-small) !important;\n transition:\n color var(--xiaohei-motion-fast) ease,\n background-color var(--xiaohei-motion-fast) ease,\n transform var(--xiaohei-motion-fast) var(--xiaohei-motion-curve);\n}\n\n#root [data-slot='sidebar.footer.action'] > button:hover,\n#root [data-slot='sidebar.settings'] > button:hover,\n#root [data-slot='sidebar.footer.action'] > button[aria-expanded='true'],\n#root [data-slot='sidebar.settings'] > button[aria-expanded='true'] {\n color: var(--xiaohei-sidebar-emphasis);\n background: var(--xiaohei-sidebar-hover);\n}\n\n#root [data-slot='sidebar.footer.action'] > button:active,\n#root [data-slot='sidebar.settings'] > button:active {\n transform: translateY(1px);\n}\n\n#root [data-slot='sidebar'] button:focus-visible {\n outline: 2px solid var(--xiaohei-sidebar-emphasis);\n outline-offset: 2px;\n}\n\n@media (prefers-reduced-motion: reduce) {\n #root [data-slot='sidebar'] button {\n transition-duration: 0ms !important;\n }\n\n\n .xiaohei-brand-mark__fallback,\n .xiaohei-brand-mark__metal {\n transition-duration: 0ms !important;\n }\n}\n\n@media (prefers-reduced-transparency: reduce) {\n #dsh-theme-xiaohei\\/sidebar-glass {\n background: var(--xiaohei-sidebar-glass-solid);\n -webkit-backdrop-filter: none;\n backdrop-filter: none;\n }\n\n}\n\n@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {\n #dsh-theme-xiaohei\\/sidebar-glass {\n background: var(--xiaohei-sidebar-glass-solid);\n }\n}\n\n@media (forced-colors: active) {\n #dsh-theme-xiaohei\\/sidebar-glass {\n border-color: CanvasText;\n background: Canvas;\n box-shadow: none;\n -webkit-backdrop-filter: none;\n backdrop-filter: none;\n }\n\n #root [data-slot='sidebar'] > div:has(button:is([aria-label='Collapse sidebar'], [aria-label='\u6536\u8D77\u4FA7\u8FB9\u680F'])) > button[aria-label='\u65B0\u5EFA\u4F1A\u8BDD'],\n #root [data-slot='sidebar'] > div:has(button:is([aria-label='Collapse sidebar'], [aria-label='\u6536\u8D77\u4FA7\u8FB9\u680F'])) > button[aria-label='New session'] {\n border-color: ButtonText;\n }\n\n}\n";
|
|
2
|
+
export declare const XIAOHEI_SIDEBAR_CSS = "\n/* The layout column and SidebarRoot both consume the native sidebar fill.\n * The theme token makes those surfaces transparent; this stable slot\n * relationship removes the layout column's remaining straight divider. */\n#root :has(> [data-slot='sidebar']) {\n background: transparent !important;\n border-right-color: transparent !important;\n}\n\n#root [data-slot='sidebar'] {\n position: relative;\n}\n\n/* Target the native control by its accessible identity, not DOM order.\n * Do not resurrect controls explicitly hidden/disabled by the Host. */\n#root [data-slot='sidebar'] button:is([aria-label='Collapse sidebar'], [aria-label='\u6536\u8D77\u4FA7\u8FB9\u680F']):not([hidden]):not([disabled]):not([aria-hidden='true']) {\n display: inline-flex !important;\n visibility: visible !important;\n opacity: 1 !important;\n pointer-events: auto !important;\n}\n\n/* Reveal wide navigation only after its column has reached the target width.\n * Keep the toggle itself native. Opacity is applied to content, never the shell\n * (which also hosts fixed-position settings dialogs). */\n@media (prefers-reduced-motion: no-preference) {\n #root [data-xiaohei-sidebar-reveal] [data-xiaohei-sidebar-brand] {\n transition: opacity 100ms ease-out;\n }\n #root [data-xiaohei-sidebar-reveal='waiting'] [data-xiaohei-sidebar-brand] {\n opacity: 0 !important;\n visibility: hidden;\n transition: none;\n }\n}\n\n/* Hide the tree scrollbar's paint, retaining its gutter so rows do not grow\n * into the glass edge. Wheel, touch and keyboard remain native; dialogs and\n * other plugin panels keep their normal scrollbar affordance. */\n#root [data-slot='sidebar.workspaces'] [role='tree'] {\n scrollbar-color: transparent transparent !important;\n}\n\n#root [data-slot='sidebar.workspaces'] [role='tree']::-webkit-scrollbar,\n#root [data-slot='sidebar.workspaces'] [role='tree']::-webkit-scrollbar-thumb,\n#root [data-slot='sidebar.workspaces'] [role='tree']::-webkit-scrollbar-track {\n background: transparent !important;\n border-color: transparent !important;\n box-shadow: none !important;\n}\n\n/* The host shell remains paint- and filter-free because Settings is a fixed\n * descendant. The glass itself lives outside #root in the scene layer. */\n#root [data-slot='sidebar'] > div {\n --dsh-sidebar-inline-padding: 18px;\n position: relative;\n background: transparent !important;\n border-right: 0;\n box-shadow: none;\n}\n\n#dsh-theme-xiaohei\\/sidebar-glass {\n position: absolute;\n box-sizing: border-box;\n left: var(--xiaohei-sidebar-glass-left, 7px);\n top: var(--xiaohei-sidebar-glass-top, 8px);\n width: var(--xiaohei-sidebar-glass-width, 0px);\n height: var(--xiaohei-sidebar-glass-height, 0px);\n pointer-events: none;\n overflow: hidden;\n border: 1px solid var(--xiaohei-sidebar-glass-edge);\n border-radius: var(--xiaohei-sidebar-glass-radius);\n background: var(--xiaohei-sidebar-glass-fill);\n box-shadow:\n inset 0 1px var(--xiaohei-sidebar-glass-highlight),\n inset 1px 0 var(--xiaohei-sidebar-glass-refraction),\n 0 18px 50px -32px var(--xiaohei-sidebar-shadow);\n -webkit-backdrop-filter:\n blur(var(--xiaohei-sidebar-glass-blur))\n saturate(var(--xiaohei-sidebar-glass-saturation));\n backdrop-filter:\n blur(var(--xiaohei-sidebar-glass-blur))\n saturate(var(--xiaohei-sidebar-glass-saturation));\n}\n\n/* Width dragging changes the full-height glass raster every frame. Suspend\n * only the filters while geometry is moving; the translucent surface remains\n * visible and the settled glass returns after the resize gesture ends. */\nhtml[data-xiaohei-sidebar-resizing] #dsh-theme-xiaohei\\/sidebar-glass {\n -webkit-backdrop-filter: none;\n backdrop-filter: none;\n}\n\n/* One restrained inner rim completes the glass edge without tinting content. */\n#dsh-theme-xiaohei\\/sidebar-glass::after {\n content: '';\n position: absolute;\n pointer-events: none;\n inset: 1px;\n border-radius: calc(var(--xiaohei-sidebar-glass-radius) - 1px);\n box-shadow:\n inset 0 1px var(--xiaohei-sidebar-glass-refraction),\n inset 0 -20px 28px -32px var(--xiaohei-sidebar-shadow-soft);\n}\n\n/* The official brand slot owns geometry in both the wide sidebar and rail.\n * The bitmap remains visible as a no-WebGL fallback while the compact\n * MetallicPaint canvas adds a restrained liquid-metal pass above it. */\n.xiaohei-brand-mark {\n position: relative;\n display: inline-grid;\n flex: none;\n place-items: center;\n width: var(--xiaohei-brand-mark-size);\n height: var(--xiaohei-brand-mark-size);\n margin: -2px;\n overflow: visible;\n pointer-events: none;\n filter: drop-shadow(0 2px 3px rgb(8 13 15 / 18%));\n transform: translateY(-1px);\n}\n\n.xiaohei-brand-mark__fallback,\n.xiaohei-brand-mark__metal {\n position: absolute;\n inset: 0;\n display: block;\n width: 100%;\n height: 100%;\n object-fit: contain;\n}\n\n.xiaohei-brand-mark__fallback {\n opacity: .94;\n transition: opacity var(--xiaohei-motion-base) ease;\n}\n\n.xiaohei-brand-mark__metal {\n opacity: 0;\n transition:\n opacity var(--xiaohei-motion-base) ease,\n filter var(--xiaohei-motion-base) ease;\n}\n\n.xiaohei-brand-mark[data-metallic-ready='true'] .xiaohei-brand-mark__fallback {\n opacity: .28;\n}\n\n.xiaohei-brand-mark[data-metallic-ready='true'] .xiaohei-brand-mark__metal {\n opacity: .92;\n}\n\n.xiaohei-brand-name {\n white-space: nowrap;\n letter-spacing: .025em;\n font-size: 17px;\n font-weight: 600;\n}\n\n/* ui-conversation currently exposes the Hero mark but not its headline as a\n * slot. Anchor the visual copy to that official mark occupant so hashed Host\n * class names and unrelated headings remain untouched. */\n#root span:has(> .xiaohei-brand-mark[data-brand-context='hero']) + span {\n font-size: 0;\n}\n\n#root span:has(> .xiaohei-brand-mark[data-brand-context='hero']) + span::after {\n content: '\u4E07\u7269\u6709\u7075\uFF0C\u81EA\u5728\u540C\u884C';\n font-size: 26px;\n font-weight: 500;\n line-height: 32px;\n}\n\n#root [data-slot='sidebar'] button:hover .xiaohei-brand-mark__metal {\n filter: brightness(1.12) contrast(1.04);\n}\n\n/* Keep native rail/wide geometry and one consistent control material. */\n#root [data-slot='sidebar'] button:is([aria-label='Collapse sidebar'], [aria-label='\u6536\u8D77\u4FA7\u8FB9\u680F']),\n#root [data-slot='sidebar'] > div:has(button:is([aria-label='Collapse sidebar'], [aria-label='\u6536\u8D77\u4FA7\u8FB9\u680F'])) > button[aria-label='\u65B0\u5EFA\u4F1A\u8BDD'],\n#root [data-slot='sidebar'] > div:has(button:is([aria-label='Collapse sidebar'], [aria-label='\u6536\u8D77\u4FA7\u8FB9\u680F'])) > button[aria-label='New session'] {\n color: var(--xiaohei-sidebar-emphasis);\n transition:\n background-color var(--xiaohei-motion-fast) ease,\n border-color var(--xiaohei-motion-fast) ease,\n transform var(--xiaohei-motion-fast) var(--xiaohei-motion-curve);\n}\n\n#root [data-slot='sidebar'] button:is([aria-label='Collapse sidebar'], [aria-label='\u6536\u8D77\u4FA7\u8FB9\u680F']):hover {\n background: var(--xiaohei-sidebar-hover);\n}\n\n#root [data-slot='sidebar'] > div:has(button:is([aria-label='Collapse sidebar'], [aria-label='\u6536\u8D77\u4FA7\u8FB9\u680F'])) > button[aria-label='\u65B0\u5EFA\u4F1A\u8BDD'],\n#root [data-slot='sidebar'] > div:has(button:is([aria-label='Collapse sidebar'], [aria-label='\u6536\u8D77\u4FA7\u8FB9\u680F'])) > button[aria-label='New session'] {\n border: 1px solid var(--xiaohei-sidebar-control-edge);\n border-radius: var(--xiaohei-radius-control);\n background: var(--xiaohei-sidebar-control);\n box-shadow: inset 0 1px var(--xiaohei-sidebar-control-highlight);\n justify-content: flex-start;\n gap: 8px;\n padding-inline: 12px;\n text-align: start;\n}\n\n#root [data-slot='sidebar'] > div:has(button:is([aria-label='Collapse sidebar'], [aria-label='\u6536\u8D77\u4FA7\u8FB9\u680F'])) > button[aria-label='\u65B0\u5EFA\u4F1A\u8BDD']:hover,\n#root [data-slot='sidebar'] > div:has(button:is([aria-label='Collapse sidebar'], [aria-label='\u6536\u8D77\u4FA7\u8FB9\u680F'])) > button[aria-label='New session']:hover {\n border-color: var(--xiaohei-sidebar-control-edge-hover);\n background: var(--xiaohei-sidebar-hover);\n}\n\n/* The footer uses a divider instead of another framed card. */\n#root [data-slot='sidebar'] > div:has(button:is([aria-label='Collapse sidebar'], [aria-label='\u6536\u8D77\u4FA7\u8FB9\u680F']))\n > :has(> div > [data-slot='sidebar.footer.action']) {\n box-sizing: border-box;\n gap: 2px;\n margin-top: 8px;\n padding-top: 8px;\n border-top: 1px solid var(--xiaohei-sidebar-control-edge);\n}\n\n#root [data-slot='sidebar.footer.action'] > button,\n#root [data-slot='sidebar.settings'] > button {\n color: var(--dsw-alias-label-secondary);\n border-radius: var(--xiaohei-radius-small) !important;\n transition:\n color var(--xiaohei-motion-fast) ease,\n background-color var(--xiaohei-motion-fast) ease,\n transform var(--xiaohei-motion-fast) var(--xiaohei-motion-curve);\n}\n\n#root [data-slot='sidebar.footer.action'] > button:hover,\n#root [data-slot='sidebar.settings'] > button:hover,\n#root [data-slot='sidebar.footer.action'] > button[aria-expanded='true'],\n#root [data-slot='sidebar.settings'] > button[aria-expanded='true'] {\n color: var(--xiaohei-sidebar-emphasis);\n background: var(--xiaohei-sidebar-hover);\n}\n\n#root [data-slot='sidebar.footer.action'] > button:active,\n#root [data-slot='sidebar.settings'] > button:active {\n transform: translateY(1px);\n}\n\n#root [data-slot='sidebar'] button:focus-visible {\n outline: 2px solid var(--xiaohei-sidebar-emphasis);\n outline-offset: 2px;\n}\n\n@media (prefers-reduced-motion: reduce) {\n #root [data-slot='sidebar'] button {\n transition-duration: 0ms !important;\n }\n\n\n .xiaohei-brand-mark__fallback,\n .xiaohei-brand-mark__metal {\n transition-duration: 0ms !important;\n }\n}\n\n@media (prefers-reduced-transparency: reduce) {\n #dsh-theme-xiaohei\\/sidebar-glass {\n background: var(--xiaohei-sidebar-glass-solid);\n -webkit-backdrop-filter: none;\n backdrop-filter: none;\n }\n\n}\n\n@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {\n #dsh-theme-xiaohei\\/sidebar-glass {\n background: var(--xiaohei-sidebar-glass-solid);\n }\n}\n\n@media (forced-colors: active) {\n #dsh-theme-xiaohei\\/sidebar-glass {\n border-color: CanvasText;\n background: Canvas;\n box-shadow: none;\n -webkit-backdrop-filter: none;\n backdrop-filter: none;\n }\n\n #root [data-slot='sidebar'] > div:has(button:is([aria-label='Collapse sidebar'], [aria-label='\u6536\u8D77\u4FA7\u8FB9\u680F'])) > button[aria-label='\u65B0\u5EFA\u4F1A\u8BDD'],\n #root [data-slot='sidebar'] > div:has(button:is([aria-label='Collapse sidebar'], [aria-label='\u6536\u8D77\u4FA7\u8FB9\u680F'])) > button[aria-label='New session'] {\n border-color: ButtonText;\n }\n\n}\n";
|
|
3
3
|
//# sourceMappingURL=sidebar.d.ts.map
|
package/lib/chrome/sidebar.js
CHANGED
|
@@ -12,6 +12,15 @@ export const XIAOHEI_SIDEBAR_CSS = `
|
|
|
12
12
|
position: relative;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
+
/* Target the native control by its accessible identity, not DOM order.
|
|
16
|
+
* Do not resurrect controls explicitly hidden/disabled by the Host. */
|
|
17
|
+
#root [data-slot='sidebar'] button:is([aria-label='Collapse sidebar'], [aria-label='收起侧边栏']):not([hidden]):not([disabled]):not([aria-hidden='true']) {
|
|
18
|
+
display: inline-flex !important;
|
|
19
|
+
visibility: visible !important;
|
|
20
|
+
opacity: 1 !important;
|
|
21
|
+
pointer-events: auto !important;
|
|
22
|
+
}
|
|
23
|
+
|
|
15
24
|
/* Reveal wide navigation only after its column has reached the target width.
|
|
16
25
|
* Keep the toggle itself native. Opacity is applied to content, never the shell
|
|
17
26
|
* (which also hosts fixed-position settings dialogs). */
|
package/lib/client.js
CHANGED
|
@@ -850,6 +850,7 @@ var XIAOHEI_HEIXIU_OPEN = "data:image/webp;base64,UklGRtYUAABXRUJQVlA4WAoAAAASAA
|
|
|
850
850
|
var XIAOHEI_HEIXIU_BLINK = "data:image/webp;base64,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";
|
|
851
851
|
|
|
852
852
|
// src/chrome/conversation-messages.ts
|
|
853
|
+
var thinkingOnlyRow = `#root [data-chat-flow-kind='assistant-step']:has(> [data-slot='conversation.chat.node'] > div:first-child > div:only-child > div:only-child > [data-variant='think']:only-child)`;
|
|
853
854
|
var XIAOHEI_CONVERSATION_MESSAGES_CSS = `
|
|
854
855
|
/* Keep DSH's native max width; only tune vertical reading rhythm. */
|
|
855
856
|
#root [data-chat-flow] {
|
|
@@ -860,6 +861,24 @@ var XIAOHEI_CONVERSATION_MESSAGES_CSS = `
|
|
|
860
861
|
color: var(--xiaohei-conversation-text);
|
|
861
862
|
}
|
|
862
863
|
|
|
864
|
+
${thinkingOnlyRow} {
|
|
865
|
+
padding-inline: 0 !important;
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
${thinkingOnlyRow}::before {
|
|
869
|
+
content: none !important;
|
|
870
|
+
display: none !important;
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
${thinkingOnlyRow} > [data-slot='conversation.chat.node'] > div:first-child {
|
|
874
|
+
inline-size: 100% !important;
|
|
875
|
+
padding: 0 !important;
|
|
876
|
+
border: 0 !important;
|
|
877
|
+
border-radius: 0 !important;
|
|
878
|
+
background: transparent !important;
|
|
879
|
+
box-shadow: none !important;
|
|
880
|
+
}
|
|
881
|
+
|
|
863
882
|
/* Message portraits are deliberately static and only identify the speaker. */
|
|
864
883
|
#root [data-chat-flow-kind='assistant-step'],
|
|
865
884
|
#root [data-chat-flow-kind='user'] {
|
|
@@ -1438,6 +1457,15 @@ var XIAOHEI_SIDEBAR_CSS = `
|
|
|
1438
1457
|
position: relative;
|
|
1439
1458
|
}
|
|
1440
1459
|
|
|
1460
|
+
/* Target the native control by its accessible identity, not DOM order.
|
|
1461
|
+
* Do not resurrect controls explicitly hidden/disabled by the Host. */
|
|
1462
|
+
#root [data-slot='sidebar'] button:is([aria-label='Collapse sidebar'], [aria-label='\u6536\u8D77\u4FA7\u8FB9\u680F']):not([hidden]):not([disabled]):not([aria-hidden='true']) {
|
|
1463
|
+
display: inline-flex !important;
|
|
1464
|
+
visibility: visible !important;
|
|
1465
|
+
opacity: 1 !important;
|
|
1466
|
+
pointer-events: auto !important;
|
|
1467
|
+
}
|
|
1468
|
+
|
|
1441
1469
|
/* Reveal wide navigation only after its column has reached the target width.
|
|
1442
1470
|
* Keep the toggle itself native. Opacity is applied to content, never the shell
|
|
1443
1471
|
* (which also hosts fixed-position settings dialogs). */
|
|
@@ -7037,6 +7065,11 @@ function installComposerBloub(doc = typeof document === "undefined" ? void 0 : d
|
|
|
7037
7065
|
};
|
|
7038
7066
|
}
|
|
7039
7067
|
|
|
7068
|
+
// src/current-session.ts
|
|
7069
|
+
function currentSession(state) {
|
|
7070
|
+
return Object.values(state.byId ?? {}).find((row) => (row.retainedBy?.mainView ?? 0) > 0)?.id ?? state.current;
|
|
7071
|
+
}
|
|
7072
|
+
|
|
7040
7073
|
// src/bloub-heixiu/signals.ts
|
|
7041
7074
|
function createHeixiuSignals() {
|
|
7042
7075
|
let value = { running: false, notice: null, revision: 0 };
|
|
@@ -7073,7 +7106,8 @@ function bindHeixiuSessions(sessions, signals) {
|
|
|
7073
7106
|
previous = next;
|
|
7074
7107
|
};
|
|
7075
7108
|
const select = () => {
|
|
7076
|
-
const
|
|
7109
|
+
const snapshot = sessions.list.getSnapshot();
|
|
7110
|
+
const id = currentSession(snapshot);
|
|
7077
7111
|
const next = id ? sessions.binding(id)?.session : void 0;
|
|
7078
7112
|
if (next === face) return;
|
|
7079
7113
|
removeSession();
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { SessionListState, SessionSummary } from '@deepseek-ai/dsh-api-session-controller/client';
|
|
2
|
+
/** Keep the host session-selection contract out of visual state reducers. */
|
|
3
|
+
export declare function currentSession(state: SessionListState & {
|
|
4
|
+
current?: SessionSummary['id'];
|
|
5
|
+
}): SessionSummary['id'] | undefined;
|
|
6
|
+
//# sourceMappingURL=current-session.d.ts.map
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** Keep the host session-selection contract out of visual state reducers. */
|
|
2
|
+
export function currentSession(state) {
|
|
3
|
+
return Object.values(state.byId ?? {}).find(row => (row.retainedBy?.mainView ?? 0) > 0)?.id ?? state.current;
|
|
4
|
+
}
|
|
5
|
+
//# sourceMappingURL=current-session.js.map
|
package/lib/state.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { currentSession as selectedSession } from './current-session.js';
|
|
1
2
|
export const XIAOHEI_STATE_ATTRIBUTE = 'data-xiaohei-state';
|
|
2
3
|
export const XIAOHEI_COMPLETE_DURATION_MS = 1600;
|
|
3
4
|
/** Resolve one official DSH snapshot using the theme's visible-state priority. */
|
|
@@ -11,7 +12,7 @@ export function resolveXiaoheiState(snapshot, summary) {
|
|
|
11
12
|
return 'error';
|
|
12
13
|
const pending = 'pending' in snapshot
|
|
13
14
|
? snapshot.pending
|
|
14
|
-
:
|
|
15
|
+
: snapshot.pendingSubmissions;
|
|
15
16
|
const runningCalls = 'runningCalls' in snapshot ? snapshot.runningCalls : [];
|
|
16
17
|
const partial = 'partial' in snapshot ? snapshot.partial : null;
|
|
17
18
|
if (pending.length > 0 || legacyPendingInteraction(summary) !== undefined)
|
|
@@ -90,7 +91,7 @@ export function bindXiaoheiSessionState(sessions, doc = typeof document === 'und
|
|
|
90
91
|
if (disposed)
|
|
91
92
|
return;
|
|
92
93
|
const listSnapshot = sessions.list.getSnapshot();
|
|
93
|
-
const nextId = listSnapshot
|
|
94
|
+
const nextId = selectedSession(listSnapshot);
|
|
94
95
|
const nextSession = nextId === undefined ? undefined : sessions.binding(nextId)?.session;
|
|
95
96
|
const changed = nextId !== currentId || nextSession !== currentSession;
|
|
96
97
|
if (changed) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lemoncat7/dsh-theme-xiaohei",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "A Luo Xiaohei-inspired animated dark theme for DeepSeek Harness",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"deepseek-harness",
|
|
@@ -30,8 +30,10 @@
|
|
|
30
30
|
"lib/**/*.d.ts",
|
|
31
31
|
"cordis.patch.yml",
|
|
32
32
|
"README.md",
|
|
33
|
+
"docs/releases/0.3.5.md",
|
|
33
34
|
"THIRD_PARTY_NOTICES.md",
|
|
34
|
-
"LICENSE"
|
|
35
|
+
"LICENSE",
|
|
36
|
+
"docs/releases/0.4.0.md"
|
|
35
37
|
],
|
|
36
38
|
"dsh": {
|
|
37
39
|
"bundle": {
|
|
@@ -60,22 +62,23 @@
|
|
|
60
62
|
"pack:docker": "docker build --output type=local,dest=./dist ."
|
|
61
63
|
},
|
|
62
64
|
"peerDependencies": {
|
|
63
|
-
"@deepseek-ai/cordis": "^4.0.
|
|
65
|
+
"@deepseek-ai/cordis": "^4.0.4"
|
|
64
66
|
},
|
|
65
67
|
"devDependencies": {
|
|
66
|
-
"@deepseek-ai/cordis": "
|
|
67
|
-
"@deepseek-ai/dsh-api-session-controller": "0.1.
|
|
68
|
-
"@deepseek-ai/dsh-client-ui-conversation": "0.1.
|
|
69
|
-
"@deepseek-ai/dsh-client-ui-renderer": "0.1.
|
|
70
|
-
"@deepseek-ai/dsh-client-ui-sidebar": "0.1.
|
|
71
|
-
"@deepseek-ai/dsh-client-ui-slots": "0.1.
|
|
72
|
-
"@deepseek-ai/dsh-client-ui-theme": "0.1.
|
|
73
|
-
"@deepseek-ai/dsh-host-webserver": "0.1.
|
|
68
|
+
"@deepseek-ai/cordis": "~4.0.4",
|
|
69
|
+
"@deepseek-ai/dsh-api-session-controller": "0.1.7-rc.2",
|
|
70
|
+
"@deepseek-ai/dsh-client-ui-conversation": "0.1.7-rc.2",
|
|
71
|
+
"@deepseek-ai/dsh-client-ui-renderer": "0.1.7-rc.2",
|
|
72
|
+
"@deepseek-ai/dsh-client-ui-sidebar": "0.1.7-rc.2",
|
|
73
|
+
"@deepseek-ai/dsh-client-ui-slots": "0.1.7-rc.2",
|
|
74
|
+
"@deepseek-ai/dsh-client-ui-theme": "0.1.7-rc.2",
|
|
75
|
+
"@deepseek-ai/dsh-host-webserver": "0.1.7-rc.2",
|
|
74
76
|
"@types/node": "^24.0.0",
|
|
75
77
|
"@types/react": "^18.3.28",
|
|
76
78
|
"esbuild": "^0.25.0",
|
|
77
79
|
"react": "^18.3.1",
|
|
78
|
-
"typescript": "^5.9.3"
|
|
80
|
+
"typescript": "^5.9.3",
|
|
81
|
+
"@deepseek-ai/dsh-client-ui-session": "0.1.7-rc.2"
|
|
79
82
|
},
|
|
80
83
|
"publishConfig": {
|
|
81
84
|
"access": "public"
|