dsh-launch-buttons
Multiple launch buttons for the DSH composer. A standalone copy of dsh-launch-button —
the original plugin is left untouched (中文说明见下方).
- Left-click the main button → launches the default item. With nothing configured yet, the default is the current conversation's workspace directory.
- Right-click the main button → opens the launch-item list (one row per item).
- Each row in that list: click the row to launch its bound program or directory,
★makes it the default,⚙(or right-clicking the row) opens that item's own settings — label, path, delete. + New launch itemat the bottom: give it a label and an absolute path, scoped to this conversation only or to the whole workspace.
State lives on the host in $DSH_HOME/launch-buttons/store.json, so it survives page
reloads and is shared by every client of the same profile.
Install
dsh plugin --profile desktop add github:leexiaode4/dsh-launch-buttons # from GitHub
dsh plugin --profile desktop add "<path to this checkout>" # from a local copy
dsh plugin --profile desktop add dsh-launch-buttons # from npm, once published
Then restart DSH completely — the wiring is host-side, a page refresh is not enough. If
dsh-launch-button is also installed, disable it in the profile patch so the composer does
not show two launcher buttons:
- id: dsh-launch-button
disabled: true
Compatibility
- Any DSH speaking the
dsh.bundleprotocol (>= 0.1.5-rc.1); no build step, no runtime dependency beyond Node itself.reactis an optional peer. - Windows, macOS and Linux: folders and documents are opened with
explorer.exe,openandxdg-openrespectively; executables are spawned directly. - The client half renders in the Web platform (browser and Electron-based desktop clients).
Tests
node --test test/core.test.mjs test/host.integration.test.mjs test/client.test.mjs
Every launch case in the suite is a refusal path — the tests never start a real process.
BSD-3-Clause.
中文
对话输入框右下角的多启动项按钮。它是 dsh-launch-button 的独立副本,原插件一行未改。
- 左键主按钮 → 启动“默认启动项”。还没有配置任何启动项时,默认就是当前对话的工作区目录。
- 右键主按钮 → 弹出启动项列表(每一行是一个启动项)。
- 列表里每一行:
- 点行本身 → 启动它绑定的程序或目录;
★→ 把它设为默认(此后左键主按钮直接启动它);⚙(或在该行上右键)→ 打开它自己的设置:名称、路径、删除。
- 列表底部
+ 新建启动项:填写名称与绝对路径,可选“只绑定这个对话”或“绑定整个工作区”。
数据放在哪
$DSH_HOME/launch-buttons/store.json:
{
"version": 2,
"sessions": { "<会话 id>": { "items": [ { "id": "…", "label": "…", "path": "…", "at": "…" } ], "defaultId": "…" } },
"workspaces": { "<工作区键>": { "items": [ … ], "defaultId": "…" } }
}
- 启动项分两个作用域:这个对话(
sessions)与这个工作区(workspaces,该目录下的所有对话共享)。 - 列表顺序:本对话的启动项 → 本工作区的启动项 → 内置的「工作区」行(兜底)。
- 默认值解析:本对话的
defaultId→ 本工作区的defaultId→ 内置工作区目录。默认项被删掉时自动回退到第一条。 defaultId可以是"workspace",表示“默认就是工作区目录本身”。- 一个作用域最多 24 个启动项。
从旧插件继承:第一次读取时,如果本插件自己的 store.json 还不存在,而旧的
$DSH_HOME/launch-button/bindings.json 存在,就把它导入(旧文件保持原样,不删)。所以换过来之后行为与原来一致,直到你配置了新东西。
安装
与 dsh-launch-button 相同的接法。推荐直接用一条命令(会自动写下面第 1、2 步):
dsh plugin --profile desktop add "C:\path\to\dsh-launch-buttons"
# 或直接从 GitHub 装:
dsh plugin --profile desktop add github:leexiaode4/dsh-launch-buttons
手动接线的两步:
在目标 profile 的
node_modules里建一个指向本目录的链接(Windows:目录 junction;macOS/Linux:ln -s):<profile>/node_modules/dsh-launch-buttons→<本目录>profile 的
package.json:dependencies加"dsh-launch-buttons": "link:<本目录>"dsh.profile.bundles数组里加"dsh-launch-buttons"
想让新的按钮替代原来的按钮时,在 profile 的
cordis.patch.yml里把原插件关掉:- id: dsh-launch-button disabled: true不关掉的话输入框右侧会同时出现两个启动按钮(一个旧的、一个新的),两个都能用。
完全退出并重开 DSH(改的是 Host 侧接线,刷新页面不够)。
也可以走桌面端的插件管理器界面(可能需要一次批准):
npx --yes @deepseek-ai/dsh@<你运行中的版本> plugin --profile desktop add "<本目录或包名>"
验证
- 打开
http://127.0.0.1:<DSH 的端口>/dsh-launch-buttons/health:应返回{"ok":true,"plugin":"dsh-launch-buttons","strategy":"multi-item",…}(带storePath)。 - 输入框右侧出现 ▶ 按钮:左键应能打开工作区目录;右键应弹出启动项列表。
- 加一个启动项 → 在列表里点它应能启动;点
★后左键主按钮应直接启动它。 - 失败时看桌面端日志里的
web boot: N entry did not activate,把原文发出来即可定位。
回退
删掉 profile package.json 里的 dsh-launch-buttons(dependencies + bundles 各一行)与那个
node_modules 链接、重启即可;$DSH_HOME/launch-buttons/ 可以直接删(旧插件的
$DSH_HOME/launch-button/ 从未被改动)。关掉原插件的 disabled: true 那两行删掉即可恢复旧按钮。
边界
- 只能启动程序或目录(
.exe/.com/.scr直接启动;目录、文档、脚本交给平台 opener 用系统默认程序打开,与双击等价:Windowsexplorer.exe、macOSopen、Linuxxdg-open;POSIX 上带可执行位的文件直接启动)。 刻意不走cmd /c start:cmd 会二次解析参数,路径里带& | ^ < > % !就会执行第二条命令,而从 Node 这边没法给 cmd 传一个安全引号化的路径(libuv 只给含空格或引号的参数加引号)。 - 路径必须是绝对路径且当前存在,添加时会检查。
- Host 启动子进程时刻意不传
windowsHide/detached:本机windowsHide: true会变成CREATE_NO_WINDOW,子进程会在加载器里以0xC0000142(STATUS_DLL_INIT_FAILED)当场死掉—— 看起来“启动成功”其实什么都没打开。 - 状态只存在 Host 侧,客户端不做 localStorage;换界面/刷新不会丢。
- 打开文件夹/文档通过系统 opener(Windows
explorer.exe),因此以管理员身份运行的 DSH 与以普通身份运行的 DSH 打开的窗口权限不同。
测试
node --test test/core.test.mjs test/host.integration.test.mjs test/client.test.mjs
core.test.mjs 覆盖纯逻辑(路径判定、启动计划、store 归并与迁移、默认值解析、回环判定);
host.integration.test.mjs 用假 ctx + 真 http server 驱动整套 JSON API(所有启动用例都是拒绝路径,不会真的启动进程);
client.test.mjs 校验模块 id、slots 注入、座位与注入的 CSS。
文件
| 文件 | 作用 |
|---|---|
lib/core.js |
纯逻辑:启动计划、store 形状与迁移、默认项解析、loopback 判定 |
lib/index.js |
Host:/dsh-launch-buttons JSON API、读写 store、启动进程 |
lib/client.js |
客户端:输入框按钮、启动项列表、单项设置面板 |
cordis.patch.yml |
bundle 补丁,把 dsh-launch-buttons 插进 cordis |
No comments yet. Be the first to write one.