dsh-codex-effort
把 DSH 输入框里的推理强度菜单换成 Codex 桌面应用(Codex.app)工作模型选择器的「强度」区: 大字档位 + 模型名 + 一条蓝→紫渐变的粗胶囊进度条(白色大圆钮,可拖), 左侧彩色闪电(快速模式 ×2)、右侧 ↻ 重置;滑到 max 时那两行被**紫色 shimmer 大字「更快消耗使用额度」**替换(只闪 1.1 秒)。
这是一个 DeepSeek Harness(DSH)插件。 装上之后,composer 右下角那个「模型 · 推理等级」控件(点开是「模型 / 推理等级」两级菜单) 会变成 Codex 那一套(布局照你录屏里 Codex 的真实样子):
收起态 ⚡ GPT-6 Astra 风格:⚡ DeepSeek Flash 极高 ⌄ ← 闪电在最前,档位在最后,顶档时档位字变紫
展开态 ┌──────────────────────────────────────────┐
│ ⚡ 极高 › ↻ │ ← 大字档位(蓝;顶档变紫)+ ›;左闪电、右重置
│ DeepSeek Flash │ ← 模型名(灰、小字、居中)
│ ▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰◯▱▱▱▱▱▱▱▱▱▱▱▱ │ ← 粗胶囊进度条:蓝→紫渐变 + 白色大圆钮
│ 选择强度 │ ← 底行(左);右侧放快速模式提示 / ×2
└──────────────────────────────────────────┘
顶档(1.1 秒):大字那两行被 更快消耗使用额度(紫色 shimmer)替换,进度条不动
点闪电:闪电变彩色 + 底行弹出 ×2(1 秒后淡出),并**不改强度**
每一项都是从 Codex 自己的代码里抄的
取证对象:本机已安装的 Codex 应用 C:\Program Files\WindowsApps\OpenAI.Codex_26.930.2377.0_x64__2p2nqsd0c76g0\app\resources\app.asar
(界面在 webview/assets/app-primary-*.js 与 app-primary-*.css 里);
布局另外对着你那段屏幕录制(Videos\屏幕录制\屏幕录制 2026-10-03 223918.mp4)逐帧核过。
逐条对照见 docs/COPY-SOURCES.md。
| Codex 里的东西 | Codex 的原值 | 本插件 |
|---|---|---|
composer.modelPicker.selectEffort.label |
选择强度 | 底行左侧的说明 |
composer.modelPicker.workPower.keyboardControl.value |
{value},第 {position} 项,共 {total} 项。 |
视觉隐藏播报 + aria-valuetext |
composer.modelPicker.power.ultraUsageWarning |
更快消耗使用额度 | 顶档时替换大字档位那两行 |
._UltraUsageWarningText_ |
紫色 shimmer:linear-gradient(100deg, purple 42%, …58%) + background-size:300% 100% + background-clip:text |
同一套渐变配方(#924ff7 / #ad7bf9) |
@keyframes _UltraUsageWarningShimmer_ |
0%{background-position:100% 0} to{background-position:0 0},animation:**1.1s ease-out**(只播一次) |
同样 1.1 秒、只播一次,到点自动换回档位名 |
._ViewControls_[data-ultra-warning-visible=true] |
警告可见时把强度切换/闪电/重置 visibility:hidden,警告层 opacity:1(position:absolute;inset:0) |
同样:警告期间那两行藏起来,警告层独占 |
._FastModeToggle_ |
快速模式(Codex 原话:"the lightning-bolt Fast mode toggle"),开启时 color: var(--color-chart-blue) |
强度区左侧的闪电,开启时整体变彩色(chart 蓝→紫→粉) |
composer.intelligencePicker.fastMode.* |
快速 / {n} 倍速 / 用量更多 / {n} 倍速度,用量更多 |
闪电 tooltip 与底行提示(倍率取 2) |
LightningBoltFill-*.js |
闪电 SVG 路径(24×24, fill=currentColor) | 逐字节抄进 BOLT_PATH,开启时切成 SVG 渐变填充 |
--color-chart-blue / --color-chart-purple |
#339cff / #924ff7(浅)#ad7bf9(深) |
进度条、档位文字、顶档紫色 |
._ViewToggleEffortLabel_[data-maximum=true] / ._ModelPickerTriggerEffortText_[data-max-effort=true] |
顶档时文字变紫 | 顶档时大字与收起态档位字都变紫 |
| 进度条外观(录屏帧) | 粗胶囊、蓝→紫渐变、白色大圆钮(≈14px 高、≈26px 钮) | 同款:整条渐变 + 右侧未填充遮罩 + 白钮 |
你上一条提的五点,逐条改了什么
| 你说的 | 现在的实现 |
|---|---|
| "变成手动选择按下了,不是滑块进度条" | 换回真滑条:轨道 + 进度填充 + 旋钮,按住就能拖、点哪跳哪、←→/Home/End 都行;刻度只是刻度(点了当然也能跳档) |
| "没有那个彩色的动效了" | 闪电开启时是彩色渐变;顶档时进度条与档位字变紫并叠光晕;警告是 Codex 那套紫色流动 shimmer |
| "快速使用额度持续那么久干啥,一秒就行" | 顶档警告按录屏实测改成停留 ≈2 秒(见下条),到点自动换回档位名;再次滑到顶档会重新弹一次 |
| "乘二也是一秒就行" | ×2 标志弹出后 1 秒开始淡出,0.35 秒淡完就消失;快速模式本身仍然是开着的(由彩色闪电表达) |
| "闪电变成彩色" | 闪电开着时换成 SVG 渐变填充(#339cff → #924ff7 → #ff66ad,即 Codex 的 chart 蓝/紫 + 粉),断电时保持灰色描边 |
| 发录屏要求"照着仿" | 逐帧核对了录屏:改成「大字档位 + 下面模型名」两行、粗胶囊渐变进度条 + 白色大圆钮、闪电在最左、↻ 在最右、底行「选择强度」、去掉了刻度与多余标题,进度按档位位置填充 |
| "那个加快使用额度呢?" | 它在(就是「更快消耗使用额度」)。我重新抽帧量了它的时长:6.2s 还在、7.4s 还在、8.2s 已消失 ⇒ 实际停留 ≈2 秒,已从 1.1 秒改成 2.2 秒;并且按录屏警告期间把 ⚡ 和 ↻ 一起藏起来(那两帧里这两个图标确实都不见了) |
| "进度条太僵硬 / 滑太快加载不出来" | 两处真 bug 一起修了:① 拖动改成直接写 DOM(旋钮/遮罩不再等 React 重渲染)+ 去掉拖动缓动、圆钮放大、条子提亮;② 提交丢单——以前用 state 记拖拽下标,按下就松(或滑太快)时闭包里的下标还是 null,onPointerUp 直接 return,那次滑动就白滑了;现在用 useRef 同步记,并且在外面松手也会提交(window 级兜底 + 指针捕获)。另外加了乐观显示:提交后界面立刻切到目标档,不再等宿主(宿主慢也不会"看着像没生效") |
| "加速使用额度没法正常显示" | 真原因找到了:警告的触发条件原来挂在拖动预览上,一边拖就把计时器跑掉了,松手时早就过期 ⇒ 看起来就是"根本不显示"。现在挂在已提交的档位上:松手 → 提交 → 立刻弹;文字加了实色紫打底(background-clip:text 不支持也不会变透明) |
| "你怎么直接给他删了"(指警告看不到) | 顺手把"限时"改成常驻:只要你停在最高档,它就一直在(Codex 的 CSS 也是 max 期间 opacity:1),shimmer 只在刚滑到顶档那一下播一次;离开顶档立刻收起。这样不可能再被错过。文案就是 Codex 的原文「更快消耗使用额度」 |
| "白色应该变成圆圈 / 进度条更粗一点" | 按录屏帧量了比例(用 16px 的「Ultra」当标尺:条子≈25px、钮≈30px),现在把进度条从 14px 加到 20px、白色圆钮 30px 正圆(aspect-ratio:1/1 + border-radius:999px,外面还有一圈极淡的描边与投影),两侧各留半个钮的余量所以贴边也不会被裁 |
| "在加快使用额度时是不可以选择模型的" | 警告原来盖住了「档位大字 + 模型名」两行;现在只盖档位大字那一行,模型名保持可见可点,警告期间照样点它打开模型列表(测试里专门有一条守着) |
| "右下角的小字应该移除" | 底行右侧常驻的「2 倍速度,用量更多」已删除;底行只剩左边 Codex 原样的「选择强度」,×2 只在点闪电时弹 1 秒(靠 margin-left:auto 靠右) |
| 进度条两处手感 | 条子 20px、圆钮 30px 正圆(见上行);拖动中圆钮放大 1.1 倍、条子提亮 |
对照:录屏里 Codex 的真实样子
这两张是从你那段录屏里抽出来的帧(_vid\extract-frames.ps1 抽帧、_vid\sample-colors.py 取色):
![]() |
![]() |
正常态:大字 Ultra ›(紫)+ 模型名 + 蓝→紫渐变粗胶囊 + 白钮;左 ⚡、右 ↻、底行 Select effort |
顶档:那两行被「更快消耗使用额度」替换(进度条不动),⚡ 与 ↻ 同时隐藏,≈2 秒后换回 |
本插件的 6 张静态预览在 preview/index.html(真实组件 + 真实 CSS 渲染出来的)。
发布到 GitHub
仓库已经初始化好(本地已有提交),只差把它推上去:
# 1) 先在网页上建一个**空仓库**(不要勾 README / .gitignore / license):
# https://github.com/new 名字建议 dsh-codex-effort
# 2) 在本目录执行(首次推送会弹浏览器让你登录 GitHub,授权一次即可):
.\publish.ps1 -User 你的GitHub用户名
publish.ps1 会替你做完这些:填掉 package.json / README.md 里的 49zr664rb8-hue、
设置本仓库 git 身份并把提交作者改成你、分支改 main、接上 origin、推送。
不想用脚本就手敲这几条:
git config user.name "你的名字"
git config user.email "你的GitHub邮箱"
git commit --amend --reset-author --no-edit # 把作者改成你
git branch -M main
git remote add origin https://github.com/你的用户名/dsh-codex-effort.git
git push -u origin main
推送要密码时不能用账号密码(GitHub 已停用)。两条路: ① 让弹出的 Git Credential Manager 走浏览器授权(最省事); ② 自己建一个 Personal Access Token(Settings → Developer settings → Tokens (classic),勾
repo), 密码处粘贴 token。 也可以用 GitHub CLI:winget install GitHub.cli然后gh auth login, 再gh repo create dsh-codex-effort --public --source=. --push(连仓库都不用先在网页建)。
安装
插件目录里没有任何需要构建的产物,拷进去就能用(client.js 是自包含的浏览器 bundle)。
从 GitHub 装(推荐):
git clone https://github.com/49zr664rb8-hue/dsh-codex-effort.git
cd dsh-codex-effort
.\install.ps1 # 装进 desktop profile
本地开发(改了代码立刻生效):
.\install.ps1 -InPlace # 直接链接源目录,改 client.js 即热更新
.\install.ps1 -Uninstall # 卸载(只删 junction 与登记,不碰插件目录)
跑测试 / 看预览(不需要 DSH 在跑):
node test/smoke.test.mjs # 223 项离线检查(含真实计时器断言)
node preview/make-preview.mjs
start preview/index.html # 6 个状态的静态预览页
install.ps1存成 UTF-8 with BOM:Windows PowerShell 5.1 读无 BOM 的 UTF-8 会把中文注释读成乱码并报语法错误。
三个登记项(与 dsh plugin add 等价,但不跑 pnpm、不动 lockfile):
profiles/<profile>/node_modules/dsh-codex-effort→ 指向插件目录的 junction;package.json的dependencies加"dsh-codex-effort": "link:<插件目录>";package.json的dsh.profile.bundles末尾加"dsh-codex-effort",同时在 profile 的cordis.patch.yml里加一条id: codex-effort / disabled: false。
装完不用重启、不用刷新:profile 开着 HMR,dsh-hmr 看到 patch 层与 dsh.profile.bundles
变化后重新组合,新增的客户端 bundle 通过 /plugins/events 的 graph 帧推给已打开的页面,
页面自己 import 新条目。换代码由客户端 HMR 的产物轮询接管,同样不用刷新。
实测记录(这份插件是怎么验的)
| 验的东西 | 手段 | 结果 |
|---|---|---|
| 渲染结果与交互 | node test/smoke.test.mjs:用极小 React 真实渲染组件树,断言 DOM 属性与计时行为 |
172 项全绿 |
| 端到端一致 | 用伪造的会话 cookie 从运行中的宿主抓下浏览器实际收到的 bundle,再拿这份字节跑同一套测试 | 172 项全绿 |
| 计时是否真的只有 1 秒 | 测试里真等 1.1s / 1.3s,断言警告自动 data-show="0"、×2 进入淡出再消失 |
见上 |
| 宿主是否真的加载 | /plugins/events 启动图里有 dsh-codex-effort |
72 条,bundle 200 text/javascript,rev 648e0ebacdc5 |
| 肉眼验收 | ❌ 没做成:本机沙箱里所有 Chromium 引擎都起不来(mojo\...\platform_channel.cc Check failed: 拒绝访问 (0x5)) |
请用 preview/index.html(6 个状态,真实组件 + 真实 CSS) |
踩到的坑(写给下一个改这个插件的人)
apply(ctx)没有第二个参数。宿主调用客户端插件时只给 cordis 上下文,React 必须由 bundle 自己在工厂里require('react')。最初把 React 写成apply(ctx, runtime)的第二个参数, 本地测试因为显式传了 runtime 而全绿,真机上却根本不挂载。现在的取法有三条路:require('react')→window.React→ 从已有 DOM 的 fiber 上借。- PowerShell 5.1 会写 BOM。
Set-Content -Encoding utf8写出来的package.json带 BOM, Node 的JSON.parse会直接抛。安装脚本因此改用无 BOM 的UTF8Encoding($false)。 (顺带:$PSScriptRoot在参数默认值求值时还没就绪,5.1 上必须放到脚本体里取。) - Codex 的"强度控件"不是分段按钮:它是
ViewControls里一个键盘/拖拽调整的标签 (左闪电、右重置、警告层铺满),.cxe-slider那种进度条外观是按需求做的增强, 不是 Codex 的原样 —— 颜色、文案、时长、警告行为才是原样。
它是怎么接管那个控件的
DSH 的 composer 模型位是一个 single 槽位(conversation.input.model,由 ui-conversation 声明、
ui-model-selection 注册)。槽位规则:同一个 single 槽位在不同优先级上可以共存,优先级最低的那个渲染。
所以本插件用 priority: -1000 注册进同一个槽位,就遮蔽了内置的模型控件:
- 不修改 DSH 任何内置代码;本插件卸载/禁用/加载失败时,内置控件自动回来;
- 内置的
/model弹窗命令完全没有被动到; - 外层包了错误边界:渲染连续三次抛错时插件主动注销自己把槽位还给内置控件(前两次先重试)。
数据、隐私与状态
- 零网络请求、零遥测、零宿主文件写入;宿主半边只有一行启动日志。
- 强度不是本插件存的状态:它由 DSH 自己的模型目录持有(
ctx.modelDirectories)。 - 本插件只在
localStorage里记每个会话的快速模式开关(dsh-codex-effort:v1)。
⚠️ 一句诚实的话:DSH 的模型目录里没有 Codex 那种服务层级(已核对:DSH 侧没有
service_tier/速度层级), 所以闪电开关在 DSH 里是纯界面状态,不会改变发给模型的请求。它复刻的是 Codex 的外观与语义提示。
文件
package.json 包身份 + dsh.bundle.patch + dsh.client(platform: web, immediately)
cordis.patch.yml 作为组合包被选中时插入宿主条目(id: codex-effort)
index.mjs 宿主半边:存在即可(让 dsh.client 进启动图),不抛错、不依赖服务
client.js 浏览器半边:滑条 / 彩色闪电 / 顶档 2 秒警告 + 错误边界(自包含,无构建)
test/mini-react.mjs 极小 React 运行时(createElement/hooks/uSES + HTML 序列化)
test/smoke.test.mjs 223 项离线检查(含真实计时器的 1 秒 / 2 秒行为)
test/fetch-served.mjs 从运行中的宿主抓"浏览器实际收到的那份"再跑同一套测试
preview/ 预览页生成器 + 结构校验 + 6 个状态的生成结果
install.ps1 安装/卸载脚本(junction + profile 三处登记)
docs/COPY-SOURCES.md 文案、颜色、图形、动画时长的逐条出处 + 踩过的坑
docs/images/ 从录屏抽的 Codex 参考帧(已裁掉任务栏等个人桌面内容)
已知限制
- 只在
conversation.input.model这个槽位上工作:DSH 若改了槽位名或模型目录的 API 形状, 控件会渲染失败 → 错误边界把槽位还给内置控件(不会白屏,但也不会自动适配)。 - 闪电是界面状态(见上文的诚实声明)。倍率写死在
client.js顶部的SPEED_MULTIPLIER = 2。 - 档位数取决于模型自己:档位名与档数一律取自 DSH 模型目录,不硬编码。例如 DeepSeek 的
thinkingLevelMap只开放low / high / max3 档,进度条就只有 3 个落点。 - 顶档警告是"短暂弹出":只有档位变成最高的那一次才弹 2 秒;已经在最高档时碰滑杆不弹。
改
client.js顶部的WARN_VISIBLE_MS/WARN_STICKY可调。 - 浅色/深色都适配(用 DSH 主题变量 + Codex 的 chart 色,且不依赖自定义属性,见 COPY-SOURCES 的踩坑表)。
- 动效遵循
prefers-reduced-motion。
许可与出处
本插件代码为原创(MIT)。借用的只有 Codex 的界面文案、配色数值、一个 SVG 路径与 一个动画时长(Apache-2.0),逐条对照见 docs/COPY-SOURCES.md。


No comments yet. Be the first to write one.