🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

ChatGPT 风格模型选择器 AprilCrystal/dsh-client-ui-gpt-helper

DeepSeek 客户端
AprilCrystal16 天前有提交已提供中文文档扫描:未发现敏感能力兼容 / 相关生态

一个 DeepSeek Harness 客户端浏览器插件,把 Web 编写器的模型席位替换成 ChatGPT…

31.5/100
综合分
2
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/10/18 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

相关生态插件(非 dsh 原生,按其对应运行时安装)
git clone https://github.com/AprilCrystal/dsh-client-ui-gpt-helper.git

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:已验证
是什么
生态插件
可安装,未声明 dsh 能力
装得上吗
本站已在 dsh 0.2.1-rc.5 下真实安装成功
非静态推断
L5 · 运行时冒烟等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 16 天前
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查⚠ 装前注意

未发布到 npm registry,仅可从源码安装

展开查看检查明细 ↓

以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。

✗npm 包dsh-client-ui-gpt-helper(未发布到 npm,仅可源码安装)
✓Node 引擎未声明 engines.node
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/13 08:09:58

安全扫描自动 · 静态分析源码
v2.7.0
🟢 扫描:未发现敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描未发现敏感能力:最多只发网络请求、读取自身元数据或只读文件,未发现执行命令、文件写入或敏感信息读取。

扫描于 2026/11/2(1 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

依赖的 DSH / Cordis 模块
@deepseek-ai/cordis
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

功能亮点

  • 带动画思考等级滑块

dsh 客户端插件:为 DeepSeek Harness Web 输入框提供 ChatGPT 风格模型选择器和带动画的思考等级滑块。

README

由 DeepSeek 最新模型翻译生成
dsh-client-ui-gpt-helper 一个 DeepSeek Harness 客户端(浏览器)插件,把 Web 编写器的模型席位替换成 ChatGPT 桌面风格控件:弹出层里按服务商分组列出模型,还有带动画和粒子拖尾的思考等级滑块,外加闪电形状的快速模式开关。 交互设计和每个时间参数都移植自本仓库自带的原型——在浏览器里打开 docs/chatgpt-pc-ui-prototype.html 就能看到原版。 它能做什么 - 模型选择——真实目录,按服务商分组,条目超过四个后支持搜索。 - 思考等级——所选模型公布的等级变成滑块上的刻度,带填充轨道和 28px 滑块。拖动、点击刻度或用方向键都行;数值吸附到最近的等级,并通过共享会话目录提交。 - 快速模式——闪电开关,点亮粒子拖尾。纯视觉效果: DSH 没有快速模式这个概念,所以除了动画它什么都不改。打开时拖尾点燃,关闭时拖尾缓缓熄灭(见粒子渐变)。 - 快速模式锁定——按住闪电 600 ms 即可把快速模式钉住。按住状态会被保存,所以刷新后、新会话里、重启应用后闪电依然是亮的;触发器会长出一个小锁徽标,弹出层里的闪电也换成锁。锁定期间普通点击无效,再按住一次即可解锁(快速模式保持开启)。 - 颜色配置——按 Ctrl+Shift+Alt+G 打开颜色面板,不用改这个文件就能给控件换主题(见颜色)。
展开完整文档(README 剩余 1 节)
dsh-client-ui-gpt-helper

一个 DeepSeek Harness 客户端(浏览器)插件,把 Web 编写器的模型席位替换成 ChatGPT 桌面风格控件:弹出层里按服务商分组列出模型,还有带动画和粒子拖尾的思考等级滑块,外加闪电形状的快速模式开关。

交互设计和每个时间参数都移植自本仓库自带的原型——在浏览器里打开 docs/chatgpt-pc-ui-prototype.html 就能看到原版。

它能做什么

- 模型选择——真实目录,按服务商分组,条目超过四个后支持搜索。
- 思考等级——所选模型公布的等级变成滑块上的刻度,带填充轨道和 28px 滑块。拖动、点击刻度或用方向键都行;数值吸附到最近的等级,并通过共享会话目录提交。
- 快速模式——闪电开关,点亮粒子拖尾。纯视觉效果: DSH 没有快速模式这个概念,所以除了动画它什么都不改。打开时拖尾点燃,关闭时拖尾缓缓熄灭(见粒子渐变)。
- 快速模式锁定——按住闪电 600 ms 即可把快速模式钉住。按住状态会被保存,所以刷新后、新会话里、重启应用后闪电依然是亮的;触发器会长出一个小锁徽标,弹出层里的闪电也换成锁。锁定期间普通点击无效,再按住一次即可解锁(快速模式保持开启)。
- 颜色配置——按 Ctrl+Shift+Alt+G 打开颜色面板,不用改这个文件就能给控件换主题(见颜色)。

它替换了自带的编写器控件,而不是并排放在旁边,并且复用了那个控件的数据层,所以 /model 命令和下一次请求始终同步。

要求

- 带 Web 客户端的 DeepSeek Harness(desktop 配置档,或任何挂载了 @deepseek-ai/dsh-web-app 的配置档)。
- 无需构建步骤。lib/.js 文件直接按发布包格式编写,所以克隆仓库就够了。

安装

这个包是 dsh bundle:package.json 声明了 dsh.bundle.patch,所以 dsh 会把 cordis.patch.yml 当作组合层,替你挂载。

dsh plugin --profile <profile> add dsh-client-ui-gpt-helper

这会把包装进配置档,并追加到配置档的 bundle 列表。配置档处于监视状态,所以 dsh 无需重启即可重新组合。用 dsh plugin --profile <profile> remove dsh-client-ui-gpt-helper 卸载。

从本地检出安装

dsh plugin --profile desktop add /absolute/path/to/dsh-client-ui-gpt-helper

手动挂载

把 cordis.patch.yml 组合进配置档自己的补丁文件,并让包能从配置档目录解析:

bash
pnpm add link:/absolute/path/to/dsh-client-ui-gpt-helper --dir "$DSH_HOME/profiles/desktop"
yaml

$DSH_HOME/profiles/<profile>/cordis.patch.yml

- insert:
- id: gpt-helper
name: dsh-client-ui-gpt-helper

补丁里的 insert 行也可以写路径,不写包名 —— dsh 会把 ./ 相对路径和绝对路径改写成文件 URL,锚定到补丁文件所在位置 —— 这样完全不需要安装。

接管是怎么发生的

conversation.input.model 是一个 single 槽位,归 @deepseek-ai/dsh-client-ui-conversation 所有,默认优先级 0 时由 @deepseek-ai/dsh-client-ui-model-selection 占用。

在相同优先级上再注册一次会抛错 —— single slot "…" already has a registration。但注册表会按优先级升序排列某个单元格的条目,然后渲染第一个,它自己的错误信息也说了:「register at a different priority to shadow it (lowest renders)」。所以这个插件必须传一个显式的负优先级: js
ctx.slots.register({ name: 'conversation.input.model', priority: -1, … })

dsh-cordis-client-runner 里那套递减的自动分配属于另一个加载器(智能体编写的运行时插件,其账本带有 agentId/pluginRunId)。像这样的启动图插件不在它的覆盖范围内,省略优先级会让注册抛错,而随包发布的控件会悄无声息地留在原位。

让随包发布的包保持启用才是关键:它的 ctx.modelDirectories 服务和 /model 斜杠命令照常工作,只有 UI 被替换。数据和提交都走同一个按会话的 ModelDirectory,所以在哪个入口切换,另一个入口和下一个请求看到的都是同一个结果。

控件

触发器 —— 一个闪电图标(只在快速模式点亮时出现,锁被持有时带锁徽标)、模型名、思考级别和一个插入符;选择落定时显示加载指示器。

思考面板(默认)

- 头部* —— 32×32 的快速模式闪电开关、一个状态按钮(在模型名上方显示级别,点击打开模型面板),以及一个重置按钮。头部是 34px 1fr 34px 网格。锁被持有时,闪电图标换成锁,状态按钮也不再显示级别,而是说明这一点;重置按钮也会清掉锁,因为快速模式本来就是它重置的一部分。
- 滑块 —— 级别位置遵循原型的规则:轨道上的偶数分数被夹到滑块的行程范围内,clamp(i/(n-1), .055, .945),这正好复现了它的 [.055, .25, .5, .75, .945]。刻度锚定到同样的比例,而不是像原型那样用 flex 分配 —— 原型内部的刻度最多会偏离它们标记的滑块位置约 7px。
- 颜色 —— 轨道用主题自己的表面色,填充用纯色 #5184f4;只有顶层才出现渐变。每一个都是 token —— 见 Colours。
- 粒子拖尾 —— 42 个确定性粒子,放在一个尺寸为 --value 的拖尾元素里,所以它们都裁剪到填充胶囊内。其中 18 个是条纹。每个粒子都带 两套 完整几何:漂移轨迹,以及顶层在关闭快速模式时显示的原地震颤——正因如此,这些粒子才是小而慢的点,而不是扁平的条纹。
- 额度提示 — 进入顶层时,标题栏会短暂收起,标题换成 更快消耗使用额度,与原型一致。
- 提示 — 用一行文字说明按住手势,因为需要按住的按压本身没有任何可供性提示。

模型面板 — 返回按钮、超过四个模型时出现搜索框,以及按服务商分组的列表,当前模型带勾选标记。

token 如何解析

每种颜色都是字面量,颜色从不经过 var() 传递。 样式表把每个 token 的出厂值内联写出;注入的规则只携带用户覆盖过的部分。
css
/* the plugin's stylesheet — the shipped pair, no variables anywhere /
.gptm-track { background: #e8e7e8; }
:root[data-dsw-theme="light"] { --c-trigger.model: #242527; } / 6 tokens differ /
.gptm-root { --c-trigger.model: #ffffff; } / the dark default /

/ injected into by applyTheme — only the overrides, as literals /
:root { --c-trigger.model: #ff0000; }

没有任何 token 被覆盖时,applyTheme 什么都不写:样式表自身的字面量就是外观。覆盖值发布在裸 :root 上,凭优先级压过出厂的 :root[data-dsw-theme="light"] 块——正因如此,你的颜色在两种主题下都能保持,而六个随主题变化的出厂 token 继续跟随应用。

颜色

控件的调色板是一张 24 个 token 的表,每个 token 有两个字面量:default(内联在样式表中,也用于 <body> 级别的深色)和 light(发布在浅色主题选择器下)。其中六个 token 在两者之间不同;其余都针对两种主题下相同的表面调校过。

颜色绝不能写成 var(--c-x) 或 var(--c-x, fallback)。 这个应用的 Chromium 会丢弃任何值 仅* 为 var(…) 的声明——包括 color、background、transform 和 box-shadow——无论变量是否已定义,也无论是否提供了回退值。在运行中的页面上实测:CSS.supports('background', 'var(--x, #fff)') 返回 false,而写成 color: var(--c-trigger.level) 的规则到达文档时是一个 空的声明块。正因如此,滑块有好几轮都不可见——它的轨道、填充、滑块和刻度,绘制被悄悄丢弃,而几何尺寸测量完全正常(235x24,位置正确,background-color: rgba(0,0,0,0))。如果样式表重新长出 var(--c-…) 引用,或者发布的覆盖值里含有 var(),selfcheck.mjs 就会失败。

按 Ctrl+Shift+Alt+G 打开颜色面板:

- 每个 token 一行:一个颜色井、一个字面量文本框(rgba(…)、渐变等),
- 一个 ↺,用来丢掉那一条覆盖值;
- 一个热键字段,上面那组组合键本身也能改(会做校验,敲到一半的组合键会被拒绝,而不是让它把能用的那组弄坏);
- 一个 JSON 面板,装着设置实际存储的那份文档,带 Import 和 Copy config JSON;
- Restore default colours,一次清空所有覆盖值。

每一行始终显示一个具体颜色——要么是覆盖值,要么是样式表里写的字面量——它的占位符则标出这一行在没人动过时会跟随哪个主题 token。没动过的 token 跟随 DSH 主题;改过的 token 在两种主题下都钉死为你的颜色;↺、清空字段,或者 Restore,都是让 token 回到跟随主题的办法。

存储位置是 localStorage,键为 dsh-client-ui-gpt-helper:config:v1(快速锁用 …:fast:v1),因为浏览器 bundle 碰不到磁盘上的文件。JSON 面板的存在,是为了让同一份文档也能放在你自己保存的文件里:复制出去,改一改,再粘回来。取值在写入时和读出存储时都会校验——手改过的数据块没法闭合一条声明再注入 CSS。

按面板顺序排列的 token:trigger.bolt、trigger.model、trigger.level、trigger.levelMax、trigger.caret、trigger.lockMark、menu.bolt、menu.boltLit、menu.level、menu.levelMax、menu.levelGrad、menu.quota、menu.quotaGrad、slider.track、slider.fill、slider.fillGrad、slider.thumb、slider.tick、slider.tickPast、slider.tickCurrent、slider.particle、slider.particleGlow、slider.particleIdle、slider.particleIdleGlow。

内置主题

docs/ 里有两套现成配色,每套都包含全部 24 个 token,对比度也校验过。把其中一套粘进面板的 JSON 区,按 Import,或者在控制台里应用: js // docs/theme-sunset.json — warm gold, for a dark app
localStorage.setItem('dsh-client-ui-gpt-helper:config:v1', JSON.stringify({
version: 1, hotkey: 'Ctrl+Shift+Alt+G',
colors: {
'trigger.bolt': '#f0b429', 'trigger.model': '#e8e6e3', 'trigger.level': '#ffc857',
'trigger.levelMax': '#ff8a5b', 'trigger.caret': '#9b948c', 'trigger.lockMark': '#ff6b6b',
'menu.bolt': '#f0b429', 'menu.boltLit': '#ffc857', 'menu.level': '#ffc857',
'menu.levelMax': '#ff9e64', 'menu.levelGrad': 'linear-gradient(90deg, #ffe08a, #ffb454 48%, #ff7a59)',
'menu.quota': '#ff9e64', 'menu.quotaGrad': 'linear-gradient(90deg, #ffd166, #ff7a59)',
'slider.track': '#3a332b', 'slider.fill': '#f0b429',
'slider.fillGrad': 'linear-gradient(90deg, #ffe08a 0%, #ffc857 34%, #ff9e64 68%, #ff6b6b 100%)',
'slider.thumb': '#fffaf0', 'slider.tick': '#5a5145',
'slider.tickPast': 'rgba(48,36,20,.55)', 'slider.tickCurrent': 'rgba(48,36,20,.62)',
'slider.particle': '#fff3d1', 'slider.particleGlow': 'rgba(255,214,120,.85)',
'slider.particleIdle': '#ffd8a8', 'slider.particleIdleGlow': 'rgba(255,216,168,.35)'
}
}));
location.reload();
docs/theme-neon.json 是另一个 —— 青色到品红,和自带的蓝色拉开最大距离。两者都用同一套亮度算法测量,和为什么强调色是这几个一样;刻度是你在自创配色方案时值得重新检查的 token,因为它们落在 FILL 上,而不是 popover 上:浅色刻度会消失在浅色填充里。

为什么强调色是这几个

自带的深色值和浅色值之间有六个 token 不同 —— 四个触发强调色,加上插入符和锁徽章 —— 因为触发器位于 composer 上,而 composer 在浅色主题里是浅色的。其他强调色没有主题配对,它们针对自己所在的表面调过:那个表面在两个主题里都一样,因为 popover 是叠在背后内容上的深色半透明层。所以白色文字在两边都正确,而中间调的强调色在白页面上看着还行,放到 popover 上却几乎看不见。这就是那份可读性报告:轨道和滑块接近白色,始终可读,但等级蓝色和它下面的模型名不行。

针对 popover 表面测得的对比度(WCAG 相对亮度;正文文字 4.5,大号文字和图形对象 3.0):

| token | 之前 | 之后 |
| menu.level | #4e7fe9 — 3.73 | #7fa8ff — 6.03 |
| menu.levelMax | #8b48f5 — 2.93 | #b98cff — 5.57 |
| menu.quota | #9b4dea — 3.13 | #c08cff — 5.69 |
| popover 模型名 | --dsw-alias-label-caption | #ffffff — 14.16 |
| popover 闪电(空闲) | --dsw-alias-label-secondary | #ffffff — 14.16 |

scripts/contrast.mjs 会从 lib/client.js 里的 token 表重新打印这张表,上面的数字就是这么来的,不是猜的。

实现说明

下面这些是不太直观的地方,保留下来是因为每一条都花掉了一轮调试。

粒子渐变

原型没有渐变:它交叉淡入淡出一个容器,容器里的粒子周期早已在运行,等级只改变拖尾的宽度和渐变。这里用 requestAnimationFrame 把 --spin 强度缓动到滑块节点上 —— 上升约 600 ms,下降约 900 ms,所以熄灭带有滑行的惯性 —— 它通过关键帧缩放每个粒子的峰值不透明度。稳态时 --spin 为 1,所以渲染出的不透明度和原型完全一致。

超椭圆陷阱

DSH 的主题插件在 @supports (corner-shape: superellipse(1.5)) 下注入一条通用规则,作用于 、:before 和 :after: css
:root { --dsw-corner-shape: superellipse(1.5) }
, :before, :after { corner-shape: var(--dsw-corner-shape) }

所以应用里每个圆角都是超椭圆,不是圆弧。border-radius: 50% 的圆会变成超椭圆 —— 一个圆角方形 —— 胶囊两端也会变形。主题 README 写明了规则:全圆形状必须把 corner-shape: round 和它的半径配对在所属样式表中,这就是为什么每个随 DSH 发布的组件样式表都会在圆角旁带上这一行。

这里所有全圆角半径——轨道、填充、轨迹、滑块、刻度、粒子、流光粒子、忙碌指示器和滑块焦点环——都搭配 corner-shape: round。装饰性圆角(菜单、触发器、行、备注)刻意不搭配,这样它们保留主题预期的平滑效果。

box-sizing 重置

原型开头是 * { box-sizing: border-box }。DSH 没有全局设置它——它按组件声明 box-sizing——所以没有重置时,弹出层按内容宽度计算尺寸,轨道会比原型的 236px 宽约 22px,导致每个档位位置偏移。插件把自己的重置限定在两个子树内。

被钳制的圆角半径

border-radius: 999px 会被盒子钳制。在最低档位产生的约 13px 填充上,浏览器按 width / (radius sum) 缩放每个半径,端帽变成约 6.4px 而不是 12px;方角端帽随后在顶部和底部附近超出 28px 滑块约 1.3px。因此填充和轨迹带上 min-width: 24px,端帽始终是真正的半圆。多出的宽度藏在滑块下面,不影响其他任何东西。数值验证:12.87px → 1.31px 突出,24px → 完全覆盖。

拖拽

拖拽由 window 的 pointermove/pointerup/pointercancel 监听器驱动,按活动指针 id 过滤,和原型一样,处理函数表放在 ref 里。把移动绑定到轨道上反而会在指针离开它的瞬间中断手势,还会让重渲染在拖拽中途落下过期的 dragging: false 闭包——两者叠加导致向右拖拽失效。视觉跟随指针连续更新;只有最近的档位在释放时提交。

滚动

和原型一样,弹出层不是滚动容器——它随内容增长,只受 max-height 约束——模型列表是唯一的滚动区域。这很重要:给整个主体设置 overflow-y: auto 也会把 overflow-x 计算为 auto,于是任何亚像素溢出都会在两侧长出滚动条。列表区域固定 overflow-x: hidden。

一个渐变,不是两个

这是刻意偏离。原型在第一个渐变之后为 fast-mode-off 声明了第二个顶层渐变(#3941c4 → #a987ff → #7d57eb),所以切换闪电图标的瞬间轨道会跳色。本插件两种状态都用 fast-mode 渐变,让 fast mode 只改变粒子和轨迹的不透明度。

它读取什么

从共享目录快照读取:current(provider/model/reasoningEffort)、groups([{ id, name, models: [{ id, name, reasoning }] }])、status、pending、error、retainedEffort。从 reasoning 读取:defaultEffort 和 efforts([{ id, name }])。提交是 directory.select({ provider, model, reasoningEffort? }),它通过 sessions.selectModel 转发给宿主。

开发 sh
npm run validate # or: node scripts/validate-plugin.mjs .
npm run selfcheck # or: node scripts/selfcheck.mjs
npm run contrast # or: node scripts/contrast.mjs
npm run loadcheck # or: node scripts/loadcheck.mjs

校验器是只读的,它断言客户端模块系统所依赖的契约:dsh.client 声明、exports 映射、__ModuleLoader__ 包装器、工厂 id 等于包名、CSS 模板字面量里没有多余的 backtick 或 ${,以及组件用到的每个 t('key') 在两个语言字典里都存在。

selfcheck.mjs 覆盖校验器覆盖不到的部分:颜色表、热键解析器、已发布的 overrides 和两个 store。bundle 的工厂需要浏览器、cordis 上下文和一个真实的模型目录,所以这项检查把工厂函数体从 lib/client.js 里原样切出来,对着一个小的 React 和 DOM stub 求值,然后跑真实函数、渲染真实组件。它断言的事情包括:样式表从不通过 var() 读取颜色、声明逃逸的尝试会被拒绝、按住会锁定快速模式而点击无法解锁它。

contrast.mjs 读取 token 表,打印每种颜色相对 popover 表面的 WCAG 对比度,任何一项低于 3.0 就失败。Why the accents are those accents 里的强调色就是这么选出来的。

loadcheck.mjs 按应用加载 bundle 的方式加载它——作为经典脚本调用 window.__ModuleLoader__.load,然后 factory(require),然后 apply() 和一次渲染——并报告失败的阶段。这条路径值得单独检查,因为这里失败不会留在插件里:应用会记录 web boot: 1 entry did not activate 然后重启,所以「我的改动有没有让 bundle 还能导入」这个问题要在重载页面之前回答,而不是之后。

客户端 bundle 支持热重载:DSH 的 client-HMR 轮询每个 bundle 的 mtime 并重新发布,所以编辑 lib/client.js 大约一秒内就能到达运行中的页面。改动 package.json 或挂载行需要重载页面。

构建标记,以及为什么这里崩溃不是局部问题

lib/client.js 里有 const BUILD,控件把它写到自己的根节点上作为 data-build,旁边还有一条 console.info('[gpt-helper] client half applied — build …')。原因是浏览器无法被问出它正在运行什么代码:这个控件的标记在不同版本之间无法区分,所以加载了过期模块的页面看起来和没加载的一模一样。改问页面:

document.querySelector('[data-gpt-helper="root"]')?.dataset.build

只要某个改动需要在运行中的页面里确认,就手动把 BUILD 加一。

三个陷阱,每一个都花掉了一轮调试:

- 渲染时的 ReferenceError 会让整个 web boot 失败。 多出来的一个元素引用了工厂里别处定义的常量在 ModelEffortControl 内部抛了错,应用随即在 %APPDATA%\@deepseek-ai\dsh-desktop\logs\crash-*-web-boot.log 里报告 web boot: 1 entry did not activate,然后重启。这个 slot 条目没有自己的错误边界:它「大声失败」的方式,是把整个启动一起带走。渲染路径里新增的任何东西,都要定义在同一作用域里,或者从外面传进来。
- HMR 会在活着的组件树下换掉模块。 换的过程中,可能还会多跑一次渲染,用的却是即将退场的模块,所以一次控制台输出里会同时出现 ReferenceError 和新构建的 applied 日志行。看最后一行,并且在相信任何一行之前先硬刷新(Ctrl+Shift+R)。
- 渲染器控制台一片空白的崩溃日志,通常是编辑器的问题,不是应用的问题。 连续多次保存 lib/client.js,HMR 轮询就可能读到写了一半的文件;随后 import 失败,什么也报不出来,日志就留在了那里。查这种日志之前,先拿它的时间戳和文件的 mtime 对一下,再跑 npm run loadcheck:如果当前文件能加载,这条日志就是化石。真正区分真故障的,是 data-build 和日志自身的错误级别。

对在这上面做东西的人来说,结论是:加标记时优先用 data- 属性,别新增节点;每次编辑后都看一眼控制台,别默认重载是干净的。

仓库结构

lib/index.js host half — an empty apply(), mirroring shipped client-only packages lib/client.js browser half — styles, locale dictionaries, and the control cordis.patch.yml the bundle layer: the row that mounts the plugin scripts/validate-plugin.mjs structural validator (see Development) scripts/selfcheck.mjs behavioural check for the colours, the hotkey and the fast lock scripts/contrast.mjs WCAG contrast of the shipped palette on the popover surface docs/chatgpt-pc-ui-prototype.html the original design prototype

注意事项

- 这是对 DSH 拥有的某个 slot 做的 UI 替换,靠优先级抢占。DSH 未来的版本可能改动这个 slot 的 props,或者改动自带控件的优先级,那样的话这里的选择器和注册逻辑都得重新看。插件选择大声失败,而不是悄悄失败:slot 条目一旦坏掉,会报 slot entry crashed in 'conversation.input.model'。
- 快速模式只是外观:DSH 没有快速模式这个概念,所以这个开关和它的锁定除了动画之外什么都不改。锁定持久化的是开关,不是任何请求行为。
- 颜色设置存在 localStorage 里,属于浏览器配置档,而不是 DSH 配置档。第二个窗口能看到,第二台机器看不到;要搬走就用 Copy config JSON。

License

MIT
预览分享卡片长什么样 ↓AprilCrystal/dsh-client-ui-gpt-helper
分享 · DeepSeek Harness Hub
AprilCrystal/dsh-client-ui-gpt-helper

一个 DeepSeek Harness 客户端浏览器插件,把 Web 编写器的模型席位替换成 ChatGPT…

这是你的仓库?认领条目

回到顶部