@max-null/dsh-node-appearance 0.1.1 → 0.3.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 CHANGED
@@ -9,6 +9,12 @@
9
9
  - **思考过程显示开关**:关闭后 Think 思考行前端隐藏(`display: none`),配置项与配色在同一张设置卡片里。
10
10
  - **即时生效**:设置改动立即重绘会话,并持久化到 DSH 用户设置文档(`$DSH_HOME/settings.yaml`)。
11
11
 
12
+ ## 截图
13
+
14
+ | 会话节点着色 | 设置卡片 |
15
+ |---|---|
16
+ | ![会话节点着色](docs/shots/会话面板截图.png) | ![设置卡片](docs/shots/设置页截图.png) |
17
+
12
18
  ## 安装
13
19
 
14
20
  ```sh
@@ -73,3 +79,9 @@ npm run build # tsc 类型 + tsdown(lib/index.js + lib/client.js)
73
79
 
74
80
  - [决策记录](docs/决策/2026-08-17-节点外观插件-独立插件决策.md)
75
81
  - [设计方案](docs/设计/DSH节点外观插件-设计方案.md)
82
+
83
+ ## SSID 系列
84
+
85
+ 本插件属于 **`@max-null/*` 插件系列**——这一系列共同构成 **[SSID(思灵 · Seek Soul in Darkness)](https://github.com/Max-Null/seek-soul-in-darkness)** 桌面体验。SSID 是整合它们的盒:`dsh-chat-rail` · `dsh-chinese-thinking` · `dsh-draft-polish` · `dsh-guardian` · `dsh-habit` · `dsh-header-unify` · `dsh-memory` · `dsh-node-appearance` · `dsh-plugin-center` · `dsh-skill-mcp-center` · `dsh-ssid-panels` · `dsh-ssid-zh-ui`。
86
+
87
+ 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.
package/lib/client.js CHANGED
@@ -29,6 +29,7 @@ window.__ModuleLoader__.load({
29
29
  command: "#f97316",
30
30
  thinking: "#c4b5fd",
31
31
  context: "#8a9bb5",
32
+ steering: "#14b8a6",
32
33
  other: "#64748b"
33
34
  };
34
35
  /** Wire tool name → category for the shipped mapping. */
@@ -89,18 +90,24 @@ window.__ModuleLoader__.load({
89
90
  const THINK_ROW = "[data-variant=\"think\"]";
90
91
  /** Selector of the injected-context row (the flow-item wrapper). */
91
92
  const CONTEXT_ROW = "[data-chat-flow-kind=\"context\"]";
93
+ /** Selector of a settled tool-result row (rc.8: tool results render as their own row). */
94
+ const TOOL_RESULT_ROW = "[data-chat-flow-kind=\"tool-result\"]";
92
95
  /**
93
96
  * The rows that carry the accent paint: the ToolRow root (not its wrapper
94
97
  * callRow — both carry data-tool, only the inner row carries data-variant),
95
- * command nodes, Think rows, and injected-context rows. The 3px inset rail is
96
- * compensated with a matching padding-left so the rail never covers the
97
- * row's leading icon.
98
+ * command nodes, Think rows, injected-context rows, and tool-result rows.
99
+ * User input rows are excluded — right-alignment already
100
+ * distinguishes them (2026-08-20 用户反馈);steering rows 也走独立规则
101
+ * (见 buildCss:在 userStack 层做 wash,不涂整行 rail)。
102
+ * The 3px inset rail is compensated
103
+ * with a matching padding-left so the rail never covers the row's leading icon.
98
104
  */
99
105
  const ACCENTED_ROWS = [
100
106
  TOOL_ROW_ROOT,
101
107
  COMMAND_ROW,
102
108
  THINK_ROW,
103
- CONTEXT_ROW
109
+ CONTEXT_ROW,
110
+ TOOL_RESULT_ROW
104
111
  ].join(",\n");
105
112
  /**
106
113
  * Accept a configured CSS color (hex, color functions) or reject it so an
@@ -129,6 +136,12 @@ window.__ModuleLoader__.load({
129
136
  return value.replace(/\\/g, "\\\\").replace(/"/g, "\\\"");
130
137
  }
131
138
  /**
139
+ * Steering marker icon: a corner-up-left arrow (mid-turn guidance inserted
140
+ * into the running answer), drawn as a mask so the icon inherits the
141
+ * configured steering color. Encoded data URI, no external asset.
142
+ */
143
+ const 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";
144
+ /**
132
145
  * Build the complete stylesheet text for one settings snapshot.
133
146
  * @param settings - the namespace scope value (may be partial or undefined).
134
147
  * @returns CSS text painting accent rows and (optionally) hiding Think rows.
@@ -149,10 +162,27 @@ window.__ModuleLoader__.load({
149
162
  lines.push(`${COMMAND_ROW} { --ncolor-accent: ${colors.command}; }`);
150
163
  lines.push(`${THINK_ROW} { --ncolor-accent: ${colors.thinking}; }`);
151
164
  lines.push(`${CONTEXT_ROW} { --ncolor-accent: ${colors.context}; }`);
165
+ lines.push(`${TOOL_RESULT_ROW} { --ncolor-accent: ${colors.file}; }`);
152
166
  lines.push(`${ACCENTED_ROWS} {
153
167
  box-shadow: inset 3px 0 0 var(--ncolor-accent);
154
168
  background-color: color-mix(in srgb, var(--ncolor-accent) 8%, transparent);
155
169
  padding-left: 3px;
170
+ }`);
171
+ lines.push(`[data-chat-flow-kind="steering"] [data-time-hover-root] > :first-child {
172
+ position: relative;
173
+ }`);
174
+ lines.push(`[data-chat-flow-kind="steering"] [data-time-hover-root] > :first-child::before {
175
+ content: '';
176
+ position: absolute;
177
+ right: 100%;
178
+ margin-right: 6px;
179
+ top: 50%;
180
+ width: 14px;
181
+ height: 14px;
182
+ transform: translateY(-50%);
183
+ background-color: ${colors.steering};
184
+ -webkit-mask: url("${STEERING_ICON}") center / contain no-repeat;
185
+ mask: url("${STEERING_ICON}") center / contain no-repeat;
156
186
  }`);
157
187
  if (settings?.showThinking === false) lines.push(`${THINK_ROW} { display: none !important; }`);
158
188
  return lines.join("\n");
@@ -170,26 +200,26 @@ window.__ModuleLoader__.load({
170
200
  }
171
201
  var card_module_css_default = {
172
202
  "toolInput": "AWuyDW_toolInput",
173
- "row": "AWuyDW_row",
203
+ "rowHint": "AWuyDW_rowHint",
174
204
  "title": "AWuyDW_title",
175
- "sectionTitle": "AWuyDW_sectionTitle",
205
+ "colorInput": "AWuyDW_colorInput",
206
+ "colorValue": "AWuyDW_colorValue",
176
207
  "addButton": "AWuyDW_addButton",
177
- "toolName": "AWuyDW_toolName",
208
+ "statusLine": "AWuyDW_statusLine",
178
209
  "disabled": "AWuyDW_disabled",
179
- "body": "AWuyDW_body",
180
- "checkbox": "AWuyDW_checkbox",
181
210
  "addRow": "AWuyDW_addRow",
182
- "colorInput": "AWuyDW_colorInput",
183
- "group": "AWuyDW_group",
184
211
  "chevronOpen": "AWuyDW_chevronOpen",
212
+ "chevron": "AWuyDW_chevron",
185
213
  "rowLabel": "AWuyDW_rowLabel",
186
- "rowHint": "AWuyDW_rowHint",
187
- "colorValue": "AWuyDW_colorValue",
188
- "statusLine": "AWuyDW_statusLine",
214
+ "row": "AWuyDW_row",
215
+ "checkbox": "AWuyDW_checkbox",
216
+ "sectionTitle": "AWuyDW_sectionTitle",
217
+ "group": "AWuyDW_group",
218
+ "removeButton": "AWuyDW_removeButton",
189
219
  "toolRow": "AWuyDW_toolRow",
190
- "chevron": "AWuyDW_chevron",
191
220
  "header": "AWuyDW_header",
192
- "removeButton": "AWuyDW_removeButton"
221
+ "toolName": "AWuyDW_toolName",
222
+ "body": "AWuyDW_body"
193
223
  };
194
224
  //#endregion
195
225
  //#region src/client/settings-card.tsx
@@ -212,6 +242,7 @@ window.__ModuleLoader__.load({
212
242
  command: "指令节点",
213
243
  thinking: "思考过程",
214
244
  context: "上下文注入",
245
+ steering: "模型引导",
215
246
  other: "其他工具"
216
247
  };
217
248
  /** Tools shown in the add-override autocomplete-free text input placeholder. */
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`, and `context` are non-tool rows. */\nexport type NodeCategory =\n | 'search' | 'agent' | 'execute' | 'file' | 'task' | 'command' | 'thinking' | 'context' | '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 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'>, 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\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, and injected-context rows. The 3px inset rail is\n * compensated with a matching padding-left so the rail never covers the\n * row's leading icon.\n */\nconst ACCENTED_ROWS = [TOOL_ROW_ROOT, COMMAND_ROW, THINK_ROW, CONTEXT_ROW].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 * 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 Exclude<NodeCategory, 'command' | 'thinking'>\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\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 // 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 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 }\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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"}
package/lib/index.js CHANGED
@@ -14,6 +14,7 @@ const DEFAULT_COLORS = {
14
14
  command: "#f97316",
15
15
  thinking: "#c4b5fd",
16
16
  context: "#8a9bb5",
17
+ steering: "#14b8a6",
17
18
  other: "#64748b"
18
19
  };
19
20
  const Config = z.object({
@@ -27,6 +28,7 @@ const Config = z.object({
27
28
  command: z.string().default(DEFAULT_COLORS.command),
28
29
  thinking: z.string().default(DEFAULT_COLORS.thinking),
29
30
  context: z.string().default(DEFAULT_COLORS.context),
31
+ steering: z.string().default(DEFAULT_COLORS.steering),
30
32
  other: z.string().default(DEFAULT_COLORS.other)
31
33
  }).default(DEFAULT_COLORS),
32
34
  toolColors: z.dict(z.string()).default({})
@@ -9,8 +9,8 @@
9
9
  export declare const NODE_APPEARANCE_NS = "node-appearance";
10
10
  /** The plugin's style tag identity (removed/replaced on every re-paint). */
11
11
  export declare const STYLE_TAG_ID = "node-appearance/rules";
12
- /** One paintable node category. `command`, `thinking`, and `context` are non-tool rows. */
13
- export type NodeCategory = 'search' | 'agent' | 'execute' | 'file' | 'task' | 'command' | 'thinking' | 'context' | 'other';
12
+ /** One paintable node category. `command`, `thinking`, `context` are non-tool rows. */
13
+ export type NodeCategory = 'search' | 'agent' | 'execute' | 'file' | 'task' | 'command' | 'thinking' | 'context' | 'steering' | 'other';
14
14
  /** Accent color per category (CSS colors). */
15
15
  export type NodeAppearanceColors = Record<NodeCategory, string>;
16
16
  /** The settings value this plugin reads from its namespace scope. */
@@ -25,7 +25,7 @@ export interface NodeAppearanceSettings {
25
25
  /** Initial palette: mid-luminance hues readable on both light and dark themes. */
26
26
  export declare const DEFAULT_COLORS: NodeAppearanceColors;
27
27
  /** Wire tool name → category for the shipped mapping. */
28
- export declare const TOOL_CATEGORIES: Record<Exclude<NodeCategory, 'command' | 'thinking' | 'context'>, readonly string[]>;
28
+ export declare const TOOL_CATEGORIES: Record<Exclude<NodeCategory, 'command' | 'thinking' | 'context' | 'steering'>, readonly string[]>;
29
29
  /**
30
30
  * Accept a configured CSS color (hex, color functions) or reject it so an
31
31
  * invalid value falls back to the category default instead of poisoning CSS.
@@ -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,2FAA2F;AAC3F,MAAM,MAAM,YAAY,GACpB,QAAQ,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,UAAU,GAAG,SAAS,GAAG,OAAO,CAAA;AAEnG,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,oBAU5B,CAAA;AAED,yDAAyD;AACzD,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,OAAO,CAAC,YAAY,EAAE,SAAS,GAAG,UAAU,GAAG,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAOhH,CAAA;AAsBD;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAKjD;AAED,6EAA6E;AAC7E,wBAAgB,aAAa,CAAC,QAAQ,EAAE,sBAAsB,GAAG,oBAAoB,CAUpF;AAOD;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,sBAAsB,GAAG,SAAS,GAAG,MAAM,CA6C7E"}
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,CAsE7E"}
@@ -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,wCAAwC,CAAA;AAEnF,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;YACd,WAAW,IAAI,qBAAqB,CAAC,sBAAsB,CAAC,CAAA;YAC5D,SAAS,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAA;SAC5C,CAAA;KACF,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,qDAAqD;AACrD,MAAM,MAAM,sBAAsB,GAChC,YAAY,CAAC,uBAAuB,CAAC,GACnC,UAAU,CAAC,qBAAqB,CAAC,CAAA;AAkBrC;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,iBAAiB,EAAE,eAAe,EAAE,gBAAgB,EAAE,YAAY,EAAE,eAAe,EAAE,EAAE,sBAAsB,+BAmGhJ"}
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,wCAAwC,CAAA;AAEnF,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;YACd,WAAW,IAAI,qBAAqB,CAAC,sBAAsB,CAAC,CAAA;YAC5D,SAAS,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAA;SAC5C,CAAA;KACF,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,qDAAqD;AACrD,MAAM,MAAM,sBAAsB,GAChC,YAAY,CAAC,uBAAuB,CAAC,GACnC,UAAU,CAAC,qBAAqB,CAAC,CAAA;AAmBrC;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,iBAAiB,EAAE,eAAe,EAAE,gBAAgB,EAAE,YAAY,EAAE,eAAe,EAAE,EAAE,sBAAsB,+BAmGhJ"}
@@ -19,6 +19,7 @@ export interface NodeAppearanceColors {
19
19
  command: string;
20
20
  thinking: string;
21
21
  context: string;
22
+ steering: string;
22
23
  other: string;
23
24
  }
24
25
  /** The plugin configuration: palette plus the Think-visibility switch. */
@@ -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,oFAAoF;AACpF,eAAO,MAAM,kBAAkB,uDAAuC,CAAA;AAEtE,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,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,oBAU5B,CAAA;AAED,eAAO,MAAM,MAAM,EAAE,CAAC,CAAC,MAAM,CAc3B,CAAA;AAEF;;;;GAIG;AACH,wBAAgB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAKxD"}
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,oFAAoF;AACpF,eAAO,MAAM,kBAAkB,uDAAuC,CAAA;AAEtE,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,CAKxD"}
package/package.json CHANGED
@@ -1,92 +1,96 @@
1
- {
2
- "name": "@max-null/dsh-node-appearance",
3
- "version": "0.1.1",
4
- "description": "会话节点外观插件:按节点类型/工具名着色的可配置配色,思考过程显示开关(DeepSeek Harness Web GUI)",
5
- "license": "MIT",
6
- "publishConfig": {
7
- "access": "public"
8
- },
9
- "type": "module",
10
- "main": "lib/index.js",
11
- "types": "lib/types/index.d.ts",
12
- "exports": {
13
- ".": {
14
- "types": "./lib/types/index.d.ts",
15
- "default": "./lib/index.js"
16
- },
17
- "./client": {
18
- "types": "./lib/types/client/index.d.ts",
19
- "default": "./lib/client.js"
20
- },
21
- "./src/*": "./src/*",
22
- "./package.json": "./package.json"
23
- },
24
- "files": [
25
- "lib",
26
- "cordis.patch.yml",
27
- "README.md"
28
- ],
29
- "dsh": {
30
- "bundle": {
31
- "patch": "./cordis.patch.yml"
32
- },
33
- "client": {
34
- "inject": [
35
- "@deepseek-ai/dsh-client-runtime",
36
- "@deepseek-ai/dsh-client-ui-settings",
37
- "@deepseek-ai/dsh-client-ui-settings-plugins"
38
- ],
39
- "platform": "web",
40
- "immediately": true
41
- }
42
- },
43
- "keywords": [
44
- "deepseek",
45
- "harness",
46
- "dsh",
47
- "dsh-plugin",
48
- "deepseek-harness",
49
- "web-ui",
50
- "chat",
51
- "theme",
52
- "color",
53
- "plugin",
54
- "cordis"
55
- ],
56
- "repository": {
57
- "type": "git",
58
- "url": "git+https://github.com/Max-Null/dsh-node-appearance.git"
59
- },
60
- "scripts": {
61
- "build": "tsc -p tsconfig.build.json \u0026\u0026 tsdown",
62
- "watch": "tsdown --watch",
63
- "typecheck": "tsc --noEmit -p tsconfig.json",
64
- "test": "vitest run",
65
- "prepublishOnly": "npm run build \u0026\u0026 npm test"
66
- },
67
- "dependencies": {
68
- "@deepseek-ai/schemastery": "\u003e=0.1.0-rc.1"
69
- },
70
- "peerDependencies": {
71
- "@deepseek-ai/cordis": "^4.0.1",
72
- "@deepseek-ai/dsh-client-runtime": "\u003e=0.1.0-rc.7",
73
- "@deepseek-ai/dsh-client-ui-settings": "\u003e=0.1.0-rc.7",
74
- "@deepseek-ai/dsh-client-ui-settings-plugins": "\u003e=0.1.0-rc.7",
75
- "@deepseek-ai/dsh-settings": "\u003e=0.1.0-rc.7",
76
- "react": "^18.2.0"
77
- },
78
- "devDependencies": {
79
- "@deepseek-ai/cordis": "^4.0.1",
80
- "@deepseek-ai/dsh-client-runtime": "\u003e=0.1.0-rc.7",
81
- "@deepseek-ai/dsh-client-ui-settings": "\u003e=0.1.0-rc.7",
82
- "@deepseek-ai/dsh-client-ui-settings-plugins": "\u003e=0.1.0-rc.7",
83
- "@deepseek-ai/dsh-settings": "\u003e=0.1.0-rc.7",
84
- "@types/node": "^26.0.0",
85
- "@types/react": "~18.3.1",
86
- "lightningcss": "^1.32.0",
87
- "react": "^18.2.0",
88
- "tsdown": "^0.22.2",
89
- "typescript": "^6.0.3",
90
- "vitest": "^4.1.8"
91
- }
92
- }
1
+ {
2
+ "name": "@max-null/dsh-node-appearance",
3
+ "version": "0.3.0",
4
+ "description": "会话节点外观插件:按节点类型/工具名着色的可配置配色,思考过程显示开关(DeepSeek Harness Web GUI)",
5
+ "license": "MIT",
6
+ "publishConfig": {
7
+ "access": "public"
8
+ },
9
+ "type": "module",
10
+ "main": "lib/index.js",
11
+ "types": "lib/types/index.d.ts",
12
+ "exports": {
13
+ ".": {
14
+ "types": "./lib/types/index.d.ts",
15
+ "default": "./lib/index.js"
16
+ },
17
+ "./client": {
18
+ "types": "./lib/types/client/index.d.ts",
19
+ "default": "./lib/client.js"
20
+ },
21
+ "./src/*": "./src/*",
22
+ "./package.json": "./package.json"
23
+ },
24
+ "files": [
25
+ "lib",
26
+ "cordis.patch.yml",
27
+ "README.md"
28
+ ],
29
+ "dsh": {
30
+ "bundle": {
31
+ "patch": "./cordis.patch.yml"
32
+ },
33
+ "client": {
34
+ "inject": [
35
+ "@deepseek-ai/dsh-client-runtime",
36
+ "@deepseek-ai/dsh-client-ui-primitives",
37
+ "@deepseek-ai/dsh-client-ui-settings",
38
+ "@deepseek-ai/dsh-client-ui-settings-plugins"
39
+ ],
40
+ "platform": "web",
41
+ "immediately": true
42
+ }
43
+ },
44
+ "keywords": [
45
+ "deepseek",
46
+ "harness",
47
+ "dsh",
48
+ "dsh-plugin",
49
+ "deepseek-harness",
50
+ "web-ui",
51
+ "chat",
52
+ "theme",
53
+ "color",
54
+ "plugin",
55
+ "cordis"
56
+ ],
57
+ "repository": {
58
+ "type": "git",
59
+ "url": "git+https://github.com/Max-Null/dsh-node-appearance.git"
60
+ },
61
+ "scripts": {
62
+ "build": "tsc -p tsconfig.build.json && tsdown",
63
+ "watch": "tsdown --watch",
64
+ "typecheck": "tsc --noEmit -p tsconfig.json",
65
+ "test": "vitest run",
66
+ "prepublishOnly": "npm run build && npm test"
67
+ },
68
+ "dependencies": {
69
+ "@deepseek-ai/schemastery": ">=0.1.0-rc.1"
70
+ },
71
+ "peerDependencies": {
72
+ "@deepseek-ai/cordis": "^4.0.1",
73
+ "@deepseek-ai/dsh-client-runtime": "^0.1.1-rc.1",
74
+ "@deepseek-ai/dsh-client-ui-primitives": "^0.1.1-rc.1",
75
+ "@deepseek-ai/dsh-client-ui-settings": "^0.1.1-rc.1",
76
+ "@deepseek-ai/dsh-client-ui-settings-plugins": "^0.1.1-rc.1",
77
+ "@deepseek-ai/dsh-settings": "^0.1.1-rc.1",
78
+ "react": "^18.2.0"
79
+ },
80
+ "devDependencies": {
81
+ "@deepseek-ai/cordis": "^4.0.1",
82
+ "@deepseek-ai/dsh-client-runtime": "^0.1.1-rc.1",
83
+ "@deepseek-ai/dsh-client-ui-primitives": "^0.1.1-rc.1",
84
+ "@deepseek-ai/dsh-client-ui-settings": "^0.1.1-rc.1",
85
+ "@deepseek-ai/dsh-client-ui-settings-plugins": "^0.1.1-rc.1",
86
+ "@deepseek-ai/dsh-client-ui-slots": "^0.1.1-rc.1",
87
+ "@deepseek-ai/dsh-settings": "^0.1.1-rc.1",
88
+ "@types/node": "^26.0.0",
89
+ "@types/react": "~18.3.1",
90
+ "lightningcss": "^1.32.0",
91
+ "react": "^18.2.0",
92
+ "tsdown": "^0.22.2",
93
+ "typescript": "^6.0.3",
94
+ "vitest": "^4.1.8"
95
+ }
96
+ }