dsh-sidebar-row-menu 1.9.3 → 1.11.0
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/AGENTS.md +77 -0
- package/CHANGELOG.md +76 -0
- package/README.en.md +55 -44
- package/README.md +45 -32
- package/lib/client.js +3308 -3864
- package/lib/host/launch.js +22 -5
- package/lib/host/permission-defaults.js +281 -0
- package/lib/host/route.js +189 -27
- package/lib/host/session-delete.js +60 -11
- package/lib/index.js +28 -3
- package/package.json +11 -3
package/AGENTS.md
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# 仓库约定(AGENTS.md)
|
|
2
|
+
|
|
3
|
+
本仓库是 [DeepSeek Harness](https://github.com/deepseek-ai) 的插件
|
|
4
|
+
`dsh-sidebar-row-menu`:宿主半边在 `lib/`,客户端半边是 **`src/client/**` 的源码 +
|
|
5
|
+
esbuild 打包出的单文件 `lib/client.js`**。
|
|
6
|
+
|
|
7
|
+
## 硬性约束
|
|
8
|
+
|
|
9
|
+
1. **不要手改 `lib/client.js`。** 它是构建产物,任何手工修改都会在下次构建时丢失。
|
|
10
|
+
客户端改动只写 `src/client/**`,然后运行 `npm run build:client`。
|
|
11
|
+
2. **客户端只有一个产物文件。** DSH 的客户端模块系统直接执行
|
|
12
|
+
`window.__ModuleLoader__.load({ factory })`,没有打包步骤的旧版插件靠单文件分发;
|
|
13
|
+
所以源码可以拆多文件,但必须打包回一个 `lib/client.js`,且 `package.json` 的
|
|
14
|
+
`exports["./client"]` 指向它。
|
|
15
|
+
3. **平台模块只能从 `src/client/platform.js` 引入。** react / react-dom / ui-primitives
|
|
16
|
+
由 DSH 的静态模块表提供,构建脚本把它们标成 external;分散 import 会让
|
|
17
|
+
「插件依赖了平台哪些导出」不可见,也容易漏配 external。
|
|
18
|
+
4. **不新增运行时依赖。** 运行时只有宿主平台模块;`esbuild` 是唯一的 devDependency。
|
|
19
|
+
5. **对外导出的名字保持稳定**(`apply` / `inject` / `name` / `closeMenu` / `closeToast`),
|
|
20
|
+
测试与宿主都按这些名字取值。
|
|
21
|
+
|
|
22
|
+
## 目录与分层
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
src/client/
|
|
26
|
+
index.js 入口:apply(ctx)、slot 注册、样式安装、生命周期清理
|
|
27
|
+
platform.js 平台模块的唯一入口(react / react-dom / ui-primitives)
|
|
28
|
+
constants.js 存储键、路由前缀、菜单 order、slot 名等常量
|
|
29
|
+
i18n.js zh / en 词条(全部文案都要走 t())
|
|
30
|
+
styles.js 全部 CSS(一次注入,类名前缀 dsrm-)
|
|
31
|
+
apps-catalog.js 应用 id → 名称 / 图标
|
|
32
|
+
dom.js fiber 解析、行/工作区/会话定位
|
|
33
|
+
runtime.js 运行期单例:rootCtx、菜单挂载(beginMenu / closeMenu)、服务查找
|
|
34
|
+
toast.js Toast 宿主
|
|
35
|
+
host-api.js 调宿主 HTTP 路由、剪贴板、cwd 解析
|
|
36
|
+
slot-ownership.js slot 条目归属判断(避免与内置条目重复)
|
|
37
|
+
lib/create-store.js 持久化 store 工厂(localStorage + useSyncExternalStore 样板)
|
|
38
|
+
store/*.js 9 个小状态:items / placements / blank-menu / children / pinned /
|
|
39
|
+
apps / permission / archived / delete-request
|
|
40
|
+
ui/*.js jsx 辅助、菜单定位、子菜单关闭、右键手势标记
|
|
41
|
+
features/*.js 功能块:工作区菜单、会话菜单、空白正文菜单、打开方式、设置页、
|
|
42
|
+
删除确认框、归档可见性、行右键入口
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## 编码约定
|
|
46
|
+
|
|
47
|
+
- 文件名 kebab-case;React hook 以 `use` 开头,工厂函数以 `create` 开头。
|
|
48
|
+
- 新增持久化状态:用 `lib/create-store.js` 的 `createStore`,不要再手写
|
|
49
|
+
`publish / subscribe / snapshot` 三件套。
|
|
50
|
+
- 菜单挂载:统一用 `runtime.js` 的 `beginMenu(slotName).render(...)`,由 `closeMenu()`
|
|
51
|
+
统一卸载;不要各自 `createRoot` 挂 `menuHost`。
|
|
52
|
+
- 菜单关闭:菜单级用 `ui/dismiss.js` 的 `useDismissOnOutside`,悬浮子菜单用
|
|
53
|
+
`useSubmenuDismiss` + `useHoverSubmenu`;不要再逐个组件写 mousedown / keydown。
|
|
54
|
+
- i18n:所有用户可见文案进 `i18n.js`,中英各一条,键名用 `域.名字`。
|
|
55
|
+
- 样式:只写 `styles.js`,类名 `dsrm-` 前缀,跟随宿主 CSS 变量(不要硬编码颜色)。
|
|
56
|
+
- 容错:`catch` 不允许完全留空,至少 `console.warn` 或注释说明为什么可以忽略。
|
|
57
|
+
- 宿主服务可能晚于插件就绪:用 `serviceOf(ctx, name)`,缺失时降级而不是抛错。
|
|
58
|
+
|
|
59
|
+
## 构建与校验
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
npm install # 只装 esbuild
|
|
63
|
+
npm run build:client # src/client/** → lib/client.js
|
|
64
|
+
npm test # pretest 会先构建;然后跑 host / manifest / client 测试
|
|
65
|
+
npm run check # 语法检查 + 构建产物与源码一致性(不一致即失败)
|
|
66
|
+
npm pack # prepack 会构建 + check,产出 .tgz
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
改完客户端代码务必 `npm run build:client && npm test`;只改 `lib/host/**` 时也跑一遍
|
|
70
|
+
`npm test`。提交前 `git status` 应包含 `lib/client.js`(产物)与源码改动。
|
|
71
|
+
|
|
72
|
+
## 发布
|
|
73
|
+
|
|
74
|
+
1. 升 `package.json` 版本,CHANGELOG 按现有双语格式加一节;
|
|
75
|
+
2. `npm test` / `npm run check` 全绿;
|
|
76
|
+
3. 在真实 DSH GUI 里用 CDP 验证受影响的菜单(右键、权限切换、删除确认、设置页);
|
|
77
|
+
4. 打 tag(`vX.Y.Z`)由 release workflow 打包发布;`lib/client.js` 必须已被构建并提交。
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,81 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.11.0 — 2026-11-06
|
|
4
|
+
|
|
5
|
+
### 中文摘要
|
|
6
|
+
|
|
7
|
+
- **切换「新会话默认权限」失败时不再假装成功。** 网络或宿主出错时,菜单会回滚到原来
|
|
8
|
+
的勾选项并弹出失败提示;之前乐观更新会留在界面上、实际没写盘,也没有任何反馈。
|
|
9
|
+
同时修掉了「读设置」晚于「写设置」返回时用旧值覆盖新值的竞态。
|
|
10
|
+
- **一次网络抖动不再让「打开方式 / 置顶应用」条目消失。** 应用列表加载失败时保留上次
|
|
11
|
+
成功的结果,而不是清空(旧行为会空白 10 秒)。
|
|
12
|
+
- **批量删除会话更快、计数更准。** 一次批量(含删除工作区)只解析一次会话索引,不再
|
|
13
|
+
每个会话扫一遍全部会话(O(N²)),并改为 4 路并发执行;若目标会话已全部不存在,
|
|
14
|
+
提示改为「会话已不存在,无需删除」,不再报「已删除 0 个」。
|
|
15
|
+
- **Windows 上从 `.cmd` / `.bat` 启动编辑器时路径不再被拆词。** 含空格或 `& ^ ( )` 的
|
|
16
|
+
目录不会再传错,也堵掉了命令注入面。
|
|
17
|
+
- **权限设置文件更安全。** 写入加文件锁(避免并发读-改-写丢更新),读到损坏的 JSON 时
|
|
18
|
+
报错而不是整表覆盖;从工作区子目录启动的会话也能命中该工作区的默认权限。
|
|
19
|
+
- **内部重构:客户端拆模块 + 打包。** `lib/client.js` 改为由 `src/client/**` 经 esbuild
|
|
20
|
+
打包的产物,9 套重复的 localStorage store、5 处子菜单关闭逻辑、菜单挂载外壳都收敛
|
|
21
|
+
成共用实现;仓库约定见 `AGENTS.md`。行为与 UI 不变。
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
|
|
25
|
+
- **A failed "default permission for new sessions" change no longer pretends to
|
|
26
|
+
succeed.** On a network or host error the menu rolls back to the previous checkmark
|
|
27
|
+
and shows a failure toast; the optimistic update used to stay on screen even though
|
|
28
|
+
nothing was persisted, with no feedback at all. A read that resolves after a write
|
|
29
|
+
can no longer overwrite the newer value either.
|
|
30
|
+
- **One network hiccup no longer empties the "Open with / pinned apps" entries.** The
|
|
31
|
+
app list keeps its last successful result on failure instead of clearing for 10
|
|
32
|
+
seconds.
|
|
33
|
+
- **Batch session deletion is faster and counts correctly.** A batch (including
|
|
34
|
+
deleting a whole workspace) resolves the session index once instead of listing every
|
|
35
|
+
session per id (O(N²)) and runs with 4-way concurrency; when all targets were already
|
|
36
|
+
gone the toast says "the sessions were already gone" instead of "deleted 0".
|
|
37
|
+
- **Windows `.cmd` / `.bat` editor launchers no longer split paths.** Directories with
|
|
38
|
+
spaces or `& ^ ( )` are quoted correctly, closing the command-injection surface.
|
|
39
|
+
- **Safer permission store.** Writes take a file lock (no lost updates on concurrent
|
|
40
|
+
read-modify-write) and a corrupt JSON file now fails loudly instead of being
|
|
41
|
+
overwritten; sessions started from a workspace subdirectory resolve that workspace's
|
|
42
|
+
default permission too.
|
|
43
|
+
- **Internal refactor: the client is now split into modules and bundled.**
|
|
44
|
+
`lib/client.js` is a build artifact of `src/client/**` via esbuild; nine duplicated
|
|
45
|
+
localStorage stores, five copies of submenu dismissal and the menu-mount shell now
|
|
46
|
+
share one implementation. Conventions live in `AGENTS.md`; behaviour and UI are
|
|
47
|
+
unchanged.
|
|
48
|
+
|
|
49
|
+
## 1.10.0 — 2026-11-06
|
|
50
|
+
|
|
51
|
+
### 中文摘要
|
|
52
|
+
|
|
53
|
+
- **工作区可以单独设置新会话的默认权限。** 工作区右键菜单新增「新会话默认权限」二级
|
|
54
|
+
菜单,列出宿主原生的权限预设(仅可查看 / 工作区内修改 / 完全权限),当前生效的一项
|
|
55
|
+
右侧打勾;选择后只影响该工作区之后新建的会话,已有会话不动。「跟随全局默认」清除
|
|
56
|
+
本工作区的设置。设置存在 `$DSH_HOME/storages/dsh-sidebar-row-menu/permission-defaults.json`,
|
|
57
|
+
由宿主插件在会话创建时通过 `permissionPresets` 原生接口落成会话事件,不靠客户端改默认值。
|
|
58
|
+
- **菜单条目可以只放进「…」菜单。** 设置 →「行菜单」→「菜单显示位置」把原来
|
|
59
|
+
「同时放进「…」菜单」的开关改成三态:右键菜单 / 「…」菜单 / 两边,每个条目至少保留
|
|
60
|
+
一边;旧配置自动迁移(开 → 两边,关 → 右键菜单)。
|
|
61
|
+
|
|
62
|
+
### Changed
|
|
63
|
+
|
|
64
|
+
- **A workspace can now set the default permission for its new sessions.** The
|
|
65
|
+
workspace context menu gains a "Default permission for new sessions" submenu listing
|
|
66
|
+
the host's native presets (read-only / workspace-write / danger-full-access) with the
|
|
67
|
+
effective one checked. The choice applies only to sessions created afterwards in
|
|
68
|
+
that workspace and never touches existing sessions; "Follow global default" clears
|
|
69
|
+
it. The mapping is stored in
|
|
70
|
+
`$DSH_HOME/storages/dsh-sidebar-row-menu/permission-defaults.json`, and the host
|
|
71
|
+
plugin applies it through the native `permissionPresets` service when a session is
|
|
72
|
+
created, so it is recorded as a normal permission event rather than by mutating the
|
|
73
|
+
client default.
|
|
74
|
+
- **Entries can live only in the "…" menu.** Settings → "Row menu" → "Menu placement"
|
|
75
|
+
replaces the old "Also show in the '…' menu" switches with a tri-state choice per
|
|
76
|
+
entry (right-click / "…" / both), always keeping at least one side; existing
|
|
77
|
+
settings migrate automatically (on → both, off → right-click).
|
|
78
|
+
|
|
3
79
|
## 1.9.3 — 2026-11-06
|
|
4
80
|
|
|
5
81
|
### 中文摘要
|
package/README.en.md
CHANGED
|
@@ -27,13 +27,14 @@ Session menu content comes from the `sidebar.workspaces.session.menu.item` slot
|
|
|
27
27
|
built-in actions and other plugins' actions are all there. This plugin only appends
|
|
28
28
|
its own entries; it does not copy or hardcode any built-in action.
|
|
29
29
|
|
|
30
|
-
> The
|
|
31
|
-
>
|
|
32
|
-
>
|
|
30
|
+
> The plugin's entries appear in the right-click menu by default. Settings → "Row
|
|
31
|
+
> menu" → "Menu placement" can move each entry to the "…" menu only, or show it in
|
|
32
|
+
> both (at least one side always stays on).
|
|
33
33
|
> On 0.2.2 both gestures share
|
|
34
34
|
> one host menu, so the plugin tells them apart by the gesture itself: a right-click
|
|
35
35
|
> sets a mark that is released once the menu panel has actually mounted, while the
|
|
36
|
-
> pointerdown on the "…" button clears it immediately.
|
|
36
|
+
> pointerdown on the "…" button clears it immediately. The "…" menu therefore only
|
|
37
|
+
> carries entries placed there (or on both sides). A right-click menu does not
|
|
37
38
|
> close when the pointer leaves it; it closes only on an outside click, an item
|
|
38
39
|
> selection, or Escape.
|
|
39
40
|
|
|
@@ -45,9 +46,10 @@ On 0.2.2 the host renders this menu, and the plugin's items interleave with the
|
|
|
45
46
|
built-in Rename (100), Reveal in file manager (200) and Delete workspace (300),
|
|
46
47
|
using the same grouping rules as the session menu: New session 90, Open in new
|
|
47
48
|
tab 110, archived-session toggle 130, Copy workspace path 150, pinned app 210,
|
|
48
|
-
Open with 220,
|
|
49
|
-
|
|
50
|
-
|
|
49
|
+
Open with 220, default permission for new sessions 225, Delete workspace and all
|
|
50
|
+
sessions 310. These items are right-click only by default; the row's "…"
|
|
51
|
+
menu keeps its native content unless you place entries under Settings → "Row
|
|
52
|
+
menu" → "Menu placement". On 0.2.1 the plugin draws the whole menu and
|
|
51
53
|
runs the official dialogs for Rename and Delete workspace.
|
|
52
54
|
|
|
53
55
|
| Item | Behavior |
|
|
@@ -60,6 +62,7 @@ runs the official dialogs for Rename and Delete workspace.
|
|
|
60
62
|
| Reveal in file manager (built-in) | Opens the workspace directory in Explorer; provided by the host on 0.2.2, absent on 0.2.1 |
|
|
61
63
|
| Pinned open-with app | A pinned app shows directly at the top level (e.g. "Open with Visual Studio Code") and opens the workspace directory |
|
|
62
64
|
| Open with | A submenu of external apps (editors, terminals, file managers) sharing the session menu's catalog, pinning and toggles; hover expands it. Host menu items draw no submenu caret, so the plugin renders the label as text plus a right-aligned chevron, matching the session menu; the 0.2.1 self-drawn menu uses an arrow icon |
|
|
65
|
+
| Default permission for new sessions | A submenu of the host's native permission presets (read-only / workspace-write / danger-full-access). The chosen preset becomes the default for **sessions created afterwards in this workspace**; the effective one is checked on the right, and "Follow global default" clears the per-workspace value. Existing sessions are never changed |
|
|
63
66
|
| Delete workspace (built-in) | Opens the official delete confirmation; removes only the workspace registration and leaves its sessions under "Ungrouped". On 0.2.1 the plugin renders this item itself |
|
|
64
67
|
| Delete workspace and all sessions | Permanently deletes every session and transcript under the workspace first, then the workspace registration. If any session fails, the workspace is kept so the user can retry. The directory itself is not deleted |
|
|
65
68
|
|
|
@@ -91,25 +94,19 @@ Both delete entries are served by this plugin's own host route. They leave
|
|
|
91
94
|
unarchived sessions alone by default; the opt-in switch extends the single-session
|
|
92
95
|
entry to them. Deletion never cascades into forked child sessions.
|
|
93
96
|
|
|
94
|
-
These entries
|
|
95
|
-
|
|
96
|
-
right-click gesture mark and releases it only once the menu panel has actually
|
|
97
|
-
appeared (0.2.2 mounts the menu asynchronously), and the pointerdown on the "…"
|
|
98
|
-
button clears it at once. While the mark is live the entries render normally;
|
|
99
|
-
otherwise they render `null`.
|
|
97
|
+
These entries appear in the **right-click menu** by default. To use them from the
|
|
98
|
+
row's "…" button, set each one under Settings → "Row menu" → "Menu placement":
|
|
100
99
|
|
|
101
|
-
|
|
102
|
-
|
|
100
|
+
- "…" menu: the entry appears only in the row's "…" menu and leaves the
|
|
101
|
+
right-click menu;
|
|
102
|
+
- "Both": it appears on both sides;
|
|
103
|
+
- "Right-click menu": the default, right-click only.
|
|
103
104
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
row's "…" button and render the official "Rename / Delete workspace" items
|
|
110
|
-
alongside the enabled plugin entries.
|
|
111
|
-
|
|
112
|
-
With everything off, the "…" button behaves exactly like DSH's own.
|
|
105
|
+
Every entry must keep at least one side, so the switch for the last active side is
|
|
106
|
+
locked. Session entries and workspace entries (0.2.2) share the same
|
|
107
|
+
`contextMenus` providers and use the gesture mark to tell which menu is being
|
|
108
|
+
rendered; on 0.2.1 the plugin takes over the row's "…" button and draws the
|
|
109
|
+
workspace menu itself with the same placement rules.
|
|
113
110
|
|
|
114
111
|
Blank draft sessions have no right-click menu and are left alone. Rows that are
|
|
115
112
|
neither a workspace nor a session (e.g. "Show more") are not intercepted.
|
|
@@ -167,24 +164,27 @@ Settings → "Row menu" toggles every new entry:
|
|
|
167
164
|
| Allow deleting unarchived sessions | Off by default; also shows "Delete session permanently" on unarchived rows. Requires the previous switch |
|
|
168
165
|
| Delete all archived sessions | Hides the bulk-delete entry |
|
|
169
166
|
| Show archived sessions | Hides the workspace "Show / hide archived sessions" entry (on by default; the entry itself only appears when that workspace has archived sessions) |
|
|
170
|
-
|
|
|
171
|
-
|
|
|
167
|
+
| Menu placement → workspace | Per-entry choice between the right-click menu, the "…" menu, or both: New session, Default permission for new sessions, Open with, Copy workspace path, Open in new tab, archived-session toggle, Delete workspace and all sessions |
|
|
168
|
+
| Menu placement → session | Per-entry choice for session-row entries: Open with, Delete session, Delete all archived sessions |
|
|
172
169
|
| Enable blank-space context menu | Master switch for the conversation-body right-click menu (blank space, thinking blocks, replies; on by default); when off, that area keeps the browser/host native menu |
|
|
173
170
|
| Pin "More" to the far right | On by default; keeps a "More actions" style overflow trigger as the last row regardless of its current toolbar position |
|
|
174
171
|
| Show top-left status widgets | Off by default; also lists everything in the header's `conversation.session.header.actions` slot (Session cost, background-job counter, …) in the conversation-body menu |
|
|
175
172
|
|
|
176
|
-
|
|
177
|
-
|
|
173
|
+
Every placement defaults to "Right-click menu", so untouched installs keep the "…"
|
|
174
|
+
menu exactly as DSH ships it.
|
|
178
175
|
|
|
179
|
-
On DSH 0.2.2 and later the "…" button and right-click share one host menu
|
|
180
|
-
plugin
|
|
181
|
-
|
|
182
|
-
so the plugin takes over the "…" button and draws the menu itself
|
|
176
|
+
On DSH 0.2.2 and later the "…" button and right-click share one host menu; the
|
|
177
|
+
plugin tells them apart by the gesture mark, and only entries placed in "…" or
|
|
178
|
+
"Both" join that menu. On 0.2.1 workspace rows have no host menu to contribute to,
|
|
179
|
+
so the plugin takes over the "…" button and draws the menu itself with the same
|
|
180
|
+
placement rules.
|
|
183
181
|
|
|
184
182
|
Switches live in browser `localStorage` (`dsh.sidebar-row-menu.items.v1`,
|
|
185
183
|
`dsh.sidebar-row-menu.open-with.v1`, `dsh.sidebar-row-menu.open-with.pinned.v1`,
|
|
186
|
-
`dsh.sidebar-row-menu.
|
|
187
|
-
and apply immediately.
|
|
184
|
+
`dsh.sidebar-row-menu.placement.v1` and `dsh.sidebar-row-menu.blank-menu.v1`)
|
|
185
|
+
and apply immediately. The legacy `dsh.sidebar-row-menu.ellipsis.v1` booleans are
|
|
186
|
+
migrated on first load (true → "Both", false → "Right-click menu"). Before the
|
|
187
|
+
first explicit pin, the plugin derives one: the
|
|
188
188
|
first detected editor (usually VS Code), or the first catalog app when no editor
|
|
189
189
|
exists.
|
|
190
190
|
|
|
@@ -366,11 +366,19 @@ pnpm install (npm or GitHub)" transition.
|
|
|
366
366
|
## Development
|
|
367
367
|
|
|
368
368
|
```powershell
|
|
369
|
-
npm
|
|
370
|
-
npm run
|
|
371
|
-
npm run
|
|
369
|
+
npm install # installs esbuild, the only devDependency
|
|
370
|
+
npm run build:client # src/client/** → lib/client.js (build artifact)
|
|
371
|
+
npm run test # builds first, then node --test, one process per file
|
|
372
|
+
npm run test:local # restricted terminals / sandboxes: --test-isolation=none
|
|
373
|
+
npm run check # syntax check + artifact freshness
|
|
374
|
+
npm run build # npm pack (prepack builds and checks first), writes the .tgz
|
|
372
375
|
```
|
|
373
376
|
|
|
377
|
+
The client half lives in `src/client/**` (ESM, multiple files) and is bundled into the
|
|
378
|
+
single file `lib/client.js` by esbuild. **Do not edit `lib/client.js` by hand** — change
|
|
379
|
+
the sources and rebuild. Layout rules, naming and the release checklist are in
|
|
380
|
+
[AGENTS.md](AGENTS.md).
|
|
381
|
+
|
|
374
382
|
The suite covers host pure functions (path validation, `vscode://file` encoding,
|
|
375
383
|
loopback checks, route status codes) and the client module (module id, exports,
|
|
376
384
|
dependency whitelist, listener install/uninstall, slot registry). Integration
|
|
@@ -389,7 +397,10 @@ lib/host/launch.js VS Code / Explorer launching
|
|
|
389
397
|
lib/host/route.js /open, /session/delete and /workspace/delete routes, HTTP status codes
|
|
390
398
|
lib/host/session-delete.js transcript verification and deletion (detach / rm / re-check)
|
|
391
399
|
lib/host/workspace-delete.js workspace + all sessions deletion, workspace kept on failure
|
|
392
|
-
lib/client.js browser half
|
|
400
|
+
lib/client.js browser half build artifact (bundled from src/client/**, do not edit)
|
|
401
|
+
src/client/ browser sources: i18n, constants, styles, stores, ui, features
|
|
402
|
+
scripts/build-client.mjs esbuild bundler (--check verifies the artifact is fresh)
|
|
403
|
+
AGENTS.md repository conventions: layering, naming, build and release
|
|
393
404
|
cordis.patch.yml bundle patch inserting the plugin into the profile tree
|
|
394
405
|
scripts/install.ps1 pnpm-free install / uninstall
|
|
395
406
|
test/*.test.mjs node:test
|
|
@@ -486,8 +497,8 @@ mark only lives until "the panel for this gesture appeared", never into the next
|
|
|
486
497
|
Workspace rows on 0.2.2 take a different path: the host menu is built from each
|
|
487
498
|
`ctx.contextMenus.register` provider's `resolve`, which has no React entry to read the
|
|
488
499
|
mark, so the provider checks the same mark while resolving. The "…" pointerdown
|
|
489
|
-
clears it before the host resolves,
|
|
490
|
-
|
|
500
|
+
clears it before the host resolves, so the provider returns entries for the
|
|
501
|
+
right-click side or the "…" side according to each entry's "Menu placement".
|
|
491
502
|
|
|
492
503
|
### Why the conversation-body menu sorts by screen position
|
|
493
504
|
|
|
@@ -593,12 +604,12 @@ menus to a data-driven service, and the plugin picks the path by host capability
|
|
|
593
604
|
|
|
594
605
|
- **0.2.2+**: workspace entries are registered with `ctx.contextMenus.register`
|
|
595
606
|
(New session 90, Open in new tab 110, Copy workspace path 150, pinned app 210,
|
|
596
|
-
Open with 220,
|
|
607
|
+
Open with 220, default permission for new sessions 225, Delete workspace and all
|
|
608
|
+
sessions 310), interleaved by
|
|
597
609
|
order with the native Rename (100), Reveal (200) and Delete workspace (300) and
|
|
598
610
|
grouped with the same separators as the session menu.
|
|
599
|
-
Right-click and the "…" button share the host's single menu; providers answer
|
|
600
|
-
|
|
601
|
-
switch is on).
|
|
611
|
+
Right-click and the "…" button share the host's single menu; providers answer per
|
|
612
|
+
entry according to the right-click gesture and that entry's "Menu placement".
|
|
602
613
|
- **0.2.1**: no `contextMenus` service, so the plugin keeps drawing its own
|
|
603
614
|
workspace menu.
|
|
604
615
|
- **Session rows**: 0.2.2 still supports the
|
package/README.md
CHANGED
|
@@ -22,10 +22,10 @@ DSH 0.2.2 把侧栏右键改成数据驱动:工作区菜单由宿主统一渲
|
|
|
22
22
|
`sidebar.workspaces.session.menu.item` slot —— 内置动作和其他插件的动作都在里面,
|
|
23
23
|
本插件只追加自己的条目,不复制、不硬编码任何内置动作。
|
|
24
24
|
|
|
25
|
-
>
|
|
26
|
-
>
|
|
25
|
+
> 本插件的条目默认只在右键展开时出现;设置 →「行菜单」→「菜单显示位置」可以逐项改成
|
|
26
|
+
> 只进「…」菜单、或两边都进(至少保留一边)。
|
|
27
27
|
> 0.2.2 上右键与「…」共用同一份宿主菜单,插件按“右键手势”区分:右键时打标,等菜单面板
|
|
28
|
-
>
|
|
28
|
+
> 真正挂载后才收尾;点「…」的按下事件会立刻清标,所以那个菜单只带设为「…」或「两边」的条目。
|
|
29
29
|
> 右键展开的菜单不会因为鼠标移出而关闭,只有点击外部、选中条目或按 Esc 才关闭。
|
|
30
30
|
|
|
31
31
|
## 功能
|
|
@@ -34,10 +34,10 @@ DSH 0.2.2 把侧栏右键改成数据驱动:工作区菜单由宿主统一渲
|
|
|
34
34
|
|
|
35
35
|
0.2.2 上这份菜单由宿主渲染,本插件条目与内置「重命名」(100)、「在文件夹显示」(200)、
|
|
36
36
|
「删除工作区」(300)按 order 交错,分组规则与会话菜单一致:新会话 90、在新标签打开 110、
|
|
37
|
-
归档会话开关 130、复制工作区路径 150、置顶应用 210、打开方式 220
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
37
|
+
归档会话开关 130、复制工作区路径 150、置顶应用 210、打开方式 220、新会话默认权限 225、
|
|
38
|
+
删除工作区及所有会话 310。这些条目默认只出现在右键菜单;行尾「…」里的菜单保持原生,
|
|
39
|
+
想让它也带上插件条目,可在设置 →「行菜单」→「菜单显示位置」里逐项选择「…」或「两边」。
|
|
40
|
+
0.2.1 上整份菜单由本插件自绘,「重命名」「删除工作区」由插件调用官方对话框。
|
|
41
41
|
|
|
42
42
|
| 菜单项 | 行为 |
|
|
43
43
|
| --- | --- |
|
|
@@ -49,6 +49,7 @@ DSH 0.2.2 把侧栏右键改成数据驱动:工作区菜单由宿主统一渲
|
|
|
49
49
|
| 在文件夹显示(内置) | 在资源管理器里打开工作区目录;0.2.2 由宿主提供,0.2.1 上不出现 |
|
|
50
50
|
| 置顶的打开方式 | 被置顶的应用直接显示在一级菜单(例如「用 Visual Studio Code 打开」),点击后用该应用打开工作区目录 |
|
|
51
51
|
| 打开方式 | 二级菜单列出宿主提供的外部应用(编辑器、终端、文件管理器);与会话菜单共用同一套应用列表、置顶与开关设置,鼠标悬浮自动展开。宿主的菜单项不画二级箭头,本插件把标签渲染成「文字 + 右对齐箭头」,与会话菜单同一位置;0.2.1 自绘菜单画的是箭头图标 |
|
|
52
|
+
| 新会话默认权限 | 二级菜单列出宿主原生权限预设(仅可查看 / 工作区内修改 / 完全权限)。选中的预设成为**该工作区下以后新建会话**的默认权限,当前生效项右侧打勾;「跟随全局默认」清除本工作区的设置。只改新会话,不动已有会话 |
|
|
52
53
|
| 删除工作区(内置) | 打开官方删除确认对话框;只删除工作区登记,会话保留并归入「未分组」。0.2.1 上由本插件代为渲染 |
|
|
53
54
|
| 删除工作区及所有会话 | 先永久删除该工作区下的每个会话及其日志,全部成功后再删除工作区登记;任一会话删除失败则保留工作区,便于重试。工作区目录本身不删除 |
|
|
54
55
|
|
|
@@ -77,17 +78,16 @@ DSH 0.2.2 把侧栏右键改成数据驱动:工作区菜单由宿主统一渲
|
|
|
77
78
|
一级菜单。两个删除入口由本插件自己的宿主路由完成,默认不会删除未归档会话;
|
|
78
79
|
开启「允许删除未归档会话」后才会对普通会话开放。删除不会级联删除 fork 子会话。
|
|
79
80
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
「…」的按下事件会立刻清标。标记有效期内的条目正常渲染,其余情况渲染直接返回 `null`。
|
|
81
|
+
这些条目默认出现在**右键菜单**。想直接使用行尾「…」菜单,可以在设置 →「行菜单」→
|
|
82
|
+
「菜单显示位置」里逐项选择:
|
|
83
83
|
|
|
84
|
-
|
|
84
|
+
- 「…」菜单:条目只出现在行尾「…」打开的菜单里,右键菜单不再显示;
|
|
85
|
+
- 「两边」:右键和「…」都显示;
|
|
86
|
+
- 「右键菜单」:默认值,只在右键菜单里出现。
|
|
85
87
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
- 工作区条目(0.2.1):开启任意一项后,本插件接管行尾「…」按钮,用同一套菜单展示
|
|
90
|
-
官方「重命名 / 删除工作区」加上已开启的插件条目。
|
|
88
|
+
每个条目至少要保留一边,最后一边的开关会被锁住。会话条目与工作区条目(0.2.2)都走同一套
|
|
89
|
+
`contextMenus` provider,按手势标记决定当前是哪份菜单;工作区条目在 0.2.1 上由本插件接管
|
|
90
|
+
行尾「…」按钮自绘,规则一致。
|
|
91
91
|
|
|
92
92
|
草稿会话(还没有任何消息的空白会话)没有右键菜单,本插件同样不接管。
|
|
93
93
|
非工作区 / 非会话的侧边栏行(如“显示更多”)也不会被拦截。
|
|
@@ -134,22 +134,23 @@ DSH 0.2.2 把侧栏右键改成数据驱动:工作区菜单由宿主统一渲
|
|
|
134
134
|
| 允许删除未归档会话 | 默认关闭;开启后未归档会话的右键菜单也会出现「永久删除会话」,需先开启上一项 |
|
|
135
135
|
| 删除所有已归档会话 | 关闭后不再出现批量删除入口 |
|
|
136
136
|
| 显示已归档会话 | 关闭后工作区菜单里不再出现「显示 / 隐藏已归档会话」(默认开启;该项只在当前工作区存在已归档会话时出现) |
|
|
137
|
-
|
|
|
138
|
-
|
|
|
137
|
+
| 菜单显示位置 → 工作区 | 逐项选择工作区行条目出现在右键菜单、「…」菜单,或两边:新会话、新会话默认权限、打开方式、复制工作区路径、在新标签中打开、归档会话开关、删除工作区及所有会话 |
|
|
138
|
+
| 菜单显示位置 → 会话 | 逐项选择会话行条目的显示位置:打开方式、永久删除会话、删除所有已归档会话 |
|
|
139
139
|
| 启用空白处右键菜单 | 会话正文(空白处、思考过程、回复)的右键菜单总开关(默认开启);关闭后该区域恢复浏览器 / 宿主的原生菜单 |
|
|
140
140
|
| 「更多」固定在最右 | 默认开启;把「更多操作」一类的溢出入口固定在菜单最后一项,不受工具条当前顺序影响 |
|
|
141
141
|
| 显示左上角状态组件 | 默认关闭;打开后会话栏左上角 `conversation.session.header.actions` 槽位里的组件(费用明细、后台任务计数等)也会列进正文右键菜单 |
|
|
142
142
|
|
|
143
|
-
|
|
143
|
+
「菜单显示位置」默认全部是「右键菜单」,所以未改动时 `…` 菜单与 DSH 完全一致。
|
|
144
144
|
|
|
145
|
-
DSH 0.2.2
|
|
146
|
-
|
|
147
|
-
|
|
145
|
+
DSH 0.2.2 起行尾「…」与右键共用同一份宿主菜单,插件条目按手势标记区分当前是哪份菜单;
|
|
146
|
+
设为「…」或「两边」的条目才会进入「…」菜单。0.2.1 上工作区行没有宿主菜单可贡献,
|
|
147
|
+
改由插件接管「…」按钮自绘,显示规则相同。
|
|
148
148
|
|
|
149
149
|
开关存在浏览器 `localStorage`(`dsh.sidebar-row-menu.items.v1`、
|
|
150
150
|
`dsh.sidebar-row-menu.open-with.v1`、`dsh.sidebar-row-menu.open-with.pinned.v1`、
|
|
151
|
-
`dsh.sidebar-row-menu.
|
|
152
|
-
|
|
151
|
+
`dsh.sidebar-row-menu.placement.v1` 与 `dsh.sidebar-row-menu.blank-menu.v1`),
|
|
152
|
+
改完立即生效,不需要重启。旧版的 `dsh.sidebar-row-menu.ellipsis.v1`(布尔值)会在首次加载时
|
|
153
|
+
自动迁移成「两边 / 右键菜单」。置顶项在第一次配置前是自动推导的:优先置顶检测到的第一个
|
|
153
154
|
编辑器(通常是 VS Code),没有编辑器时置顶应用列表里的第一个。
|
|
154
155
|
|
|
155
156
|
### 与 dsh-session-menu 共存
|
|
@@ -312,11 +313,18 @@ cmd /c rmdir "$env:USERPROFILE\.dsh\profiles\desktop\node_modules\dsh-sidebar-ro
|
|
|
312
313
|
## 开发
|
|
313
314
|
|
|
314
315
|
```powershell
|
|
315
|
-
npm
|
|
316
|
-
npm run
|
|
317
|
-
npm run
|
|
316
|
+
npm install # 只装 esbuild(唯一的 devDependency)
|
|
317
|
+
npm run build:client # src/client/** → lib/client.js(构建产物)
|
|
318
|
+
npm run test # 先构建再跑 node --test,逐文件子进程
|
|
319
|
+
npm run test:local # 受限终端 / 沙箱:--test-isolation=none,同进程跑
|
|
320
|
+
npm run check # 语法检查 + 产物与源码是否一致
|
|
321
|
+
npm run build # npm pack(prepack 会先构建 + check),产出 .tgz
|
|
318
322
|
```
|
|
319
323
|
|
|
324
|
+
客户端源码在 `src/client/**`(ESM,多文件),由 esbuild 打包成单文件 `lib/client.js`;
|
|
325
|
+
**不要手改 `lib/client.js`**,改完源码要重新构建。目录分层、命名、构建与发布约定见
|
|
326
|
+
[AGENTS.md](AGENTS.md)。
|
|
327
|
+
|
|
320
328
|
测试覆盖宿主侧纯函数(路径校验、`vscode://file` 编码、loopback 判定、路由状态码)
|
|
321
329
|
和客户端模块(模块 id、导出、依赖白名单、监听器安装/卸载、slot 注册表),并用伪造的
|
|
322
330
|
`__reactFiber$`、DOM 与 `Menu` 宿主做集成测试:工作区右键的菜单项顺序、会话右键是否
|
|
@@ -334,7 +342,10 @@ lib/host/launch.js VS Code / 资源管理器启动
|
|
|
334
342
|
lib/host/route.js /open、/session/delete 与 /workspace/delete 路由、HTTP 状态码
|
|
335
343
|
lib/host/session-delete.js 会话日志目录的校验与删除(detach / rm / 复查)
|
|
336
344
|
lib/host/workspace-delete.js 删除工作区及其所有会话;会话失败时保留工作区
|
|
337
|
-
lib/client.js
|
|
345
|
+
lib/client.js 客户端半边构建产物(由 src/client/** 打包,勿手改)
|
|
346
|
+
src/client/ 客户端源码:i18n、常量、样式、store、ui、features
|
|
347
|
+
scripts/build-client.mjs esbuild 打包脚本(--check 校验产物是否最新)
|
|
348
|
+
AGENTS.md 仓库约定:分层、命名、构建与发布
|
|
338
349
|
cordis.patch.yml bundle patch:把插件插进 profile 插件树
|
|
339
350
|
scripts/install.ps1 无 pnpm 的安装 / 卸载脚本
|
|
340
351
|
test/*.test.mjs node:test
|
|
@@ -412,8 +423,9 @@ DSH 的归档可见性只有一个全局筛选(`archivedFilter`:隐藏已归
|
|
|
412
423
|
|
|
413
424
|
工作区行在 0.2.2 上走的是另一条路:宿主菜单的数据来自 `ctx.contextMenus.register` 的
|
|
414
425
|
`resolve`,没有 React 条目可以读标记,所以 provider 在解析时直接判断同一枚手势标记,
|
|
415
|
-
并且行尾「…」的 `pointerdown` 清标发生在宿主解析之前 ——
|
|
416
|
-
|
|
426
|
+
并且行尾「…」的 `pointerdown` 清标发生在宿主解析之前 —— 右键时按「右键菜单 / 两边」
|
|
427
|
+
返回条目,点「…」时按「… 菜单 / 两边」返回。「菜单显示位置」的开关让 provider 分别
|
|
428
|
+
跳过一侧的手势判断。
|
|
417
429
|
|
|
418
430
|
### 会话正文右键为什么按视觉顺序
|
|
419
431
|
|
|
@@ -508,10 +520,11 @@ DSH 宿主按该范围拒绝安装不兼容的宿主,插件市场也按它显
|
|
|
508
520
|
与 `contextMenus` 实现适配。DSH 0.2.2 起把侧栏右键菜单改成数据驱动,本包按宿主能力自动选路:
|
|
509
521
|
|
|
510
522
|
- **0.2.2 及以上**:工作区行改用 `ctx.contextMenus.register` 贡献动作
|
|
511
|
-
(新会话 90、新标签 110、复制路径 150、置顶应用 210、打开方式 220
|
|
523
|
+
(新会话 90、新标签 110、复制路径 150、置顶应用 210、打开方式 220、新会话默认权限 225、
|
|
524
|
+
删除工作区及所有会话 310),
|
|
512
525
|
与原生「重命名」「在文件夹显示」「删除工作区」按 order 交错排列;分组分隔线与会话菜单同一
|
|
513
526
|
套规则。右键与「…」共用同一份宿主菜单,插件不再自绘,也不再接管「…」按钮。provider 解析时
|
|
514
|
-
|
|
527
|
+
按右键手势与每项的「菜单显示位置」决定是否返回条目。会话行由宿主自己把原生
|
|
515
528
|
菜单开在指针处,本包条目继续从 `sidebar.workspaces.session.menu.item` 渲染;
|
|
516
529
|
- **0.2.1**:没有 `contextMenus` 服务,保持原来的自绘工作区菜单;会话右键仍由插件把
|
|
517
530
|
行尾「…」菜单搬到指针。
|