dsh-workspace-plus 0.2.0 → 0.4.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/README.md +135 -38
- package/lib/client.js +1867 -1653
- package/lib/index.js +790 -707
- package/package.json +65 -65
package/README.md
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# dsh-workspace-plus
|
|
2
|
+
[](https://dsh-plugin.org/plugins/sen70s/dsh-workspace-plus)
|
|
2
3
|
|
|
3
4
|
DeepSeek Harness Web GUI 的插件。一个功能,三个入口:
|
|
4
5
|
|
|
@@ -6,7 +7,7 @@ DeepSeek Harness Web GUI 的插件。一个功能,三个入口:
|
|
|
6
7
|
| --- | --- |
|
|
7
8
|
| **工作区行上的目录按钮**(弹窗) | 一个工作区登记 N 个目录,每个目录带标签;标签在对话里可直接指代 |
|
|
8
9
|
| **对话输入框里的 `@`** | 打 `@` 就能看到本工作区的标签,选中即插入一个指向该目录绝对路径的引用 |
|
|
9
|
-
| **设置 → `workspace+`** |
|
|
10
|
+
| **设置 → `workspace+`** | **每个工作区一个开关**:是否在该工作区启用本功能(默认工作区默认关闭) |
|
|
10
11
|
|
|
11
12
|
它解决的问题:一个工作区(DSH 里 = 一个目录)装不下真实项目。前后端分在两个仓库、文档在第三个目录时,
|
|
12
13
|
每次都要在对话里手写绝对路径,而且目录名相似时 agent 容易改错文件。本插件让工作区带上
|
|
@@ -16,6 +17,12 @@ DeepSeek Harness Web GUI 的插件。一个功能,三个入口:
|
|
|
16
17
|
>
|
|
17
18
|
> agent 直接去 `D:\proj\backend`,不会因为旁边有个 `D:\proj\backend-legacy` 而改错。
|
|
18
19
|
|
|
20
|
+
名字相似的目录摆在一处,本就是容易出事的地方。让机器记住哪个是哪个,比每次都由人在对话里
|
|
21
|
+
把路径抄一遍要可靠些 —— 抄写这桩事,人向来是做不过机器的;而记错门牌这桩事,机器又向来是做不过人的。
|
|
22
|
+
插件能做的,只是把它擅长的那一半接过来。
|
|
23
|
+
|
|
24
|
+
> 想先看看它长什么样、怎么用:[**使用**](#使用) 一节里配了截图。
|
|
25
|
+
|
|
19
26
|
> 本仓库只包含插件本身;没有改动 DSH 安装目录里的任何文件。state 文件由插件自己写在 `~/.dsh/workspaceplus/`。
|
|
20
27
|
|
|
21
28
|
## 目录结构
|
|
@@ -29,7 +36,9 @@ dsh-workspace-plus/
|
|
|
29
36
|
│ └── client.js # 浏览器半:设置页 + 目录弹窗 + 工作区行按钮(无需构建)
|
|
30
37
|
├── icon.svg # 插件管理页显示的图标
|
|
31
38
|
├── LICENSE # MIT
|
|
32
|
-
├──
|
|
39
|
+
├── docs/ # README 里那几张截图
|
|
40
|
+
├── tools/verify.mjs # 离线自检(387 项断言,不需要 DSH 在跑)
|
|
41
|
+
├── tools/preview/ # 截图是怎么来的:真实 React + 真实壳层样式 + 无头 Edge(见其 README)
|
|
33
42
|
└── README.md
|
|
34
43
|
```
|
|
35
44
|
|
|
@@ -38,15 +47,18 @@ dsh-workspace-plus/
|
|
|
38
47
|
|
|
39
48
|
## 设置:设置 → `workspace+`
|
|
40
49
|
|
|
41
|
-
|
|
50
|
+
**每个工作区一个开关**:这个工作区里启用还是停用 workspace+。一个开关同时管三处 ——
|
|
51
|
+
工作区行上的目录按钮、注入该工作区对话的标签表、以及 `workspace_dirs` 工具。
|
|
52
|
+
关掉**不会删除**已登记的标签,只是让这个工作区暂时不参与。
|
|
42
53
|
|
|
43
|
-
|
|
44
|
-
指向它,即使它的注册被删掉这个身份也会保留)。它属于产品而不属于本插件,所以:
|
|
54
|
+
默认值不是一刀切:
|
|
45
55
|
|
|
46
|
-
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
56
|
+
- 除默认工作区外,**每个工作区默认开启**。
|
|
57
|
+
- 「默认工作区」是 DSH 首次启动时自动创建的那个(`workspaceRegistry` 里 `defaultWorkspaceId`
|
|
58
|
+
指向它,即使它的注册被删掉这个身份也会保留)。它属于产品而不属于本插件,所以**默认关闭**:
|
|
59
|
+
不显示目录按钮、不注入上下文、`workspace_dirs` 对它直接返回一个指向上面的开关的错误。
|
|
60
|
+
在设置页打开它自己那一行的开关即可,无需重启、无需刷新。
|
|
61
|
+
- 拨动开关写的是**这个工作区的显式值**,所以它一定覆盖默认值;设置页不会因为「默认值恰好相同」而装作没生效。
|
|
50
62
|
|
|
51
63
|
宿主怎么认出默认工作区:它只调用**公开的** `workspaceRegistry.initializeDefault()`,
|
|
52
64
|
并传一个「拒绝创建」的目录解析器 —— 已有默认工作区时该调用直接返回它(无副作用),
|
|
@@ -56,6 +68,26 @@ dsh-workspace-plus/
|
|
|
56
68
|
> 首次探测可能早于注册表服务初始化完成而失败。失败时状态保持「未决」并在下一次请求/工具调用时重试,
|
|
57
69
|
> 而不是把「没有默认工作区」永久缓存下来 —— 否则默认工作区会被静默启用。
|
|
58
70
|
|
|
71
|
+
### 设置是怎么存的
|
|
72
|
+
|
|
73
|
+
```json
|
|
74
|
+
{
|
|
75
|
+
"settings": {
|
|
76
|
+
"defaultWorkspaceEnabled": false,
|
|
77
|
+
"workspaceEnabled": { "d:\\projects\\api": false }
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
- `workspaceEnabled` 是**按工作区**那一层:键是工作区目录(和 `workspaces` 一样大小写折叠),
|
|
83
|
+
值 `true` / `false` 是显式覆盖。
|
|
84
|
+
- 键由宿主下发(`/workspaceplus/api` 快照里每个工作区的 `key`),浏览器半**不会**自己从路径猜 ——
|
|
85
|
+
Windows 下大小写折叠规则一旦不一致,猜出来的键会「存得进去但永远匹配不上」,是个静默失效。
|
|
86
|
+
旧宿主没有这个字段时,设置页把开关置灰并提示重启 dsh。
|
|
87
|
+
- `defaultWorkspaceEnabled` 是「默认工作区那一行的默认值」。字段保留是为了兼容旧状态文件,
|
|
88
|
+
正常使用中不需要手改;在设置页拨默认工作区那一行写入的是 `workspaceEnabled` 里的显式覆盖。
|
|
89
|
+
- 旧状态文件(没有 `settings`,或没有 `workspaceEnabled`)照常工作:缺失的那层归一化成「没有覆盖」。
|
|
90
|
+
|
|
59
91
|
## 功能是怎么工作的
|
|
60
92
|
|
|
61
93
|
### 数据
|
|
@@ -65,6 +97,7 @@ dsh-workspace-plus/
|
|
|
65
97
|
```json
|
|
66
98
|
{
|
|
67
99
|
"version": 1,
|
|
100
|
+
"settings": { "defaultWorkspaceEnabled": false, "workspaceEnabled": {} },
|
|
68
101
|
"workspaces": {
|
|
69
102
|
"d:\\proj": {
|
|
70
103
|
"path": "D:\\proj",
|
|
@@ -126,7 +159,7 @@ dsh-workspace-plus/
|
|
|
126
159
|
> 「Workspace row menus are visual-only except Rename/Delete」,
|
|
127
160
|
> 代码里 `ProjectRowItem` 也只收到 `actions: { rename, delete }`。
|
|
128
161
|
|
|
129
|
-
所以「往那个菜单里加一项」无法用官方 API
|
|
162
|
+
所以「往那个菜单里加一项」无法用官方 API 做到。替代方案是把按钮**插进该行的操作区**
|
|
130
163
|
(`rowActions`),定位不依赖易变的哈希类名,而用壳层自己发出的稳定锚点:
|
|
131
164
|
|
|
132
165
|
- `data-slot="sidebar.workspaces"` —— 渲染器给每个 slot 出口都加的锚(`SlotOutlet`)
|
|
@@ -134,9 +167,14 @@ dsh-workspace-plus/
|
|
|
134
167
|
`buildGroup(workspace.workspaceId, workspace.workspaceId, …)` 保证这个 key **就是** workspace id,
|
|
135
168
|
与宿主 `workspaceRegistry` 的 `Workspace.id`(客户端 `workspaceView().workspaceId`)一致
|
|
136
169
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
170
|
+
**位置:夹在中间。** 壳层渲染的操作区是 `[「更多」菜单, 「新会话」按钮]`,本插件的按钮插在
|
|
171
|
+
**最后一个子节点之前**,于是那一行读作「更多 · 工作区目录设置 · 新会话」,新会话保持最后一个。
|
|
172
|
+
(`insertBefore(node, null)` 等价于 append,所以操作区只有一个子节点时会退化成「排在菜单之后」,
|
|
173
|
+
而不是硬造一对不存在的顺序。)
|
|
174
|
+
|
|
175
|
+
React 重渲染时并不知道这个节点的存在,可能把自己的子节点重新插到它两边,所以**位置是每次对账都重新
|
|
176
|
+
确认的**,不是创建时设一次。对账由 `MutationObserver` 驱动,覆盖增、删、移位三种情况,
|
|
177
|
+
重复对账是幂等的。点击时 `preventDefault + stopPropagation`,所以不会触发行本身的展开/折叠。
|
|
140
178
|
|
|
141
179
|
外观上刻意对齐壳层自己的行内按钮(`Rows.module.css` 的 `.iconButton`):16×16、无边框、无底色、
|
|
142
180
|
`color: label-tertiary`,**hover 只变颜色不加背景**;图标直接复用官方的文件夹图形
|
|
@@ -149,15 +187,20 @@ dsh-workspace-plus/
|
|
|
149
187
|
侧边栏不会多出任何图标(有一个 1.2s 的 settle 窗口避免闪烁)。
|
|
150
188
|
|
|
151
189
|
弹窗**锁定触发它的那个工作区**:从哪个工作区行点的,就只编辑那个工作区,弹窗里没有选择器,
|
|
152
|
-
|
|
190
|
+
只显示工作区名和根目录。卡片宽度是 `min(760px, 100%)`(壳层默认的 380px 装不下一行
|
|
191
|
+
「标签 + 绝对路径 + 说明 + 行尾图标」)。位于工作区根目录之外的目录,行尾是一个**黄色盾牌图标**,
|
|
192
|
+
说明放在 hover / 键盘聚焦才出现的 tooltip 里(见下面的沙箱一节)。
|
|
153
193
|
如果 HTTP 通道不可用,弹窗会明确说明原因(区分 401 / 404 / 传输不可达),而不是假装映射是空的 ——
|
|
154
194
|
此时仍然可以在对话里用 `workspace_dirs` 管理。
|
|
155
195
|
|
|
156
|
-
|
|
157
|
-
`ctx.uiWorkspace.pickDirectory()
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
`
|
|
196
|
+
**路径没有手动输入框**:添加表单的第一行就是一个字段样式的按钮(文件夹图标 + 「选择目录…」),
|
|
197
|
+
**点击它直接打开系统的目录选择器**,也就是壳层自己的 `ctx.uiWorkspace.pickDirectory()`
|
|
198
|
+
(就是「选择工作区」用的那一个),所以桌面版是原生对话框、浏览器版是壳层的浏览面板。
|
|
199
|
+
选中后路径显示在这个字段里,**标签为空时**还会按目录名猜一个合法标签
|
|
200
|
+
(`D:\proj\my api` → `my-api`;纯中文目录名不猜,避免塞一个宿主会拒绝的标签);
|
|
201
|
+
标签和说明在同一行,路径在它们的上一行。取消选择不会改动任何字段。
|
|
202
|
+
路径为空时「添加」保持禁用;`ui-workspace` 没有挂载时(合成里没有这一行)这个字段自动置灰,
|
|
203
|
+
并用 `title` 说明改用 `workspace_dirs`,插件其余部分照常工作。
|
|
161
204
|
|
|
162
205
|
> 唯一的例外是兜底入口:它是全局的、没有工作区上下文,所以那条路径下弹窗会退回显示选择器。
|
|
163
206
|
> 正常使用中不会看到它。
|
|
@@ -180,7 +223,7 @@ dsh-workspace-plus/
|
|
|
180
223
|
| 事项 | 做法 |
|
|
181
224
|
| --- | --- |
|
|
182
225
|
| 注册 | `ctx.inject(['inputTriggers'], …)` → `registerSource({ trigger: '@', name: 'workspace-plus', … })`;`(trigger, name)` 必须唯一,`@reference` 是官方占用的 |
|
|
183
|
-
| 候选 | 所有 `enabled !== false`
|
|
226
|
+
| 候选 | 所有 `enabled !== false` 且登记了目录的工作区;被设置页关掉的工作区自然被排除 |
|
|
184
227
|
| 排序 | 从管道给的 `{ sessionId }` 反查 cwd(`sessions.list` 投影,与 `ui-reference`/`ui-session` 同一处),命中的工作区提到最前;读不到就按原序 |
|
|
185
228
|
| **必须是 async** | 管线是 `source.candidates(...).then(...)` 直接调用 —— 同步返回数组会在它自己的循环里抛错 |
|
|
186
229
|
| 分组标题 | `showGroupTitle: false` + 每行自带 `section`(工作区标题),否则标题会是管道字典里查不到的 key |
|
|
@@ -241,7 +284,7 @@ for (const root of writableRoots(policy)) if (await isPathUnder(fresh.targetKey,
|
|
|
241
284
|
2. 保持 `workspace-write`,接受每次越界写入弹一次批准(agent 会按工具提示发起升级)。
|
|
242
285
|
|
|
243
286
|
插件本身不做任何绕过沙箱的事,只是把限制如实告诉 agent(上下文里会标注哪些目录在根目录之外)
|
|
244
|
-
|
|
287
|
+
和界面(行尾一个黄色盾牌图标,悬浮或键盘聚焦时用 tooltip 说明原因)。
|
|
245
288
|
|
|
246
289
|
## 安装
|
|
247
290
|
|
|
@@ -260,14 +303,14 @@ dsh plugin --profile desktop add <本地 checkout 目录>
|
|
|
260
303
|
|
|
261
304
|
`lib/` 是仓库里已提交的产物、包内没有 `prepare` 构建脚本,所以上面三种方式都不需要
|
|
262
305
|
pnpm 的 `allowBuilds` 构建授权,装到的就是可直接加载的代码。想锁定版本可以用
|
|
263
|
-
`github:Sen70s/dsh-workspace-plus#v0.
|
|
306
|
+
`github:Sen70s/dsh-workspace-plus#v0.4.0`。要求 DSH `>=0.1.7-rc.2`(桌面版当前就是
|
|
264
307
|
`@deepseek-ai/dsh-desktop 0.1.7-rc.2`;npm 上是 `next` 通道)。
|
|
265
308
|
|
|
266
309
|
> 0.1.0 曾以包名 `dsh-workspaceplus` 发布;自 0.1.1 起更名为 `dsh-workspace-plus`,旧包已废弃,
|
|
267
310
|
> 请勿再安装。
|
|
268
311
|
|
|
269
312
|
装完后**重启 `dsh`** 并刷新页面。悬停任一工作区那一行,操作区会多出一个目录图标,点它打开弹窗;
|
|
270
|
-
设置面板里会多出一个 `workspace+`
|
|
313
|
+
设置面板里会多出一个 `workspace+` 分区(默认工作区那一行默认关着,其它工作区默认开着,见下一节);
|
|
271
314
|
对话输入框里打 `@` 会多出一组「工作区目录」候选。
|
|
272
315
|
|
|
273
316
|
卸载:
|
|
@@ -278,18 +321,62 @@ dsh plugin --profile desktop remove dsh-workspace-plus
|
|
|
278
321
|
|
|
279
322
|
## 使用
|
|
280
323
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
324
|
+
我向来不惮于把话说明白,只是插件的用法,说一遍也就够了,不必绕弯子。
|
|
325
|
+
|
|
326
|
+
### 一、先把目录登记上
|
|
327
|
+
|
|
328
|
+
把鼠标停在左侧边栏的任意一个工作区上,那一行的右边会浮出三个小东西。头一个是「更多」,末尾一个是「新会话」,中间那个文件夹,是本插件的。
|
|
329
|
+
|
|
330
|
+

|
|
331
|
+
|
|
332
|
+
它排在中间,不是末尾 —— 末尾那个位置是壳层的,我不去占。人有各人的座位,插件也一样。
|
|
333
|
+
|
|
334
|
+
点它,「工作区目录设置」就开出来了:
|
|
335
|
+
|
|
336
|
+

|
|
284
337
|
|
|
285
|
-
|
|
338
|
+
表格里是已经登记过的目录,一行一个:标签、绝对路径、说明,如此而已。若某个目录在工作区根目录之外,行尾会立一个小小的黄盾牌 —— 这个下面再讲。
|
|
286
339
|
|
|
287
|
-
|
|
288
|
-
|
|
340
|
+
**路径是不用手打的。** 表单最上头那个带文件夹图标的格子,它本身就是个按钮。点它,系统的目录选择器就开了:
|
|
341
|
+
|
|
342
|
+

|
|
343
|
+
|
|
344
|
+
选中之后,路径落进格子里;标签若还空着,便从目录名里猜一个(`D:\proj\my api` → `my-api`;纯中文的目录名不猜,因为宿主不收,猜了也是白猜)。再补一句说明,点「添加」,完事。标签和说明占同一行,路径在它们上面那一行 —— 三样东西原本挤作一处,那是我的不是。
|
|
345
|
+
|
|
346
|
+
### 二、那个黄盾牌
|
|
347
|
+
|
|
348
|
+
目录若在工作区根目录之外,它就立在那里,不写字。非得你把鼠标放上去,或者用键盘 Tab 把它聚焦了,它才开口:
|
|
349
|
+
|
|
350
|
+

|
|
351
|
+
|
|
352
|
+
说的是:DSH 的沙箱只认工作区根目录这一个可写根;会话权限不是 `danger-full-access` 的时候,根目录之外只能读,要写就得逐次批准。这不是插件不肯通融,是它本来就只有这一条路。
|
|
353
|
+
|
|
354
|
+
所以要图省事,**把工作区建在几个工程的共同父目录上**,让所有标签都落在里头。这是最省事的办法,也是唯一的办法。
|
|
355
|
+
|
|
356
|
+
### 三、开关,一个工作区一个
|
|
357
|
+
|
|
358
|
+
设置 → `workspace+`:
|
|
359
|
+
|
|
360
|
+

|
|
361
|
+
|
|
362
|
+
一个工作区一行,一行一个开关。这个开关管三件事:那一行的目录按钮出不出现、标签表注不注入这个工作区的对话、`workspace_dirs` 认不认这个工作区。
|
|
363
|
+
|
|
364
|
+
默认值并不整齐:**除默认工作区外,都默认是开的**;而默认工作区 —— 也就是 DSH 第一次启动时自己建起来的那一个 —— 默认关着。它属于产品,不属于这个插件,我不便替你做主。要用,把它那一行的开关拨开就是。
|
|
365
|
+
|
|
366
|
+
关掉**不会删掉标签**。哪天想起来了再拨回来,目录还在那里。
|
|
367
|
+
|
|
368
|
+
### 四、在对话里
|
|
369
|
+
|
|
370
|
+
前提是工作区 `D:\proj` 底下挂了 `backend` 和 `docs` 两个标签。于是:
|
|
371
|
+
|
|
372
|
+
- 打一个 `@`,菜单里多出一组「工作区目录」。选 `backend`,输入框里就落下一个 `backend` 的 chip —— 而**送给模型的是那个绝对路径**。这一点要紧:哪怕注入的标签表被上下文压缩挤掉了,模型手里那个路径也还是硬的。
|
|
373
|
+
- 「把 `D:\proj\backend` 记成 backend,说明写后端 API」→ agent 调 `workspace_dirs add`
|
|
289
374
|
- 「现在有哪些标签?」→ `workspace_dirs list`
|
|
290
|
-
-
|
|
291
|
-
- 「删掉 docs
|
|
292
|
-
-
|
|
375
|
+
- 「backend 改指向 `D:\proj\backend-v2`」→ `workspace_dirs update`
|
|
376
|
+
- 「删掉 docs」→ `workspace_dirs remove`
|
|
377
|
+
- 诸事办完,才可以说那句:「backend 加个健康检查接口」。agent 去的是 `D:\proj\backend`,不会因为隔壁站着一个 `backend-legacy` 就摸错了门。
|
|
378
|
+
|
|
379
|
+
标签表是每次请求都注入的,所以上面这些,多数时候你不说,它也晓得。
|
|
293
380
|
|
|
294
381
|
## 自检
|
|
295
382
|
|
|
@@ -299,7 +386,7 @@ dsh plugin --profile desktop remove dsh-workspace-plus
|
|
|
299
386
|
node tools/verify.mjs
|
|
300
387
|
```
|
|
301
388
|
|
|
302
|
-
它会(当前 `
|
|
389
|
+
它会(当前 `387/387 checks passed`,另有 1 项按环境跳过):
|
|
303
390
|
|
|
304
391
|
- 校验 manifest、patch 层、`dsh.client.inject` 的取值;
|
|
305
392
|
- 用临时 `DSH_HOME` 运行宿主半:标签/路径校验、增删改、去重、大小写折叠、损坏文件容错、原子写;
|
|
@@ -310,13 +397,22 @@ node tools/verify.mjs
|
|
|
310
397
|
点击只开弹窗而不冒泡到行、dispose 清理干净;
|
|
311
398
|
- 校验弹窗的外部 store(打开/切换/关闭/退订)与各槽位注册,
|
|
312
399
|
校验行按钮 CSS 与壳层 `.iconButton` 的度量一致(16×16、无底色、hover 只变色),
|
|
313
|
-
|
|
400
|
+
校验样式表在**模块热重载**后仍是一个、且是当前版本的 tag(不会新旧并存),
|
|
401
|
+
校验**按钮的位置**(落在「更多」和「新会话」之间、新会话保持最后一个、被 React 挤走后会自动归位、
|
|
402
|
+
只有一个子节点时退化为排在菜单之后、dispose 后壳层自己的按钮原样不动),
|
|
403
|
+
校验**工作区闸门**(宿主快照标 disabled 后行按钮消失、开关打开后回来、探测失败会重试),
|
|
404
|
+
校验**按工作区设置**(覆盖能关掉一个平时开着的工作区、也能打开默认工作区、覆盖优先于默认值、
|
|
405
|
+
`null` 恢复默认、非法值整批拒绝且一个字节都不写、旧状态文件缺这一层照常工作、
|
|
406
|
+
设置页一个工作区一个开关、按键由宿主下发而不是从路径猜、旧宿主没有 key 时置灰并提示),
|
|
407
|
+
- 校验**弹窗的形状**(卡片被拉宽到 760px、description 与脚注都不再渲染、
|
|
408
|
+
「工作区根目录之外」不再是行内文字而是带 tooltip 的盾牌图标、路径是控件而不是输入框且位于标签行之上、
|
|
409
|
+
路径为空时「添加」禁用),
|
|
314
410
|
校验**目录选择器**(标签猜测始终满足宿主语法、取消不改变任何字段、失败被捕获并给出原因、
|
|
315
|
-
没有挂载 ui-workspace
|
|
411
|
+
没有挂载 ui-workspace 时字段自动置灰且不会调用),
|
|
316
412
|
- 校验 **`@` source**(触发器的唯一性、`candidates` 返回 thenable、按标签/说明/路径过滤、
|
|
317
413
|
默认工作区关闭时不出候选、pick 产出的 chip 与它序列化出的绝对路径一致、坏 payload 不插入),
|
|
318
|
-
并用最小 React + Button/Switch/Modal
|
|
319
|
-
共享快照更新)与弹窗/面板的各状态文案。
|
|
414
|
+
并用最小 React + Button/Switch/Modal/Tooltip 桩**真实渲染**设置页(每个工作区一个开关 →
|
|
415
|
+
POST 一次按键的 settings op → 共享快照更新)与弹窗/面板的各状态文案。
|
|
320
416
|
|
|
321
417
|
## 故障排查
|
|
322
418
|
|
|
@@ -338,7 +434,8 @@ node tools/verify.mjs
|
|
|
338
434
|
### 工作区行上没有出现目录按钮
|
|
339
435
|
|
|
340
436
|
1. 先确认宿主半已加载(见下一条的判据)。
|
|
341
|
-
2.
|
|
437
|
+
2. **这个工作区在 设置 → `workspace+` 里被关着**:默认工作区默认就是关的,其它工作区如果显示关了,
|
|
438
|
+
说明有人(或某个旧开关)把它关掉了 —— 打开它自己那一行即可,无需重启或刷新。
|
|
342
439
|
3. 悬停工作区行才会显示操作区,这是壳层的行为。
|
|
343
440
|
4. 兜底入口会在 1.2s 后出现在侧边栏(`workdirs`);如果它出现了,说明行锚点没匹配上 ——
|
|
344
441
|
多半是 DSH 升级改了行 DOM。此时功能仍然可用(走 `workspace_dirs` 工具或兜底入口),
|