@max-null/dsh-node-appearance 0.3.0 → 0.3.4
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 +88 -87
- package/lib/client.js +43 -37
- package/lib/client.js.map +1 -1
- package/lib/index.js +9 -6
- package/lib/types/client/index.d.ts +1 -1
- package/lib/types/client/index.d.ts.map +1 -1
- package/lib/types/client/palette.d.ts.map +1 -1
- package/lib/types/client/settings-card.d.ts +5 -7
- package/lib/types/client/settings-card.d.ts.map +1 -1
- package/lib/types/index.d.ts +4 -2
- package/lib/types/index.d.ts.map +1 -1
- package/package.json +15 -16
package/README.md
CHANGED
|
@@ -1,87 +1,88 @@
|
|
|
1
|
-
# dsh-node-appearance
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
在 profile
|
|
26
|
-
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
`
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
1
|
+
# dsh-node-appearance
|
|
2
|
+
|
|
3
|
+
本插件属于 **`@max-null/*` 插件系列**——这一系列共同构成 **[SSID(思灵 · Seek Soul in Darkness)](https://github.com/Max-Null/seek-soul-in-darkness)** 桌面体验。SSID 是整合它们的盒:`dsh-capture` · `dsh-chat-rail` · `dsh-chinese-thinking` · `dsh-draft-polish` · `dsh-guardian` · `dsh-habit` · `dsh-memory` · `dsh-node-appearance` · `dsh-plugin-center` · `dsh-quick-toolbar` · `dsh-skill-mcp-center` · `dsh-ssid-panels` · `dsh-ssid-zh-ui` · `dsh-achievements`。
|
|
4
|
+
|
|
5
|
+
This plugin belongs to the **`@max-null/*` family** — a set of plugins that together form the **[SSID (思灵 · Seek Soul in Darkness)](https://github.com/Max-Null/seek-soul-in-darkness)** desktop experience.
|
|
6
|
+
|
|
7
|
+
会话节点外观插件:按节点类型 / 工具名给 DeepSeek Harness Web GUI 的会话面板节点着色(可配置配色),并提供"显示思考过程"开关。纯前端渲染增强,不改 DSH 源码,`cordis.yml` 一行挂载。
|
|
8
|
+
|
|
9
|
+
## 功能
|
|
10
|
+
|
|
11
|
+
- **节点着色**:工具调用、联网搜索、智能体调用、代码 / 指令执行、文件操作、任务 / 目标、指令节点(`/command`)、思考行(Think)——每种类别一个可配置颜色,左侧 3px 色条 + 淡色底,深 / 浅主题均可读。
|
|
12
|
+
- **工具级颜色覆盖**:任意工具名(如 `web_search`、`subagent`、`run_code`)可单独指定颜色,优先级高于类别色。
|
|
13
|
+
- **思考过程显示开关**:关闭后 Think 思考行前端隐藏(`display: none`),配置项与配色在同一张设置卡片里。
|
|
14
|
+
- **即时生效**:设置改动立即重绘会话,并持久化到 DSH 用户设置文档(`$DSH_HOME/settings.yaml`)。
|
|
15
|
+
|
|
16
|
+
## 截图
|
|
17
|
+
|
|
18
|
+
| 会话节点着色 | 设置卡片 |
|
|
19
|
+
|---|---|
|
|
20
|
+
|  |  |
|
|
21
|
+
|
|
22
|
+
## 安装
|
|
23
|
+
|
|
24
|
+
```sh
|
|
25
|
+
# 在 dsh profile 目录(如 ~/.dsh/profiles/web)
|
|
26
|
+
pnpm add @max-null/dsh-node-appearance
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
在 profile 的 `package.json`(`dsh.profile.bundles`)加入 `@max-null/dsh-node-appearance`,或在 profile 的 `cordis.patch.yml` 插入:
|
|
30
|
+
|
|
31
|
+
```yaml
|
|
32
|
+
- insert:
|
|
33
|
+
- id: node-appearance
|
|
34
|
+
name: '@max-null/dsh-node-appearance'
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
重启 `dsh web` 后生效。设置入口:设置 → 插件配置 → **节点外观**。
|
|
38
|
+
|
|
39
|
+
## 配置
|
|
40
|
+
|
|
41
|
+
`cordis.yml` / settings 文档均可覆盖(以下为初始化配色):
|
|
42
|
+
|
|
43
|
+
```yaml
|
|
44
|
+
node-appearance:
|
|
45
|
+
showThinking: true
|
|
46
|
+
colors:
|
|
47
|
+
search: '#3b82f6' # 联网搜索
|
|
48
|
+
agent: '#a855f7' # 智能体调用
|
|
49
|
+
execute: '#f59e0b' # 代码 / 指令执行
|
|
50
|
+
file: '#22c55e' # 文件操作
|
|
51
|
+
task: '#ec4899' # 任务 / 目标
|
|
52
|
+
command: '#f97316' # 指令节点
|
|
53
|
+
thinking: '#c4b5fd' # 思考过程
|
|
54
|
+
context: '#8a9bb5' # 上下文注入
|
|
55
|
+
other: '#64748b' # 其他工具
|
|
56
|
+
toolColors: {} # 工具名 → 颜色覆盖
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## 工作方式
|
|
60
|
+
|
|
61
|
+
双面插件(Host + browser half,`dsh.client` bundle 由 DSH client 模块系统自动加载):
|
|
62
|
+
|
|
63
|
+
- Host half 通过 `installSettingsSection` 注册 `node-appearance` settings namespace,插件配置作为 base 层。
|
|
64
|
+
- Browser half 绑定 `ctx.settingsScope`,把快照交给纯函数 `buildCss()` 生成 CSS,注入一个 `<style data-plugin-css="node-appearance/rules">` 标签;快照变化即重绘。
|
|
65
|
+
- 着色目标全部使用 DSH 会话 DOM 的稳定 data 属性(`data-chat-flow-kind` / `data-tool` / `data-variant`),不依赖任何 CSS Modules 哈希类名。
|
|
66
|
+
|
|
67
|
+
## 已知限制
|
|
68
|
+
|
|
69
|
+
- v0.1 不做运行态动画与节点折叠。
|
|
70
|
+
- 命令节点只有类别色(`command`),暂无命令名级配色。
|
|
71
|
+
- `toolColors` 按工具名精确匹配;DSH 工具名变更时旧条目静默失效(可在设置面板删除)。
|
|
72
|
+
|
|
73
|
+
## 开发
|
|
74
|
+
|
|
75
|
+
```sh
|
|
76
|
+
npm install
|
|
77
|
+
npm run typecheck # tsc
|
|
78
|
+
npm test # vitest(CSS 规则生成 + Config schema)
|
|
79
|
+
npm run build # tsc 类型 + tsdown(lib/index.js + lib/client.js)
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## 文档
|
|
83
|
+
|
|
84
|
+
- [决策记录](docs/决策/2026-08-17-节点外观插件-独立插件决策.md)
|
|
85
|
+
- [设计方案](docs/设计/DSH节点外观插件-设计方案.md)
|
|
86
|
+
|
|
87
|
+
## SSID 系列
|
|
88
|
+
|
package/lib/client.js
CHANGED
|
@@ -184,12 +184,15 @@ window.__ModuleLoader__.load({
|
|
|
184
184
|
-webkit-mask: url("${STEERING_ICON}") center / contain no-repeat;
|
|
185
185
|
mask: url("${STEERING_ICON}") center / contain no-repeat;
|
|
186
186
|
}`);
|
|
187
|
-
if (settings?.showThinking === false)
|
|
187
|
+
if (settings?.showThinking === false) {
|
|
188
|
+
lines.push(`${THINK_ROW} { display: none !important; }`);
|
|
189
|
+
lines.push(`[data-chat-flow-kind="assistant"]:has(${THINK_ROW}:only-child),`, `[data-chat-flow-kind="assistant-step"]:has(${THINK_ROW}:only-child) { display: none !important; }`);
|
|
190
|
+
}
|
|
188
191
|
return lines.join("\n");
|
|
189
192
|
}
|
|
190
193
|
//#endregion
|
|
191
|
-
//#region \0dsh-css:H:\MaxNull\WorkStation\dsh-node-appearance\src\client\card.module.css.mjs
|
|
192
|
-
const css = ".
|
|
194
|
+
//#region \0dsh-css:H:\MaxNull\WorkStation\max-null-plugins\dsh-node-appearance\src\client\card.module.css.mjs
|
|
195
|
+
const css = ".CDqThG_group{border-bottom:1px solid var(--dsw-alias-border-l2);flex-direction:column;gap:10px;padding:12px 0;display:flex}.CDqThG_header{appearance:none;width:100%;font:inherit;text-align:left;cursor:pointer;background:0 0;border:0;border-radius:6px;align-items:center;gap:8px;padding:0;display:flex}.CDqThG_title{min-width:0;color:var(--dsw-alias-label-primary);flex:1;font-size:13px;font-weight:500;line-height:1.5}.CDqThG_chevron{color:var(--dsw-alias-label-tertiary);flex:none;transition:transform .16s}.CDqThG_chevronOpen{color:var(--dsw-alias-label-tertiary);flex:none;transition:transform .16s;transform:rotate(180deg)}.CDqThG_body{flex-direction:column;display:flex}.CDqThG_row{align-items:center;gap:10px;padding:6px 0;font-size:13px;display:flex}.CDqThG_rowLabel{color:var(--dsw-alias-label-primary);flex:none;font-size:13px;font-weight:500;line-height:1.5}.CDqThG_rowHint{color:var(--dsw-alias-label-tertiary);white-space:nowrap;flex:none;font-size:12px;line-height:1.5}.CDqThG_checkbox{accent-color:var(--dsw-alias-brand-primary);cursor:pointer;width:15px;height:15px}.CDqThG_switch{cursor:pointer;background:var(--dsw-alias-border-l4,#00000029);border:none;border-radius:11px;flex:none;width:40px;height:22px;margin-left:auto;padding:0;transition:background .15s}.CDqThG_switch.CDqThG_on{background:var(--dsw-alias-state-business-primary,#4fc3f7)}.CDqThG_switch .CDqThG_knob{background:#fff;border-radius:8px;width:16px;height:16px;margin-left:2px;transition:margin-left .15s;display:block}.CDqThG_switch.CDqThG_on .CDqThG_knob{margin-left:22px}.CDqThG_colorInput{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);cursor:pointer;border-radius:6px;width:44px;height:26px;margin-left:auto;padding:2px}.CDqThG_colorInput:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:1px}.CDqThG_colorValue{color:var(--dsw-alias-label-secondary);font-family:ui-monospace,monospace;font-size:12px}.CDqThG_sectionTitle{letter-spacing:.06em;text-transform:uppercase;color:var(--dsw-alias-label-tertiary);border-top:1px solid var(--dsw-alias-border-l2);margin-top:10px;padding:10px 0 4px;font-size:12px;font-weight:600;line-height:1.5}.CDqThG_toolRow{align-items:center;gap:10px;padding:6px 0;font-size:13px;display:flex}.CDqThG_toolName{text-overflow:ellipsis;white-space:nowrap;min-width:0;color:var(--dsw-alias-label-secondary);flex:1;font-family:ui-monospace,monospace;font-size:12px;line-height:1.5;overflow:hidden}.CDqThG_removeButton,.CDqThG_addButton{appearance:none;font:inherit;cursor:pointer;color:var(--dsw-alias-label-secondary);background:0 0;border:none;border-radius:7px;padding:5px 8px;font-size:12.5px;line-height:1.5}.CDqThG_removeButton:hover:not(:disabled),.CDqThG_addButton:hover:not(:disabled){color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-1)}.CDqThG_removeButton:disabled,.CDqThG_addButton:disabled{opacity:.4;cursor:default}.CDqThG_removeButton:focus-visible,.CDqThG_addButton:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:1px}.CDqThG_addRow{align-items:center;gap:10px;padding:10px 0 4px;display:flex}.CDqThG_toolInput{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);min-width:0;height:34px;font:inherit;color:var(--dsw-alias-label-primary);border-radius:8px;flex:1;padding:0 12px;font-size:13px;line-height:1.5}.CDqThG_toolInput:focus-visible{border-color:var(--dsw-alias-brand-primary);outline:none}.CDqThG_statusLine{color:var(--dsw-alias-label-tertiary);margin:0 0 8px;font-size:12px;line-height:1.5}.CDqThG_disabled{opacity:.5;pointer-events:none}";
|
|
193
196
|
const tagId = "@max-null/dsh-node-appearance/card.module.css";
|
|
194
197
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
|
|
195
198
|
const tag = document.createElement("style");
|
|
@@ -199,27 +202,30 @@ window.__ModuleLoader__.load({
|
|
|
199
202
|
document.head.appendChild(tag);
|
|
200
203
|
}
|
|
201
204
|
var card_module_css_default = {
|
|
202
|
-
"
|
|
203
|
-
"
|
|
204
|
-
"
|
|
205
|
-
"
|
|
206
|
-
"colorValue": "
|
|
207
|
-
"
|
|
208
|
-
"
|
|
209
|
-
"
|
|
210
|
-
"
|
|
211
|
-
"
|
|
212
|
-
"
|
|
213
|
-
"
|
|
214
|
-
"
|
|
215
|
-
"
|
|
216
|
-
"
|
|
217
|
-
"
|
|
218
|
-
"
|
|
219
|
-
"
|
|
220
|
-
"
|
|
221
|
-
"
|
|
222
|
-
"
|
|
205
|
+
"switch": "CDqThG_switch",
|
|
206
|
+
"removeButton": "CDqThG_removeButton",
|
|
207
|
+
"header": "CDqThG_header",
|
|
208
|
+
"body": "CDqThG_body",
|
|
209
|
+
"colorValue": "CDqThG_colorValue",
|
|
210
|
+
"row": "CDqThG_row",
|
|
211
|
+
"title": "CDqThG_title",
|
|
212
|
+
"rowLabel": "CDqThG_rowLabel",
|
|
213
|
+
"toolRow": "CDqThG_toolRow",
|
|
214
|
+
"statusLine": "CDqThG_statusLine",
|
|
215
|
+
"checkbox": "CDqThG_checkbox",
|
|
216
|
+
"disabled": "CDqThG_disabled",
|
|
217
|
+
"group": "CDqThG_group",
|
|
218
|
+
"chevronOpen": "CDqThG_chevronOpen",
|
|
219
|
+
"chevron": "CDqThG_chevron",
|
|
220
|
+
"addButton": "CDqThG_addButton",
|
|
221
|
+
"rowHint": "CDqThG_rowHint",
|
|
222
|
+
"on": "CDqThG_on",
|
|
223
|
+
"colorInput": "CDqThG_colorInput",
|
|
224
|
+
"knob": "CDqThG_knob",
|
|
225
|
+
"toolName": "CDqThG_toolName",
|
|
226
|
+
"addRow": "CDqThG_addRow",
|
|
227
|
+
"toolInput": "CDqThG_toolInput",
|
|
228
|
+
"sectionTitle": "CDqThG_sectionTitle"
|
|
223
229
|
};
|
|
224
230
|
//#endregion
|
|
225
231
|
//#region src/client/settings-card.tsx
|
|
@@ -297,18 +303,19 @@ window.__ModuleLoader__.load({
|
|
|
297
303
|
htmlFor: "node-appearance-show-thinking",
|
|
298
304
|
children: "显示思考过程"
|
|
299
305
|
}),
|
|
300
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
301
|
-
id: "node-appearance-show-thinking",
|
|
302
|
-
className: card_module_css_default.checkbox,
|
|
303
|
-
type: "checkbox",
|
|
304
|
-
checked: showThinking,
|
|
305
|
-
onChange: (event) => {
|
|
306
|
-
setShowThinking(event.target.checked);
|
|
307
|
-
}
|
|
308
|
-
}),
|
|
309
306
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
310
307
|
className: card_module_css_default.rowHint,
|
|
311
308
|
children: "关闭后会话中的 Think 思考行隐藏"
|
|
309
|
+
}),
|
|
310
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
311
|
+
id: "node-appearance-show-thinking",
|
|
312
|
+
className: `${card_module_css_default.switch}${showThinking ? ` ${card_module_css_default.on}` : ""}`,
|
|
313
|
+
type: "button",
|
|
314
|
+
"aria-pressed": showThinking,
|
|
315
|
+
onClick: () => {
|
|
316
|
+
setShowThinking(!showThinking);
|
|
317
|
+
},
|
|
318
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: card_module_css_default.knob })
|
|
312
319
|
})
|
|
313
320
|
]
|
|
314
321
|
}),
|
|
@@ -453,10 +460,9 @@ window.__ModuleLoader__.load({
|
|
|
453
460
|
scope.set("toolColors", toolColors);
|
|
454
461
|
}
|
|
455
462
|
};
|
|
456
|
-
ctx.slots.inject("settings.
|
|
457
|
-
name: "settings.
|
|
458
|
-
|
|
459
|
-
order: 30,
|
|
463
|
+
ctx.slots.inject("settings.plugin.item", () => ctx.slots.register({
|
|
464
|
+
name: "settings.plugin.item",
|
|
465
|
+
key: NODE_APPEARANCE_NS,
|
|
460
466
|
inject: () => face
|
|
461
467
|
}, NodeAppearanceRow));
|
|
462
468
|
}
|
package/lib/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","names":["useState","css","IconChevronDownOutline14"],"sources":["../src/client/palette.ts","../src/client/settings-card.tsx","../src/client/index.ts"],"sourcesContent":["/**\n * Node appearance palette: category/tool mapping, default colors, and the pure\n * CSS-rule generator that paints the chat flow. Browser-half owned; the Host\n * half mirrors the same defaults through its schemastery schema (the two\n * cannot share a value import — the browser bundle purity gate forbids\n * cross-package value imports).\n */\n\n/** The settings namespace this plugin owns (spelled identically in both halves). */\nexport const NODE_APPEARANCE_NS = 'node-appearance'\n\n/** The plugin's style tag identity (removed/replaced on every re-paint). */\nexport const STYLE_TAG_ID = `${NODE_APPEARANCE_NS}/rules`\n\n/** One paintable node category. `command`, `thinking`, `context` are non-tool rows. */\nexport type NodeCategory =\n | 'search' | 'agent' | 'execute' | 'file' | 'task' | 'command' | 'thinking' | 'context' | 'steering' | 'other'\n\n/** Accent color per category (CSS colors). */\nexport type NodeAppearanceColors = Record<NodeCategory, string>\n\n/** The settings value this plugin reads from its namespace scope. */\nexport interface NodeAppearanceSettings {\n /** Show assistant reasoning blocks as Think rows; false hides them. */\n showThinking?: boolean | undefined\n /** Per-category accent colors; missing keys fall back to defaults. */\n colors?: Partial<NodeAppearanceColors> | undefined\n /** Per-tool accent overrides keyed by wire tool name. */\n toolColors?: Record<string, string> | undefined\n}\n\n/** Initial palette: mid-luminance hues readable on both light and dark themes. */\nexport const DEFAULT_COLORS: NodeAppearanceColors = {\n search: '#3b82f6', // blue — web_search / web_fetch\n agent: '#a855f7', // purple — subagent / workflow / send_message …\n execute: '#f59e0b', // amber — bash / pwsh / run_code / terminal_*\n file: '#22c55e', // green — read / write / edit / glob / grep\n task: '#ec4899', // pink — todo_write / goal / job_* / schedule_*\n command: '#f97316', // orange — /command nodes\n thinking: '#c4b5fd', // light purple — Think rows\n context: '#8a9bb5', // slate blue — injected context rows (informational)\n steering: '#14b8a6', // teal — steering rows (rc.8)\n other: '#64748b', // slate — every unlisted tool\n}\n\n/** Wire tool name → category for the shipped mapping. */\nexport const TOOL_CATEGORIES: Record<Exclude<NodeCategory, 'command' | 'thinking' | 'context' | 'steering'>, readonly string[]> = {\n search: ['web_search', 'web_fetch'],\n agent: ['subagent', 'subagent_acp', 'subagent_fork', 'send_message', 'interrupt_agent', 'list_agents', 'report', 'workflow'],\n execute: ['bash', 'pwsh', 'run_code', 'terminal_open', 'terminal_close', 'terminal_list', 'terminal_read', 'terminal_send', 'terminal_signal', 'str_replace_editor'],\n file: ['read', 'write', 'edit', 'read_image', 'glob', 'grep'],\n task: ['todo_write', 'create_goal', 'get_goal', 'update_goal', 'job_kill', 'job_list', 'job_output', 'schedule_create', 'schedule_delete', 'schedule_list', 'exit_plan_mode'],\n other: [],\n}\n\n/** Selector matching every tool row inside a tool-call node. */\nconst TOOL_ROW = '[data-chat-flow-kind=\"tool-call\"] [data-tool]'\n/** The ToolRow root itself (carries data-variant; the wrapper callRow does not). */\nconst TOOL_ROW_ROOT = '[data-chat-flow-kind=\"tool-call\"] [data-tool][data-variant]'\n/** Selector of the command node wrapper. */\nconst COMMAND_ROW = '[data-chat-flow-kind=\"command\"]'\n/** Selector of the Think reasoning row. */\nconst THINK_ROW = '[data-variant=\"think\"]'\n/** Selector of the injected-context row (the flow-item wrapper). */\nconst CONTEXT_ROW = '[data-chat-flow-kind=\"context\"]'\n/** Selector of a settled tool-result row (rc.8: tool results render as their own row). */\nconst TOOL_RESULT_ROW = '[data-chat-flow-kind=\"tool-result\"]'\n\n/**\n * The rows that carry the accent paint: the ToolRow root (not its wrapper\n * callRow — both carry data-tool, only the inner row carries data-variant),\n * command nodes, Think rows, injected-context rows, and tool-result rows.\n * User input rows are excluded — right-alignment already\n * distinguishes them (2026-08-20 用户反馈);steering rows 也走独立规则\n * (见 buildCss:在 userStack 层做 wash,不涂整行 rail)。\n * The 3px inset rail is compensated\n * with a matching padding-left so the rail never covers the row's leading icon.\n */\nconst ACCENTED_ROWS = [\n TOOL_ROW_ROOT, COMMAND_ROW, THINK_ROW, CONTEXT_ROW, TOOL_RESULT_ROW,\n].join(',\\n')\n\n/**\n * Accept a configured CSS color (hex, color functions) or reject it so an\n * invalid value falls back to the category default instead of poisoning CSS.\n * @param value - configured color string.\n * @returns whether the value is a plausible CSS color literal.\n */\nexport function isCssColor(value: string): boolean {\n const trimmed = value.trim()\n if (trimmed === '') return false\n if (/^#[0-9a-f]{3,8}$/i.test(trimmed)) return true\n return /^(rgb|rgba|hsl|hsla|hwb|lab|lch|oklab|oklch|color|device-cmyk)\\(/i.test(trimmed)\n}\n\n/** Resolve the effective palette from user settings merged over defaults. */\nexport function resolveColors(settings: NodeAppearanceSettings): NodeAppearanceColors {\n const colors: NodeAppearanceColors = { ...DEFAULT_COLORS }\n const configured = settings.colors\n if (configured !== undefined && typeof configured === 'object' && configured !== null) {\n for (const key of Object.keys(DEFAULT_COLORS) as NodeCategory[]) {\n const value = configured[key]\n if (typeof value === 'string' && isCssColor(value)) colors[key] = value\n }\n }\n return colors\n}\n\n/** Escape a tool name into a CSS attribute selector string literal. */\nfunction attributeLiteral(value: string): string {\n return value.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"')\n}\n\n/**\n * Steering marker icon: a corner-up-left arrow (mid-turn guidance inserted\n * into the running answer), drawn as a mask so the icon inherits the\n * configured steering color. Encoded data URI, no external asset.\n */\nconst STEERING_ICON = \"data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='9 14 4 9 9 4'/%3E%3Cpath d='M20 20v-7a4 4 0 0 0-4-4H4'/%3E%3C/svg%3E\"\n\n/**\n * Build the complete stylesheet text for one settings snapshot.\n * @param settings - the namespace scope value (may be partial or undefined).\n * @returns CSS text painting accent rows and (optionally) hiding Think rows.\n */\nexport function buildCss(settings: NodeAppearanceSettings | undefined): string {\n const colors = resolveColors(settings ?? {})\n const toolOverrides = settings?.toolColors\n const lines: string[] = []\n\n // Unlisted tools keep the neutral fallback. Declared BEFORE the per-tool\n // rules: both selectors carry equal specificity (two attribute selectors),\n // so of two conflicting declarations the later one wins — a fallback\n // declared after the category rules would override every category color.\n lines.push(`${TOOL_ROW} { --ncolor-accent: ${colors.other}; }`)\n\n // Per-tool accent assignments (explicit overrides win over category color).\n for (const [category, tools] of Object.entries(TOOL_CATEGORIES)) {\n const key = category as keyof typeof TOOL_CATEGORIES\n for (const tool of tools) {\n const override = toolOverrides?.[tool]\n const color = typeof override === 'string' && isCssColor(override)\n ? override\n : colors[key]\n lines.push(`[data-chat-flow-kind=\"tool-call\"] [data-tool=\"${attributeLiteral(tool)}\"] { --ncolor-accent: ${color}; }`)\n }\n }\n\n // Non-tool accent rows.\n lines.push(`${COMMAND_ROW} { --ncolor-accent: ${colors.command}; }`)\n lines.push(`${THINK_ROW} { --ncolor-accent: ${colors.thinking}; }`)\n lines.push(`${CONTEXT_ROW} { --ncolor-accent: ${colors.context}; }`)\n lines.push(`${TOOL_RESULT_ROW} { --ncolor-accent: ${colors.file}; }`)\n\n // One shared paint rule: 3px inset left rail (layout-free) + 8% wash. The\n // matching padding-left moves the row content off the rail so the leading\n // icon is never covered.\n lines.push(`${ACCENTED_ROWS} {\n box-shadow: inset 3px 0 0 var(--ncolor-accent);\n background-color: color-mix(in srgb, var(--ncolor-accent) 8%, transparent);\n padding-left: 3px;\n}`)\n\n // Steering rows (mid-turn user steering) stay visually distinct from plain\n // user rows with a compass marker beside the right-aligned bubble. The\n // marker is a mask over the user-stack — the container that hugs the bubble\n // — positioned to the left of it, so the tint reads as a glyph next to the\n // message rather than a detached full-width rail (2026-08-21 用户反馈:\n // 整行 rail 突兀,改在 userStack 层做图标区分;slot 方案不可行:\n // conversation.message.images 是 single 槽且已被官方 ui-attachment 占用).\n lines.push(`[data-chat-flow-kind=\"steering\"] [data-time-hover-root] > :first-child {\n position: relative;\n}`)\n lines.push(`[data-chat-flow-kind=\"steering\"] [data-time-hover-root] > :first-child::before {\n content: '';\n position: absolute;\n right: 100%;\n margin-right: 6px;\n top: 50%;\n width: 14px;\n height: 14px;\n transform: translateY(-50%);\n background-color: ${colors.steering};\n -webkit-mask: url(\"${STEERING_ICON}\") center / contain no-repeat;\n mask: url(\"${STEERING_ICON}\") center / contain no-repeat;\n}`)\n\n // Visibility switch: hide Think rows entirely on the frontend. `!important`\n // outranks the module stylesheet's `.root { display: flex }` (same\n // specificity, but the plugin style tag is injected before the module's).\n if (settings?.showThinking === false) {\n lines.push(`${THINK_ROW} { display: none !important; }`)\n }\n\n return lines.join('\\n')\n}\n","/**\n * The plugin's General-settings row: a \"节点外观\" title with the standard\n * chevron, expanding to palette rows, tool overrides, and the Think\n * visibility switch. Reads the namespace scope through the injected hooks\n * face and writes through the injected actions; every change applies\n * immediately. Drawn by hand (no value import from ui-settings-plugins — the\n * client bundle purity gate forbids cross-plugin value imports), styled with\n * the DSH design tokens like the shipped Appearance row.\n */\n\nimport { useState, type ChangeEvent, type FormEvent } from 'react'\nimport type { SettingsScopeSnapshot } from '@deepseek-ai/dsh-client-runtime/client'\nimport { IconChevronDownOutline14 } from '@deepseek-ai/dsh-client-ui-primitives'\nimport type { InjectFace, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'\nimport type {} from '@deepseek-ai/dsh-client-ui-settings/client'\nimport {\n DEFAULT_COLORS, isCssColor, resolveColors, TOOL_CATEGORIES,\n type NodeAppearanceSettings, type NodeCategory,\n} from './palette.ts'\nimport css from './card.module.css'\n\n/** The row's inject face: the read-only scope snapshot plus write actions. */\nexport interface NodeAppearanceRowFace {\n hooks: {\n /** The bound settings-scope snapshot, rendered as useNodeAppearance. */\n nodeAppearance: {\n getSnapshot(): SettingsScopeSnapshot<NodeAppearanceSettings>\n subscribe(listener: () => void): () => void\n }\n }\n /** Write the Think visibility switch. */\n setShowThinking(show: boolean): void\n /** Merge one category color into the palette section. */\n setCategoryColor(category: NodeCategory, color: string): void\n /** Merge one tool override into the toolColors section. */\n setToolColor(tool: string, color: string): void\n /** Remove one tool override. */\n removeToolColor(tool: string): void\n}\n\n/** Props the renderer binds for this General row. */\nexport type NodeAppearanceRowProps =\n PropsRuntime<'settings.general.item'>\n & InjectFace<NodeAppearanceRowFace>\n\n/** Chinese labels per category (product copy is Chinese). */\nconst CATEGORY_LABELS: Record<NodeCategory, string> = {\n search: '联网搜索',\n agent: '智能体调用',\n execute: '代码 / 指令执行',\n file: '文件操作',\n task: '任务 / 目标',\n command: '指令节点',\n thinking: '思考过程',\n context: '上下文注入',\n steering: '模型引导',\n other: '其他工具',\n}\n\n/** Tools shown in the add-override autocomplete-free text input placeholder. */\nconst TOOL_SUGGESTIONS = Object.values(TOOL_CATEGORIES).flat().join('、')\n\n/**\n * Render the node-appearance General row.\n * @param props - the injected scope snapshot hook and write actions.\n * @returns the row, always visible once its namespace is served.\n */\nexport function NodeAppearanceRow({ useNodeAppearance, setShowThinking, setCategoryColor, setToolColor, removeToolColor }: NodeAppearanceRowProps) {\n const [open, setOpen] = useState(false)\n const [toolName, setToolName] = useState('')\n const [toolColor, setToolColorDraft] = useState('#64748b')\n const snapshot = useNodeAppearance(snapshot => snapshot)\n const colors = resolveColors(snapshot.value ?? {})\n const toolColors = snapshot.value?.toolColors ?? {}\n const showThinking = snapshot.value?.showThinking ?? true\n const disabled = snapshot.writable === false\n\n const addTool = (event: FormEvent) => {\n event.preventDefault()\n const name = toolName.trim()\n if (name === '' || !isCssColor(toolColor)) return\n setToolColor(name, toolColor)\n setToolName('')\n }\n\n return (\n <div className={css.group}>\n <button\n type=\"button\"\n className={css.header}\n aria-expanded={open}\n onClick={() => { setOpen(!open) }}\n >\n <span className={css.title}>节点外观</span>\n <IconChevronDownOutline14 className={open ? css.chevronOpen : css.chevron} />\n </button>\n {open && (\n <div className={css.body}>\n {snapshot.status !== 'ready' && (\n <p className={css.statusLine}>\n {snapshot.status === 'unavailable'\n ? '配置暂不可用:插件主机侧未挂载或连接非本机。'\n : '配置加载中…'}\n </p>\n )}\n <div className={`${disabled ? css.disabled : ''}`}>\n <div className={css.row}>\n <label className={css.rowLabel} htmlFor=\"node-appearance-show-thinking\">显示思考过程</label>\n <input\n id=\"node-appearance-show-thinking\"\n className={css.checkbox}\n type=\"checkbox\"\n checked={showThinking}\n onChange={(event: ChangeEvent<HTMLInputElement>) => { setShowThinking(event.target.checked) }}\n />\n <span className={css.rowHint}>关闭后会话中的 Think 思考行隐藏</span>\n </div>\n {(Object.keys(CATEGORY_LABELS) as NodeCategory[]).map(category => (\n <div className={css.row} key={category}>\n <label className={css.rowLabel} htmlFor={`node-appearance-color-${category}`}>\n {CATEGORY_LABELS[category]}\n </label>\n <input\n id={`node-appearance-color-${category}`}\n className={css.colorInput}\n type=\"color\"\n value={colors[category]}\n onChange={(event: ChangeEvent<HTMLInputElement>) => { setCategoryColor(category, event.target.value) }}\n />\n <span className={css.colorValue}>{colors[category]}</span>\n </div>\n ))}\n <div className={css.sectionTitle}>工具颜色覆盖(可选)</div>\n {Object.entries(toolColors).map(([tool, color]) => (\n <div className={css.toolRow} key={tool}>\n <span className={css.toolName} title={tool}>{tool}</span>\n <input\n className={css.colorInput}\n type=\"color\"\n value={isCssColor(color) ? color : DEFAULT_COLORS.other}\n onChange={(event: ChangeEvent<HTMLInputElement>) => { setToolColor(tool, event.target.value) }}\n />\n <button type=\"button\" className={css.removeButton} onClick={() => { removeToolColor(tool) }}>删除</button>\n </div>\n ))}\n <form className={css.addRow} onSubmit={addTool}>\n <input\n className={css.toolInput}\n type=\"text\"\n placeholder={`工具名,如 ${TOOL_SUGGESTIONS}`}\n value={toolName}\n onChange={(event: ChangeEvent<HTMLInputElement>) => { setToolName(event.target.value) }}\n />\n <input\n className={css.colorInput}\n type=\"color\"\n value={toolColor}\n onChange={(event: ChangeEvent<HTMLInputElement>) => { setToolColorDraft(event.target.value) }}\n />\n <button type=\"submit\" className={css.addButton} disabled={toolName.trim() === ''}>添加</button>\n </form>\n </div>\n </div>\n )}\n </div>\n )\n}\n","/**\n * Browser half: binds the `node-appearance` settings scope, paints the chat\n * flow from it (a single <style data-plugin-css> tag rebuilt on every\n * snapshot change), and registers the settings card.\n */\n\nimport type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client'\nimport type { SettingsScope } from '@deepseek-ai/dsh-client-runtime/client'\n// Type-only: the ctx.settingsScope Context merge and the slot's declaration.\n// Cross-plugin collaboration goes through cordis services; a value import\n// would fail the client bundle-purity gate.\nimport type {} from '@deepseek-ai/dsh-client-ui-settings/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-settings-plugins/client'\nimport { buildCss, NODE_APPEARANCE_NS, STYLE_TAG_ID, type NodeAppearanceSettings } from './palette.ts'\nimport { NodeAppearanceRow, type NodeAppearanceRowFace } from './settings-card.tsx'\n\nexport const inject = ['slots', 'connection', 'remote', 'settingsScope']\n\n/** Upsert the plugin's paint stylesheet with the current snapshot's CSS. */\nfunction paint(scope: SettingsScope<NodeAppearanceSettings>): void {\n let tag = document.querySelector<HTMLStyleElement>(`style[data-plugin-css=\"${STYLE_TAG_ID}\"]`)\n if (tag === null) {\n tag = document.createElement('style')\n tag.dataset.plugin = NODE_APPEARANCE_NS\n tag.dataset.pluginCss = STYLE_TAG_ID\n document.head.appendChild(tag)\n }\n tag.textContent = buildCss(scope.getSnapshot().value)\n}\n\n/**\n * Mount the node-appearance plugin on the page.\n * @param ctx - client root context.\n */\nexport function apply(ctx: ClientContext): void {\n const scope = ctx.settingsScope.bind<NodeAppearanceSettings>({ namespace: NODE_APPEARANCE_NS })\n // Paint once from the current snapshot (defaults before the first Host read).\n paint(scope)\n ctx.effect(\n () => scope.subscribe(() => { paint(scope) }),\n 'dsh-node-appearance: repaint on settings change',\n )\n\n const face: NodeAppearanceRowFace = {\n hooks: { nodeAppearance: scope },\n setShowThinking: (show) => { void scope.set('showThinking', show) },\n setCategoryColor: (category, color) => {\n const value = scope.getSnapshot().value\n void scope.set('colors', { ...value?.colors, [category]: color })\n },\n setToolColor: (tool, color) => {\n const value = scope.getSnapshot().value\n void scope.set('toolColors', { ...value?.toolColors, [tool]: color })\n },\n removeToolColor: (tool) => {\n const value = scope.getSnapshot().value\n const toolColors = { ...value?.toolColors }\n delete toolColors[tool]\n void scope.set('toolColors', toolColors)\n },\n }\n\n // The General settings section stacks preference rows (locale → Language,\n // ui-theme → Appearance, dsh-skin → Skins). Node appearance is the same\n // kind of visual preference, so it registers here beside them.\n ctx.slots.inject('settings.general.item', () => ctx.slots.register({\n name: 'settings.general.item',\n id: NODE_APPEARANCE_NS,\n order: 30,\n inject: () => face,\n }, NodeAppearanceRow))\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"client.js","names":["useState","css","IconChevronDownOutline14"],"sources":["../src/client/palette.ts","../src/client/settings-card.tsx","../src/client/index.ts"],"sourcesContent":["/**\n * Node appearance palette: category/tool mapping, default colors, and the pure\n * CSS-rule generator that paints the chat flow. Browser-half owned; the Host\n * half mirrors the same defaults through its schemastery schema (the two\n * cannot share a value import — the browser bundle purity gate forbids\n * cross-package value imports).\n */\n\n/** The settings namespace this plugin owns (spelled identically in both halves). */\nexport const NODE_APPEARANCE_NS = 'node-appearance'\n\n/** The plugin's style tag identity (removed/replaced on every re-paint). */\nexport const STYLE_TAG_ID = `${NODE_APPEARANCE_NS}/rules`\n\n/** One paintable node category. `command`, `thinking`, `context` are non-tool rows. */\nexport type NodeCategory =\n | 'search' | 'agent' | 'execute' | 'file' | 'task' | 'command' | 'thinking' | 'context' | 'steering' | 'other'\n\n/** Accent color per category (CSS colors). */\nexport type NodeAppearanceColors = Record<NodeCategory, string>\n\n/** The settings value this plugin reads from its namespace scope. */\nexport interface NodeAppearanceSettings {\n /** Show assistant reasoning blocks as Think rows; false hides them. */\n showThinking?: boolean | undefined\n /** Per-category accent colors; missing keys fall back to defaults. */\n colors?: Partial<NodeAppearanceColors> | undefined\n /** Per-tool accent overrides keyed by wire tool name. */\n toolColors?: Record<string, string> | undefined\n}\n\n/** Initial palette: mid-luminance hues readable on both light and dark themes. */\nexport const DEFAULT_COLORS: NodeAppearanceColors = {\n search: '#3b82f6', // blue — web_search / web_fetch\n agent: '#a855f7', // purple — subagent / workflow / send_message …\n execute: '#f59e0b', // amber — bash / pwsh / run_code / terminal_*\n file: '#22c55e', // green — read / write / edit / glob / grep\n task: '#ec4899', // pink — todo_write / goal / job_* / schedule_*\n command: '#f97316', // orange — /command nodes\n thinking: '#c4b5fd', // light purple — Think rows\n context: '#8a9bb5', // slate blue — injected context rows (informational)\n steering: '#14b8a6', // teal — steering rows (rc.8)\n other: '#64748b', // slate — every unlisted tool\n}\n\n/** Wire tool name → category for the shipped mapping. */\nexport const TOOL_CATEGORIES: Record<Exclude<NodeCategory, 'command' | 'thinking' | 'context' | 'steering'>, readonly string[]> = {\n search: ['web_search', 'web_fetch'],\n agent: ['subagent', 'subagent_acp', 'subagent_fork', 'send_message', 'interrupt_agent', 'list_agents', 'report', 'workflow'],\n execute: ['bash', 'pwsh', 'run_code', 'terminal_open', 'terminal_close', 'terminal_list', 'terminal_read', 'terminal_send', 'terminal_signal', 'str_replace_editor'],\n file: ['read', 'write', 'edit', 'read_image', 'glob', 'grep'],\n task: ['todo_write', 'create_goal', 'get_goal', 'update_goal', 'job_kill', 'job_list', 'job_output', 'schedule_create', 'schedule_delete', 'schedule_list', 'exit_plan_mode'],\n other: [],\n}\n\n/** Selector matching every tool row inside a tool-call node. */\nconst TOOL_ROW = '[data-chat-flow-kind=\"tool-call\"] [data-tool]'\n/** The ToolRow root itself (carries data-variant; the wrapper callRow does not). */\nconst TOOL_ROW_ROOT = '[data-chat-flow-kind=\"tool-call\"] [data-tool][data-variant]'\n/** Selector of the command node wrapper. */\nconst COMMAND_ROW = '[data-chat-flow-kind=\"command\"]'\n/** Selector of the Think reasoning row. */\nconst THINK_ROW = '[data-variant=\"think\"]'\n/** Selector of the injected-context row (the flow-item wrapper). */\nconst CONTEXT_ROW = '[data-chat-flow-kind=\"context\"]'\n/** Selector of a settled tool-result row (rc.8: tool results render as their own row). */\nconst TOOL_RESULT_ROW = '[data-chat-flow-kind=\"tool-result\"]'\n\n/**\n * The rows that carry the accent paint: the ToolRow root (not its wrapper\n * callRow — both carry data-tool, only the inner row carries data-variant),\n * command nodes, Think rows, injected-context rows, and tool-result rows.\n * User input rows are excluded — right-alignment already\n * distinguishes them (2026-08-20 用户反馈);steering rows 也走独立规则\n * (见 buildCss:在 userStack 层做 wash,不涂整行 rail)。\n * The 3px inset rail is compensated\n * with a matching padding-left so the rail never covers the row's leading icon.\n */\nconst ACCENTED_ROWS = [\n TOOL_ROW_ROOT, COMMAND_ROW, THINK_ROW, CONTEXT_ROW, TOOL_RESULT_ROW,\n].join(',\\n')\n\n/**\n * Accept a configured CSS color (hex, color functions) or reject it so an\n * invalid value falls back to the category default instead of poisoning CSS.\n * @param value - configured color string.\n * @returns whether the value is a plausible CSS color literal.\n */\nexport function isCssColor(value: string): boolean {\n const trimmed = value.trim()\n if (trimmed === '') return false\n if (/^#[0-9a-f]{3,8}$/i.test(trimmed)) return true\n return /^(rgb|rgba|hsl|hsla|hwb|lab|lch|oklab|oklch|color|device-cmyk)\\(/i.test(trimmed)\n}\n\n/** Resolve the effective palette from user settings merged over defaults. */\nexport function resolveColors(settings: NodeAppearanceSettings): NodeAppearanceColors {\n const colors: NodeAppearanceColors = { ...DEFAULT_COLORS }\n const configured = settings.colors\n if (configured !== undefined && typeof configured === 'object' && configured !== null) {\n for (const key of Object.keys(DEFAULT_COLORS) as NodeCategory[]) {\n const value = configured[key]\n if (typeof value === 'string' && isCssColor(value)) colors[key] = value\n }\n }\n return colors\n}\n\n/** Escape a tool name into a CSS attribute selector string literal. */\nfunction attributeLiteral(value: string): string {\n return value.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"')\n}\n\n/**\n * Steering marker icon: a corner-up-left arrow (mid-turn guidance inserted\n * into the running answer), drawn as a mask so the icon inherits the\n * configured steering color. Encoded data URI, no external asset.\n */\nconst STEERING_ICON = \"data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='9 14 4 9 9 4'/%3E%3Cpath d='M20 20v-7a4 4 0 0 0-4-4H4'/%3E%3C/svg%3E\"\n\n/**\n * Build the complete stylesheet text for one settings snapshot.\n * @param settings - the namespace scope value (may be partial or undefined).\n * @returns CSS text painting accent rows and (optionally) hiding Think rows.\n */\nexport function buildCss(settings: NodeAppearanceSettings | undefined): string {\n const colors = resolveColors(settings ?? {})\n const toolOverrides = settings?.toolColors\n const lines: string[] = []\n\n // Unlisted tools keep the neutral fallback. Declared BEFORE the per-tool\n // rules: both selectors carry equal specificity (two attribute selectors),\n // so of two conflicting declarations the later one wins — a fallback\n // declared after the category rules would override every category color.\n lines.push(`${TOOL_ROW} { --ncolor-accent: ${colors.other}; }`)\n\n // Per-tool accent assignments (explicit overrides win over category color).\n for (const [category, tools] of Object.entries(TOOL_CATEGORIES)) {\n const key = category as keyof typeof TOOL_CATEGORIES\n for (const tool of tools) {\n const override = toolOverrides?.[tool]\n const color = typeof override === 'string' && isCssColor(override)\n ? override\n : colors[key]\n lines.push(`[data-chat-flow-kind=\"tool-call\"] [data-tool=\"${attributeLiteral(tool)}\"] { --ncolor-accent: ${color}; }`)\n }\n }\n\n // Non-tool accent rows.\n lines.push(`${COMMAND_ROW} { --ncolor-accent: ${colors.command}; }`)\n lines.push(`${THINK_ROW} { --ncolor-accent: ${colors.thinking}; }`)\n lines.push(`${CONTEXT_ROW} { --ncolor-accent: ${colors.context}; }`)\n lines.push(`${TOOL_RESULT_ROW} { --ncolor-accent: ${colors.file}; }`)\n\n // One shared paint rule: 3px inset left rail (layout-free) + 8% wash. The\n // matching padding-left moves the row content off the rail so the leading\n // icon is never covered.\n lines.push(`${ACCENTED_ROWS} {\n box-shadow: inset 3px 0 0 var(--ncolor-accent);\n background-color: color-mix(in srgb, var(--ncolor-accent) 8%, transparent);\n padding-left: 3px;\n}`)\n\n // Steering rows (mid-turn user steering) stay visually distinct from plain\n // user rows with a compass marker beside the right-aligned bubble. The\n // marker is a mask over the user-stack — the container that hugs the bubble\n // — positioned to the left of it, so the tint reads as a glyph next to the\n // message rather than a detached full-width rail (2026-08-21 用户反馈:\n // 整行 rail 突兀,改在 userStack 层做图标区分;slot 方案不可行:\n // conversation.message.images 是 single 槽且已被官方 ui-attachment 占用).\n lines.push(`[data-chat-flow-kind=\"steering\"] [data-time-hover-root] > :first-child {\n position: relative;\n}`)\n lines.push(`[data-chat-flow-kind=\"steering\"] [data-time-hover-root] > :first-child::before {\n content: '';\n position: absolute;\n right: 100%;\n margin-right: 6px;\n top: 50%;\n width: 14px;\n height: 14px;\n transform: translateY(-50%);\n background-color: ${colors.steering};\n -webkit-mask: url(\"${STEERING_ICON}\") center / contain no-repeat;\n mask: url(\"${STEERING_ICON}\") center / contain no-repeat;\n}`)\n\n // Visibility switch: hide Think rows entirely on the frontend. `!important`\n // outranks the module stylesheet's `.root { display: flex }` (same\n // specificity, but the plugin style tag is injected before the module's).\n if (settings?.showThinking === false) {\n lines.push(`${THINK_ROW} { display: none !important; }`)\n // A think-only node leaves its flowItem seat with zero height: the seat\n // still consumes the column's 16px flex gap on both sides, doubling the\n // spacing between the neighbors. Hide the whole seat when the think row\n // is the only child of its block container — block-internal thinks\n // (text + reasoning in one node) stay gap-neutral after hiding the row.\n lines.push(\n `[data-chat-flow-kind=\"assistant\"]:has(${THINK_ROW}:only-child),`,\n `[data-chat-flow-kind=\"assistant-step\"]:has(${THINK_ROW}:only-child) { display: none !important; }`,\n )\n }\n\n return lines.join('\\n')\n}\n","/**\n * The plugin's General-settings row: a \"节点外观\" title with the standard\n * chevron, expanding to palette rows, tool overrides, and the Think\n * visibility switch. Reads the namespace scope through the injected hooks\n * face and writes through the injected actions; every change applies\n * immediately. Drawn by hand (no value import from ui-settings-plugins — the\n * client bundle purity gate forbids cross-plugin value imports), styled with\n * the DSH design tokens like the shipped Appearance row.\n */\n\nimport { useState, type ChangeEvent, type FormEvent } from 'react'\nimport type { ObservableSnapshot } from '@deepseek-ai/dsh-client-store'\nimport type { SettingsScope, SettingsScopeSnapshot } from '@deepseek-ai/dsh-client-ui-settings/client'\nimport { IconChevronDownOutline14 } from '@deepseek-ai/dsh-client-ui-primitives'\nimport type { InjectFace, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'\nimport type {} from '@deepseek-ai/dsh-client-ui-settings/client'\nimport {\n DEFAULT_COLORS, isCssColor, resolveColors, TOOL_CATEGORIES,\n type NodeAppearanceSettings, type NodeCategory,\n} from './palette.ts'\nimport css from './card.module.css'\n\n/** The row's inject face: the read-only scope snapshot plus write actions. */\nexport interface NodeAppearanceRowFace {\n hooks: {\n /** The bound settings-scope snapshot, rendered as useNodeAppearance. */\n nodeAppearance: ObservableSnapshot<SettingsScopeSnapshot<NodeAppearanceSettings>>\n }\n /** Write the Think visibility switch. */\n setShowThinking(show: boolean): void\n /** Merge one category color into the palette section. */\n setCategoryColor(category: NodeCategory, color: string): void\n /** Merge one tool override into the toolColors section. */\n setToolColor(tool: string, color: string): void\n /** Remove one tool override. */\n removeToolColor(tool: string): void\n}\n\n/** Props the renderer binds for this plugin config card. */\nexport type NodeAppearanceRowProps =\n PropsRuntime<'settings.plugin.item'>\n & InjectFace<NodeAppearanceRowFace>\n\n/** Chinese labels per category (product copy is Chinese). */\nconst CATEGORY_LABELS: Record<NodeCategory, string> = {\n search: '联网搜索',\n agent: '智能体调用',\n execute: '代码 / 指令执行',\n file: '文件操作',\n task: '任务 / 目标',\n command: '指令节点',\n thinking: '思考过程',\n context: '上下文注入',\n steering: '模型引导',\n other: '其他工具',\n}\n\n/** Tools shown in the add-override autocomplete-free text input placeholder. */\nconst TOOL_SUGGESTIONS = Object.values(TOOL_CATEGORIES).flat().join('、')\n\n/**\n * Render the node-appearance General row.\n * @param props - the injected scope snapshot hook and write actions.\n * @returns the row, always visible once its namespace is served.\n */\nexport function NodeAppearanceRow({ useNodeAppearance, setShowThinking, setCategoryColor, setToolColor, removeToolColor }: NodeAppearanceRowProps) {\n const [open, setOpen] = useState(false)\n const [toolName, setToolName] = useState('')\n const [toolColor, setToolColorDraft] = useState('#64748b')\n const snapshot = useNodeAppearance(snapshot => snapshot)\n const colors = resolveColors(snapshot.value ?? {})\n const toolColors = snapshot.value?.toolColors ?? {}\n const showThinking = snapshot.value?.showThinking ?? true\n const disabled = snapshot.writable === false\n\n const addTool = (event: FormEvent) => {\n event.preventDefault()\n const name = toolName.trim()\n if (name === '' || !isCssColor(toolColor)) return\n setToolColor(name, toolColor)\n setToolName('')\n }\n\n return (\n <div className={css.group}>\n <button\n type=\"button\"\n className={css.header}\n aria-expanded={open}\n onClick={() => { setOpen(!open) }}\n >\n <span className={css.title}>节点外观</span>\n <IconChevronDownOutline14 className={open ? css.chevronOpen : css.chevron} />\n </button>\n {open && (\n <div className={css.body}>\n {snapshot.status !== 'ready' && (\n <p className={css.statusLine}>\n {snapshot.status === 'unavailable'\n ? '配置暂不可用:插件主机侧未挂载或连接非本机。'\n : '配置加载中…'}\n </p>\n )}\n <div className={`${disabled ? css.disabled : ''}`}>\n <div className={css.row}>\n <label className={css.rowLabel} htmlFor=\"node-appearance-show-thinking\">显示思考过程</label>\n <span className={css.rowHint}>关闭后会话中的 Think 思考行隐藏</span>\n <button\n id=\"node-appearance-show-thinking\"\n className={`${css.switch}${showThinking ? ` ${css.on}` : ''}`}\n type=\"button\"\n aria-pressed={showThinking}\n onClick={() => { setShowThinking(!showThinking) }}\n >\n <span className={css.knob} />\n </button>\n </div>\n {(Object.keys(CATEGORY_LABELS) as NodeCategory[]).map(category => (\n <div className={css.row} key={category}>\n <label className={css.rowLabel} htmlFor={`node-appearance-color-${category}`}>\n {CATEGORY_LABELS[category]}\n </label>\n <input\n id={`node-appearance-color-${category}`}\n className={css.colorInput}\n type=\"color\"\n value={colors[category]}\n onChange={(event: ChangeEvent<HTMLInputElement>) => { setCategoryColor(category, event.target.value) }}\n />\n <span className={css.colorValue}>{colors[category]}</span>\n </div>\n ))}\n <div className={css.sectionTitle}>工具颜色覆盖(可选)</div>\n {Object.entries(toolColors).map(([tool, color]) => (\n <div className={css.toolRow} key={tool}>\n <span className={css.toolName} title={tool}>{tool}</span>\n <input\n className={css.colorInput}\n type=\"color\"\n value={isCssColor(color) ? color : DEFAULT_COLORS.other}\n onChange={(event: ChangeEvent<HTMLInputElement>) => { setToolColor(tool, event.target.value) }}\n />\n <button type=\"button\" className={css.removeButton} onClick={() => { removeToolColor(tool) }}>删除</button>\n </div>\n ))}\n <form className={css.addRow} onSubmit={addTool}>\n <input\n className={css.toolInput}\n type=\"text\"\n placeholder={`工具名,如 ${TOOL_SUGGESTIONS}`}\n value={toolName}\n onChange={(event: ChangeEvent<HTMLInputElement>) => { setToolName(event.target.value) }}\n />\n <input\n className={css.colorInput}\n type=\"color\"\n value={toolColor}\n onChange={(event: ChangeEvent<HTMLInputElement>) => { setToolColorDraft(event.target.value) }}\n />\n <button type=\"submit\" className={css.addButton} disabled={toolName.trim() === ''}>添加</button>\n </form>\n </div>\n </div>\n )}\n </div>\n )\n}\n","/**\n * Browser half: binds the `node-appearance` settings scope, paints the chat\n * flow from it (a single <style data-plugin-css> tag rebuilt on every\n * snapshot change), and registers the settings card.\n */\n\nimport type { Context as ClientContext } from '@deepseek-ai/cordis'\nimport type { SettingsScope } from '@deepseek-ai/dsh-client-ui-settings/client'\n// Type-only: the ctx.settingsScope Context merge and the slot's declaration.\n// Cross-plugin collaboration goes through cordis services; a value import\n// would fail the client bundle-purity gate.\nimport type {} from '@deepseek-ai/dsh-client-ui-settings/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-settings-plugins/client'\n// Type-only: the ctx.slots Context merge comes from the renderer package\n// (slot registry), not from the removed dsh-client-runtime module.\nimport type {} from '@deepseek-ai/dsh-client-ui-renderer/client'\nimport { buildCss, NODE_APPEARANCE_NS, STYLE_TAG_ID, type NodeAppearanceSettings } from './palette.ts'\nimport { NodeAppearanceRow, type NodeAppearanceRowFace } from './settings-card.tsx'\n\nexport const inject = ['slots', 'connection', 'remote', 'settingsScope']\n\n/** Upsert the plugin's paint stylesheet with the current snapshot's CSS. */\nfunction paint(scope: SettingsScope<NodeAppearanceSettings>): void {\n let tag = document.querySelector<HTMLStyleElement>(`style[data-plugin-css=\"${STYLE_TAG_ID}\"]`)\n if (tag === null) {\n tag = document.createElement('style')\n tag.dataset.plugin = NODE_APPEARANCE_NS\n tag.dataset.pluginCss = STYLE_TAG_ID\n document.head.appendChild(tag)\n }\n tag.textContent = buildCss(scope.getSnapshot().value)\n}\n\n/**\n * Mount the node-appearance plugin on the page.\n * @param ctx - client root context.\n */\nexport function apply(ctx: ClientContext): void {\n // settingsScope 由官方 ui-settings 服务提供(DSH 0.1.2-alpha 内核 client\n // 模块表);bind 返回该命名空间的强类型 scope(read/set/unset/subscribe)。\n const scope = ctx.settingsScope.bind<NodeAppearanceSettings>({ namespace: NODE_APPEARANCE_NS })\n // Paint once from the current snapshot (defaults before the first Host read).\n paint(scope)\n ctx.effect(\n () => scope.subscribe(() => { paint(scope) }),\n 'dsh-node-appearance: repaint on settings change',\n )\n\n const face: NodeAppearanceRowFace = {\n hooks: { nodeAppearance: scope },\n setShowThinking: (show) => { void scope.set('showThinking', show) },\n setCategoryColor: (category, color) => {\n const value = scope.getSnapshot().value\n void scope.set('colors', { ...value?.colors, [category]: color })\n },\n setToolColor: (tool, color) => {\n const value = scope.getSnapshot().value\n void scope.set('toolColors', { ...value?.toolColors, [tool]: color })\n },\n removeToolColor: (tool) => {\n const value = scope.getSnapshot().value\n const toolColors = { ...value?.toolColors }\n delete toolColors[tool]\n void scope.set('toolColors', toolColors)\n },\n }\n\n // alpha.2:General 区 slot(settings.general.item)已退役,接入官方\n // 「可配置插件」Tab 的 settings.plugin.item(keyed by namespace)——官方\n // 卡片姿势见 dsh-client-ui-settings-plugins/src/client/index.ts(BashCard 等)。\n ctx.slots.inject('settings.plugin.item', () => ctx.slots.register({\n name: 'settings.plugin.item',\n key: NODE_APPEARANCE_NS,\n inject: () => face,\n // npm ui-slots (0.0.1-rc.1) 类型未合并 keyed-slot 选项(官方 monorepo 类型\n // 才有)——运行时与官方源码一致,类型期放宽(官方类型同步后收紧)。\n } as never, NodeAppearanceRow))\n}\n"],"mappings":"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"}
|
package/lib/index.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { installSettingsSection, settingsNamespace } from "@deepseek-ai/dsh-settings";
|
|
2
1
|
import z from "@deepseek-ai/schemastery";
|
|
3
2
|
//#region src/index.ts
|
|
4
3
|
const name = "dsh-node-appearance";
|
|
5
|
-
/** The settings namespace this plugin owns (spelled identically in both halves).
|
|
6
|
-
|
|
4
|
+
/** The settings namespace this plugin owns (spelled identically in both halves).
|
|
5
|
+
* dsh-settings 0.1.2-alpha.2 起 register/installSection 用 SettingsNamespaceInput
|
|
6
|
+
* 模板字面量自动 parse——settingsNamespace() 函数已删除,改裸字面量。 */
|
|
7
|
+
const NODE_APPEARANCE_NS = "node-appearance";
|
|
7
8
|
/** Initial palette: mid-luminance hues readable on both light and dark themes. */
|
|
8
9
|
const DEFAULT_COLORS = {
|
|
9
10
|
search: "#3b82f6",
|
|
@@ -39,9 +40,11 @@ const Config = z.object({
|
|
|
39
40
|
* @param config - the composed entry config (becomes the section's base layer).
|
|
40
41
|
*/
|
|
41
42
|
function apply(ctx, config) {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
ctx.inject(["settings"], (settingsCtx) => {
|
|
44
|
+
settingsCtx.settings.installSection(ctx, NODE_APPEARANCE_NS, Config, config, {
|
|
45
|
+
setSource: () => {},
|
|
46
|
+
onChange: () => {}
|
|
47
|
+
});
|
|
45
48
|
});
|
|
46
49
|
}
|
|
47
50
|
//#endregion
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* flow from it (a single <style data-plugin-css> tag rebuilt on every
|
|
4
4
|
* snapshot change), and registers the settings card.
|
|
5
5
|
*/
|
|
6
|
-
import type { ClientContext } from '@deepseek-ai/
|
|
6
|
+
import type { Context as ClientContext } from '@deepseek-ai/cordis';
|
|
7
7
|
export declare const inject: string[];
|
|
8
8
|
/**
|
|
9
9
|
* Mount the node-appearance plugin on the page.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAanE,eAAO,MAAM,MAAM,UAAqD,CAAA;AAcxE;;;GAGG;AACH,wBAAgB,KAAK,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI,CAwC9C"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"palette.d.ts","sourceRoot":"","sources":["../../../src/client/palette.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,oFAAoF;AACpF,eAAO,MAAM,kBAAkB,oBAAoB,CAAA;AAEnD,4EAA4E;AAC5E,eAAO,MAAM,YAAY,0BAAgC,CAAA;AAEzD,uFAAuF;AACvF,MAAM,MAAM,YAAY,GACpB,QAAQ,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,UAAU,GAAG,SAAS,GAAG,UAAU,GAAG,OAAO,CAAA;AAEhH,8CAA8C;AAC9C,MAAM,MAAM,oBAAoB,GAAG,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,CAAA;AAE/D,qEAAqE;AACrE,MAAM,WAAW,sBAAsB;IACrC,uEAAuE;IACvE,YAAY,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;IAClC,sEAAsE;IACtE,MAAM,CAAC,EAAE,OAAO,CAAC,oBAAoB,CAAC,GAAG,SAAS,CAAA;IAClD,yDAAyD;IACzD,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAAA;CAChD;AAED,kFAAkF;AAClF,eAAO,MAAM,cAAc,EAAE,oBAW5B,CAAA;AAED,yDAAyD;AACzD,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,OAAO,CAAC,YAAY,EAAE,SAAS,GAAG,UAAU,GAAG,SAAS,GAAG,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAO7H,CAAA;AA6BD;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAKjD;AAED,6EAA6E;AAC7E,wBAAgB,aAAa,CAAC,QAAQ,EAAE,sBAAsB,GAAG,oBAAoB,CAUpF;AAcD;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,sBAAsB,GAAG,SAAS,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"palette.d.ts","sourceRoot":"","sources":["../../../src/client/palette.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,oFAAoF;AACpF,eAAO,MAAM,kBAAkB,oBAAoB,CAAA;AAEnD,4EAA4E;AAC5E,eAAO,MAAM,YAAY,0BAAgC,CAAA;AAEzD,uFAAuF;AACvF,MAAM,MAAM,YAAY,GACpB,QAAQ,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,UAAU,GAAG,SAAS,GAAG,UAAU,GAAG,OAAO,CAAA;AAEhH,8CAA8C;AAC9C,MAAM,MAAM,oBAAoB,GAAG,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,CAAA;AAE/D,qEAAqE;AACrE,MAAM,WAAW,sBAAsB;IACrC,uEAAuE;IACvE,YAAY,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;IAClC,sEAAsE;IACtE,MAAM,CAAC,EAAE,OAAO,CAAC,oBAAoB,CAAC,GAAG,SAAS,CAAA;IAClD,yDAAyD;IACzD,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAAA;CAChD;AAED,kFAAkF;AAClF,eAAO,MAAM,cAAc,EAAE,oBAW5B,CAAA;AAED,yDAAyD;AACzD,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,OAAO,CAAC,YAAY,EAAE,SAAS,GAAG,UAAU,GAAG,SAAS,GAAG,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAO7H,CAAA;AA6BD;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAKjD;AAED,6EAA6E;AAC7E,wBAAgB,aAAa,CAAC,QAAQ,EAAE,sBAAsB,GAAG,oBAAoB,CAUpF;AAcD;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,sBAAsB,GAAG,SAAS,GAAG,MAAM,CA+E7E"}
|
|
@@ -7,17 +7,15 @@
|
|
|
7
7
|
* client bundle purity gate forbids cross-plugin value imports), styled with
|
|
8
8
|
* the DSH design tokens like the shipped Appearance row.
|
|
9
9
|
*/
|
|
10
|
-
import type {
|
|
10
|
+
import type { ObservableSnapshot } from '@deepseek-ai/dsh-client-store';
|
|
11
|
+
import type { SettingsScopeSnapshot } from '@deepseek-ai/dsh-client-ui-settings/client';
|
|
11
12
|
import type { InjectFace, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
|
|
12
13
|
import { type NodeAppearanceSettings, type NodeCategory } from './palette.ts';
|
|
13
14
|
/** The row's inject face: the read-only scope snapshot plus write actions. */
|
|
14
15
|
export interface NodeAppearanceRowFace {
|
|
15
16
|
hooks: {
|
|
16
17
|
/** The bound settings-scope snapshot, rendered as useNodeAppearance. */
|
|
17
|
-
nodeAppearance:
|
|
18
|
-
getSnapshot(): SettingsScopeSnapshot<NodeAppearanceSettings>;
|
|
19
|
-
subscribe(listener: () => void): () => void;
|
|
20
|
-
};
|
|
18
|
+
nodeAppearance: ObservableSnapshot<SettingsScopeSnapshot<NodeAppearanceSettings>>;
|
|
21
19
|
};
|
|
22
20
|
/** Write the Think visibility switch. */
|
|
23
21
|
setShowThinking(show: boolean): void;
|
|
@@ -28,8 +26,8 @@ export interface NodeAppearanceRowFace {
|
|
|
28
26
|
/** Remove one tool override. */
|
|
29
27
|
removeToolColor(tool: string): void;
|
|
30
28
|
}
|
|
31
|
-
/** Props the renderer binds for this
|
|
32
|
-
export type NodeAppearanceRowProps = PropsRuntime<'settings.
|
|
29
|
+
/** Props the renderer binds for this plugin config card. */
|
|
30
|
+
export type NodeAppearanceRowProps = PropsRuntime<'settings.plugin.item'> & InjectFace<NodeAppearanceRowFace>;
|
|
33
31
|
/**
|
|
34
32
|
* Render the node-appearance General row.
|
|
35
33
|
* @param props - the injected scope snapshot hook and write actions.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings-card.d.ts","sourceRoot":"","sources":["../../../src/client/settings-card.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"settings-card.d.ts","sourceRoot":"","sources":["../../../src/client/settings-card.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAA;AACvE,OAAO,KAAK,EAAiB,qBAAqB,EAAE,MAAM,4CAA4C,CAAA;AAEtG,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAA;AAEhF,OAAO,EAEL,KAAK,sBAAsB,EAAE,KAAK,YAAY,EAC/C,MAAM,cAAc,CAAA;AAGrB,8EAA8E;AAC9E,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE;QACL,wEAAwE;QACxE,cAAc,EAAE,kBAAkB,CAAC,qBAAqB,CAAC,sBAAsB,CAAC,CAAC,CAAA;KAClF,CAAA;IACD,yCAAyC;IACzC,eAAe,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAAA;IACpC,yDAAyD;IACzD,gBAAgB,CAAC,QAAQ,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7D,2DAA2D;IAC3D,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/C,gCAAgC;IAChC,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CACpC;AAED,4DAA4D;AAC5D,MAAM,MAAM,sBAAsB,GAChC,YAAY,CAAC,sBAAsB,CAAC,GAClC,UAAU,CAAC,qBAAqB,CAAC,CAAA;AAmBrC;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,iBAAiB,EAAE,eAAe,EAAE,gBAAgB,EAAE,YAAY,EAAE,eAAe,EAAE,EAAE,sBAAsB,+BAqGhJ"}
|
package/lib/types/index.d.ts
CHANGED
|
@@ -7,8 +7,10 @@
|
|
|
7
7
|
import type { Context } from '@deepseek-ai/cordis';
|
|
8
8
|
import z from '@deepseek-ai/schemastery';
|
|
9
9
|
export declare const name = "dsh-node-appearance";
|
|
10
|
-
/** The settings namespace this plugin owns (spelled identically in both halves).
|
|
11
|
-
|
|
10
|
+
/** The settings namespace this plugin owns (spelled identically in both halves).
|
|
11
|
+
* dsh-settings 0.1.2-alpha.2 起 register/installSection 用 SettingsNamespaceInput
|
|
12
|
+
* 模板字面量自动 parse——settingsNamespace() 函数已删除,改裸字面量。 */
|
|
13
|
+
export declare const NODE_APPEARANCE_NS = "node-appearance";
|
|
12
14
|
/** Accent color per category (CSS colors). */
|
|
13
15
|
export interface NodeAppearanceColors {
|
|
14
16
|
search: string;
|
package/lib/types/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAElD,OAAO,CAAC,MAAM,0BAA0B,CAAA;AAExC,eAAO,MAAM,IAAI,wBAAwB,CAAA;AAEzC
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAElD,OAAO,CAAC,MAAM,0BAA0B,CAAA;AAExC,eAAO,MAAM,IAAI,wBAAwB,CAAA;AAEzC;;sDAEsD;AACtD,eAAO,MAAM,kBAAkB,oBAAoB,CAAA;AAEnD,8CAA8C;AAC9C,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;CACd;AAED,0EAA0E;AAC1E,MAAM,WAAW,MAAM;IACrB,uFAAuF;IACvF,YAAY,EAAE,OAAO,CAAA;IACrB,kCAAkC;IAClC,MAAM,EAAE,oBAAoB,CAAA;IAC5B,yDAAyD;IACzD,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CACnC;AAED,kFAAkF;AAClF,eAAO,MAAM,cAAc,EAAE,oBAW5B,CAAA;AAED,eAAO,MAAM,MAAM,EAAE,CAAC,CAAC,MAAM,CAe3B,CAAA;AAEF;;;;GAIG;AACH,wBAAgB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAUxD"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@max-null/dsh-node-appearance",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.4",
|
|
4
4
|
"description": "会话节点外观插件:按节点类型/工具名着色的可配置配色,思考过程显示开关(DeepSeek Harness Web GUI)",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"publishConfig": {
|
|
@@ -32,8 +32,6 @@
|
|
|
32
32
|
},
|
|
33
33
|
"client": {
|
|
34
34
|
"inject": [
|
|
35
|
-
"@deepseek-ai/dsh-client-runtime",
|
|
36
|
-
"@deepseek-ai/dsh-client-ui-primitives",
|
|
37
35
|
"@deepseek-ai/dsh-client-ui-settings",
|
|
38
36
|
"@deepseek-ai/dsh-client-ui-settings-plugins"
|
|
39
37
|
],
|
|
@@ -69,22 +67,23 @@
|
|
|
69
67
|
"@deepseek-ai/schemastery": ">=0.1.0-rc.1"
|
|
70
68
|
},
|
|
71
69
|
"peerDependencies": {
|
|
72
|
-
"@deepseek-ai/cordis": "^4.0.
|
|
73
|
-
"@deepseek-ai/dsh-client-
|
|
74
|
-
"@deepseek-ai/dsh-client-ui-
|
|
75
|
-
"@deepseek-ai/dsh-client-ui-settings": "^0.1.
|
|
76
|
-
"@deepseek-ai/dsh-client-ui-
|
|
77
|
-
"@deepseek-ai/dsh-settings": "^0.1.
|
|
70
|
+
"@deepseek-ai/cordis": "^4.0.2",
|
|
71
|
+
"@deepseek-ai/dsh-client-ui-primitives": "^0.1.2-alpha.2",
|
|
72
|
+
"@deepseek-ai/dsh-client-ui-settings": "^0.1.2-alpha.2",
|
|
73
|
+
"@deepseek-ai/dsh-client-ui-settings-plugins": "^0.1.2-alpha.2",
|
|
74
|
+
"@deepseek-ai/dsh-client-ui-slots": "^0.1.2-alpha.2",
|
|
75
|
+
"@deepseek-ai/dsh-settings": "^0.1.2-alpha.2",
|
|
78
76
|
"react": "^18.2.0"
|
|
79
77
|
},
|
|
80
78
|
"devDependencies": {
|
|
81
|
-
"@deepseek-ai/cordis": "^4.0.
|
|
82
|
-
"@deepseek-ai/dsh-client-
|
|
83
|
-
"@deepseek-ai/dsh-client-ui-primitives": "^0.1.
|
|
84
|
-
"@deepseek-ai/dsh-client-ui-
|
|
85
|
-
"@deepseek-ai/dsh-client-ui-settings
|
|
86
|
-
"@deepseek-ai/dsh-client-ui-
|
|
87
|
-
"@deepseek-ai/dsh-
|
|
79
|
+
"@deepseek-ai/cordis": "^4.0.2",
|
|
80
|
+
"@deepseek-ai/dsh-client-store": "^0.1.2-alpha.2",
|
|
81
|
+
"@deepseek-ai/dsh-client-ui-primitives": "^0.1.2-alpha.2",
|
|
82
|
+
"@deepseek-ai/dsh-client-ui-renderer": "^0.1.2-alpha.2",
|
|
83
|
+
"@deepseek-ai/dsh-client-ui-settings": "^0.1.2-alpha.2",
|
|
84
|
+
"@deepseek-ai/dsh-client-ui-settings-plugins": "^0.1.2-alpha.2",
|
|
85
|
+
"@deepseek-ai/dsh-client-ui-slots": "^0.1.2-alpha.2",
|
|
86
|
+
"@deepseek-ai/dsh-settings": "^0.1.2-alpha.2",
|
|
88
87
|
"@types/node": "^26.0.0",
|
|
89
88
|
"@types/react": "~18.3.1",
|
|
90
89
|
"lightningcss": "^1.32.0",
|