dsh-folder-sidebar 0.17.1 → 0.18.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/CHANGELOG.md +9 -0
- package/README.md +181 -180
- package/client.js +1837 -1766
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.18.0
|
|
4
|
+
|
|
5
|
+
- 长名称不再只能看省略号:悬停行(会话、文件夹、未分组、搜索结果、面包屑文件夹名)时,放不下的标题会缓慢横向滚到末尾再回来;不溢出的标题完全不动,`prefers-reduced-motion` 下不滚动。
|
|
6
|
+
- 跑马灯位移与时长由纯函数 `marqueeShiftOf` / `marqueeDurationOf` 计算,已加入 `test/logic.test.mjs` 覆盖(阈值、上下限、单调性)。
|
|
7
|
+
|
|
8
|
+
## 0.17.1
|
|
9
|
+
|
|
10
|
+
- 重新发布以完成 npm 的暂存审批(内容与 0.17.0 一致)。0.17.0 在 npm 上归档为未批准的暂存版本。
|
|
11
|
+
|
|
3
12
|
## 0.17.0 — first public release
|
|
4
13
|
|
|
5
14
|
首次公开发布。把 DSH 侧栏的「工作区 / 会话」列表换成分文件夹的进入式导航,并尽量与内置侧栏(`ui-workspace`)的语义和视觉对齐。
|
package/README.md
CHANGED
|
@@ -1,180 +1,181 @@
|
|
|
1
|
-
# dsh-folder-sidebar
|
|
2
|
-
|
|
3
|
-
把 DeepSeek Harness 侧栏的「工作区 / 会话」列表换成分文件夹的进入式导航:**侧栏先只列工作区(文件夹),点进去才显示该工作区的会话列表**,并有返回上一级。会话行首带状态位,文件夹图标本身就是工作区的状态位。
|
|
4
|
-
|
|
5
|
-
## 行为
|
|
6
|
-
|
|
7
|
-
- **顶栏固定**:两级完全相同(标题「工作区」+ 搜索 / 视图选项 / 添加工作区 按钮),位置和结构不变。
|
|
8
|
-
- **搜索集成在顶栏**(对齐官方):平时只有一个放大镜按钮;点击后输入框**淡入并占据整个顶栏**(标题淡出、其余按钮让位,约 150–180ms 过渡,尊重 `prefers-reduced-motion`),带 `✕` 关闭;Esc 也关闭。输入后列表切换为跨工作区的扁平结果,点击结果打开会话并自动收起搜索。隐藏层不参与 Tab 与无障碍树。
|
|
9
|
-
- **视图选项**(对齐官方:排序与显示筛选合并在同一个菜单里,不再分成两个按钮)。菜单分两段:
|
|
10
|
-
1. **排序**(标题会写明「排序 · 文件夹 / 会话」,因为两级各自独立):手动顺序 / 按名称 / 按最近活动,外加 **正序 ↑ / 倒序 ↓**;选中项带 `✓`。
|
|
11
|
-
2. **显示**:隐藏已归档 / 全部会话 / 仅显示已归档。
|
|
12
|
-
- 两级偏好互不影响,一起存在 `localStorage` 的 `dsh.folder-sidebar.sort`(`{ folders: {mode, dir}, sessions: {mode, dir} }`),归档筛选存在 `dsh.folder-sidebar.archived`。
|
|
13
|
-
- 选模式时会重置到该模式的自然方向:名称 = 正序,最近活动 = 倒序,手动顺序 = 正序;之后可以单独切方向。
|
|
14
|
-
- 方向就是比较器的符号:名称 A→Z / Z→A;最近活动 最早→最新 / 最新→最早;手动顺序 = Host 顺序 / 它的逆序(倒序只影响显示,不改 Host 里存的顺序)。
|
|
15
|
-
- 会话级里「手动顺序」与「按最近活动」等价(会话只有「按最近更新」这一种原生顺序),置顶会话在任何模式下都排最前。
|
|
16
|
-
- 文件夹级只有在「手动顺序 + 正序」下才显示「上移 / 下移」,也只有这时能拖拽(其他情况顺序是派生的,手动移没有意义)。
|
|
17
|
-
- **拖拽排序**(对齐官方):文件夹行可直接拖动,落在目标行的上半/下半决定插到它前面还是后面,落点有品牌色指示线;松开即通过 Host 的 workspace 排序接口持久化。搜索中或排序模式非「手动 + 正序」时自动禁用。
|
|
18
|
-
- **第一级:工作区文件夹列表**。每行:文件夹图标(兼状态位)、名称、`…` 菜单、会话数、`›`。
|
|
19
|
-
- **第二级:进入某个工作区**。顶栏保持不变;顶栏下面多一条**文件夹行**:
|
|
20
|
-
```
|
|
21
|
-
‹ 文件夹名 +
|
|
22
|
-
```
|
|
23
|
-
点这一行任意位置 = 返回上一级(文件夹列表);点右侧 `+` = 在当前工作区新开会话(不触发返回)。下面才是该工作区的会话列表。
|
|
24
|
-
- **默认停在当前会话所在的工作区**;返回后停在文件夹列表,不会被自动拉回。
|
|
25
|
-
- **搜索**:标题匹配即时本地过滤;内容匹配 250 ms 防抖后走 Host 的会话检索,结果带所属工作区与命中片段,点击直接打开。
|
|
26
|
-
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
|
36
|
-
|
|
|
37
|
-
|
|
|
38
|
-
|
|
|
39
|
-
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
|
49
|
-
|
|
|
50
|
-
|
|
|
51
|
-
|
|
|
52
|
-
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
|
72
|
-
|
|
|
73
|
-
|
|
|
74
|
-
|
|
|
75
|
-
|
|
|
76
|
-
|
|
|
77
|
-
|
|
|
78
|
-
|
|
|
79
|
-
|
|
|
80
|
-
|
|
|
81
|
-
|
|
|
82
|
-
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
-
|
|
112
|
-
- **
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
-
|
|
120
|
-
-
|
|
121
|
-
-
|
|
122
|
-
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
|
132
|
-
|
|
|
133
|
-
|
|
|
134
|
-
|
|
|
135
|
-
|
|
|
136
|
-
|
|
|
137
|
-
|
|
|
138
|
-
|
|
|
139
|
-
|
|
|
140
|
-
|
|
|
141
|
-
|
|
|
142
|
-
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
-
|
|
152
|
-
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
-
|
|
158
|
-
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
locale/
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
test/
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
node
|
|
179
|
-
node test/
|
|
180
|
-
|
|
1
|
+
# dsh-folder-sidebar
|
|
2
|
+
|
|
3
|
+
把 DeepSeek Harness 侧栏的「工作区 / 会话」列表换成分文件夹的进入式导航:**侧栏先只列工作区(文件夹),点进去才显示该工作区的会话列表**,并有返回上一级。会话行首带状态位,文件夹图标本身就是工作区的状态位。
|
|
4
|
+
|
|
5
|
+
## 行为
|
|
6
|
+
|
|
7
|
+
- **顶栏固定**:两级完全相同(标题「工作区」+ 搜索 / 视图选项 / 添加工作区 按钮),位置和结构不变。
|
|
8
|
+
- **搜索集成在顶栏**(对齐官方):平时只有一个放大镜按钮;点击后输入框**淡入并占据整个顶栏**(标题淡出、其余按钮让位,约 150–180ms 过渡,尊重 `prefers-reduced-motion`),带 `✕` 关闭;Esc 也关闭。输入后列表切换为跨工作区的扁平结果,点击结果打开会话并自动收起搜索。隐藏层不参与 Tab 与无障碍树。
|
|
9
|
+
- **视图选项**(对齐官方:排序与显示筛选合并在同一个菜单里,不再分成两个按钮)。菜单分两段:
|
|
10
|
+
1. **排序**(标题会写明「排序 · 文件夹 / 会话」,因为两级各自独立):手动顺序 / 按名称 / 按最近活动,外加 **正序 ↑ / 倒序 ↓**;选中项带 `✓`。
|
|
11
|
+
2. **显示**:隐藏已归档 / 全部会话 / 仅显示已归档。
|
|
12
|
+
- 两级偏好互不影响,一起存在 `localStorage` 的 `dsh.folder-sidebar.sort`(`{ folders: {mode, dir}, sessions: {mode, dir} }`),归档筛选存在 `dsh.folder-sidebar.archived`。
|
|
13
|
+
- 选模式时会重置到该模式的自然方向:名称 = 正序,最近活动 = 倒序,手动顺序 = 正序;之后可以单独切方向。
|
|
14
|
+
- 方向就是比较器的符号:名称 A→Z / Z→A;最近活动 最早→最新 / 最新→最早;手动顺序 = Host 顺序 / 它的逆序(倒序只影响显示,不改 Host 里存的顺序)。
|
|
15
|
+
- 会话级里「手动顺序」与「按最近活动」等价(会话只有「按最近更新」这一种原生顺序),置顶会话在任何模式下都排最前。
|
|
16
|
+
- 文件夹级只有在「手动顺序 + 正序」下才显示「上移 / 下移」,也只有这时能拖拽(其他情况顺序是派生的,手动移没有意义)。
|
|
17
|
+
- **拖拽排序**(对齐官方):文件夹行可直接拖动,落在目标行的上半/下半决定插到它前面还是后面,落点有品牌色指示线;松开即通过 Host 的 workspace 排序接口持久化。搜索中或排序模式非「手动 + 正序」时自动禁用。
|
|
18
|
+
- **第一级:工作区文件夹列表**。每行:文件夹图标(兼状态位)、名称、`…` 菜单、会话数、`›`。
|
|
19
|
+
- **第二级:进入某个工作区**。顶栏保持不变;顶栏下面多一条**文件夹行**:
|
|
20
|
+
```
|
|
21
|
+
‹ 文件夹名 +
|
|
22
|
+
```
|
|
23
|
+
点这一行任意位置 = 返回上一级(文件夹列表);点右侧 `+` = 在当前工作区新开会话(不触发返回)。下面才是该工作区的会话列表。
|
|
24
|
+
- **默认停在当前会话所在的工作区**;返回后停在文件夹列表,不会被自动拉回。
|
|
25
|
+
- **搜索**:标题匹配即时本地过滤;内容匹配 250 ms 防抖后走 Host 的会话检索,结果带所属工作区与命中片段,点击直接打开。
|
|
26
|
+
- **长名称**:放不下的标题在悬停该行时横向滚动(会话行、文件夹行、未分组、搜索结果、面包屑文件名都生效),滚到末尾再回滚;能放下的标题静止不动,`prefers-reduced-motion` 下不滚动。
|
|
27
|
+
- 侧栏收起成窄栏时只渲染一个文件夹图标,点击展开。
|
|
28
|
+
|
|
29
|
+
## 状态位
|
|
30
|
+
|
|
31
|
+
**会话行**:最前面一个固定 12px 的状态位(无状态时留空,标题始终对齐)。
|
|
32
|
+
|
|
33
|
+
| 占位 | 含义 | 来源 |
|
|
34
|
+
|---|---|---|
|
|
35
|
+
| 转圈(spinner) | 正在运行 | `useSessionStatus` 的 `running`(含摘要的 `running`) |
|
|
36
|
+
| 绿 `✓` | **有未读的新完成**(你当时没在看它);打开这个会话即清除 | `useSessionStatus` 的 `completionUnread` |
|
|
37
|
+
| 黄 `?` | 正在等你回答或审批(`pendingInteraction`) | `useSessionStatus` |
|
|
38
|
+
| 红 `!` | 最近一轮失败或中断(`error` / `blocked` / `max-tokens` / `interrupted`,及非用户原因的 `aborted`);下一次开跑才清除 | Host 投影 `failed` / `interrupted` |
|
|
39
|
+
| 空心灰点 | 你自己按停止(`aborted` by user) | Host 投影 `stopped` |
|
|
40
|
+
| 灰点(实心、淡) | 已处理完(读过、没有新完成)、从未运行过 | — |
|
|
41
|
+
|
|
42
|
+
会话行与文件夹行共用同一套图形语言:等待是 `?`、失败是 `!`、运行是转圈,完成是绿 `✓`,停止与空闲用点——所以两级列表切换时视觉一致。
|
|
43
|
+
|
|
44
|
+
**文件夹行**:状态位固定在图标上,只有一个,不额外占位。
|
|
45
|
+
|
|
46
|
+
| 图标 | 含义 |
|
|
47
|
+
|---|---|
|
|
48
|
+
| 转圈(spinner,不是转动文件夹) | 有会话正在运行 |
|
|
49
|
+
| 黄色 `?` | 有会话在等你回答/审批 |
|
|
50
|
+
| 红色 `!` | 有会话最近一轮失败或中断 |
|
|
51
|
+
| 绿色 `✓` | 有会话最近一轮正常完成 |
|
|
52
|
+
| 空心灰文件夹 | 有会话被主动停止 |
|
|
53
|
+
| 普通文件夹 | 没有可显示的状态 |
|
|
54
|
+
|
|
55
|
+
一个文件夹里有多种状态时按**优先级取一个**:等待 > 运行 > 失败 > 未读完成 > 主动停止;同一优先级里取**状态起始时间最早**的那个(`since` 最早;投影缺失时退化为会话 `updatedAt`)。
|
|
56
|
+
|
|
57
|
+
**悬浮卡**:会话行悬停 350ms 列出该会话的**全部**状态(等待的具体类型、运行、失败、未读完成、停止,最后一行是相对时间);文件夹行悬停列出它包含的状态及各自会话数(如「运行中 ×2」)。悬浮卡不拦截指针,滚动即消失。
|
|
58
|
+
|
|
59
|
+
**为什么完成用「未读」而不是「完成过」**:内置 ui-session 的 `completionUnread` 才是官方的「已处理」判定——它只在**看到某个会话从运行变为结束、且当时它不是当前会话**时置位,并且每次开启/切到该会话就清除;这个事实只存在于浏览器,永不上报 Host。用它作绿 `✓`,读完切走就不会再亮。
|
|
60
|
+
|
|
61
|
+
**为什么红/黄/转圈不用这个**:失败与等待是持久事实(`turn/end` 的 reason、`pendingInteraction`),与「你是否看过」无关;转圈就是当前 `running`。红色会在下一次开跑或正常完成时被覆盖,不会因为你看过而消失。
|
|
62
|
+
|
|
63
|
+
**为什么状态要 Host 投影**:会话摘要(`SessionSummary`)只有 `running`、`updatedAt` 等字段,没有「最近一轮结果」;唯一可靠来源是会话事件 `turn/end` 的 `reason`。插件因此在 Host 侧注册一个 session projection,把最近一轮折叠成 `idle / running / completed / failed / interrupted / stopped` 并带上状态起始时间 `since`(`stateVersion = 3`),Client 从 `projectionsBySession[id].values['folder-sidebar/turn']` 读取——值在 Host 算好并增量推送,浏览器不自己翻事件。
|
|
64
|
+
|
|
65
|
+
## 与官方实现的对齐情况
|
|
66
|
+
|
|
67
|
+
官方侧栏由 `ui-workspace` 的 `sessionStatuses()` 推导状态、由 `ui-primitives` 的 `StateDot` 渲染:
|
|
68
|
+
|
|
69
|
+
| 状态 | 官方做法 | 本插件 | 是否对齐 |
|
|
70
|
+
|---|---|---|---|
|
|
71
|
+
| 运行中 | `running` → `ongoing`,`StateDot` 渲染 **14px SVG spinner** | 同源,转圈 | ✅ 已对齐(尺寸也对齐) |
|
|
72
|
+
| 等待 | `pendingInteraction`(approval / plan-review / question)→ `warning` 黄点;**优先级最高,运行中也会显示黄** | 同源,黄点,优先级已改为等待 > 运行 | ✅ 已对齐 |
|
|
73
|
+
| 完成未读 | `completionUnread` → `done` 绿点;打开该会话即清除 | 同源,绿 `✓` | ✅ 已对齐 |
|
|
74
|
+
| 空闲 / 已读 | `idle` 时侧栏**不渲染**点 | 渲染淡灰点 | ⚠️ 有意偏离(按你的要求) |
|
|
75
|
+
| 失败 / 中断 | **官方没有失败状态**(`StateDot` 有 `error` 色,但侧栏从不使用) | 红点,来自本插件 Host 投影 | ➕ 本插件新增 |
|
|
76
|
+
| 主动停止 | 无对应概念 | 空心灰点 | ➕ 本插件新增 |
|
|
77
|
+
| 文件夹聚合 | 官方**不聚合**(文档明说:折叠分组里等待的行不会点亮分组头) | 文件夹图标即状态位,优先级 + 同级最旧 | ➕ 本插件新增(按你的要求) |
|
|
78
|
+
| 悬浮卡 | 悬浮卡里列出**全部**状态的文字标签 | 同左(含文件夹的状态计数) | ✅ 已对齐 |
|
|
79
|
+
| 归档筛选 / 取消归档 / 撤销 | 视图选项三选一、归档行不可打开、提示可撤销、搜索结果可取消归档 | 同左(顶栏漏斗按钮) | ✅ 已对齐 |
|
|
80
|
+
| 未分组 | 不属于任何工作区的会话进 Ungrouped | 同左(列表末尾伪文件夹) | ✅ 已对齐 |
|
|
81
|
+
| subagent 会话隐藏 | 侧栏不显示 subagent 来源会话 | 同左 | ✅ 已对齐 |
|
|
82
|
+
| 操作失败提示 | 通知通道(Toast / 对话框错误) | 底部提示条 | ✅ 已对齐 |
|
|
83
|
+
| 拖拽排序 | 拖拽重排 + 插入指示线 + 跨组落点 | 暂用菜单「上移 / 下移」 | ⏳ 待做(下一批) |
|
|
84
|
+
|
|
85
|
+
点/圈的几何在官方 `StateDot` 基础上整体放大一档以便阅读:18px 状态位、12px 点(内圈 60%)、15px 符号;转圈保持 14px(与官方 StateDot 一致)。
|
|
86
|
+
|
|
87
|
+
## 菜单(`…` 按钮或鼠标右键)
|
|
88
|
+
|
|
89
|
+
会话行:置顶 / 取消置顶、重命名(行内输入,Enter 提交、Esc 取消)、分叉、复制会话 ID、归档。
|
|
90
|
+
归档仍在运行的会话时,Host 会拒绝,行内改为「该会话仍在运行,停止并归档?」二次确认。
|
|
91
|
+
|
|
92
|
+
文件夹行:重命名工作区(行内输入)、在此新建会话、上移 / 下移、删除工作区(二次确认;只删注册,不动会话与文件)。顶部 `+` 是添加工作区(系统目录选择器)。
|
|
93
|
+
|
|
94
|
+
两处都支持**鼠标右键**在指针位置打开同一份菜单;菜单是固定定位浮层,不会被列表裁切,滚动或点击别处自动关闭,Esc 也能关。
|
|
95
|
+
|
|
96
|
+
> 会话没有「删除」能力:Host 只提供归档 / 取消归档,所以菜单里是「归档」。
|
|
97
|
+
|
|
98
|
+
> 「上移 / 下移」通过 Host 的 workspace 排序接口持久化,改动会同步到内置侧栏的顺序;它只在文件夹级「手动顺序 + 正序」时出现,按名称 / 按最近活动请用顶栏的排序菜单。
|
|
99
|
+
|
|
100
|
+
## 安装与生效
|
|
101
|
+
|
|
102
|
+
从 npm 安装(推荐):
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
npm install dsh-folder-sidebar
|
|
106
|
+
# 或在 DSH 的 Plugin Manager / plugin_manager 里指定 install_bundle 目标 dsh-folder-sidebar
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
从源码目录安装(本地链接,便于改代码):
|
|
110
|
+
|
|
111
|
+
- `plugin_manager` 的 `install_bundle` 指向本目录。
|
|
112
|
+
- **Client 改动**(`client.js`、locale):刷新页面。
|
|
113
|
+
- **Host 改动**(`index.js`——状态色投影):需要**完整重启 DSH**。
|
|
114
|
+
|
|
115
|
+
仓库:<https://github.com/Aliboder/dsh-folder-sidebar> · 包:<https://www.npmjs.com/package/dsh-folder-sidebar>
|
|
116
|
+
|
|
117
|
+
## 归档与「未分组」(对齐官方)
|
|
118
|
+
|
|
119
|
+
- **视图选项**(顶栏漏斗按钮):隐藏已归档(默认)/ 全部会话 / 仅显示已归档;选择存在浏览器 `localStorage`(`dsh.folder-sidebar.archived`)。
|
|
120
|
+
- 已归档会话以半透明行显示、**点击不会打开**(提示「已归档,取消归档后才能打开」);菜单改为「取消归档 / 重命名 / 分叉 / 复制 ID」;「仅显示已归档」时没有归档会话的文件夹会被隐藏。
|
|
121
|
+
- 归档成功的提示条带**撤销**按钮,直接取消归档。
|
|
122
|
+
- **未分组**:不属于任何工作区(且非 subagent 来源)的会话出现在文件夹列表末尾的「未分组」里,可打开、可归档;它没有「新建会话」(没有工作区可归属)。
|
|
123
|
+
- **subagent 来源的会话始终隐藏**,与官方侧栏一致。
|
|
124
|
+
|
|
125
|
+
## 图标
|
|
126
|
+
|
|
127
|
+
插件不 import 宿主包(规范也禁止),而是**按 `ui-primitives` 的真实几何复刻**:全部 16×16 网格、`strokeWidth: 1`(官方 Regular 权重)、`currentColor`。
|
|
128
|
+
|
|
129
|
+
| 用途 | 官方来源 |
|
|
130
|
+
|---|---|
|
|
131
|
+
| 文件夹 | `IconFolderCloseRegular` |
|
|
132
|
+
| 行尾进入箭头 | `IconTriangleRightFillRegular`(官方行箭头) |
|
|
133
|
+
| 返回 | `IconChevronLeftOutlineRegular` |
|
|
134
|
+
| 搜索 | `IconSearchOutlineRegular` |
|
|
135
|
+
| 关闭搜索 | `IconCloseFillRegular` |
|
|
136
|
+
| 更多 `…` | `IconEllipsisOutlineRegular` |
|
|
137
|
+
| 视图选项 | `IconSlidersTwoOutlineRegular` |
|
|
138
|
+
| 置顶 | `IconPinFillRegular` |
|
|
139
|
+
| 新建会话 | `IconNewChatOutlineRegular` |
|
|
140
|
+
| 添加工作区 | `IconProjectAddOutlineRegular` |
|
|
141
|
+
| 完成 | `IconCheckOutlineRegular`(绿) |
|
|
142
|
+
| 等待 | `IconQuestionOutlineRegular`(黄) |
|
|
143
|
+
| 失败/中断 | `IconWarningOutlineRegular`(红) |
|
|
144
|
+
|
|
145
|
+
## 失败提示
|
|
146
|
+
|
|
147
|
+
置顶 / 归档 / 取消归档 / 重命名 / 分叉 / 排序 / 删除工作区 / 添加工作区失败时,底部显示一条提示条(不再只写 console)。
|
|
148
|
+
|
|
149
|
+
## 已知限制
|
|
150
|
+
|
|
151
|
+
- 没有「展开其余」水位线。
|
|
152
|
+
- 搜索内容命中走 Host 索引;搜索期间列表被结果替代(Esc 清空恢复)。
|
|
153
|
+
- 文件夹状态位只统计当前筛选下可见的会话。
|
|
154
|
+
|
|
155
|
+
## 工程结构
|
|
156
|
+
|
|
157
|
+
- 纯逻辑(排序比较器、状态优先级、文件夹状态聚合、归档筛选、相对时间、路径 basename)集中放在 `client.js` **模块顶层**,不依赖 React/DOM;文件末尾在 Node 环境(`module.exports` 存在且 `window` 缺失)把这份 API 导出,因此 `test/logic.test.mjs` 加载的是**真正发布的那份源码**,不是副本。
|
|
158
|
+
- 每个文件夹的会话行用一次 `useMemo` 建索引(`rowsIndex`),列表渲染、状态位聚合、悬浮卡共用同一份,避免同一帧内重复过滤排序。
|
|
159
|
+
- 新增测试:`test/logic.test.mjs`(排序 × 方向、置顶、状态优先级、文件夹聚合、持久化、时间格式化、路径解析)。
|
|
160
|
+
|
|
161
|
+
## 文件
|
|
162
|
+
|
|
163
|
+
```
|
|
164
|
+
package.json # dsh.bundle.patch + dsh.client + zod 依赖
|
|
165
|
+
cordis.patch.yml # 插入 folder-sidebar 行
|
|
166
|
+
index.js # Host:sessionProjections 单元 folder-sidebar/turn
|
|
167
|
+
client.js # 全部 UI:两级导航、菜单、搜索、状态色
|
|
168
|
+
locale/en.json # 插件列表展示文案
|
|
169
|
+
locale/zh.json
|
|
170
|
+
icon.svg
|
|
171
|
+
test/smoke.test.mjs # 清单与 id 一致性自检
|
|
172
|
+
test/projection.test.mjs # 投影状态机单测(不启动 DSH)
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## 本地验证
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
node --check index.js && node --check client.js
|
|
179
|
+
node test/smoke.test.mjs
|
|
180
|
+
node test/projection.test.mjs
|
|
181
|
+
```
|