DeepSeek Harness Hub
← 返回列表

空白会话主视觉皮肤ml020/dsh-workbuddy

DeepSeek Harnessspec-screened在 GitHub 查看 ↗
未验证

用 Wordless 风格重绘品牌磁贴与工作区选择菜单

尚未跑自动兼容性验证,可查看页面内的依赖与入口分析。 · 最近上游提交 2026/8/31 · 已提供中文文档

DSH 的无文字风格 WorkBuddy 主视觉:替换空白会话品牌标识和工作区选择器,同时保留原生编辑器。

综合分
28.3
GitHub 分
28.3
用户评分
★ Stars
0
周下载量
安装插件(需先安装 dsh CLI 引擎:npm install -g @deepseek-ai/dsh)
dsh plugin --profile web add ml020/dsh-workbuddy
该插件未发布到 npm,走 GitHub 源安装(pnpm 若拦截 prepare 脚本,按其提示在 pnpm-workspace.yaml 的 allowBuilds 中放行后重跑)
数据截至 2026/9/16(元数据每日更新 · 实装验证按队列轮转,单条结论的验证时间见上方)
依赖的 DSH / Cordis 模块
@deepseek-ai/cordis@deepseek-ai/dsh-client-locale@deepseek-ai/dsh-client-ui-conversation@deepseek-ai/dsh-client-ui-renderer@deepseek-ai/dsh-client-ui-slots@deepseek-ai/dsh-invariants
用户评分
还没有人投票,来当第一个
订阅周报,不错过优质插件更新
每周一封 · 高评分插件 + 新用户活动

README

dsh-workbuddy

为 DeepSeek Harness(dsh)的空白会话主视觉提供 Wordless 风格皮肤。

以 Wordless 温暖、极简的外观,重新设计两个主视觉槽位——品牌磁贴和工作区选择器菜单。原生 dsh Web 编辑器(对话框)和原生选择器标签绝不触碰。

它改变了什么

| 槽位 | 类型 | 你将获得 |
| --- | --- | --- |
| conversation.hero.brand.mark | single | 带 WorkBuddy W 的青柠渐变磁贴 |
| conversation.hero.workspace | single | Wordless 风格菜单,锚定到宿主的标签 |
| ↳ conversation.hero.workspace.directoryFlow | single | 此条目声明的子孔位,因此目录选择器仍可正常工作 |
| conversation.composer.bar | — | 未触碰——原始 dsh 对话框保持不变 |

两个目标槽位都是 kind: 'single',因此插件使用 ctx.slots.inject 取代随附的占用者,而不是在其旁边添加。每个槽位独立注入——inject 会等待其槽位被声明,因此链式调用会将工作区占用者与品牌磁贴槽位的生命周期耦合在一起。

选择器槽位如何工作

conversation.hero.workspace 不是欢迎面板。宿主(ConversationRoot)自行渲染触发标签并拥有打开状态;槽位占用者只是菜单主体,它接收:

| Prop | 含义 |
| --- | --- |
| open | 选择器是否展开——关闭时占用者渲染 null |
| anchorRef | 指向宿主触发标签的 ref,用于定位菜单 |
| selectedId | 当前活动的工作区(渲染时带尾部对勾) |
| onPick | 选择一个工作区;宿主连接或复用其空白会话 |
| onClose | 关闭——绑定到 Esc 以及任何外部按压 |

菜单是 position: fixed 并根据锚点矩形测量,因此它摆脱了主视觉的 overflow: hidden auto 滚动主体;当标签下方没有空间时,它会翻转到上方。

| 按键 | 行为 |
| --- | --- |
| ↑ / ↓ | 移动光标,在两端循环 |
| Home / End | 跳到第一行 / 最后一行 |
| Enter / Space | 提交光标所在行 |
| Esc | 关闭,并将焦点交还给宿主的标签 |
| Tab / Shift+Tab | 关闭并交还焦点,而不是让打开的菜单停留在通过 Tab 进入的任何内容后面 |
| 任何可打印字符 | 类型提前——跳到名称以该字符开头的下一行;再次按下可在共享该首字母的行之间循环 |

键盘路径依赖的三个细节,每个更简单的实现都会弄错:
- 焦点落在光标所在行,而不是菜单容器上。 从第 0 行开始的光标必须已经拥有焦点,否则第一次按 ↓ 会跳到第 1 行,列表顶部就被悄悄跳过了。
- 光标在宿主报告的选中项上打开,因此操作员在移动之前就能看到自己所在的位置——并且在读取时会被钳制,这样即使刷新把行从它下面移除,仍然会有一行带有 tabindex=0。如果不钳制,菜单会继续渲染,却悄悄失去键盘可导航性。
- 待处理的快照显示为加载中,而不是空。 在工作区列表到达之前,“还没有工作区”是一个错误答案的闪现。

添加工作区仍然有效

宿主的 renderSlot 调用不携带创建回调,因此只渲染列表的换肤会悄悄丢掉主区域的“添加工作区……”操作。本条目避免这一点的方式与已发布的选取器相同——由它自己补上缺失的那一半:

- 它声明了一个 conversation.hero.workspace.directoryFlow 子孔位,任何组合的目录选取器包都会像为原生选取器那样填充它;
- 它把 createWorkspace(直接来自 workspaces 服务)注入到自身;
- 添加行依赖该孔位的占用状态,因此它会随着目录选取器的加载和卸载而出现和消失。

采用选中的目录一次只进行一次交互:当流程打开或路径正在被采用时,每一行都被禁用。被拒绝的 createWorkspace 会在可重试对话框中显示,而不是消失;而在交互中途卸载的占用者会撤回流程,使各行恢复。

那个对话框是一个真正的模态框:它把 Tab 困在自身内部(正如 aria-modal 所承诺的,而不只是声明),在 Esc 时关闭,并在被关闭时把焦点交还给宿主的 chip——除了重试时,此时选取流程会接管焦点,两者不会争夺同一个按键。

主区域没有为欢迎标题或入口 chip 暴露任何槽位——hero.headline 是宿主中的硬编码文案,不是槽位。因此,Wordless 风格的欢迎面板没有地方可放,除非与宿主布局冲突;这个插件只是对 dsh 实际提供的内容进行换肤。

安装

dsh plugin add ml020/dsh-workbuddy

设计

令牌位于 src/client/styles/tokens.module.css,作用域在 .root 下,带有 --wb- 前缀,因此它们永远不会与 dsh 自己的 --dsw- 主题变量冲突。浅色和深色遵循 prefers-color-scheme。

| 令牌 | 浅色 | 深色 |
| --- | --- | --- |
| 工作区 | #fbfbfa | #151610 |
| 侧边栏 | #f1f1ee | #202219 |
| 强调色 | #ccf257 | #bfe650 |
| 选中行背景 | #eef4dc | #303a1c |

UI 字体是 Manrope,工作区路径字体是 DM Mono。

布局

src/
index.ts              host loader (no-op, browser-only plugin)
invariant.ts          package-owned invariant companion
client/
index.ts            slot registration + directory-flow occupancy source
BrandMark.tsx       conversation.hero.brand.mark
WorkspaceMenu.tsx   conversation.hero.workspace(以及添加流程)
locales.ts          zh / en 词典(命名空间 workbuddy)
icons.tsx           内联 SVG
styles/             CSS Modules + 设计令牌
scripts/
check-bundle.mjs      断言 lib/ 仍符合 dsh 打包契约
tests/
browser-plugin.client.spec.tsx
invariant.client.spec.ts
mock-slots.ts         插槽注册表和框架 prop 的替身
setup.ts              jsdom 未实现的布局 API

开发

npm install
npm run typecheck     # tsc --noEmit(无错误)
npm run test          # vitest run
npm run lint          # oxlint
npm run build         # lib/index.js · lib/invariant.js · lib/client.js
npm run verify        # 以上全部,外加打包契约

dsh UI 客户端包是 __ModuleLoader__ 打包产物,只能在 dsh Web 宿主内运行,因此浏览器测试用例使用 tests/mock-slots.ts 中的替身来测试插件,而不是直接导入它们。

截图

docs/.png 是从真实组件拍摄的,而非绘制。preview/ 使用 Vite 将 BrandMark 和 WorkspaceMenu 挂载到与宿主一致的 dsh 外壳中,Playwright 以 2× 在浅色、深色和选中状态下拍摄。

cd preview
npm install
npx playwright install chromium   # 每台机器一次
npm run shoot

测试框架处理的一个细节:菜单打开时会聚焦其光标所在行,而在没有先前输入的情况下,浏览器会将这种脚本化聚焦视为键盘*聚焦,并在截图中绘制 :focus-visible。测试框架在捕获前会取消聚焦,因此预览展示的是点击该 chip 时实际的样子。

npm run check:bundle 之所以存在,是因为 tsc、vitest 或 oxlint 都不会检查 lib/,而失败模式是静默的。宿主将客户端部分作为 CommonJS 闭包工厂加载,带有特定的 banner 和 footer,并通过自己的模块表解析每个跨插件导入:去掉 footer,或让打包器内联 React,包仍然能构建、仍然能通过所有测试,却会在无人关注的浏览器控制台中于加载时抛出错误。这些检查在真实构建后针对产物进行断言,CI 也以相同方式运行它们。

许可证

MIT

上游仓库有新提交时邮件通知你(每天最多一封,无更新不打扰),随时一键退订。

💬 加入 DPharness 群聊

插件用法、部署报错、新插件第一时间同步——群里问,比一个人翻文档快。

点击加入 QQ 群
DPharness 群聊二维码,手机 QQ 扫码进群
扫码进群