@deepseek-harness-tui/dsh-tui 0.10.2 → 0.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.
Files changed (277) hide show
  1. package/README.md +171 -124
  2. package/bin/dsh-tui.js +748 -22
  3. package/cordis.patch.yml +38 -10
  4. package/cordis.yml +2 -0
  5. package/lib/types/adapter/channel/session-projection.d.ts.map +1 -1
  6. package/lib/types/adapter/channel/session-projection.js +2 -0
  7. package/lib/types/adapter/channel/ui-policy.d.ts +4 -1
  8. package/lib/types/adapter/channel/ui-policy.d.ts.map +1 -1
  9. package/lib/types/adapter/channel/ui-policy.js +5 -1
  10. package/lib/types/adapter/kernel/host-facade.d.ts.map +1 -1
  11. package/lib/types/adapter/kernel/host-facade.js +1 -0
  12. package/lib/types/adapter/kernel/replay.d.ts.map +1 -1
  13. package/lib/types/adapter/kernel/replay.js +3 -0
  14. package/lib/types/adapter/kernel/runtime.d.ts.map +1 -1
  15. package/lib/types/adapter/kernel/runtime.js +2 -0
  16. package/lib/types/adapter/kernel/slices/workspace.d.ts.map +1 -1
  17. package/lib/types/adapter/kernel/slices/workspace.js +1 -0
  18. package/lib/types/adapter/ports/channel-ui.d.ts +22 -2
  19. package/lib/types/adapter/ports/channel-ui.d.ts.map +1 -1
  20. package/lib/types/adapter/ports/channel-view.d.ts +66 -0
  21. package/lib/types/adapter/ports/channel-view.d.ts.map +1 -1
  22. package/lib/types/adapter/ports/channel-workspace.d.ts +23 -0
  23. package/lib/types/adapter/ports/channel-workspace.d.ts.map +1 -1
  24. package/lib/types/adapter/ports/workspace.d.ts +2 -0
  25. package/lib/types/adapter/ports/workspace.d.ts.map +1 -1
  26. package/lib/types/adapter/upstream/workspace-driver.d.ts.map +1 -1
  27. package/lib/types/adapter/upstream/workspace-driver.js +10 -2
  28. package/lib/types/commands.d.ts.map +1 -1
  29. package/lib/types/commands.js +1 -0
  30. package/lib/types/components/ContextBarView.d.ts +15 -7
  31. package/lib/types/components/ContextBarView.d.ts.map +1 -1
  32. package/lib/types/components/ContextBarView.js +26 -22
  33. package/lib/types/components/ImagePreviewOverlay.d.ts.map +1 -1
  34. package/lib/types/components/ImagePreviewOverlay.js +11 -5
  35. package/lib/types/components/Markdown.d.ts +11 -1
  36. package/lib/types/components/Markdown.d.ts.map +1 -1
  37. package/lib/types/components/Markdown.js +20 -2
  38. package/lib/types/components/MermaidDiagram.d.ts +13 -0
  39. package/lib/types/components/MermaidDiagram.d.ts.map +1 -0
  40. package/lib/types/components/MermaidDiagram.js +61 -0
  41. package/lib/types/components/MessageList.d.ts +26 -1
  42. package/lib/types/components/MessageList.d.ts.map +1 -1
  43. package/lib/types/components/MessageList.js +72 -7
  44. package/lib/types/components/PageMargin.d.ts +1 -1
  45. package/lib/types/components/PromptInput.d.ts +37 -1
  46. package/lib/types/components/PromptInput.d.ts.map +1 -1
  47. package/lib/types/components/PromptInput.js +243 -28
  48. package/lib/types/components/ScrollbarGutter.d.ts +20 -5
  49. package/lib/types/components/ScrollbarGutter.d.ts.map +1 -1
  50. package/lib/types/components/ScrollbarGutter.js +88 -10
  51. package/lib/types/components/StreamingMarkdown.d.ts.map +1 -1
  52. package/lib/types/components/StreamingMarkdown.js +30 -28
  53. package/lib/types/components/Tooltip.d.ts.map +1 -1
  54. package/lib/types/components/Tooltip.js +45 -7
  55. package/lib/types/components/messages/UserPromptMessage.d.ts.map +1 -1
  56. package/lib/types/components/messages/UserPromptMessage.js +5 -7
  57. package/lib/types/components/messages/useImageInspection.d.ts.map +1 -1
  58. package/lib/types/components/messages/useImageInspection.js +19 -9
  59. package/lib/types/components/promptDraftCache.d.ts +102 -0
  60. package/lib/types/components/promptDraftCache.d.ts.map +1 -0
  61. package/lib/types/components/promptDraftCache.js +76 -0
  62. package/lib/types/components/questions/AskUserQuestionPanel.d.ts +17 -1
  63. package/lib/types/components/questions/AskUserQuestionPanel.d.ts.map +1 -1
  64. package/lib/types/components/questions/AskUserQuestionPanel.js +40 -7
  65. package/lib/types/components/questions/QuestionMinimizedBar.d.ts +12 -0
  66. package/lib/types/components/questions/QuestionMinimizedBar.d.ts.map +1 -0
  67. package/lib/types/components/questions/QuestionMinimizedBar.js +43 -0
  68. package/lib/types/components/sessions/SessionListRow.d.ts +23 -1
  69. package/lib/types/components/sessions/SessionListRow.d.ts.map +1 -1
  70. package/lib/types/components/sessions/SessionListRow.js +52 -5
  71. package/lib/types/components/workspaces/HomeWorkspaceRow.d.ts +49 -0
  72. package/lib/types/components/workspaces/HomeWorkspaceRow.d.ts.map +1 -0
  73. package/lib/types/components/workspaces/HomeWorkspaceRow.js +50 -0
  74. package/lib/types/dsh-adapter/bundled-presets.d.ts +10 -0
  75. package/lib/types/dsh-adapter/bundled-presets.d.ts.map +1 -0
  76. package/lib/types/dsh-adapter/bundled-presets.js +80 -0
  77. package/lib/types/dsh-adapter/channel/action-readiness.d.ts +1 -1
  78. package/lib/types/dsh-adapter/channel/action-readiness.d.ts.map +1 -1
  79. package/lib/types/dsh-adapter/channel/action-readiness.js +3 -0
  80. package/lib/types/dsh-adapter/channel/agent-view-projection.d.ts +1 -1
  81. package/lib/types/dsh-adapter/channel/agent-view-projection.d.ts.map +1 -1
  82. package/lib/types/dsh-adapter/channel/agent-view-projection.js +19 -2
  83. package/lib/types/dsh-adapter/channel/background-action.d.ts.map +1 -1
  84. package/lib/types/dsh-adapter/channel/background-action.js +52 -29
  85. package/lib/types/dsh-adapter/channel/binding.d.ts +19 -2
  86. package/lib/types/dsh-adapter/channel/binding.d.ts.map +1 -1
  87. package/lib/types/dsh-adapter/channel/binding.js +78 -18
  88. package/lib/types/dsh-adapter/channel/composer-images.d.ts +5 -0
  89. package/lib/types/dsh-adapter/channel/composer-images.d.ts.map +1 -1
  90. package/lib/types/dsh-adapter/channel/composer-images.js +105 -6
  91. package/lib/types/dsh-adapter/channel/context-bookkeeping.d.ts +8 -0
  92. package/lib/types/dsh-adapter/channel/context-bookkeeping.d.ts.map +1 -1
  93. package/lib/types/dsh-adapter/channel/context-bookkeeping.js +3 -2
  94. package/lib/types/dsh-adapter/channel/ide-selection.d.ts +58 -0
  95. package/lib/types/dsh-adapter/channel/ide-selection.d.ts.map +1 -0
  96. package/lib/types/dsh-adapter/channel/ide-selection.js +226 -0
  97. package/lib/types/dsh-adapter/channel/input-delivery.d.ts +6 -1
  98. package/lib/types/dsh-adapter/channel/input-delivery.d.ts.map +1 -1
  99. package/lib/types/dsh-adapter/channel/input-delivery.js +9 -1
  100. package/lib/types/dsh-adapter/channel/local-actions.d.ts +3 -19
  101. package/lib/types/dsh-adapter/channel/local-actions.d.ts.map +1 -1
  102. package/lib/types/dsh-adapter/channel/local-actions.js +2 -1
  103. package/lib/types/dsh-adapter/channel/model-actions.d.ts +4 -1
  104. package/lib/types/dsh-adapter/channel/model-actions.d.ts.map +1 -1
  105. package/lib/types/dsh-adapter/channel/model-actions.js +82 -6
  106. package/lib/types/dsh-adapter/channel/model-switch.d.ts.map +1 -1
  107. package/lib/types/dsh-adapter/channel/model-switch.js +49 -31
  108. package/lib/types/dsh-adapter/channel/projection.d.ts +4 -0
  109. package/lib/types/dsh-adapter/channel/projection.d.ts.map +1 -1
  110. package/lib/types/dsh-adapter/channel/projection.js +29 -19
  111. package/lib/types/dsh-adapter/channel/reports.d.ts.map +1 -1
  112. package/lib/types/dsh-adapter/channel/reports.js +4 -12
  113. package/lib/types/dsh-adapter/channel/session-fork.d.ts.map +1 -1
  114. package/lib/types/dsh-adapter/channel/session-fork.js +26 -2
  115. package/lib/types/dsh-adapter/channel/session-live-adoption.d.ts +3 -0
  116. package/lib/types/dsh-adapter/channel/session-live-adoption.d.ts.map +1 -1
  117. package/lib/types/dsh-adapter/channel/session-live-adoption.js +1 -0
  118. package/lib/types/dsh-adapter/channel/session-metadata.d.ts +10 -0
  119. package/lib/types/dsh-adapter/channel/session-metadata.d.ts.map +1 -1
  120. package/lib/types/dsh-adapter/channel/session-metadata.js +2 -2
  121. package/lib/types/dsh-adapter/channel/session-resume.d.ts +11 -2
  122. package/lib/types/dsh-adapter/channel/session-resume.d.ts.map +1 -1
  123. package/lib/types/dsh-adapter/channel/session-resume.js +291 -94
  124. package/lib/types/dsh-adapter/channel/session-rewind.d.ts.map +1 -1
  125. package/lib/types/dsh-adapter/channel/session-rewind.js +34 -16
  126. package/lib/types/dsh-adapter/channel/session-tree-actions.d.ts.map +1 -1
  127. package/lib/types/dsh-adapter/channel/session-tree-actions.js +19 -3
  128. package/lib/types/dsh-adapter/channel/settings-host.d.ts.map +1 -1
  129. package/lib/types/dsh-adapter/channel/settings-host.js +4 -3
  130. package/lib/types/dsh-adapter/channel/state.d.ts +1 -1
  131. package/lib/types/dsh-adapter/channel/state.d.ts.map +1 -1
  132. package/lib/types/dsh-adapter/channel/state.js +1 -1
  133. package/lib/types/dsh-adapter/channel/transcript.d.ts.map +1 -1
  134. package/lib/types/dsh-adapter/channel/transcript.js +6 -12
  135. package/lib/types/dsh-adapter/channel/types.d.ts +6 -1
  136. package/lib/types/dsh-adapter/channel/types.d.ts.map +1 -1
  137. package/lib/types/dsh-adapter/channel/workspace-actions.d.ts +4 -1
  138. package/lib/types/dsh-adapter/channel/workspace-actions.d.ts.map +1 -1
  139. package/lib/types/dsh-adapter/channel/workspace-actions.js +41 -1
  140. package/lib/types/dsh-adapter/channel.d.ts.map +1 -1
  141. package/lib/types/dsh-adapter/channel.js +67 -6
  142. package/lib/types/dsh-adapter/compat/messages.d.ts +15 -0
  143. package/lib/types/dsh-adapter/compat/messages.d.ts.map +1 -0
  144. package/lib/types/dsh-adapter/compat/messages.js +15 -0
  145. package/lib/types/dsh-adapter/compat/settings.d.ts +33 -0
  146. package/lib/types/dsh-adapter/compat/settings.d.ts.map +1 -0
  147. package/lib/types/dsh-adapter/compat/settings.js +43 -0
  148. package/lib/types/dsh-adapter/compat/shell.d.ts +25 -0
  149. package/lib/types/dsh-adapter/compat/shell.d.ts.map +1 -0
  150. package/lib/types/dsh-adapter/compat/shell.js +11 -0
  151. package/lib/types/dsh-adapter/contract.d.ts +4 -4
  152. package/lib/types/dsh-adapter/contract.d.ts.map +1 -1
  153. package/lib/types/dsh-adapter/contract.js +15 -6
  154. package/lib/types/dsh-adapter/ide-channel.d.ts +224 -0
  155. package/lib/types/dsh-adapter/ide-channel.d.ts.map +1 -0
  156. package/lib/types/dsh-adapter/ide-channel.js +556 -0
  157. package/lib/types/dsh-adapter/index.d.ts +18 -3
  158. package/lib/types/dsh-adapter/index.d.ts.map +1 -1
  159. package/lib/types/dsh-adapter/index.js +32 -5
  160. package/lib/types/dsh-adapter/plugin.d.ts +5 -2
  161. package/lib/types/dsh-adapter/plugin.d.ts.map +1 -1
  162. package/lib/types/dsh-adapter/plugin.js +173 -42
  163. package/lib/types/dsh-adapter/preset-resolution.d.ts +8 -0
  164. package/lib/types/dsh-adapter/preset-resolution.d.ts.map +1 -1
  165. package/lib/types/dsh-adapter/preset-resolution.js +10 -0
  166. package/lib/types/dsh-adapter/session-mount-heartbeat.d.ts +53 -0
  167. package/lib/types/dsh-adapter/session-mount-heartbeat.d.ts.map +1 -0
  168. package/lib/types/dsh-adapter/session-mount-heartbeat.js +100 -0
  169. package/lib/types/dsh-adapter/sessionTree.d.ts.map +1 -1
  170. package/lib/types/dsh-adapter/sessionTree.js +3 -2
  171. package/lib/types/dsh-adapter/subagents.d.ts.map +1 -1
  172. package/lib/types/dsh-adapter/subagents.js +6 -5
  173. package/lib/types/dsh-adapter/workspaces.d.ts +46 -3
  174. package/lib/types/dsh-adapter/workspaces.d.ts.map +1 -1
  175. package/lib/types/dsh-adapter/workspaces.js +116 -0
  176. package/lib/types/effortPrefs.d.ts +15 -3
  177. package/lib/types/effortPrefs.d.ts.map +1 -1
  178. package/lib/types/effortPrefs.js +37 -3
  179. package/lib/types/homePrefs.d.ts +15 -0
  180. package/lib/types/homePrefs.d.ts.map +1 -0
  181. package/lib/types/homePrefs.js +53 -0
  182. package/lib/types/i18n.d.ts +257 -296
  183. package/lib/types/i18n.d.ts.map +1 -1
  184. package/lib/types/i18n.js +78 -84
  185. package/lib/types/ink/colorize.d.ts +10 -0
  186. package/lib/types/ink/colorize.d.ts.map +1 -1
  187. package/lib/types/ink/colorize.js +21 -0
  188. package/lib/types/ink/components/ScrollBox.d.ts.map +1 -1
  189. package/lib/types/ink/components/ScrollBox.js +12 -1
  190. package/lib/types/ink/dom.d.ts +1 -0
  191. package/lib/types/ink/dom.d.ts.map +1 -1
  192. package/lib/types/ink/hooks/use-copy-on-select.d.ts +5 -1
  193. package/lib/types/ink/hooks/use-copy-on-select.d.ts.map +1 -1
  194. package/lib/types/ink/hooks/use-copy-on-select.js +15 -1
  195. package/lib/types/ink/ink.d.ts.map +1 -1
  196. package/lib/types/ink/ink.js +36 -1
  197. package/lib/types/ink/output.d.ts +10 -1
  198. package/lib/types/ink/output.d.ts.map +1 -1
  199. package/lib/types/ink/output.js +109 -17
  200. package/lib/types/ink/render-border.d.ts +6 -1
  201. package/lib/types/ink/render-border.d.ts.map +1 -1
  202. package/lib/types/ink/render-border.js +25 -9
  203. package/lib/types/ink/render-node-to-output.d.ts.map +1 -1
  204. package/lib/types/ink/render-node-to-output.js +48 -6
  205. package/lib/types/ink/renderer.d.ts +6 -0
  206. package/lib/types/ink/renderer.d.ts.map +1 -1
  207. package/lib/types/ink/renderer.js +2 -1
  208. package/lib/types/ink/selection.d.ts +60 -0
  209. package/lib/types/ink/selection.d.ts.map +1 -1
  210. package/lib/types/ink/selection.js +129 -0
  211. package/lib/types/ink/sixel-graphics.d.ts +19 -1
  212. package/lib/types/ink/sixel-graphics.d.ts.map +1 -1
  213. package/lib/types/ink/sixel-graphics.js +124 -12
  214. package/lib/types/ink/terminal-image.d.ts +18 -1
  215. package/lib/types/ink/terminal-image.d.ts.map +1 -1
  216. package/lib/types/ink/terminal.d.ts +17 -0
  217. package/lib/types/ink/terminal.d.ts.map +1 -1
  218. package/lib/types/ink/terminal.js +20 -1
  219. package/lib/types/screens/Chat.d.ts +17 -1
  220. package/lib/types/screens/Chat.d.ts.map +1 -1
  221. package/lib/types/screens/Chat.js +284 -72
  222. package/lib/types/screens/SessionSupervisor.d.ts +84 -0
  223. package/lib/types/screens/SessionSupervisor.d.ts.map +1 -0
  224. package/lib/types/screens/SessionSupervisor.js +350 -0
  225. package/lib/types/screens/SessionTree.js +2 -2
  226. package/lib/types/screens/Settings.d.ts.map +1 -1
  227. package/lib/types/screens/Settings.js +32 -9
  228. package/lib/types/screens/StatusLine.d.ts +13 -0
  229. package/lib/types/screens/StatusLine.d.ts.map +1 -1
  230. package/lib/types/screens/StatusLine.js +36 -17
  231. package/lib/types/screens/StatusMetrics.d.ts +79 -22
  232. package/lib/types/screens/StatusMetrics.d.ts.map +1 -1
  233. package/lib/types/screens/StatusMetrics.js +153 -88
  234. package/lib/types/screens/sessionSupervisor/model.d.ts +83 -0
  235. package/lib/types/screens/sessionSupervisor/model.d.ts.map +1 -0
  236. package/lib/types/screens/sessionSupervisor/model.js +69 -0
  237. package/lib/types/screens/sessionSupervisor/useSessionSupervisor.d.ts +120 -0
  238. package/lib/types/screens/sessionSupervisor/useSessionSupervisor.d.ts.map +1 -0
  239. package/lib/types/screens/sessionSupervisor/useSessionSupervisor.js +593 -0
  240. package/lib/types/sessionMounts.d.ts +272 -0
  241. package/lib/types/sessionMounts.d.ts.map +1 -0
  242. package/lib/types/sessionMounts.js +706 -0
  243. package/lib/types/sessions/format.d.ts.map +1 -1
  244. package/lib/types/sessions/format.js +4 -1
  245. package/lib/types/sessions/resumeFailure.d.ts +38 -0
  246. package/lib/types/sessions/resumeFailure.d.ts.map +1 -0
  247. package/lib/types/sessions/resumeFailure.js +58 -0
  248. package/lib/types/terminal-utils/mermaid.d.ts +44 -0
  249. package/lib/types/terminal-utils/mermaid.d.ts.map +1 -0
  250. package/lib/types/terminal-utils/mermaid.js +83 -0
  251. package/lib/types/tips.d.ts.map +1 -1
  252. package/lib/types/tips.js +175 -19
  253. package/lib/types/tuiDisplayPrefs.d.ts +7 -9
  254. package/lib/types/tuiDisplayPrefs.d.ts.map +1 -1
  255. package/lib/types/tuiDisplayPrefs.js +31 -28
  256. package/lib/types/update.d.ts +61 -0
  257. package/lib/types/update.d.ts.map +1 -1
  258. package/lib/types/update.js +194 -0
  259. package/lib/types/utils/imageResize.d.ts +90 -0
  260. package/lib/types/utils/imageResize.d.ts.map +1 -0
  261. package/lib/types/utils/imageResize.js +272 -0
  262. package/lib/types/utils/keymap.d.ts +5 -1
  263. package/lib/types/utils/keymap.d.ts.map +1 -1
  264. package/lib/types/utils/keymap.js +23 -0
  265. package/lib/types/workspaces.d.ts +2 -1
  266. package/lib/types/workspaces.d.ts.map +1 -1
  267. package/lib/types/workspaces.js +1 -1
  268. package/node_modules/@deepseek-harness-tui/dsh-auth/package.json +10 -10
  269. package/package.json +120 -103
  270. package/presets/liangshen/.dsh-tui-managed.json +1 -1
  271. package/presets/liangshen/agent.cordis.yml +15 -0
  272. package/lib/types/screens/AgentView.d.ts +0 -23
  273. package/lib/types/screens/AgentView.d.ts.map +0 -1
  274. package/lib/types/screens/AgentView.js +0 -546
  275. package/lib/types/screens/SessionBrowser.d.ts +0 -42
  276. package/lib/types/screens/SessionBrowser.d.ts.map +0 -1
  277. package/lib/types/screens/SessionBrowser.js +0 -911
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Publishes this TUI process's mounted-session set to the cross-process
3
+ * ledger ({@link ../../sessionMounts.js}).
4
+ *
5
+ * A TUI terminal hosts several agent sessions at once — the attached one plus
6
+ * every parked background session — and two processes driving the same
7
+ * session log would interleave writes into one append-only transcript. The
8
+ * ledger is what lets another TUI see "this session is already mounted" and
9
+ * refuse it, so the published set has to cover EVERY live agent in this
10
+ * process, not just the attached one.
11
+ *
12
+ * Reading the agent registry is what makes that automatic, and the small timer
13
+ * is what keeps it honest: agents are created from more than seven paths
14
+ * (`/new`, `/resume`, `/bg`, fork, rewind, model switch, boot attach), so an
15
+ * announce-at-each-call-site design would silently drop a session the day
16
+ * someone adds an eighth. Deriving the set from the registry has exactly one
17
+ * place to be right.
18
+ *
19
+ * Publishing is NOT a liveness witness: {@link ../../sessionMounts.js} decides
20
+ * liveness from the owner's pid alone, so a late or missed publish cannot keep
21
+ * a dead process's claim alive and there is no timestamp here to expire. The
22
+ * timer's only job is to keep the published SET current, and it is deliberately
23
+ * unref'd: it must never be the reason a quitting TUI stays alive. Teardown
24
+ * removes the record outright so a clean exit frees its sessions immediately.
25
+ *
26
+ * Registered through the host's single teardown funnel by the caller, so both
27
+ * the interval and the ledger record are released exactly once.
28
+ *
29
+ * @module
30
+ */
31
+ import { clearOwnMounts, publishMounts } from '../sessionMounts.js';
32
+ /**
33
+ * How often the mounted set is republished. One small file write, not tied to
34
+ * any render frame; it bounds how long a peer can read a set that predates a
35
+ * session this process just mounted.
36
+ */
37
+ const PUBLISH_INTERVAL_MS = 15_000;
38
+ /**
39
+ * Collect the session ids this process currently has mounted: every live agent
40
+ * the registry knows about, minus sub-agent runs.
41
+ *
42
+ * Sub-agents are excluded because they are not independently mountable: they
43
+ * are a parent session's own work, they never appear as `/resume` rows, and
44
+ * claiming their ids would make the parent look occupied to a TUI that only
45
+ * wants to read the parent.
46
+ * @param ctx - The plugin context, for the agent registry.
47
+ * @returns Session ids as strings.
48
+ */
49
+ export function mountedSessionIds(ctx) {
50
+ const roster = ctx.get('agents');
51
+ const ids = [];
52
+ for (const agent of roster?.list?.() ?? []) {
53
+ if (agent.session.header.origin === 'subagent')
54
+ continue;
55
+ const id = String(agent.id);
56
+ if (id.length > 0)
57
+ ids.push(id);
58
+ }
59
+ return ids;
60
+ }
61
+ /**
62
+ * Start publishing this process's mounted sessions.
63
+ *
64
+ * The first publish runs synchronously so a session mounted during boot is
65
+ * claimed before the user can reach a second terminal.
66
+ * @param ctx - The plugin context, for the agent registry.
67
+ * @returns A disposer that stops publishing and releases the claim.
68
+ */
69
+ export function startSessionMountHeartbeat(ctx) {
70
+ let stopped = false;
71
+ const beat = () => {
72
+ if (stopped)
73
+ return;
74
+ try {
75
+ publishMounts(mountedSessionIds(ctx));
76
+ }
77
+ catch {
78
+ // PUBLISHING is best-effort; DECIDING is not. A beat that cannot write
79
+ // costs announcement until the next one, and must not disturb this
80
+ // session — while the paths that grant a mount refuse outright when they
81
+ // cannot read the ledger, because that is the one error nothing can
82
+ // repair afterwards.
83
+ }
84
+ };
85
+ beat();
86
+ const timer = setInterval(beat, PUBLISH_INTERVAL_MS);
87
+ // Never let the publisher hold the process open: quitting the TUI must not
88
+ // wait for a timer that exists only to describe a process that is leaving.
89
+ timer.unref?.();
90
+ return () => {
91
+ stopped = true;
92
+ clearInterval(timer);
93
+ try {
94
+ clearOwnMounts();
95
+ }
96
+ catch {
97
+ // A leftover record is ignored once this pid is gone.
98
+ }
99
+ };
100
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"sessionTree.d.ts","sourceRoot":"","sources":["../../../src/dsh-adapter/sessionTree.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sessionTree.d.ts","sourceRoot":"","sources":["../../../src/dsh-adapter/sessionTree.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import { isCompactionCheckpointSource, toolResultPayload } from './compat/messages.js';
1
2
  export const TREE_FILTERS = ['default', 'no-tools', 'user-only', 'all'];
2
3
  /**
3
4
  * Confirm-time preview for a USER-message pick: how much of its branch the
@@ -345,7 +346,7 @@ export function extractEntries(sessionId, events) {
345
346
  switch (event.type) {
346
347
  case 'user/message': {
347
348
  const source = event.data.source;
348
- if (source.kind === 'plugin' && source.plugin === 'compact') {
349
+ if (isCompactionCheckpointSource(source)) {
349
350
  const summary = textOf(event.data.content);
350
351
  push({
351
352
  seq: event.seq,
@@ -408,7 +409,7 @@ export function extractEntries(sessionId, events) {
408
409
  const entry = entries[index];
409
410
  entries[index] = {
410
411
  ...entry,
411
- toolStatus: event.data.error === undefined ? 'ok' : 'error',
412
+ toolStatus: event.data.error !== undefined || toolResultPayload(event.data.message).isError ? 'error' : 'ok',
412
413
  };
413
414
  openTools.delete(event.data.message.source.callId);
414
415
  break;
@@ -1 +1 @@
1
- {"version":3,"file":"subagents.d.ts","sourceRoot":"","sources":["../../../src/dsh-adapter/subagents.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAA;AAClE,OAAO,KAAK,EAAE,aAAa,EAAsC,kBAAkB,EAAE,gBAAgB,EAAsB,MAAM,kCAAkC,CAAA;AACnK,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAA;AAiBnK,qBAAa,qBAAqB;IAChC,OAAO,CAAC,MAAM,CAAmC;IACjD,OAAO,CAAC,cAAc,CAA6B;IACnD,OAAO,CAAC,SAAS,CAAwB;IACzC,OAAO,CAAC,OAAO,CAA2C;IAE1D,OAAO,CAAC,UAAU;IAMlB,OAAO,CAAC,QAAQ;IAOhB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,SAAa,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,IAAI,GAAE,OAAO,CAAC,aAAa,CAAM,GAAG,IAAI;IA0B1G,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI;IAMpD,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS;IAE5D,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,kBAA2B,GAAG,IAAI;IA0BpF,8DAA8D;IAC9D,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IASlC;mFAC+E;IAC/E,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,oBAAoB,GAAG,IAAI;IA+BjE,OAAO,CAAC,cAAc;IAStB,OAAO,CAAC,eAAe;IAyBvB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI;IAoDrD,6EAA6E;IAC7E,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,GAAG,IAAI;IAO7D,2EAA2E;IAC3E,OAAO,CAAC,SAAS;IAUjB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,gBAAgB,CAAC,GAAG;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IASvF,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAU3J,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,UAAU,SAAc,GAAG,IAAI;IAC9E,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAC9C,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,SAAc,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI;IAE1E,OAAO,CAAC,MAAM;IAcd;;sEAEkE;IAClE,KAAK,IAAI,IAAI;IAOb,QAAQ,IAAI,aAAa,EAAE;IAC3B,GAAG,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAC/C,SAAS,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI;IAC3C,OAAO,CAAC,MAAM;CACf"}
1
+ {"version":3,"file":"subagents.d.ts","sourceRoot":"","sources":["../../../src/dsh-adapter/subagents.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAA;AAElE,OAAO,KAAK,EAAE,aAAa,EAAsC,kBAAkB,EAAE,gBAAgB,EAAsB,MAAM,kCAAkC,CAAA;AACnK,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAA;AAiBnK,qBAAa,qBAAqB;IAChC,OAAO,CAAC,MAAM,CAAmC;IACjD,OAAO,CAAC,cAAc,CAA6B;IACnD,OAAO,CAAC,SAAS,CAAwB;IACzC,OAAO,CAAC,OAAO,CAA2C;IAE1D,OAAO,CAAC,UAAU;IAMlB,OAAO,CAAC,QAAQ;IAOhB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,SAAa,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,IAAI,GAAE,OAAO,CAAC,aAAa,CAAM,GAAG,IAAI;IA0B1G,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI;IAMpD,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS;IAE5D,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,kBAA2B,GAAG,IAAI;IA0BpF,8DAA8D;IAC9D,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IASlC;mFAC+E;IAC/E,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,oBAAoB,GAAG,IAAI;IA+BjE,OAAO,CAAC,cAAc;IAStB,OAAO,CAAC,eAAe;IAyBvB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI;IAmDrD,6EAA6E;IAC7E,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,GAAG,IAAI;IAO7D,2EAA2E;IAC3E,OAAO,CAAC,SAAS;IAUjB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,gBAAgB,CAAC,GAAG;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IASvF,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAU3J,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,UAAU,SAAc,GAAG,IAAI;IAC9E,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAC9C,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,SAAc,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI;IAE1E,OAAO,CAAC,MAAM;IAcd;;sEAEkE;IAClE,KAAK,IAAI,IAAI;IAOb,QAAQ,IAAI,aAAa,EAAE;IAC3B,GAAG,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAC/C,SAAS,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI;IAC3C,OAAO,CAAC,MAAM;CACf"}
@@ -1,3 +1,4 @@
1
+ import { toolResultPayload } from './compat/messages.js';
1
2
  const MAX_OUTPUT_EVENTS = 160;
2
3
  const MAX_OUTPUT_LINES = 160;
3
4
  export class SubagentActivityStore {
@@ -208,15 +209,15 @@ export class SubagentActivityStore {
208
209
  const state = this.states.get(agentId);
209
210
  const tool = callId !== undefined ? state?.toolCalls.find(entry => entry.id === callId) : undefined;
210
211
  if (tool) {
211
- tool.status = data.error !== undefined ? 'failed' : 'completed';
212
+ const payload = toolResultPayload(data.message);
213
+ tool.status = data.error !== undefined || payload.isError ? 'failed' : 'completed';
212
214
  tool.endedAt = Date.now();
213
215
  if (data.error !== undefined)
214
216
  tool.error = String(data.error);
217
+ else if (payload.isError)
218
+ tool.error = this.previewOf(payload.content);
215
219
  else {
216
- const block = data.message?.content?.[0];
217
- tool.resultPreview = block !== undefined && block.type === 'tool-result'
218
- ? this.previewOf(block.content)
219
- : undefined;
220
+ tool.resultPreview = this.previewOf(payload.content);
220
221
  }
221
222
  this.notify();
222
223
  }
@@ -1,5 +1,5 @@
1
- import type { TuiWorkspaceTarget, TuiWorkspaceCommand, TuiWorkspaceCommandResult } from '../adapter/ports/channel-workspace.js';
2
- export type { TuiWorkspaceTarget, TuiWorkspaceKind, TuiWorkspaceCommand, TuiWorkspaceCommandResult, TuiWorkspaceChoice } from '../adapter/ports/channel-workspace.js';
1
+ import type { TuiWorkspaceTarget, TuiWorkspaceCommand, TuiWorkspaceCommandResult, TuiWorkspaceEntry } from '../adapter/ports/channel-workspace.js';
2
+ export type { TuiWorkspaceTarget, TuiWorkspaceKind, TuiWorkspaceCommand, TuiWorkspaceCommandResult, TuiWorkspaceChoice, TuiWorkspaceEntry } from '../adapter/ports/channel-workspace.js';
3
3
  import { Context, Service } from '@deepseek-ai/cordis';
4
4
  export interface TuiCommandShell {
5
5
  resolve(request: {
@@ -45,9 +45,39 @@ export interface TuiWorkspaceHost {
45
45
  describe(cwd: string): TuiWorkspaceTarget;
46
46
  commandShell(cwd: string): Promise<TuiCommandShell | undefined>;
47
47
  rename(cwd: string, title: string): Promise<TuiWorkspaceTarget>;
48
+ /** Drop a workspace registration (never the directory or its session logs). */
49
+ remove(cwd: string): Promise<boolean>;
50
+ /**
51
+ * The durable ledger's own listing, in its own order.
52
+ *
53
+ * Unlike `list`, this merges nothing and appends nothing: it is the set of
54
+ * registrations the sidebar manages, including entries with no sessions and
55
+ * entries whose directory has disappeared.
56
+ */
57
+ listRegistry(): Promise<readonly TuiWorkspaceEntry[]>;
48
58
  commands(): readonly Pick<TuiWorkspaceCommand, 'name' | 'aliases' | 'description'>[];
49
59
  runCommand(name: string, input: string, cwd: string, signal?: AbortSignal): Promise<TuiWorkspaceCommandResult | undefined>;
50
60
  }
61
+ /** Registry-backed list surface for the workspace home screen. */
62
+ type RegistryWorkspaceEntry = TuiWorkspaceEntry;
63
+ /**
64
+ * Enumerate the durable workspace registry, in its own display order.
65
+ *
66
+ * The sidebar needs the *registry* (every workspace the user ever registered,
67
+ * including ones with no sessions yet), not the session-derived grouping the
68
+ * `/resume` browser builds. Order, ids and titles come from the ledger;
69
+ * `sessionCount` is filled in by the caller (the adapter holds no session
70
+ * index), and `present` is derived here.
71
+ */
72
+ export declare function listRegistryWorkspaces(runtime: TuiWorkspaceRuntime | undefined): Promise<readonly RegistryWorkspaceEntry[]>;
73
+ /**
74
+ * Remove a workspace registration by path. Sessions and the directory survive:
75
+ * only the ledger entry goes away, so the sessions reappear as ungrouped.
76
+ *
77
+ * @returns True when a record was removed, false when no record owned `cwd`
78
+ * (or the ledger is unmounted).
79
+ */
80
+ export declare function removeRegistryWorkspace(runtime: TuiWorkspaceRuntime | undefined, cwd: string, owner?: object): Promise<boolean>;
51
81
  declare module '@deepseek-ai/cordis' {
52
82
  interface Context {
53
83
  tuiWorkspaces: TuiWorkspaceRuntime;
@@ -66,6 +96,19 @@ export declare class TuiWorkspaceRuntime extends Service {
66
96
  describe(cwd: string): TuiWorkspaceTarget;
67
97
  commandShell(cwd: string): Promise<TuiCommandShell | undefined>;
68
98
  rename(cwd: string, title: string): Promise<TuiWorkspaceTarget>;
99
+ /**
100
+ * Drop a workspace registration; the directory and session logs survive.
101
+ *
102
+ * Plugin-facing, and therefore bound by the SAME rule as {@link rename}: a
103
+ * live calling activation is required, and the target must be a cwd one of
104
+ * that activation's own providers vouches for. Without both, a plugin that
105
+ * never owned the workspace 鈥?including one whose fiber was already disposed
106
+ * and whose caller context is a retained handle 鈥?could delete a host
107
+ * registration. Shadow policy alone is not caller authentication.
108
+ */
109
+ remove(cwd: string): Promise<boolean>;
110
+ /** The durable ledger's own listing, in its own order. */
111
+ listRegistry(): Promise<readonly TuiWorkspaceEntry[]>;
69
112
  commands(): readonly Pick<TuiWorkspaceCommand, 'name' | 'aliases' | 'description'>[];
70
113
  runCommand(name: string, input: string, cwd: string, signal?: AbortSignal): Promise<TuiWorkspaceCommandResult | undefined>;
71
114
  private notifyProviderWaiters;
@@ -74,7 +117,7 @@ export declare class TuiWorkspaceRuntime extends Service {
74
117
  export declare function getHostWorkspaceRuntime(runtime: TuiWorkspaceRuntime | undefined): TuiWorkspaceHost | undefined;
75
118
  /** Local-only fallback for direct embedders that call createChannel() without
76
119
  * mounting the optional workspace registry/provider service. */
77
- export declare function createLocalWorkspaceRuntime(): Pick<TuiWorkspaceRuntime, 'list' | 'resolve' | 'describe' | 'commandShell' | 'rename' | 'commands' | 'runCommand'>;
120
+ export declare function createLocalWorkspaceRuntime(): Pick<TuiWorkspaceRuntime, 'list' | 'resolve' | 'describe' | 'commandShell' | 'rename' | 'remove' | 'listRegistry' | 'commands' | 'runCommand'>;
78
121
  export declare function localWorkspaceUri(path: string): string;
79
122
  /** Resolve a native absolute path or the standard file URL form. */
80
123
  export declare function parseLocalWorkspaceReference(reference: string): TuiWorkspaceTarget | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"workspaces.d.ts","sourceRoot":"","sources":["../../../src/dsh-adapter/workspaces.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"workspaces.d.ts","sourceRoot":"","sources":["../../../src/dsh-adapter/workspaces.ts"],"names":[],"mappings":"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"}
@@ -10,6 +10,90 @@ import { Service } from '@deepseek-ai/cordis';
10
10
  import { activationFiber, bindCallerEffect, compositionRoot, concreteService, requirePluginCaller } from './host-access.js';
11
11
  import { assertCapabilityShadowPolicy, } from '../adapter/kernel/runtime.js';
12
12
  import { adapterRuntimeFor } from '../adapter/kernel/runtime-context.js';
13
+ /**
14
+ * Enumerate the durable workspace registry, in its own display order.
15
+ *
16
+ * The sidebar needs the *registry* (every workspace the user ever registered,
17
+ * including ones with no sessions yet), not the session-derived grouping the
18
+ * `/resume` browser builds. Order, ids and titles come from the ledger;
19
+ * `sessionCount` is filled in by the caller (the adapter holds no session
20
+ * index), and `present` is derived here.
21
+ */
22
+ export async function listRegistryWorkspaces(runtime) {
23
+ if (runtime === undefined)
24
+ return [];
25
+ const registry = workspaceRegistry(runtime);
26
+ if (registry === undefined)
27
+ return [];
28
+ const out = [];
29
+ for (const workspace of registry.list()) {
30
+ let present = true;
31
+ try {
32
+ present = (await workspace.status?.()) !== 'missing-dir';
33
+ }
34
+ catch {
35
+ // An unreadable status is not evidence of absence.
36
+ present = true;
37
+ }
38
+ out.push({
39
+ id: String(workspace.id),
40
+ path: workspace.path,
41
+ title: workspace.title,
42
+ present,
43
+ sessionCount: 0,
44
+ });
45
+ }
46
+ return out;
47
+ }
48
+ /**
49
+ * Remove a workspace registration by path. Sessions and the directory survive:
50
+ * only the ledger entry goes away, so the sessions reappear as ungrouped.
51
+ *
52
+ * @returns True when a record was removed, false when no record owned `cwd`
53
+ * (or the ledger is unmounted).
54
+ */
55
+ export async function removeRegistryWorkspace(runtime, cwd, owner) {
56
+ if (runtime === undefined)
57
+ return false;
58
+ const registry = workspaceRegistry(runtime);
59
+ if (registry === undefined)
60
+ return false;
61
+ const workspace = registry.list().find(candidate => sameCwd(candidate.path, cwd));
62
+ if (workspace === undefined)
63
+ return false;
64
+ // The durable ledger is host-owned: a plugin may only drop a registration
65
+ // for a cwd one of ITS OWN providers still vouches for. `owner === undefined`
66
+ // is the host facade's own call (the sidebar's remove action).
67
+ if (owner !== undefined && !ownsWorkspace(runtime, owner, cwd)) {
68
+ throw new Error('workspace is not owned by the calling activation');
69
+ }
70
+ return registry.delete(workspace.id);
71
+ }
72
+ /**
73
+ * Whether a calling activation's own providers still vouch for `cwd`.
74
+ *
75
+ * This is the same evidence `renameWorkspace` accepts, and the only ownership
76
+ * fact the local ledger records 鈥?the registry entry itself carries no creator.
77
+ * A provider `describe()` that returns a target means the cwd belongs to that
78
+ * provider's scheme, so the activation behind it is the one entitled to mutate
79
+ * the registration.
80
+ * @param runtime - The workspace service.
81
+ * @param owner - Live activation fiber of the caller.
82
+ * @param cwd - Directory to test.
83
+ * @returns True when one of the caller's providers owns `cwd`.
84
+ */
85
+ function ownsWorkspace(runtime, owner, cwd) {
86
+ for (const provider of providersFor(workspaceStateFor(runtime), owner)) {
87
+ try {
88
+ if (provider.describe(cwd) !== undefined)
89
+ return true;
90
+ }
91
+ catch {
92
+ // A provider that throws on describe vouches for nothing.
93
+ }
94
+ }
95
+ return false;
96
+ }
13
97
  export const name = 'dsh-tui-workspaces';
14
98
  /** Bound every provider promise so one plugin cannot park workspace flows. */
15
99
  export const WORKSPACE_PROVIDER_TIMEOUT_MS = 2000;
@@ -53,6 +137,11 @@ export class TuiWorkspaceRuntime extends Service {
53
137
  assertCapabilityShadowPolicy('host.workspaces.rename', state.runtime.mode, state.runtime.slices);
54
138
  return renameWorkspace(runtime, cwd, title, undefined);
55
139
  },
140
+ remove: (cwd) => {
141
+ assertCapabilityShadowPolicy('host.workspaces.remove', state.runtime.mode, state.runtime.slices);
142
+ return removeRegistryWorkspace(runtime, cwd);
143
+ },
144
+ listRegistry: () => listRegistryWorkspaces(runtime),
56
145
  commands: () => workspaceCommands(runtime, undefined),
57
146
  runCommand: (name, input, cwd, signal) => {
58
147
  assertCapabilityShadowPolicy('host.workspaces.runCommand', state.runtime.mode, state.runtime.slices);
@@ -107,6 +196,27 @@ export class TuiWorkspaceRuntime extends Service {
107
196
  const owner = workspaceCaller(this, 'tuiWorkspaces.rename');
108
197
  return renameWorkspace(this, cwd, title, owner);
109
198
  }
199
+ /**
200
+ * Drop a workspace registration; the directory and session logs survive.
201
+ *
202
+ * Plugin-facing, and therefore bound by the SAME rule as {@link rename}: a
203
+ * live calling activation is required, and the target must be a cwd one of
204
+ * that activation's own providers vouches for. Without both, a plugin that
205
+ * never owned the workspace 鈥?including one whose fiber was already disposed
206
+ * and whose caller context is a retained handle 鈥?could delete a host
207
+ * registration. Shadow policy alone is not caller authentication.
208
+ */
209
+ async remove(cwd) {
210
+ assertCapabilityShadowPolicy('host.workspaces.remove', workspaceStateFor(this).runtime.mode, workspaceStateFor(this).runtime.slices);
211
+ const owner = workspaceCaller(this, 'tuiWorkspaces.remove');
212
+ return removeRegistryWorkspace(this, cwd, owner);
213
+ }
214
+ /** The durable ledger's own listing, in its own order. */
215
+ async listRegistry() {
216
+ assertCapabilityShadowPolicy('host.workspaces.list', workspaceStateFor(this).runtime.mode, workspaceStateFor(this).runtime.slices);
217
+ workspaceCaller(this, 'tuiWorkspaces.listRegistry');
218
+ return listRegistryWorkspaces(this);
219
+ }
110
220
  commands() {
111
221
  assertCapabilityShadowPolicy('host.workspaces.commands', workspaceStateFor(this).runtime.mode, workspaceStateFor(this).runtime.slices);
112
222
  const owner = workspaceCaller(this, 'tuiWorkspaces.commands');
@@ -376,6 +486,12 @@ export function createLocalWorkspaceRuntime() {
376
486
  async rename() {
377
487
  throw new Error('workspace registry is unavailable');
378
488
  },
489
+ async remove() {
490
+ return false;
491
+ },
492
+ async listRegistry() {
493
+ return [];
494
+ },
379
495
  commands() {
380
496
  return [];
381
497
  },
@@ -3,9 +3,9 @@
3
3
  * `/effort` (slider or `/effort <id>`; `/effort status` reports the current
4
4
  * level) — note Shift+Tab cycles session modes (default/plan/full), not
5
5
  * effort levels. The choice lands here so the next boot starts on it. The
6
- * file is best-effort: a missing/corrupt file or a level the current adapter
7
- * does not offer just falls back to the provider default — the first
8
- * request/header event always re-asserts the truth on the status line.
6
+ * file is best-effort; a level the current route's tier list does not offer
7
+ * falls back to the nearest LOWER tier (nearestLowerEffort, never up) with a
8
+ * loud notice — a missing/corrupt file falls back to the provider default.
9
9
  */
10
10
  /**
11
11
  * The persisted reasoning-effort id, or undefined when unset or invalid.
@@ -26,6 +26,18 @@ export declare function readEffortPref(dir?: string): string | undefined;
26
26
  * @returns The winning level id, or undefined for the adapter default.
27
27
  */
28
28
  export declare function resolveEffortDefault(settingsDefault: string | undefined, configured: string | undefined, persisted: string | undefined): string | undefined;
29
+ /**
30
+ * Resolve a preferred effort tier against a route's available tiers when the
31
+ * exact tier is absent: pick the NEAREST LOWER standard tier that the route
32
+ * offers (max→high, high→low, …). Only-down, never-up — a user who prefers
33
+ * `low` on a route without it must not be pushed to `high`. Unknown tier ids
34
+ * (custom route tiers outside the standard order) never participate: an
35
+ * unknown preference yields undefined, an unknown candidate is skipped.
36
+ * @param preferred - The preferred tier id (exact match short-circuits).
37
+ * @param available - Tier ids the current route offers.
38
+ * @returns The tier id to apply, or undefined to keep the model default.
39
+ */
40
+ export declare function nearestLowerEffort(preferred: string, available: readonly string[]): string | undefined;
29
41
  /**
30
42
  * Persist the chosen reasoning-effort id (best effort).
31
43
  * @param effort - Adapter-owned effort id to persist.
@@ -1 +1 @@
1
- {"version":3,"file":"effortPrefs.d.ts","sourceRoot":"","sources":["../../src/effortPrefs.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAQH;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,GAAG,GAAE,MAAkB,GAAG,MAAM,GAAG,SAAS,CAS1E;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAClC,eAAe,EAAE,MAAM,GAAG,SAAS,EACnC,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,SAAS,EAAE,MAAM,GAAG,SAAS,GAC5B,MAAM,GAAG,SAAS,CAEpB;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,GAAE,MAAkB,GAAG,OAAO,CAQhF"}
1
+ {"version":3,"file":"effortPrefs.d.ts","sourceRoot":"","sources":["../../src/effortPrefs.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAQH;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,GAAG,GAAE,MAAkB,GAAG,MAAM,GAAG,SAAS,CAS1E;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAClC,eAAe,EAAE,MAAM,GAAG,SAAS,EACnC,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,SAAS,EAAE,MAAM,GAAG,SAAS,GAC5B,MAAM,GAAG,SAAS,CAEpB;AAKD;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,CAgBtG;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,GAAE,MAAkB,GAAG,OAAO,CAQhF"}
@@ -3,9 +3,9 @@
3
3
  * `/effort` (slider or `/effort <id>`; `/effort status` reports the current
4
4
  * level) — note Shift+Tab cycles session modes (default/plan/full), not
5
5
  * effort levels. The choice lands here so the next boot starts on it. The
6
- * file is best-effort: a missing/corrupt file or a level the current adapter
7
- * does not offer just falls back to the provider default — the first
8
- * request/header event always re-asserts the truth on the status line.
6
+ * file is best-effort; a level the current route's tier list does not offer
7
+ * falls back to the nearest LOWER tier (nearestLowerEffort, never up) with a
8
+ * loud notice — a missing/corrupt file falls back to the provider default.
9
9
  */
10
10
  import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
11
11
  import { join } from 'node:path';
@@ -43,6 +43,40 @@ export function readEffortPref(dir = PREFS_DIR) {
43
43
  export function resolveEffortDefault(settingsDefault, configured, persisted) {
44
44
  return settingsDefault ?? configured ?? persisted;
45
45
  }
46
+ /** Standard effort-tier order, weakest to strongest. */
47
+ const EFFORT_TIER_ORDER = ['off', 'low', 'medium', 'high', 'max'];
48
+ /**
49
+ * Resolve a preferred effort tier against a route's available tiers when the
50
+ * exact tier is absent: pick the NEAREST LOWER standard tier that the route
51
+ * offers (max→high, high→low, …). Only-down, never-up — a user who prefers
52
+ * `low` on a route without it must not be pushed to `high`. Unknown tier ids
53
+ * (custom route tiers outside the standard order) never participate: an
54
+ * unknown preference yields undefined, an unknown candidate is skipped.
55
+ * @param preferred - The preferred tier id (exact match short-circuits).
56
+ * @param available - Tier ids the current route offers.
57
+ * @returns The tier id to apply, or undefined to keep the model default.
58
+ */
59
+ export function nearestLowerEffort(preferred, available) {
60
+ if (preferred === '' || available.length === 0)
61
+ return undefined;
62
+ if (available.includes(preferred))
63
+ return preferred;
64
+ const preferredRank = EFFORT_TIER_ORDER.indexOf(preferred);
65
+ if (preferredRank <= 0)
66
+ return undefined; // unknown id, or 'off' has nothing lower
67
+ let result;
68
+ let resultRank = -1;
69
+ for (const candidate of available) {
70
+ const rank = EFFORT_TIER_ORDER.indexOf(candidate);
71
+ if (rank < 0 || rank >= preferredRank)
72
+ continue;
73
+ if (rank > resultRank) {
74
+ result = candidate;
75
+ resultRank = rank;
76
+ }
77
+ }
78
+ return result;
79
+ }
46
80
  /**
47
81
  * Persist the chosen reasoning-effort id (best effort).
48
82
  * @param effort - Adapter-owned effort id to persist.
@@ -0,0 +1,15 @@
1
+ interface HomePrefs {
2
+ /** True once the workspace home has been shown as the landing screen. */
3
+ seen?: boolean;
4
+ }
5
+ /** Read the persisted landing preference; an unreadable file reads as unset. */
6
+ export declare function readHomePrefs(): HomePrefs;
7
+ /**
8
+ * Record that the workspace home has been shown.
9
+ *
10
+ * @returns True when the preference was durably written; false when the data
11
+ * directory is not writable (the caller stays silent — see the module note).
12
+ */
13
+ export declare function markHomeSeen(): boolean;
14
+ export {};
15
+ //# sourceMappingURL=homePrefs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"homePrefs.d.ts","sourceRoot":"","sources":["../../src/homePrefs.ts"],"names":[],"mappings":"AA0BA,UAAU,SAAS;IACjB,yEAAyE;IACzE,IAAI,CAAC,EAAE,OAAO,CAAA;CACf;AAED,gFAAgF;AAChF,wBAAgB,aAAa,IAAI,SAAS,CASzC;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,IAAI,OAAO,CAQtC"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Landing-screen preference for the TUI's workspace home screen.
3
+ *
4
+ * A one-key preference under `~/.dsh-tui/home.json`, deliberately NOT a cordis
5
+ * config value: "has this installation shown the user the workspace home on a
6
+ * fresh launch yet" is per-machine UI state, like the lang and tray
7
+ * preferences next to it — not a deployment choice a cordis.yml row should own.
8
+ *
9
+ * The rule it enables is one-shot: the FIRST ordinary launch (no explicit
10
+ * `--resume`, no workspace target) lands on the workspace home instead of a
11
+ * blank conversation, because that is the launch where "which project am I
12
+ * working on" has no answer yet. After that the chat screen is the landing
13
+ * surface again, and the home screen stays reachable as a screen.
14
+ *
15
+ * A preference file that cannot be read or written is never fatal: the worst
16
+ * outcome is one extra home screen, or a chat screen where the home was
17
+ * expected. Both are recoverable with a single keypress.
18
+ *
19
+ * @module @deepseek-harness-tui/dsh-tui/homePrefs
20
+ */
21
+ import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
22
+ import { join } from 'node:path';
23
+ import { DATA_DIR } from './utils/paths.js';
24
+ const PREFS_FILE = join(DATA_DIR, 'home.json');
25
+ /** Read the persisted landing preference; an unreadable file reads as unset. */
26
+ export function readHomePrefs() {
27
+ try {
28
+ const parsed = JSON.parse(readFileSync(PREFS_FILE, 'utf8'));
29
+ if (typeof parsed !== 'object' || parsed === null)
30
+ return {};
31
+ const seen = parsed.seen;
32
+ return typeof seen === 'boolean' ? { seen } : {};
33
+ }
34
+ catch {
35
+ return {};
36
+ }
37
+ }
38
+ /**
39
+ * Record that the workspace home has been shown.
40
+ *
41
+ * @returns True when the preference was durably written; false when the data
42
+ * directory is not writable (the caller stays silent — see the module note).
43
+ */
44
+ export function markHomeSeen() {
45
+ try {
46
+ mkdirSync(DATA_DIR, { recursive: true });
47
+ writeFileSync(PREFS_FILE, `${JSON.stringify({ ...readHomePrefs(), seen: true }, null, 2)}\n`, 'utf8');
48
+ return true;
49
+ }
50
+ catch {
51
+ return false;
52
+ }
53
+ }