dsh-sidebar-suite 0.2.9 → 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.
@@ -58,6 +58,10 @@ const DEFAULT_CONFIG = {
58
58
  // 0.2.4: the host's workspace list folds after five sessions and paints a
59
59
  // "展开其余 N 个会话" button. This plugin expands every group instead.
60
60
  expandAllSessions: true,
61
+ // 0.4.0: right-clicking a temporary session row offers "keep as a normal
62
+ // session" and "delete now". Off means the row behaves like a plain session
63
+ // row again — the escape hatch if another plugin owns the context menu.
64
+ rowMenu: true,
61
65
  deleteOnExit: true,
62
66
  // Daily cleanup (0.2.2). Independent of deleteOnExit: a user who keeps DSH
63
67
  // open for days wants "delete at 03:00 every night", and a user who closes it
@@ -148,6 +152,7 @@ const CONFIG_KEYS = {
148
152
  inChatMode: { key: 'TEMP_IN_CHAT_MODE', text: (value) => String(value) },
149
153
  buttonStyle: { key: 'TEMP_BUTTON_STYLE', text: (value) => String(value) },
150
154
  expandAllSessions: { key: 'EXPAND_ALL_SESSIONS', text: (value) => (value ? 'on' : 'off') },
155
+ rowMenu: { key: 'TEMP_ROW_MENU', text: (value) => (value ? 'on' : 'off') },
151
156
  deleteOnExit: { key: 'DELETE_ON_EXIT', text: (value) => (value ? 'on' : 'off') },
152
157
  scheduleDelete: { key: 'SCHEDULE_DELETE', text: (value) => (value ? 'on' : 'off') },
153
158
  scheduleTime: { key: 'SCHEDULE_TIME', text: (value) => String(value) },
@@ -185,6 +190,7 @@ function parseConfig() {
185
190
  if (kv.EXPAND_ALL_SESSIONS !== undefined) {
186
191
  next.expandAllSessions = kv.EXPAND_ALL_SESSIONS.toLowerCase() !== 'off'
187
192
  }
193
+ if (kv.TEMP_ROW_MENU !== undefined) next.rowMenu = kv.TEMP_ROW_MENU.toLowerCase() !== 'off'
188
194
  if (kv.DELETE_ON_EXIT !== undefined) next.deleteOnExit = kv.DELETE_ON_EXIT.toLowerCase() !== 'off'
189
195
  if (kv.SCHEDULE_DELETE !== undefined) next.scheduleDelete = kv.SCHEDULE_DELETE.toLowerCase() !== 'off'
190
196
  if (kv.SCHEDULE_TIME !== undefined) {
@@ -224,7 +230,7 @@ function refreshConfigIfChanged() {
224
230
  state.configStamp = stamp
225
231
  const next = parseConfig()
226
232
  const fields = [
227
- 'showButton', 'inChatMode', 'buttonStyle', 'expandAllSessions',
233
+ 'showButton', 'inChatMode', 'buttonStyle', 'expandAllSessions', 'rowMenu',
228
234
  'deleteOnExit', 'scheduleDelete', 'scheduleTime', 'maxKept',
229
235
  ]
230
236
  const changed = fields.some((field) => next[field] !== state.config[field])
@@ -255,6 +261,7 @@ function saveConfig(patch) {
255
261
  if (input.inChatMode === 'show' || input.inChatMode === 'hide') next.inChatMode = input.inChatMode
256
262
  if (input.buttonStyle === 'own' || input.buttonStyle === 'pair') next.buttonStyle = input.buttonStyle
257
263
  if (typeof input.expandAllSessions === 'boolean') next.expandAllSessions = input.expandAllSessions
264
+ if (typeof input.rowMenu === 'boolean') next.rowMenu = input.rowMenu
258
265
  if (typeof input.deleteOnExit === 'boolean') next.deleteOnExit = input.deleteOnExit
259
266
  if (typeof input.scheduleDelete === 'boolean') next.scheduleDelete = input.scheduleDelete
260
267
  const clock = normalizeClock(input.scheduleTime)
@@ -324,6 +331,7 @@ function publicConfig() {
324
331
  inChatMode: state.config.inChatMode,
325
332
  buttonStyle: state.config.buttonStyle,
326
333
  expandAllSessions: state.config.expandAllSessions,
334
+ rowMenu: state.config.rowMenu,
327
335
  deleteOnExit: state.config.deleteOnExit,
328
336
  scheduleDelete: state.config.scheduleDelete,
329
337
  scheduleTime: state.config.scheduleTime,
@@ -536,6 +544,59 @@ async function purgeAll(reason, options) {
536
544
  return report
537
545
  }
538
546
 
547
+ /**
548
+ * Delete one tracked session from the sidebar menu (0.4.0).
549
+ *
550
+ * Same steps as `purgeAll` for a single id: remove the directories, verify they
551
+ * are really gone, fall back to hiding the row when a file is locked. Two
552
+ * deliberate differences:
553
+ *
554
+ * - **Only tracked ids are accepted.** This route is reachable from the page, so
555
+ * it must never become "delete any session by id". An untracked id is refused
556
+ * before any filesystem call.
557
+ * - **A failed delete keeps the id tracked**, exactly like `purgeAll`, so the
558
+ * next launch retries it instead of leaving an undeletable row that silently
559
+ * stopped being temporary.
560
+ */
561
+ async function removeOne(sessionId) {
562
+ await ensureReady()
563
+ const id = normalizeId(sessionId)
564
+ if (id.length === 0) return { ok: false, error: 'invalid session id' }
565
+ if (!state.tracked.includes(id)) return { ok: false, error: 'not a temporary session' }
566
+ let removed = 0
567
+ try {
568
+ removed = await removeSession(id)
569
+ } catch (error) {
570
+ void error
571
+ }
572
+ const gone = removed > 0 && sessionDirsSync(id).length === 0
573
+ let hidden = false
574
+ if (!gone) hidden = await hideSession(id)
575
+ const report = {
576
+ reason: 'single',
577
+ at: new Date().toISOString(),
578
+ tried: 1,
579
+ removed: gone ? 1 : 0,
580
+ hidden: hidden ? 1 : 0,
581
+ skipped: 0,
582
+ failed: [],
583
+ }
584
+ if (gone || hidden) {
585
+ state.tracked = state.tracked.filter((item) => item !== id)
586
+ await saveStore()
587
+ state.lastPurge = report
588
+ return { ok: true, removed: gone, hidden, ids: state.tracked.slice(), count: state.tracked.length }
589
+ }
590
+ report.failed.push(id)
591
+ state.lastPurge = report
592
+ return {
593
+ ok: false,
594
+ error: 'delete failed — the session files are locked',
595
+ ids: state.tracked.slice(),
596
+ count: state.tracked.length,
597
+ }
598
+ }
599
+
539
600
  /** Delete every tracked session synchronously — the quit path has no `await`. */
540
601
  function purgeSync(reason) {
541
602
  if (state.tracked.length === 0) return { reason, tried: 0, removed: 0, kept: [] }
@@ -723,6 +784,7 @@ function status() {
723
784
  chatModePolicy: state.config.inChatMode,
724
785
  buttonStyle: state.config.buttonStyle,
725
786
  expandAllSessions: state.config.expandAllSessions,
787
+ rowMenu: state.config.rowMenu,
726
788
  deleteOnExit: state.config.deleteOnExit,
727
789
  scheduleDelete: state.config.scheduleDelete,
728
790
  scheduleTime: state.config.scheduleTime,
@@ -860,6 +922,12 @@ export function createTempSessionHost(initialCtx) {
860
922
  if (sessionId.length === 0) return json({ ok: false, error: 'sessionId required' }, 400)
861
923
  return json(await untrack(sessionId))
862
924
  }],
925
+ // 0.4.0 — delete one temporary session from the row menu.
926
+ ['/api/dsh-temp-session.remove', ['POST', 'GET'], async (request) => {
927
+ const { sessionId } = queryOf(request)
928
+ if (sessionId.length === 0) return json({ ok: false, error: 'sessionId required' }, 400)
929
+ return json(await removeOne(sessionId))
930
+ }],
863
931
  ['/api/dsh-temp-session.purge', ['POST', 'GET'], async () => {
864
932
  await ensureReady()
865
933
  return json({ ok: true, ...(await purgeAll('manual')) })
package/locale/en.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "meta": {
3
3
  "title": "侧栏布局大师 · Sidebar Suite",
4
- "description": "一款专门针对改进 DSH 左侧栏体验的插件:三种布局一键切换、会话默认全展开、临时会话默认在退出 DSH 时删除(每天定时清理默认关,可在本页开启并设时间)、设置与反馈都在本页(全部 8 项配置都有开关,改配置文件约 3 秒自动生效、免重启),强实用性;界面沿用宿主原生配色、圆角与间距,只加属性不重构宿主结构,克制又好看。|A plugin dedicated to a better DSH sidebar: one-click layouts, always-expanded sessions, temp sessions deleted when DSH quits by default (daily cleanup off by default and opt-in) and in-page settings/feedback — every config key has a switch and file edits hot-reload — seriously practical; native colours, radii and spacing with zero host-DOM rewrites — restrained and good-looking.",
4
+ "description": "一款专门针对改进 DSH 左侧栏体验的插件:三种布局一键切换、会话默认全展开、临时会话默认在退出 DSH 时删除(每天定时清理默认关,可在本页开启并设时间)、临时会话可右键保留为正式会话或立即删除、设置与反馈都在本页(全部 9 项配置都有开关,改配置文件约 3 秒自动生效、免重启),强实用性;界面沿用宿主原生配色、圆角与间距,只加属性不重构宿主结构,克制又好看。|A plugin dedicated to a better DSH sidebar: one-click layouts, always-expanded sessions, temp sessions deleted when DSH quits by default (daily cleanup off by default and opt-in) and a right-click menu to keep or delete one temp session, in-page settings/feedback — every config key has a switch and file edits hot-reload — seriously practical; native colours, radii and spacing with zero host-DOM rewrites — restrained and good-looking.",
5
5
  "detail": "DETAIL.md"
6
6
  }
7
7
  }
package/locale/zh.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "meta": {
3
3
  "title": "侧栏布局大师 · Sidebar Suite",
4
- "description": "一款专门针对改进 DSH 左侧栏体验的插件:三种布局一键切换、会话默认全展开、临时会话默认在退出 DSH 时删除(每天定时清理默认关,可在本页开启并设时间)、设置与反馈都在本页(全部 8 项配置都有开关,改配置文件约 3 秒自动生效、免重启),强实用性;界面沿用宿主原生配色、圆角与间距,只加属性不重构宿主结构,克制又好看。|A plugin dedicated to a better DSH sidebar: one-click layouts, always-expanded sessions, temp sessions deleted when DSH quits by default (daily cleanup off by default and opt-in) and in-page settings/feedback — every config key has a switch and file edits hot-reload — seriously practical; native colours, radii and spacing with zero host-DOM rewrites — restrained and good-looking.",
4
+ "description": "一款专门针对改进 DSH 左侧栏体验的插件:三种布局一键切换、会话默认全展开、临时会话默认在退出 DSH 时删除(每天定时清理默认关,可在本页开启并设时间)、临时会话可右键保留为正式会话或立即删除、设置与反馈都在本页(全部 9 项配置都有开关,改配置文件约 3 秒自动生效、免重启),强实用性;界面沿用宿主原生配色、圆角与间距,只加属性不重构宿主结构,克制又好看。|A plugin dedicated to a better DSH sidebar: one-click layouts, always-expanded sessions, temp sessions deleted when DSH quits by default (daily cleanup off by default and opt-in) and a right-click menu to keep or delete one temp session, in-page settings/feedback — every config key has a switch and file edits hot-reload — seriously practical; native colours, radii and spacing with zero host-DOM rewrites — restrained and good-looking.",
5
5
  "detail": "DETAIL.md"
6
6
  }
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-sidebar-suite",
3
- "version": "0.2.9",
3
+ "version": "0.4.0",
4
4
  "license": "MIT",
5
5
  "author": "Yonan",
6
6
  "repository": {
@@ -14,7 +14,7 @@
14
14
  "publishConfig": {
15
15
  "access": "public"
16
16
  },
17
- "description": "一款专门针对改进 DSH 左侧栏体验的插件:三种布局一键切换、默认布局在详情页顶部直接设、会话列表默认全展开、「临时会话」开原生会话且默认在退出 DSH 时删除(DELETE_ON_EXIT 默认开;每天定时清理默认关,可在详情页开启并自设时间)、详情页三种反馈入口、全部 8 项配置都有图形开关且改文件免重启 —— 强实用性;界面沿用宿主原生配色、圆角与间距,只加属性与一条控制栏、不重构宿主结构 —— 克制美观。|A plugin dedicated to the DSH sidebar experience: one-click layouts, always-expanded sessions, native temp sessions deleted when DSH quits by default (DELETE_ON_EXIT on; daily cleanup off by default and opt-in) in-page settings/feedback, a control for every config key and hot-reloaded config edits — seriously practical; native colours, radii and spacing with zero host-DOM rewrites — restrained and good-looking.",
17
+ "description": "一款专门针对改进 DSH 左侧栏体验的插件:三种布局一键切换、默认布局在详情页顶部直接设、会话列表默认全展开、「临时会话」开原生会话且默认在退出 DSH 时删除(DELETE_ON_EXIT 默认开;每天定时清理默认关,可在详情页开启并自设时间)、详情页三种反馈入口、临时会话可右键「保留为正式会话」或「立即删除」、全部 9 项配置都有图形开关且改文件免重启 —— 强实用性;界面沿用宿主原生配色、圆角与间距,只加属性与一条控制栏、不重构宿主结构 —— 克制美观。|A plugin dedicated to the DSH sidebar experience: one-click layouts, always-expanded sessions, native temp sessions deleted when DSH quits by default (DELETE_ON_EXIT on; daily cleanup off by default and opt-in) in-page settings/feedback, a right-click menu to keep or delete one temp session, a control for every config key and hot-reloaded config edits — seriously practical; native colours, radii and spacing with zero host-DOM rewrites — restrained and good-looking.",
18
18
  "keywords": [
19
19
  "dsh-plugin",
20
20
  "dsh",
@@ -27,7 +27,7 @@
27
27
  ],
28
28
  "type": "module",
29
29
  "scripts": {
30
- "test": "node tests/test_020.mjs && node tests/test_022.mjs && node tests/test_023.mjs && node tests/test_024.mjs && node tests/test_025.mjs && node tests/test_028.mjs && node tests/test_029.mjs",
30
+ "test": "node tests/test_020.mjs && node tests/test_022.mjs && node tests/test_023.mjs && node tests/test_024.mjs && node tests/test_025.mjs && node tests/test_028.mjs && node tests/test_029.mjs && node tests/test_030.mjs && node tests/test_031.mjs && node tests/test_032.mjs && node tests/test_033.mjs",
31
31
  "check": "node --check lib/index.js && node --check lib/client.js && node --check lib/temp-session-host.mjs && npm pack --dry-run"
32
32
  },
33
33
  "main": "lib/index.js",
@@ -33,6 +33,13 @@ TEMP_BUTTON_STYLE=pair
33
33
  # off = keep DSH's own folding and leave that button visible
34
34
  EXPAND_ALL_SESSIONS=on
35
35
 
36
+ # 右键临时会话时,是否弹出「保留为正式会话 / 立即删除」菜单 / Right-click menu
37
+ # on = 弹出(默认)。选「保留为正式会话」后,这个会话就不再算临时,退出时不会删。
38
+ # off = 不接管右键菜单(别的插件抢右键时用这个)
39
+ # on = show the menu (default). "Keep as a normal session" makes it permanent.
40
+ # off = leave the context menu alone (use this if another plugin owns it)
41
+ TEMP_ROW_MENU=on
42
+
36
43
  # 退出 DSH 时删除临时会话 / Delete temporary sessions when DSH quits
37
44
  # on = 退出时删除(默认);off = 不删除,临时会话就变成普通会话
38
45
  DELETE_ON_EXIT=on
@@ -117,6 +117,29 @@
117
117
 
118
118
  ---
119
119
 
120
+ ### 3.4 第三方插件加的页签(0.3.0)
121
+
122
+ 这一版给**别的插件**开了一个口:它们可以往你侧栏里加自己的一页。
123
+
124
+ 你不需要做任何设置。什么时候会看到:
125
+
126
+ - 装了某个使用这个接口的插件之后,**控制栏下面会多出一排页签**,比如 `扩展 │ 工作区 │ 那个插件的名字`。
127
+ - 点哪个,侧栏中间那块就换成哪一页。
128
+ - **再点一次当前页签**,就退回原来的会话列表 / 扩展列表。
129
+ - 你在哪一页会被记住,下次打开还在那一页。
130
+
131
+ 三种布局下的差别:
132
+
133
+ | 你选的布局 | 页签条长什么样 |
134
+ |---|---|
135
+ | 标签页(默认) | `扩展 / 工作区 / 插件页` 三种并排 |
136
+ | 折叠 | 只有插件页进条;扩展和工作区还是用原来那两个折叠按钮 |
137
+ | 浮层 | 只有插件页进条;扩展还是用「浮出面板」按钮 |
138
+
139
+ **一个都没装的话,这排页签根本不会出现** —— 界面和 0.2.x 一模一样,不会平白多一行东西。
140
+
141
+ > 想自己写一个?接口是 `ctx.sidebarSuite.registerTab({ id, title, icon, mount })`,`mount` 拿到一个空容器,你爱画什么画什么。完整示例在 README 和 DETAIL 里。
142
+
120
143
  ## 四、临时会话(重点)
121
144
 
122
145
  ### 4.1 它到底是什么
@@ -160,9 +183,16 @@ DSH **没有公开的「删除会话」接口**(官方界面的「归档」只
160
183
 
161
184
  为什么必须这样:要用原生窗口、还要能中途切走再切回,它就只能是真会话。如果要求「连磁盘都不许写」,那就只能是不在侧栏、不能多任务的纯内存方案 —— 和你要的正好相反。
162
185
 
163
- ### 4.5 想让它别删
186
+ ### 4.5 想留住某一个 / 想全都不删
187
+
188
+ **只想留住某一个(推荐,0.4.0)**:在侧栏里**右键那个带「临时」标签的会话**,选「保留为正式会话」。
189
+
190
+ 它立刻变成普通会话 —— 退出不删、定时清理也不碰,**其它临时会话照旧按时删掉**。同一个菜单里还有「立即删除」,用来当场删掉这一个,不用等退出。
191
+
192
+ - 右键**普通会话**时插件完全不插手,你的其它右键菜单照常出现。
193
+ - 右键没反应?看配置第 41 行 `TEMP_ROW_MENU` 是不是被改成 `off` 了(详情页的「临时会话右键菜单」开关写的是同一行)。
164
194
 
165
- 配置第 38 行 `DELETE_ON_EXIT=off`(见下一节)。关掉后不删除,临时会话就等于普通会话。
195
+ **想全部保留**:把配置第 45 行 `DELETE_ON_EXIT=off`(见下一节)。关掉后所有临时会话都不再删除,等于普通会话。
166
196
 
167
197
  ---
168
198
 
@@ -178,18 +208,19 @@ DSH **没有公开的「删除会话」接口**(官方界面的「归档」只
178
208
  | **19** | `TEMP_IN_CHAT_MODE=hide` | `hide` / `show` | 装了 `dsh-deepseek-chat` 时,处于 CHAT 官网模式要不要显示按钮 |
179
209
  | **27** | `TEMP_BUTTON_STYLE=pair` | `pair` / `own` | `pair` = 和「新会话」并排;`own` = 单独占一整行,完全不改「新会话」 |
180
210
  | **34** | `EXPAND_ALL_SESSIONS=on` | `on` / `off` | `on` = 会话列表全部展开、隐藏「展开其余 N 个会话」;`off` = 恢复 DSH 原来的折叠 |
181
- | **38** | `DELETE_ON_EXIT=on` | `on` / `off` | **退出 DSH 时**删不删 |
182
- | **44** | `SCHEDULE_DELETE=off` | `on` / `off` | **每天定时清理**要不要开 |
183
- | **49** | `SCHEDULE_TIME=03:00` | `HH:MM`(如 `03:00`、`23:30`) | 定时清理的时间点,24 小时制、本机时间 |
184
- | **53** | `MAX_KEPT=20` | 1–200 | 最多同时留几个临时会话,超了先删最早的 |
211
+ | **41** | `TEMP_ROW_MENU=on` | `on` / `off` | `on` = 右键临时会话可「保留为正式会话 / 立即删除」;`off` = 不接管右键(别的插件抢右键时用) |
212
+ | **45** | `DELETE_ON_EXIT=on` | `on` / `off` | **退出 DSH 时**删不删 |
213
+ | **51** | `SCHEDULE_DELETE=off` | `on` / `off` | **每天定时清理**要不要开 |
214
+ | **56** | `SCHEDULE_TIME=03:00` | `HH:MM`(如 `03:00`、`23:30`) | 定时清理的时间点,24 小时制、本机时间 |
215
+ | **60** | `MAX_KEPT=20` | 1–200 | 最多同时留几个临时会话,超了先删最早的 |
185
216
 
186
- > 这一整节都可以不动手改文件 —— 0.2.8 起详情页有**全部 8 项的图形化开关**,见 5.1。两种改法写的是**同一份文件**,改完都在约 3 秒内生效,不会打架。
217
+ > 这一整节都可以不动手改文件 —— 0.2.8 起详情页有**全部 9 项的图形化开关**,见 5.1。两种改法写的是**同一份文件**,改完都在约 3 秒内生效,不会打架。
187
218
 
188
219
  ### 5.1 全部设置都在详情页里改(推荐,不用改文件)
189
220
 
190
221
  打开 DSH → 插件 → `dsh-sidebar-suite` → 详情页最上面那张卡。0.2.8 起这里是**两块设置**:
191
222
 
192
- **第一块「侧栏与临时会话」**(这一节表里 8 个键里的前 4 个 + 保留上限,全都能点):
223
+ **第一块「侧栏与临时会话」**(这一节表里 9 个键里的前 5 个 + 保留上限,全都能点):
193
224
 
194
225
  ```
195
226
  侧栏与临时会话 · Sidebar & temp session options
@@ -199,6 +230,7 @@ DSH **没有公开的「删除会话」接口**(官方界面的「归档」只
199
230
  CHAT 官网模式 [隐藏按钮] / [照常显示]
200
231
  按钮摆法 [并排] / [独占一行]
201
232
  会话默认全展开 [开] / [关]
233
+ 临时会话右键菜单 [开] / [关]
202
234
  最多保留 [ 20 ] 个临时会话(1–200)
203
235
  设置版本 12 · …/temp-session-config.txt
204
236
  ```