DeepSeek Harness 插件

dsh-hotkeys-platform

DSH web plugin: 快捷键设定平台 —— ctx.hotkeys 注册表服务,插件注册动作、统一配置快捷键(英文原文)

跳到安装方式

来源信息

GitHub 仓库
whitewatercn/dsh-hotkeys-platform
最近更新
2026年8月20日
分类
工具与能力
GitHub stars
0
载体类型
plugin
目录证据
上游声明已找到 dsh.bundle
证据路径
package.json#dsh.bundle
核对版本
0.1.0-rc.8
上游核对日期
2026-08-20

该证据由上游目录提供。本站没有安装、运行或安全审核这个插件。

安装

默认先复制一段 Prompt,让 Agent 读 GitHub 仓库和源码;需要自己装时再切到命令。

复制这段 Prompt,发给 DSH、Codex 或其他 Agent,让它先读 GitHub 仓库和源码。

请先不要安装或执行任何命令。阅读这个插件的 GitHub 仓库、README 和关键源码,然后用清楚、直接的方式回答以下问题,帮助我判断它是否适合我的需求:

1. 这个插件是什么,解决什么问题;
2. 适合哪些用户和典型使用场景;
3. 安装后如何使用,并给出一个最小使用示例;
4. 有哪些已知限制,以及隐私、安全、兼容性或维护风险;
5. 给出“推荐 / 有条件推荐 / 不推荐”的明确建议和理由。

请区分仓库明确说明、根据源码推断和未知信息。证据不足时请明确说明,不要猜测或照抄 README。

GitHub:https://github.com/whitewatercn/dsh-hotkeys-platform
插件名:dsh-hotkeys-platform
作者:whitewatercn

检查来源文件

安装前先看这个插件目录里的 README 和其他文件。

文件资源管理器3 个文件
README.md来源说明 · 只读预览

正在开发中,还不能使用

dsh-hotkeys-platform

DeepSeek Harness(DSH)Web 插件:快捷键设定平台。

把「每个插件各自拦截键盘、各写各的设置」升级为一个注册表服务 ctx.hotkeys

  • 任何插件通过 ctx.hotkeys.registerAction(...) 注册「动作 → 处理器」;
  • 动作的默认键、触发范围(scope)、描述由插件声明;
  • 用户的显式改键统一持久化在平台;
  • 设置页(DSH 设置 → 快捷键)与 /hotkeys 命令提供统一配置。

架构与 dsh-better-sidebar 同构:平台 ctx.provide('hotkeys', service),业务动作由消费插件注册(吃狗粮),能力对等。

---

使用示例:[docs/example.md](./docs/example.md)

快速开始(消费插件)

export const inject = ['hotkeys']

export function apply(ctx: Context): void {
  ctx.effect(() =>
    ctx.hotkeys.registerAction({
      id: 'my-plugin:send-message',
      title: () => t('发送'),
      description: '发送当前消息',
      group: '消息',
      scope: 'input',
      defaultKey: 'Control+Enter',
      handler: (event, h) => {
        // 命中后的处理;返回 false 表示「不消费,放行给 DSH 原生行为」。
        h.dispatchEnter(h.target ?? event.target)
      },
    })
  )
}

要点:

  • inject = ['hotkeys'] 让 Cordis 在平台就绪后才激活你的插件(ctx.hotkeys 恒存在);
  • registerAction 返回 disposer,必须包在 ctx.effect(...) 里(HMR-safe);
  • id 建议包前缀(my-plugin:xxx),避免冲突。

---

关键点说明

说明
ctx.get('hotkeys') + 判空平台是可选项,读不到就跳过;不要用 inject 之外的 ctx.hotkeys 直接访问
ctx.effect 包裹registerAction 返回 disposer,fiber 卸载(HMR/禁用)时自动撤销注册,否则下次激活抛 already registered
id 用包前缀dsh-better-archive:open-archived,避免与别的插件冲突
scope: 'global'任意处可触发;若动作只在输入框有意义,改 scope: 'input';提问卡内用 question-card;精确判定用 custom + target(el)
handler 返回 false表示「不消费这次按键,放行给 DSH 原生/后续动作」——例如你想让某键只在特定条件下生效,条件不满足时 return false

需要 host 能力的动作

如果某个快捷键动作要触发 host 侧能力(读写文件、执行命令、归档会话等),平台不承载这些逻辑——由你的插件自带 host 路由,handler 里 fetch 即可。例如 better-archive 的「清空全部归档」动作可以这样写:

handler: async () => {
  await fetch('/archived/delete-all', {
    method: 'POST',
    headers: { 'content-type': 'application/json' },
    body: JSON.stringify({ confirm: true }),
  })
}

> 这正是平台「host 仅可选扩展」的设计:host 半只留一个可选的 hotkeys 设置命名空间,业务 host 能力一律由各插件自己的 /路由 提供。

验证

1. 重启 dsh web(peer 依赖新增需重启),浏览器强刷; 2. 打开「设置 → 快捷键」,应看到「归档」分组下出现「打开已归档」动作,当前键显示 Ctrl+Shift+A; 3. 在任意界面按下 Ctrl+Shift+A,应跳转到「已归档」设置页; 4. 点「录制」把键改成别的组合键,或点「禁用」整体关闭。

---

动作描述符

| 字段 | 说明 | |---|---| | id | 唯一 id,建议包前缀 | | title | 标题(字符串或 () => string,i18n 友好) | | description | 描述,显示在设置页 | | group | 分组(设置页分区展示) | | defaultKey | 默认组合键,如 'Control+Enter';空串 = 默认不绑 | | scope | global / input / question-card / command-palette / custom | | target | scope='custom' 时的精确判定 (el) => boolean | | handler | (event, ctx) => void | false;返回 false 表示不消费、放行 | | hidden | 设置页隐藏(默认 false) | | order | 排序(升序,默认 100) |

内置 scope

scope判定
global任意处
input可编辑文本区(textarea / input[type=text])
question-cardDeepSeek 提问卡([data-question-key])内
command-palette命令菜单/下拉打开时
custom自定义 target(el) 判定

Handler 上下文 ctxtarget(事件目标)、dispatchEnter(el)(合成裸 Enter,防重入)、insertTextAtCaret(el, text)hasOpenOverlay()isEditableTarget(el)

---

服务 API

interface HotkeyService {
  registerAction(d: HotkeyActionDescriptor): () => void
  getActions(): readonly HotkeyActionDescriptor[]
  getBindings(): Readonly<Record<string, string>>   // 只存用户改过的
  effectiveKey(actionId: string): string | null     // 用户绑定 ?? 默认 ?? null(禁用)
  setBinding(actionId: string, combo: string): void // combo='' 表示显式禁用
  clearBinding(actionId: string): void              // 删除绑定,回落 defaultKey
  record(actionId: string): Promise<string | null>  // 录制
  subscribe(listener: () => void): () => void
  readonly features: readonly string[]              // 'record' | 'subscribe' | 'effectiveKey' | 'clearBinding'
  readonly version: string
}

---

持久化与语义

  • localStorage 键 dsh.hotkeys.v1,只存用户显式改过的 { actionId: combo }
  • 三态:未出现(回落 defaultKey)/ 具体串(用户绑定)/ ''(显式禁用,连默认也关掉);
  • 迁移:首次启动自动从旧 dsh-hotkeysdsh.sendkeys.v1 迁非默认绑定(保留旧键)。

---

安装

dsh plugin --profile web add dsh-hotkeys-platform
# 或本地开发
dsh plugin --profile web add link:<本仓库路径>

重启 dsh web(host 改动需重启;client 改动浏览器强刷)。

---

如何配置快捷键(用户教程)

入口一:设置页(推荐)

1. 打开 DSH 设置(左下角齿轮图标)。 2. 左侧导航选择「快捷键」分区。 3. 页面按分组列出所有插件注册的动作,每个动作显示标题、描述、动作 id 与当前生效键。 4. 配置操作(可视化点选 + 键盘录制,两条路写同一份绑定): - 编辑(可视化):点动作右侧「编辑」展开组合键编辑器—— - 修饰键:勾选 Ctrl / ⌘/Win / Alt/⌥ / Shift(多选); - 主键:下拉选常用键(Enter、Space、Tab、Esc、方向键、F1-F12…),或直接输入任意键名; - 预览实时显示拼出的组合键,点「保存」生效,「清除」回到默认键; - 好处:能配「浏览器保留键」(如 Cmd+WCtrl+T 录不到但可手工拼)、能精确微调单个修饰键。 - 录制(快捷):点「录制」→ 提示「请按下新的组合键」→ 直接按键即完成。Esc 取消;15 秒无操作自动取消。 - 禁用:点「禁用」,该动作完全关闭(连默认键也不再触发)。 - 已改过的动作会出现「禁用」按钮;未改过的动作使用默认键。

入口二:/hotkeys 命令

1. 在消息输入框输入 /hotkeys。 2. 弹出菜单列出所有动作及当前键。 3. 选「🎙 录制「xxx」键」→ 按下组合键。

组合键语法

  • 格式:修饰键 + 主键,用 + 连接,如 Control+Shift+Enter
  • 修饰键别名(任选一种写法):
修饰键别名
CtrlCtrl / Control /
MetaMeta / Cmd / Command / Win /
ShiftShift /
AltAlt / Option /
  • 单字符主键自动大写;空格键写作 Space

键位三态

状态含义
未改过使用动作声明的默认键(defaultKey
已录制使用你设置的键
已禁用完全不触发

冲突说明

当多个动作绑定了同一个组合键,先注册的动作优先触发;冲突的动作在设置页会红色高亮,请改绑其中一个避免歧义。

---

构建与测试

pnpm install
pnpm typecheck
pnpm test      # vitest 单测(combo / scope / store / dispatcher)
pnpm build     # tsc 声明 + tsdown(host ESM + client.js + client-registry.js)

---

目录

src/
├── index.ts               # host half(可选设置命名空间,其余留空)
├── combo.ts               # 组合键解析/匹配/描述(纯函数)
├── scope.ts               # 内置 scope 判定(纯函数)
├── store.ts               # bindings 持久化 + 迁移(纯函数)
├── context-types.ts       # HotkeyService 类型 + Context 增补
└── client/
    ├── index.tsx          # apply:ctx.provide + settings.section + /hotkeys 命令
    ├── service.ts         # HotkeyService 实现工厂
    ├── dispatcher.ts      # 全局 keydown 分发(纯决策可测)
    ├── record.ts          # 录制
    ├── dom-utils.ts       # overlay/合成 Enter/toast
    └── HotkeysSettingsPanel.tsx  # 设置页

License

MIT