dsh-command-palette 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +4 -1
- package/README.md +4 -1
- package/client.js +67 -2
- package/package.json +2 -2
package/README.en.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
[](https://www.npmjs.com/package/dsh-command-palette)
|
|
6
6
|
[](https://github.com/chenyangcun/dsh-command-palette)
|
|
7
7
|
|
|
8
|
-
A keyboard-first command palette for standard DeepSeek Harness (DSH). Double-tap Shift to search and open sessions, workspaces, available features, or reusable custom commands.
|
|
8
|
+
A keyboard-first command palette for standard DeepSeek Harness (DSH). Double-tap Shift to search and open sessions, workspaces, settings pages, available features, or reusable custom commands.
|
|
9
9
|
|
|
10
10
|
## Install
|
|
11
11
|
|
|
@@ -21,6 +21,7 @@ Restart the current DSH Web process after installation, then open **Settings →
|
|
|
21
21
|
- **Recent sessions** — shows the six most recently updated valid sessions by default
|
|
22
22
|
- **Session search** — searches titles, working directories, Agent presets, and session IDs
|
|
23
23
|
- **Workspace switching** — starts a session in the selected workspace directly from the palette
|
|
24
|
+
- **Settings navigation** — discovers registered DSH settings sections and opens the selected page directly
|
|
24
25
|
- **Custom commands** — saves frequently used prompts and either creates a session each time or reuses a dedicated session
|
|
25
26
|
- **Workspace binding** — chooses the workspace used when a custom command creates a session
|
|
26
27
|
- **Provider API** — lets other Client plugins register commands or trigger the palette
|
|
@@ -32,6 +33,8 @@ Restart the current DSH Web process after installation, then open **Settings →
|
|
|
32
33
|
3. Use `↑` / `↓` to select, Enter to run, and Esc to close.
|
|
33
34
|
4. Add, edit, or remove custom commands under **Settings → Command Palette**.
|
|
34
35
|
|
|
36
|
+
The palette reads the current settings-section registry whenever it opens, so settings pages added by other plugins automatically appear in the **Settings** group.
|
|
37
|
+
|
|
35
38
|
When **Reuse dedicated session** is enabled, the first run creates and stores a session binding. Later runs continue in that session. If the bound session is archived or unavailable, the plugin creates a replacement automatically.
|
|
36
39
|
|
|
37
40
|
## Standard DSH and extension API
|
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
[](https://www.npmjs.com/package/dsh-command-palette)
|
|
6
6
|
[](https://github.com/chenyangcun/dsh-command-palette)
|
|
7
7
|
|
|
8
|
-
适用于标准版 DeepSeek Harness(DSH)的键盘优先命令面板。连续快速按两次 Shift
|
|
8
|
+
适用于标准版 DeepSeek Harness(DSH)的键盘优先命令面板。连续快速按两次 Shift,即可搜索和打开会话、工作区、设置页面、已安装功能或可复用的自定义指令。
|
|
9
9
|
|
|
10
10
|
## 安装
|
|
11
11
|
|
|
@@ -21,6 +21,7 @@ dsh plugin --profile web add dsh-command-palette
|
|
|
21
21
|
- **最近会话**——默认展示最近更新的六个有效会话
|
|
22
22
|
- **会话搜索**——按标题、工作目录、Agent 预设或会话 ID 搜索
|
|
23
23
|
- **工作区切换**——从命令面板直接在目标工作区启动会话
|
|
24
|
+
- **设置页跳转**——自动读取 DSH 已注册的设置菜单,搜索后直接打开对应设置页面
|
|
24
25
|
- **自定义指令**——保存常用 Prompt,可选择每次新建会话或复用专属会话
|
|
25
26
|
- **工作区绑定**——为自定义指令的新会话指定目标工作区
|
|
26
27
|
- **扩展 Provider**——其他 Client 插件可以注册自己的命令或触发面板
|
|
@@ -32,6 +33,8 @@ dsh plugin --profile web add dsh-command-palette
|
|
|
32
33
|
3. 使用 `↑` / `↓` 选择,按 Enter 执行,按 Esc 关闭。
|
|
33
34
|
4. 在 **设置 → 命令面板** 中添加、编辑或删除自定义指令。
|
|
34
35
|
|
|
36
|
+
插件会在每次打开面板时读取当前已注册的设置页面,因此其他插件新增的设置菜单也会自动出现在“设置”分组中。
|
|
37
|
+
|
|
35
38
|
自定义指令启用“复用专属会话”后,首次执行会创建会话并保存绑定;后续执行继续向同一会话发送内容。如果绑定会话已经归档或不可用,插件会自动创建新会话。
|
|
36
39
|
|
|
37
40
|
## 标准 DSH 与扩展接口
|
package/client.js
CHANGED
|
@@ -7,8 +7,8 @@ window.__ModuleLoader__.load({
|
|
|
7
7
|
const React = require('react')
|
|
8
8
|
const ReactDOM = require('react-dom')
|
|
9
9
|
|
|
10
|
-
const GROUP_ORDER = ['features', 'browser', 'workspaces', 'sessions']
|
|
11
|
-
const GROUP_LABELS = { features: '功能', browser: '浏览器', workspaces: '工作区', sessions: '会话', recent: '最近会话' }
|
|
10
|
+
const GROUP_ORDER = ['features', 'settings', 'browser', 'workspaces', 'sessions']
|
|
11
|
+
const GROUP_LABELS = { features: '功能', settings: '设置', browser: '浏览器', workspaces: '工作区', sessions: '会话', recent: '最近会话' }
|
|
12
12
|
const SUPPORTED_GROUPS = new Set(GROUP_ORDER)
|
|
13
13
|
|
|
14
14
|
function normalizeCustomCommand(value) {
|
|
@@ -106,6 +106,69 @@ window.__ModuleLoader__.load({
|
|
|
106
106
|
return [command.title, command.subtitle, ...(command.keywords || [])].filter(Boolean).join(' ').toLocaleLowerCase()
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
+
function resolveSettingsLabel(value) {
|
|
110
|
+
try {
|
|
111
|
+
const label = typeof value === 'function' ? value() : value
|
|
112
|
+
return typeof label === 'string' ? label.trim() : ''
|
|
113
|
+
} catch {
|
|
114
|
+
return ''
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function findSettingsNavigationButton(label) {
|
|
119
|
+
for (const dialog of document.querySelectorAll('[role="dialog"]')) {
|
|
120
|
+
const nav = dialog.querySelector('nav')
|
|
121
|
+
if (!nav) continue
|
|
122
|
+
const button = Array.from(nav.querySelectorAll('button')).find((item) => item.textContent?.trim() === label)
|
|
123
|
+
if (button) return button
|
|
124
|
+
}
|
|
125
|
+
return null
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
async function openSettingsSection(label) {
|
|
129
|
+
let button = findSettingsNavigationButton(label)
|
|
130
|
+
if (!button) {
|
|
131
|
+
const trigger = document.querySelector('button[aria-haspopup="dialog"][aria-expanded]')
|
|
132
|
+
if (!trigger) throw new Error('当前 DSH 页面未提供可用的设置入口。')
|
|
133
|
+
trigger.click()
|
|
134
|
+
button = findSettingsNavigationButton(label)
|
|
135
|
+
for (let attempt = 0; !button && attempt < 4; attempt += 1) {
|
|
136
|
+
await new Promise((resolve) => requestAnimationFrame(resolve))
|
|
137
|
+
button = findSettingsNavigationButton(label)
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
if (!button) throw new Error(`无法打开设置页面:${label}`)
|
|
141
|
+
button.click()
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function createSettingsProvider(ctx) {
|
|
145
|
+
return {
|
|
146
|
+
id: 'settings',
|
|
147
|
+
collect: () => {
|
|
148
|
+
let entries
|
|
149
|
+
try { entries = ctx.slots.entries('settings.section') }
|
|
150
|
+
catch { return [] }
|
|
151
|
+
return Array.from(entries || [])
|
|
152
|
+
.map((entry) => ({
|
|
153
|
+
id: typeof entry?.options?.id === 'string' ? entry.options.id.trim() : '',
|
|
154
|
+
order: typeof entry?.options?.order === 'number' ? entry.options.order : 0,
|
|
155
|
+
title: resolveSettingsLabel(entry?.options?.label)
|
|
156
|
+
}))
|
|
157
|
+
.filter(({ id, title }) => id && title)
|
|
158
|
+
.sort((left, right) => left.order - right.order)
|
|
159
|
+
.map(({ id, title }) => ({
|
|
160
|
+
id,
|
|
161
|
+
group: 'settings',
|
|
162
|
+
icon: '⚙',
|
|
163
|
+
title,
|
|
164
|
+
subtitle: '打开设置页面',
|
|
165
|
+
keywords: ['settings', '设置', id],
|
|
166
|
+
run: () => openSettingsSection(title)
|
|
167
|
+
}))
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
109
172
|
function recentTimestamp(value) {
|
|
110
173
|
return typeof value === 'number' ? value : Date.parse(String(value || '')) || 0
|
|
111
174
|
}
|
|
@@ -358,6 +421,7 @@ window.__ModuleLoader__.load({
|
|
|
358
421
|
const commandSettings = ctx.get('settingsScope').bind({ namespace: 'command-palette' })
|
|
359
422
|
const paletteService = createCommandPaletteService()
|
|
360
423
|
ctx.provide('commandPalette', paletteService)
|
|
424
|
+
const removeSettingsProvider = paletteService.registerProvider(createSettingsProvider(ctx))
|
|
361
425
|
installStyles()
|
|
362
426
|
const saveCustomCommands = async (next) => {
|
|
363
427
|
const commands = normalizeCustomCommands(next)
|
|
@@ -399,6 +463,7 @@ window.__ModuleLoader__.load({
|
|
|
399
463
|
ctx.slots.inject('shell.overlay', () => ctx.slots.register({ name: 'shell.overlay', id: 'dsh-command-palette', order: 220, inject: injected }, Palette))
|
|
400
464
|
ctx.slots.inject('settings.section', () => ctx.slots.register({ name: 'settings.section', id: 'command-palette-settings', order: 90, label: () => '命令面板', inject: injected }, ShortcutSettings))
|
|
401
465
|
ctx.effect(() => () => {
|
|
466
|
+
removeSettingsProvider()
|
|
402
467
|
paletteService.close()
|
|
403
468
|
document.querySelector('style[data-plugin-css="dsh-command-palette"]')?.remove()
|
|
404
469
|
}, 'dsh-command-palette: cleanup')
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-command-palette",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "A keyboard-first command palette for DeepSeek Harness sessions, workspaces, features, and reusable custom commands.",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "A keyboard-first command palette for DeepSeek Harness sessions, workspaces, settings, features, and reusable custom commands.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "chenyangcun",
|
|
7
7
|
"type": "module",
|