dsh-enter-swap
中文 | English
DSH(DeepSeek Harness)Web 插件:输入框 Enter = 换行,Shift+Enter = 发送。
极简、零依赖、装完即用;输入框工具栏带一个滑动开关,随时可还原原生键位。
功能
- Enter → 换行;Shift+Enter → 发送
- 输入框工具栏(模型选择器左侧)常驻键位胶囊:〔Shift+Enter 发送消息〕〔Enter 换行〕(0.1.2 起,0.1.4 起改挂引擎原生插槽,不遮挡正文)
- 滑动开关:胶囊左侧的键位开关,关掉立即恢复原生(Enter 发送、Shift+Enter 换行),一个按键都不再拦截;状态存浏览器本地,刷新/重开标签页保持,多标签页实时同步(0.1.5 起)
- Ctrl/Cmd+Enter(原生加速投递)、Alt+Enter 保持原生
- 中文输入法组词过程不拦截(IME 组帧放行)
- 斜杠命令 / @提及候选菜单打开时,Enter 照常选中菜单项
- 无设置页、无网络请求、无文件读写、零 npm 依赖
安装
dsh plugin --profile web add github:xuqiuba888/dsh-enter-swap
其他 profile 同理(--profile <名>)。装完重启 dsh(Desktop/NEXT 重启应用),
浏览器/界面硬刷新(Ctrl+Shift+R)生效。
卸载与更新
dsh plugin --profile web update dsh-enter-swap # 更新到最新
dsh plugin --profile web remove dsh-enter-swap # 卸载,刷新即回原生
文件结构
├── package.json # dsh.client(Web 插件)+ dsh.bundle(profile patch)声明
├── cordis.patch.yml # bundle patch:插入插件行
├── pnpm-lock.yaml # 依赖快照(零依赖,仅为 link 安装惯例)
├── lib/
│ └── index.js # Host 半部:空实现(本插件不需要宿主行为)
└── client/
└── client.js # Client 半部:捕获阶段按键互换 + 键位开关
实现要点
- 在 document 捕获阶段监听
keydown,仅当目标位于输入框
([data-composer-input="true"])内才处理
- 手势判定:Alt/Ctrl/Cmd 一律放行;
isComposing / keyCode 229 放行;
检测到挂载在 <body> 直下且可见的 portal 菜单(role="menu" / "listbox",即斜杠/@候选弹层)时放行,Enter 照常选中菜单项——隐藏的
残留弹层(如新开会话后的工作区选择器)不算菜单开着
- 命中时
preventDefault + stopPropagation,再把互换后的手势以合成
KeyboardEvent 派发回引擎——语义(发送/排队/换行)仍由引擎自己决定
- 开关状态存
localStorage['dsh-enter-swap:enabled'](缺省开,读不到也按开),
storage 事件跨标签页同步;关闭时监听器第一行就返回,等于插件不存在
- Client bundle 为纯 JS,
__ModuleLoader__ 工厂格式,无需构建步骤
测试
node test/client-switch.test.mjs
不需要依赖、不需要浏览器:用桩替换 React 与 DOM,直接跑真实的 client bundle。
覆盖默认开、拦截与手势互换、点击关闭、关闭后零拦截、跨标签页同步、脏值回退、
存储被拒、卸载清理。
兼容性
DSH 0.2.x(在 0.2.1-rc.2 web 界面上开发并验证)。不使用任何引擎版本特定的
内部 API。
License
MIT