@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
@@ -1 +1 @@
1
- {"version":3,"file":"model-actions.d.ts","sourceRoot":"","sources":["../../../../src/dsh-adapter/channel/model-actions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAqB,KAAK,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAC3E,OAAO,KAAK,EAAE,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AACtE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAA;AAM9D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAC9C,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAE1E,KAAK,OAAO,GAAG,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAA;AAEtD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,IAAI,CAAC,YAAY,EAAE,UAAU,GAAG,OAAO,GAAG,iBAAiB,GAAG,cAAc,GAAG,aAAa,GAAG,SAAS,GAAG,MAAM,CAAC,EACzH,IAAI,EAAE;IACJ,KAAK,EAAE,IAAI,CAAC,YAAY,EAAE,SAAS,CAAC,CAAA;IACpC,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,SAAS,GAAG,WAAW,CAAC,CAAA;IAC/C,SAAS,EAAE,iBAAiB,CAAA;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,KAAK,IAAI,KAAK,CAAA;IACd,MAAM,EAAE,YAAY,CAAC,QAAQ,CAAC,CAAA;CAC/B;;gCA2CsC,OAAO,CAAC,IAAI,CAAC;+BAWpB,IAAI;uBAmBN,OAAO,CAAC;QAAE,OAAO,EAAE,SAAS,YAAY,EAAE,CAAC;QAAC,aAAa,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,CAAC;oBAWjF,MAAM,KAAG,OAAO,CAAC,OAAO,CAAC;2BAoBxB,MAAM,GAAG,SAAS,KAAG,IAAI;4BAM1B,IAAI;sBAeV,OAAO,CAAC,SAAS,YAAY,EAAE,CAAC;;YAvHnB,MAAM;cAAQ,MAAM;;8BA4HzB,IAAI;0BACR,IAAI;;6BASD,IAAI;;uBAOJ,OAAO,CAAC,SAAS,YAAY,EAAE,CAAC;6BAQxB,MAAM,KAAG,OAAO,CAAC,OAAO,CAAC;EAkChE"}
1
+ {"version":3,"file":"model-actions.d.ts","sourceRoot":"","sources":["../../../../src/dsh-adapter/channel/model-actions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAqB,KAAK,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAC3E,OAAO,KAAK,EAAE,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AACtE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAA;AAM9D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAC9C,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAE1E,KAAK,OAAO,GAAG,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAA;AAEtD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,IAAI,CAAC,YAAY,EAAE,UAAU,GAAG,OAAO,GAAG,iBAAiB,GAAG,cAAc,GAAG,aAAa,GAAG,SAAS,GAAG,eAAe,GAAG,MAAM,CAAC,EAC3I,IAAI,EAAE;IACJ,KAAK,EAAE,IAAI,CAAC,YAAY,EAAE,SAAS,CAAC,CAAA;IACpC,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,SAAS,GAAG,WAAW,CAAC,CAAA;IAC/C,SAAS,EAAE,iBAAiB,CAAA;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,KAAK,IAAI,KAAK,CAAA;IACd,MAAM,EAAE,YAAY,CAAC,QAAQ,CAAC,CAAA;IAC9B;6EACyE;IACzE,mBAAmB,IAAI,IAAI,CAAA;CAC5B;;gCA8DsC,OAAO,CAAC,IAAI,CAAC;+BA+DpB,IAAI;uBAqBN,OAAO,CAAC;QAAE,OAAO,EAAE,SAAS,YAAY,EAAE,CAAC;QAAC,aAAa,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,CAAC;oBAWjF,MAAM,KAAG,OAAO,CAAC,OAAO,CAAC;2BAoBxB,MAAM,GAAG,SAAS,KAAG,IAAI;4BAM1B,IAAI;sBAeV,OAAO,CAAC,SAAS,YAAY,EAAE,CAAC;;YAhMnB,MAAM;cAAQ,MAAM;;8BAqMzB,IAAI;0BACR,IAAI;;6BASD,IAAI;;uBAOJ,OAAO,CAAC,SAAS,YAAY,EAAE,CAAC;6BAQxB,MAAM,KAAG,OAAO,CAAC,OAAO,CAAC;EAkChE"}
@@ -1,9 +1,9 @@
1
1
  import { ReasoningEffortId } from '@deepseek-ai/dsh-llm';
2
- import { readEffortPref, resolveEffortDefault, writeEffortPref } from '../../effortPrefs.js';
2
+ import { nearestLowerEffort, readEffortPref, resolveEffortDefault, writeEffortPref } from '../../effortPrefs.js';
3
3
  import { snapshotLiveSessionEvents } from '../compat/liveSession.js';
4
4
  import { getLang, t, tOr } from '../../i18n.js';
5
5
  import { migratePresetPref, writePresetPref } from '../../presetPrefs.js';
6
- import { resolveCompatiblePreset, rosterOf } from '../preset-resolution.js';
6
+ import { presetDisplayId, resolveCompatiblePreset, rosterOf } from '../preset-resolution.js';
7
7
  /**
8
8
  * Route metadata, effort preference and preset/model catalog actions.
9
9
  * This owns the async catalog caches and their generation fences; callers only
@@ -13,6 +13,9 @@ export function createModelActions(ctx, state, deps) {
13
13
  const { owner, selection, notify } = deps;
14
14
  const llmRuntime = ctx.get('llm');
15
15
  let preferredEffort = deps.initialEffort ?? readEffortPref();
16
+ // Last fallback notice shown for a (preferred → applied) pair: bind fires on
17
+ // every session switch, so an unchanged downgrade must not re-toast.
18
+ let lastEffortFallbackNotice;
16
19
  // State construction cannot call this factory yet; seed the visible value
17
20
  // before the root starts binding or exposes the completed ChannelState.
18
21
  state.reasoningEffort = preferredEffort;
@@ -27,11 +30,28 @@ export function createModelActions(ctx, state, deps) {
27
30
  });
28
31
  const effortCurrent = (capture) => owner.current() && deps.binding.isCurrent(capture.binding) &&
29
32
  state.provider === capture.provider && state.model === capture.model && effortOperation === capture.operation;
33
+ /** Route-level metadata shared by every resolveModelInfo consumer. The
34
+ * context window follows the route, not the binding: a resume rebuilds
35
+ * the binding (effortCurrent goes false) while the capacity answer for
36
+ * the same provider/model is still the live truth, so this runs before
37
+ * any effort freshness gate. Lifetime is the one fence it keeps: the
38
+ * answer crosses an await, so a Channel released while the lookup was in
39
+ * flight must neither write into its dead state nor re-arm the
40
+ * context-low warning through checkContextWarning. */
41
+ const applyRouteMetadata = (capture, info) => {
42
+ if (!owner.current())
43
+ return;
44
+ if (state.provider === capture.provider && state.model === capture.model && info.context !== undefined) {
45
+ state.contextWindow = info.context.contextWindow;
46
+ deps.checkContextWarning();
47
+ }
48
+ };
30
49
  const resolveEfforts = async (capture) => {
31
50
  if (llmRuntime === undefined || typeof llmRuntime.resolveModelInfo !== 'function')
32
51
  return 'unavailable';
33
52
  try {
34
53
  const info = await llmRuntime.resolveModelInfo(capture.provider, capture.model);
54
+ applyRouteMetadata(capture, info);
35
55
  if (!effortCurrent(capture))
36
56
  return 'stale';
37
57
  const efforts = info.reasoning?.efforts ?? [];
@@ -55,9 +75,62 @@ export function createModelActions(ctx, state, deps) {
55
75
  // This same binding-time lookup is the route's initial tier refresh even
56
76
  // without a stored preference. Do not make a separate competing refresh
57
77
  // operation that could invalidate the selected preference completion.
58
- if (preferredEffort === undefined || !resolved.efforts.some(effort => effort.id === preferredEffort))
78
+ if (preferredEffort === undefined)
59
79
  return;
60
- selection.current = { provider: capture.provider, model: capture.model, reasoningEffort: ReasoningEffortId(preferredEffort) };
80
+ const available = resolved.efforts.map(effort => effort.id);
81
+ // Exact hit applies silently; a miss falls back to the nearest LOWER tier
82
+ // the route offers (never up), and both miss paths notify exactly once
83
+ // per (preferred → applied) pair — bind fires on every session switch,
84
+ // so an unchanged downgrade must not re-toast.
85
+ const applied = nearestLowerEffort(preferredEffort, available);
86
+ if (applied === undefined) {
87
+ if (lastEffortFallbackNotice?.preferred !== preferredEffort || lastEffortFallbackNotice.applied !== undefined) {
88
+ lastEffortFallbackNotice = { preferred: preferredEffort, applied: undefined };
89
+ notify(t('effort-preference-unsupported', { preferred: preferredEffort }), { color: 'warning' });
90
+ }
91
+ // Nothing is pinned, so the ROUTE's model default is what actually ships
92
+ // and the readout (status line, /effort status) must say so. Every switch
93
+ // tail clears it before this runs (session-resume.ts / model-switch.ts /
94
+ // session-live-adoption.ts / background-action.ts), but a resumed log's
95
+ // replayed `request/header` can leave an older tier behind — neither blank
96
+ // nor "last route's tier" is the truth. Only the readout moves: pinning
97
+ // the default into selection.current would put a tier the user never chose
98
+ // onto the wire, which is exactly what "never up" forbids.
99
+ const shipped = resolved.defaultEffort;
100
+ if (state.reasoningEffort !== shipped) {
101
+ state.reasoningEffort = shipped;
102
+ state.emit();
103
+ }
104
+ // An effort pin installed earlier (an exact hit, /effort <id>) survives
105
+ // every path that is NOT a bind: /settings' effortDefault hands the level
106
+ // straight to setDefaultEffort → applyPreferredEffort (plugin.ts:804 →
107
+ // setDefaultEffort above), which never resets selection.current — the four
108
+ // switch tails that do are all on the bind side. Leaving it would put the
109
+ // OLD tier back on the wire while the readout above announces the model
110
+ // default. Drop the effort only: the provider/model half of the pin is
111
+ // this route's, not the stale tier's. No emit — setDefaultEffort reaches
112
+ // here through that same non-bind path, and nothing UI-visible reads this
113
+ // ref (it is the router's ModelSelectionRef, not the IDE ChannelSelection
114
+ // the status line shows); the readout above already emits when it moves.
115
+ if (selection.current?.reasoningEffort !== undefined) {
116
+ selection.current = { provider: capture.provider, model: capture.model };
117
+ }
118
+ return;
119
+ }
120
+ // Dedupe gates ONLY the toast: bind resets selection.current on every
121
+ // session switch, so the pin below must re-apply unconditionally — an
122
+ // early return here would ship the model default from the second session
123
+ // on (review C1). The status line shows the tier that actually ships.
124
+ const fresh = lastEffortFallbackNotice?.preferred !== preferredEffort || lastEffortFallbackNotice.applied !== applied;
125
+ if (applied !== preferredEffort && fresh) {
126
+ lastEffortFallbackNotice = { preferred: preferredEffort, applied };
127
+ notify(t('effort-preference-downgraded', { preferred: preferredEffort, applied }), { color: 'warning' });
128
+ }
129
+ if (applied === preferredEffort)
130
+ lastEffortFallbackNotice = undefined;
131
+ state.reasoningEffort = applied;
132
+ selection.current = { provider: capture.provider, model: capture.model, reasoningEffort: ReasoningEffortId(applied) };
133
+ state.emit();
61
134
  };
62
135
  const refreshEffortLevels = () => {
63
136
  if (llmRuntime === undefined || typeof llmRuntime.resolveModelInfo !== 'function')
@@ -65,7 +138,10 @@ export function createModelActions(ctx, state, deps) {
65
138
  const capture = captureEffort();
66
139
  const generation = ++effortLevelsGeneration;
67
140
  void llmRuntime.resolveModelInfo(capture.provider, capture.model).then(info => {
68
- if (!effortCurrent(capture) || generation !== effortLevelsGeneration)
141
+ if (generation !== effortLevelsGeneration)
142
+ return;
143
+ applyRouteMetadata(capture, info);
144
+ if (!effortCurrent(capture))
69
145
  return;
70
146
  state.effortLevels = (info.reasoning?.efforts ?? []).map(level => level.id);
71
147
  state.emit();
@@ -192,7 +268,7 @@ export function createModelActions(ctx, state, deps) {
192
268
  return [];
193
269
  const localized = getLang() === 'en';
194
270
  try {
195
- return (await presets.list()).map(preset => ({ id: preset.id, ...(preset.name === undefined ? {} : { name: localized ? tOr(`preset-name-${preset.id}`, preset.name) : preset.name }), ...(preset.description === undefined ? {} : { description: localized ? tOr(`preset-desc-${preset.id}`, preset.description) : preset.description }), ...(preset.broken === undefined ? {} : { broken: preset.broken }), isDefault: preset.id === presets.defaultId }));
271
+ return (await presets.list()).map(preset => ({ id: preset.id, ...(preset.name === undefined ? {} : { name: localized ? tOr(`preset-name-${presetDisplayId(preset.id)}`, preset.name) : preset.name }), ...(preset.description === undefined ? {} : { description: localized ? tOr(`preset-desc-${presetDisplayId(preset.id)}`, preset.description) : preset.description }), ...(preset.broken === undefined ? {} : { broken: preset.broken }), isDefault: preset.id === presets.defaultId }));
196
272
  }
197
273
  catch {
198
274
  return [];
@@ -1 +1 @@
1
- {"version":3,"file":"model-switch.d.ts","sourceRoot":"","sources":["../../../../src/dsh-adapter/channel/model-switch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAGlD,OAAO,EAAa,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAOvE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAC9C,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAA;AAC3D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAE9C,KAAK,OAAO,GAAG,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAA;AACtD,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,sBAAsB,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,YAAY,EACjF,KAAK,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,GAAG,aAAa,GAAG,UAAU,GAAG,OAAO,GAAG,eAAe,GAAG,cAAc,GAAG,iBAAiB,GAAG,MAAM,CAAC,CAAA;AAElJ,uHAAuH;AACvH,wBAAgB,uBAAuB,CACrC,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,WAAW,EAClB,IAAI,EAAE;IACJ,KAAK,EAAE,IAAI,CAAC,YAAY,EAAE,SAAS,CAAC,CAAA;IACpC,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,GAAG,OAAO,CAAC,CAAA;IAC3F,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;IACzB,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACjC,cAAc,IAAI,IAAI,CAAA;IACtB,cAAc,IAAI,IAAI,CAAA;IACtB,SAAS,IAAI,IAAI,CAAA;IACjB,MAAM,CAAC,MAAM,EAAE,SAAS,YAAY,EAAE,GAAG,IAAI,CAAA;IAC7C,YAAY,IAAI,IAAI,CAAA;IACpB,SAAS,IAAI,IAAI,CAAA;IACjB,eAAe,IAAI,IAAI,CAAA;IACvB,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACrC,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACrC,iBAAiB,IAAI,IAAI,CAAA;IACzB,mBAAmB,IAAI,IAAI,CAAA;IAC3B,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IAClC,MAAM,EAAE,YAAY,CAAC,QAAQ,CAAC,CAAA;CAC/B,IAEa,UAAU,MAAM,EAAE,OAAO,MAAM,KAAG,OAAO,CAAC,OAAO,CAAC,CAgEjE"}
1
+ {"version":3,"file":"model-switch.d.ts","sourceRoot":"","sources":["../../../../src/dsh-adapter/channel/model-switch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAGlD,OAAO,EAAa,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAQvE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAC9C,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAA;AAC3D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAE9C,KAAK,OAAO,GAAG,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAA;AACtD,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,sBAAsB,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,YAAY,EACjF,KAAK,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,GAAG,aAAa,GAAG,UAAU,GAAG,OAAO,GAAG,eAAe,GAAG,cAAc,GAAG,iBAAiB,GAAG,MAAM,CAAC,CAAA;AAElJ,uHAAuH;AACvH,wBAAgB,uBAAuB,CACrC,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,WAAW,EAClB,IAAI,EAAE;IACJ,KAAK,EAAE,IAAI,CAAC,YAAY,EAAE,SAAS,CAAC,CAAA;IACpC,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,GAAG,OAAO,CAAC,CAAA;IAC3F,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;IACzB,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACjC,cAAc,IAAI,IAAI,CAAA;IACtB,cAAc,IAAI,IAAI,CAAA;IACtB,SAAS,IAAI,IAAI,CAAA;IACjB,MAAM,CAAC,MAAM,EAAE,SAAS,YAAY,EAAE,GAAG,IAAI,CAAA;IAC7C,YAAY,IAAI,IAAI,CAAA;IACpB,SAAS,IAAI,IAAI,CAAA;IACjB,eAAe,IAAI,IAAI,CAAA;IACvB,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACrC,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACrC,iBAAiB,IAAI,IAAI,CAAA;IACzB,mBAAmB,IAAI,IAAI,CAAA;IAC3B,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IAClC,MAAM,EAAE,YAAY,CAAC,QAAQ,CAAC,CAAA;CAC/B,IAEa,UAAU,MAAM,EAAE,OAAO,MAAM,KAAG,OAAO,CAAC,OAAO,CAAC,CA4EjE"}
@@ -5,6 +5,7 @@ import { writeModelPref } from '../../modelPrefs.js';
5
5
  import { touchSession } from '../../sessionHistory.js';
6
6
  import { liveSessionCreateOptions, sliceLiveSessionSeed } from '../compat/index.js';
7
7
  import { composePreset, runningPresetOf } from '../presets.js';
8
+ import { reserveNewSession } from '../../sessionMounts.js';
8
9
  import { attachSessionToWorkspace } from '../workspace.js';
9
10
  import { resetSessionProjection } from './session-reset.js';
10
11
  /** Model-route adoption transaction. It settles compaction before its fork snapshot and owns the post-commit reset. */
@@ -34,6 +35,10 @@ export function createModelSwitchAction(ctx, state, deps) {
34
35
  return false;
35
36
  }
36
37
  const childId = SessionId(randomUUID());
38
+ // Announce the id before the factory: from the moment `agents.create`
39
+ // returns this process holds the only write handle on a log the publisher
40
+ // will not name until its next beat.
41
+ const { reservation } = await reserveNewSession(String(childId));
37
42
  const composed = await composePreset(ctx, runningPresetOf(deps.binding.agent.session));
38
43
  let handle;
39
44
  try {
@@ -50,6 +55,7 @@ export function createModelSwitchAction(ctx, state, deps) {
50
55
  })));
51
56
  }
52
57
  catch (error) {
58
+ reservation.abandon();
53
59
  deps.notify(t('model-switch-failed', { err: error instanceof Error ? error.message : String(error) }), { color: 'error', timeoutMs: 8000 });
54
60
  return false;
55
61
  }
@@ -61,38 +67,50 @@ export function createModelSwitchAction(ctx, state, deps) {
61
67
  }
62
68
  if (!deps.binding.isCurrent(adoption) || !deps.owner.current()) {
63
69
  await deps.binding.abandon(handle);
70
+ reservation.abandon();
64
71
  return false;
65
72
  }
66
- return deps.binding.adopt(handle, adoption, (_previous, disposePrevious) => {
67
- resetSessionProjection(state, deps.rowIds, deps.resetProjector, deps.resetSubagents, deps.resetJobs);
68
- state.status = handle.agent.status;
69
- state.agentId = handle.agent.id;
70
- state.agentPreset = composed.agentPreset;
71
- state.provider = provider;
72
- state.model = model;
73
- state.contextWindow = undefined;
74
- state.effortLevels = undefined;
75
- state.reasoningEffort = undefined;
76
- deps.dropModelCompletion();
77
- deps.replay(seed);
78
- deps.settleReplay();
79
- state.working = handle.agent.status === 'running';
80
- // Reset the input FIFO and pending-decision indicators BEFORE the first
81
- // emit: a submit from a session-changed subscriber must not chain onto
82
- // the replaced session's parked promise (main's bind → clear → refresh
83
- // order).
84
- deps.clearStagedImages();
85
- deps.bindAgent();
86
- deps.onModelSwitch(model);
87
- deps.refreshCommands();
88
- void deps.refreshLoadedContext();
89
- void deps.refreshSkillCommands();
90
- touchSession(childId);
91
- state.emit();
92
- disposePrevious('dispose');
93
- if (!writeModelPref(provider, model))
94
- deps.notify(t('model-pref-write-failed'), { color: 'warning' });
95
- return true;
96
- });
73
+ let committed = false;
74
+ try {
75
+ const result = deps.binding.adopt(handle, adoption, (_previous, disposePrevious) => {
76
+ resetSessionProjection(state, deps.rowIds, deps.resetProjector, deps.resetSubagents, deps.resetJobs);
77
+ state.status = handle.agent.status;
78
+ state.agentId = handle.agent.id;
79
+ state.agentPreset = composed.agentPreset;
80
+ state.provider = provider;
81
+ state.model = model;
82
+ state.contextWindow = undefined;
83
+ state.effortLevels = undefined;
84
+ state.reasoningEffort = undefined;
85
+ deps.dropModelCompletion();
86
+ deps.replay(seed);
87
+ deps.settleReplay();
88
+ state.working = handle.agent.status === 'running';
89
+ // Reset the input FIFO and pending-decision indicators BEFORE the first
90
+ // emit: a submit from a session-changed subscriber must not chain onto
91
+ // the replaced session's parked promise (main's bind → clear → refresh
92
+ // order).
93
+ deps.clearStagedImages();
94
+ deps.bindAgent();
95
+ deps.onModelSwitch(model);
96
+ deps.refreshCommands();
97
+ void deps.refreshLoadedContext();
98
+ void deps.refreshSkillCommands();
99
+ touchSession(childId);
100
+ state.emit();
101
+ disposePrevious('dispose');
102
+ if (!writeModelPref(provider, model))
103
+ deps.notify(t('model-pref-write-failed'), { color: 'warning' });
104
+ return true;
105
+ });
106
+ committed = true;
107
+ return result;
108
+ }
109
+ finally {
110
+ if (committed)
111
+ reservation.settle();
112
+ else
113
+ reservation.abandon();
114
+ }
97
115
  };
98
116
  }
@@ -2,6 +2,7 @@ import type { Agent, AssistantStreamFrame } from '@deepseek-ai/dsh-agent';
2
2
  import type { SessionEvent } from '@deepseek-ai/dsh-session';
3
3
  import type { ContentBlock } from '@deepseek-ai/dsh-llm';
4
4
  import type { ChannelState, ToolCallView, ToolResultView, ToolsRegistryLike } from './types.js';
5
+ import type { SelectionAttachment } from '../../adapter/ports/channel-view.js';
5
6
  import type { InputConvergence } from './input-actions.js';
6
7
  import type { BackgroundJobStore } from '../jobs.js';
7
8
  import type { TuiRendererHost } from '../renderers.js';
@@ -22,6 +23,9 @@ interface ProjectionDependencies {
22
23
  /** DSH attachment service, resolved at call time (a late-mounted provider
23
24
  * must still serve images for rows projected earlier). */
24
25
  attachments(): unknown;
26
+ /** What a submitted message's IDE selection attached (keyed by the message
27
+ * id the durable event carries), for the user row's indicator line. */
28
+ selectionAttached(messageId: string): SelectionAttachment | undefined;
25
29
  }
26
30
  /** One authoritative reducer for both durable replay and live session events. */
27
31
  export declare function createChannelProjection(state: ProjectionState, deps: ProjectionDependencies): {
@@ -1 +1 @@
1
- {"version":3,"file":"projection.d.ts","sourceRoot":"","sources":["../../../../src/dsh-adapter/channel/projection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAA;AACzE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAC5D,OAAO,KAAK,EAAE,YAAY,EAAe,MAAM,sBAAsB,CAAA;AACrE,OAAO,KAAK,EAAE,YAAY,EAAwB,YAAY,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AACrH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAC1D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AACpD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAYtD,KAAK,eAAe,GAAG,IAAI,CAAC,YAAY,EAAE,MAAM,GAAG,cAAc,GAAG,iBAAiB,GAAG,aAAa,GAAG,MAAM,GAAG,iBAAiB,GAAG,QAAQ,GAAG,WAAW,GAAG,cAAc,GAAG,eAAe,GAAG,KAAK,GAAG,eAAe,GAAG,SAAS,GAAG,WAAW,GAAG,YAAY,GAAG,eAAe,GAAG,iBAAiB,GAAG,cAAc,GAAG,OAAO,GAAG,aAAa,GAAG,cAAc,GAAG,QAAQ,GAAG,MAAM,CAAC,CAAA;AACxX,UAAU,sBAAsB;IAC/B,KAAK,IAAI,KAAK,CAAA;IACd,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;IACzB,mBAAmB,IAAI,IAAI,CAAA;IAC3B,uBAAuB,EAAE,MAAM,EAAE,CAAA;IACjC,IAAI,EAAE,IAAI,CAAC,kBAAkB,EAAE,cAAc,GAAG,WAAW,CAAC,CAAA;IAC5D,gBAAgB,EAAE,IAAI,CAAC,gBAAgB,EAAE,gBAAgB,CAAC,CAAA;IAC1D,mBAAmB,IAAI,IAAI,CAAA;IAC3B,MAAM,EAAE,YAAY,CAAC,QAAQ,CAAC,CAAA;IAC9B,KAAK,CAAC,EAAE,iBAAiB,CAAA;IACzB,QAAQ,CAAC,EAAE,eAAe,CAAA;IAC1B;+DAC2D;IAC3D,WAAW,IAAI,OAAO,CAAA;CACtB;AACD,iFAAiF;AACjF,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,eAAe,EAAE,IAAI,EAAE,sBAAsB;iBA6+BxE,IAAI;2BAxpBQ,SAAS,YAAY,EAAE,KAAG,IAAI;yBAiGhC,YAAY,KAAG,IAAI;+BAxBb,oBAAoB,KAAG,IAAI;2BAtKjC,IAAI;6BAgBF,IAAI;4BA/IH,MAAM,WAAW,MAAM,KAAG,YAAY,GAAG,SAAS;8BAYhD,MAAM,WAAW,MAAM,QAAQ,YAAY,CAAC,aAAa,CAAC,CAAC,MAAM,CAAC,KAAG,cAAc,GAAG,SAAS;sBAwBvG,SAAS,YAAY,EAAE,GAAG,SAAS,KAAG,MAAM;2BASvC,SAAS,YAAY,EAAE,GAAG,SAAS,KAAG,MAAM;EA21B3E"}
1
+ {"version":3,"file":"projection.d.ts","sourceRoot":"","sources":["../../../../src/dsh-adapter/channel/projection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAA;AACzE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAC5D,OAAO,KAAK,EAAE,YAAY,EAAe,MAAM,sBAAsB,CAAA;AACrE,OAAO,KAAK,EAAE,YAAY,EAAwB,YAAY,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AACrH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAA;AAE9E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAC1D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AACpD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAatD,KAAK,eAAe,GAAG,IAAI,CAAC,YAAY,EAAE,MAAM,GAAG,cAAc,GAAG,iBAAiB,GAAG,aAAa,GAAG,MAAM,GAAG,iBAAiB,GAAG,QAAQ,GAAG,WAAW,GAAG,cAAc,GAAG,eAAe,GAAG,KAAK,GAAG,eAAe,GAAG,SAAS,GAAG,WAAW,GAAG,YAAY,GAAG,eAAe,GAAG,iBAAiB,GAAG,cAAc,GAAG,OAAO,GAAG,aAAa,GAAG,cAAc,GAAG,QAAQ,GAAG,MAAM,CAAC,CAAA;AACxX,UAAU,sBAAsB;IAC/B,KAAK,IAAI,KAAK,CAAA;IACd,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;IACzB,mBAAmB,IAAI,IAAI,CAAA;IAC3B,uBAAuB,EAAE,MAAM,EAAE,CAAA;IACjC,IAAI,EAAE,IAAI,CAAC,kBAAkB,EAAE,cAAc,GAAG,WAAW,CAAC,CAAA;IAC5D,gBAAgB,EAAE,IAAI,CAAC,gBAAgB,EAAE,gBAAgB,CAAC,CAAA;IAC1D,mBAAmB,IAAI,IAAI,CAAA;IAC3B,MAAM,EAAE,YAAY,CAAC,QAAQ,CAAC,CAAA;IAC9B,KAAK,CAAC,EAAE,iBAAiB,CAAA;IACzB,QAAQ,CAAC,EAAE,eAAe,CAAA;IAC1B;+DAC2D;IAC3D,WAAW,IAAI,OAAO,CAAA;IACtB;4EACwE;IACxE,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,mBAAmB,GAAG,SAAS,CAAA;CACrE;AACD,iFAAiF;AACjF,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,eAAe,EAAE,IAAI,EAAE,sBAAsB;iBAi/BxE,IAAI;2BAhqBQ,SAAS,YAAY,EAAE,KAAG,IAAI;yBAiGhC,YAAY,KAAG,IAAI;+BAxBb,oBAAoB,KAAG,IAAI;2BAtKjC,IAAI;6BAgBF,IAAI;4BA3IH,MAAM,WAAW,MAAM,KAAG,YAAY,GAAG,SAAS;8BAYhD,MAAM,WAAW,MAAM,QAAQ,YAAY,CAAC,aAAa,CAAC,CAAC,MAAM,CAAC,KAAG,cAAc,GAAG,SAAS;sBAoBvG,SAAS,YAAY,EAAE,GAAG,SAAS,KAAG,MAAM;2BASvC,SAAS,YAAY,EAAE,GAAG,SAAS,KAAG,MAAM;EAm2B3E"}
@@ -1,7 +1,9 @@
1
+ import { replaySelectionAttachment } from './ide-selection.js';
1
2
  import { isSubagentToolName, parseJobOutputId, toolCommandOf, BACKGROUND_START_ACK, todoPanelItems } from './projection-helpers.js';
2
3
  import { ARGS_PREVIEW_LIMIT, harnessToolResultView, LOCAL_OUTPUT_LIMIT, prepareReplayEvents, preview, RESULT_PREVIEW_LIMIT, toolErrorText } from './transcript.js';
3
4
  import { estimateTokens, isTokenDelta, tokenDeltaChars, usageOutputTokens } from './usage.js';
4
5
  import { transcriptImagesOf } from '../transcript-images.js';
6
+ import { isCompactionCheckpointSource, toolResultPayload } from '../compat/messages.js';
5
7
  import { isPeakHour } from '../../deepseekPricing.js';
6
8
  import { t } from '../../i18n.js';
7
9
  import { logForDebugging } from '../../utils/debug.js';
@@ -150,12 +152,8 @@ export function createChannelProjection(state, deps) {
150
152
  const tool = toolsRegistry?.get(name, deps.agent());
151
153
  if (tool?.presentResult === undefined)
152
154
  return undefined;
153
- const block = data.message.content[0];
154
- // oxlint-disable-next-line typescript/no-unnecessary-condition -- durable session data may not match type
155
- const content = block !== undefined && block.type === 'tool-result' ? block.content : [];
156
155
  return tool.presentResult(JSON.parse(rawArgs), {
157
- content,
158
- isError: block?.isError === true,
156
+ ...toolResultPayload(data.message),
159
157
  ...(data.meta !== undefined ? { meta: data.meta } : {}),
160
158
  });
161
159
  }
@@ -436,13 +434,9 @@ export function createChannelProjection(state, deps) {
436
434
  }
437
435
  switch (event.type) {
438
436
  case 'user/message': {
439
- // Compaction checkpoint: `source = { kind: 'plugin', plugin:
440
- // 'compact' }` (dsh-compact's COMPACT_CHECKPOINT_SOURCE). Render the
441
- // framed summary after /compact as a Divider title + a summary row
442
- // that defaults folded (`compact` kind) instead of skipping it like
443
- // other injected context.
444
- if (event.data.source.kind === 'plugin' &&
445
- event.data.source.plugin === 'compact') {
437
+ // Both legacy and V4 checkpoints render as a folded summary rather
438
+ // than disappearing with the other injected context.
439
+ if (isCompactionCheckpointSource(event.data.source)) {
446
440
  const summary = textOf(event.data.content);
447
441
  appendRow({ id: deps.rowIds.value, kind: 'notice', text: 'Session summary is ready' });
448
442
  deps.rowIds.value += 1;
@@ -494,11 +488,22 @@ export function createChannelProjection(state, deps) {
494
488
  const text = firstTextOf(event.data.content);
495
489
  const images = transcriptImages(event.data.content);
496
490
  if (text || images.length > 0) {
491
+ // IDE selection indicator: the delivery path remembered what this
492
+ // message attached; the durable event carries the same message id.
493
+ // On replay (session resumed in a NEW process) the in-memory map
494
+ // starts empty, so the indicator falls back to the durable content
495
+ // itself — the `<attached-file … selection>` block IS part of the
496
+ // persisted event, and the session log is the source of truth
497
+ // (maintainer review round 3: the indicator used to vanish after a
498
+ // restart because nothing re-derived it from the event).
499
+ const selectionAttached = deps.selectionAttached(event.data.id)
500
+ ?? replaySelectionAttachment(event.data.content);
497
501
  appendRow({
498
502
  id: deps.rowIds.value,
499
503
  kind: 'user',
500
504
  text,
501
505
  ...(images.length === 0 ? {} : { images }),
506
+ ...(selectionAttached === undefined ? {} : { selectionAttached }),
502
507
  seq: event.seq,
503
508
  });
504
509
  state.lastUserText = text || t('transcript-image-message', { count: images.length });
@@ -759,8 +764,8 @@ export function createChannelProjection(state, deps) {
759
764
  const images = transcriptImages(event.data.message.content);
760
765
  card.images = images.length === 0 ? undefined : images;
761
766
  card.tool.durationMs = Math.max(0, Date.now() - card.tool.startedAt);
762
- const failure = event.data.error;
763
- if (failure !== undefined) {
767
+ const payload = toolResultPayload(event.data.message);
768
+ if (event.data.error !== undefined || payload.isError) {
764
769
  card.tool.status = 'error';
765
770
  const errorText = toolErrorText(event);
766
771
  card.tool.errorText = errorText;
@@ -768,9 +773,7 @@ export function createChannelProjection(state, deps) {
768
773
  }
769
774
  else {
770
775
  card.tool.status = 'ok';
771
- const block = event.data.message.content[0];
772
- // oxlint-disable-next-line typescript/no-unnecessary-condition -- durable session data may not match type
773
- const result = block !== undefined && block.type === 'tool-result' ? textOf(block.content) : '';
776
+ const result = textOf(payload.content);
774
777
  card.tool.resultFull = result || undefined;
775
778
  card.tool.resultText = result ? preview(result, RESULT_PREVIEW_LIMIT) : undefined;
776
779
  // The tool's own settled-state view (applied diff, terminal
@@ -865,7 +868,10 @@ export function createChannelProjection(state, deps) {
865
868
  }
866
869
  const reason = event.data.reason;
867
870
  if (reason.kind === 'completed') {
868
- deps.checkContextWarning();
871
+ // Replay drains a resumed session's history through the projector;
872
+ // its totals describe the past, not a live context-low state.
873
+ if (!replaying)
874
+ deps.checkContextWarning();
869
875
  break;
870
876
  }
871
877
  if (reason.kind === 'aborted' || reason.kind === 'interrupted') {
@@ -887,7 +893,11 @@ export function createChannelProjection(state, deps) {
887
893
  const detail = reason.kind === 'error' ? cleanRenderText(reason.error.message, NOTICE_CELLS) : '';
888
894
  appendRow({ id: deps.rowIds.value, kind: 'notice', text: `turn ${reason.kind}${detail ? ` · ${detail}` : ''}` });
889
895
  deps.rowIds.value += 1;
890
- deps.notify(t('turn-failed', { detail: detail ? ` · ${detail}` : '' }), { color: 'error', timeoutMs: 8000 });
896
+ // Historical failure notices belong to the transcript row above;
897
+ // re-raising them as a live toast on every /resume re-alarmes the
898
+ // user over a turn that already ended.
899
+ if (!replaying)
900
+ deps.notify(t('turn-failed', { detail: detail ? ` · ${detail}` : '' }), { color: 'error', timeoutMs: 8000 });
891
901
  break;
892
902
  }
893
903
  case 'request/context':
@@ -1 +1 @@
1
- {"version":3,"file":"reports.d.ts","sourceRoot":"","sources":["../../../../src/dsh-adapter/channel/reports.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAA;AAInD,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAA;AACjE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAA;AAU5E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAE9C,+EAA+E;AAC/E,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE;IACtD,KAAK,EAAE,IAAI,CAAC,YAAY,EAAE,SAAS,CAAC,CAAA;IACpC,OAAO,IAAI;QAAE,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;QAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAA;IACjE,OAAO,CAAC,OAAO,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;QAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAA;IACjF,GAAG,IAAI,MAAM,CAAA;IACb,KAAK,IAAI,MAAM,CAAA;IACf,QAAQ,IAAI,MAAM,CAAA;IAClB,aAAa,IAAI,MAAM,GAAG,SAAS,CAAA;IACnC,YAAY,IAAI,MAAM,CAAA;IACtB,OAAO,EAAE,qBAAqB,CAAA;IAC9B,UAAU,IAAI,UAAU,CAAC,OAAO,cAAc,CAAC,CAAA;CAChD;;qBAcuB,MAAM,EAAE;yBAkCJ,MAAM,GAAG,IAAI;yBAsCb,MAAM,GAAG,QAAQ,GAAG,IAAI;sBAY3B,MAAM,EAAE;wBAmCJ,MAAM,KAAG,MAAM,EAAE;EAM7C"}
1
+ {"version":3,"file":"reports.d.ts","sourceRoot":"","sources":["../../../../src/dsh-adapter/channel/reports.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAA;AAInD,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAA;AACjE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAA;AAU5E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAG9C,+EAA+E;AAC/E,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE;IACtD,KAAK,EAAE,IAAI,CAAC,YAAY,EAAE,SAAS,CAAC,CAAA;IACpC,OAAO,IAAI;QAAE,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;QAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAA;IACjE,OAAO,CAAC,OAAO,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;QAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAA;IACjF,GAAG,IAAI,MAAM,CAAA;IACb,KAAK,IAAI,MAAM,CAAA;IACf,QAAQ,IAAI,MAAM,CAAA;IAClB,aAAa,IAAI,MAAM,GAAG,SAAS,CAAA;IACnC,YAAY,IAAI,MAAM,CAAA;IACtB,OAAO,EAAE,qBAAqB,CAAA;IAC9B,UAAU,IAAI,UAAU,CAAC,OAAO,cAAc,CAAC,CAAA;CAChD;;qBAcuB,MAAM,EAAE;yBA2BJ,MAAM,GAAG,IAAI;yBAmCb,MAAM,GAAG,QAAQ,GAAG,IAAI;sBAY3B,MAAM,EAAE;wBAmCJ,MAAM,KAAG,MAAM,EAAE;EAM7C"}
@@ -10,6 +10,7 @@ import { snapshotLiveSessionEvents } from '../compat/liveSession.js';
10
10
  import { getHostGrantStore } from '../host-grants.js';
11
11
  import { getHostFacade } from '../plugin-host.js';
12
12
  import { pluginsInfoLines } from '../plugins-info.js';
13
+ import { toolResultText } from './transcript.js';
13
14
  /** Local reports and filesystem actions, fenced to the originating binding. */
14
15
  export function createReportActions(ctx, deps) {
15
16
  const current = (capture) => deps.owner.current() && deps.current(capture);
@@ -57,12 +58,6 @@ export function createReportActions(ctx, deps) {
57
58
  }
58
59
  return '';
59
60
  };
60
- const textOf = (content) => (content ?? []).flatMap(block => {
61
- if (block === null || typeof block !== 'object')
62
- return [];
63
- const record = block;
64
- return record.type === 'text' && typeof record.text === 'string' ? [record.text] : [];
65
- }).join('').trim();
66
61
  const exportSession = () => {
67
62
  const capture = deps.capture();
68
63
  const agent = capture.agent;
@@ -90,12 +85,9 @@ export function createReportActions(ctx, deps) {
90
85
  parts.push(`${t('export-tool-section', { name: event.data.name })}\n\n\`\`\`json\n${event.data.arguments}\n\`\`\`\n`);
91
86
  break;
92
87
  case 'tool/result': {
93
- const block = event.data.message.content[0];
94
- if (block?.type === 'tool-result') {
95
- const text = textOf(block.content);
96
- if (text)
97
- parts.push(`${t('export-result-section')}\n\n\`\`\`\n${text}\n\`\`\`\n`);
98
- }
88
+ const text = toolResultText(event);
89
+ if (text)
90
+ parts.push(`${t('export-result-section')}\n\n\`\`\`\n${text}\n\`\`\`\n`);
99
91
  break;
100
92
  }
101
93
  }
@@ -1 +1 @@
1
- {"version":3,"file":"session-fork.d.ts","sourceRoot":"","sources":["../../../../src/dsh-adapter/channel/session-fork.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAsB,MAAM,wBAAwB,CAAA;AAC7E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAa,KAAK,OAAO,EAAqB,MAAM,0BAA0B,CAAA;AAOrF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAC9C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAE9C,KAAK,SAAS,GAAG,IAAI,CAAC,YAAY,EAAE,SAAS,GAAG,KAAK,GAAG,UAAU,GAAG,OAAO,GAAG,cAAc,CAAC,CAAA;AAE9F,8EAA8E;AAC9E,wBAAgB,uBAAuB,CACrC,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,SAAS,EAChB,IAAI,EAAE;IACJ,KAAK,EAAE,IAAI,CAAC,YAAY,EAAE,SAAS,CAAC,CAAA;IACpC,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACjC,MAAM,EAAE,YAAY,CAAC,QAAQ,CAAC,CAAA;IAC9B,MAAM,IAAI,OAAO,CAAA;IACjB,oBAAoB,CAAC,MAAM,EAAE,MAAM,OAAO,CAAC,WAAW,CAAC,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,WAAW,CAAC;QAAC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;KAAE,CAAC,CAAA;CACrH,SAEgB,OAAO,CAAC,OAAO,CAAC,CAmElC"}
1
+ {"version":3,"file":"session-fork.d.ts","sourceRoot":"","sources":["../../../../src/dsh-adapter/channel/session-fork.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAsB,MAAM,wBAAwB,CAAA;AAC7E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAa,KAAK,OAAO,EAAqB,MAAM,0BAA0B,CAAA;AASrF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAC9C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAE9C,KAAK,SAAS,GAAG,IAAI,CAAC,YAAY,EAAE,SAAS,GAAG,KAAK,GAAG,UAAU,GAAG,OAAO,GAAG,cAAc,CAAC,CAAA;AAE9F,8EAA8E;AAC9E,wBAAgB,uBAAuB,CACrC,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,SAAS,EAChB,IAAI,EAAE;IACJ,KAAK,EAAE,IAAI,CAAC,YAAY,EAAE,SAAS,CAAC,CAAA;IACpC,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACjC,MAAM,EAAE,YAAY,CAAC,QAAQ,CAAC,CAAA;IAC9B,MAAM,IAAI,OAAO,CAAA;IACjB,oBAAoB,CAAC,MAAM,EAAE,MAAM,OAAO,CAAC,WAAW,CAAC,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,WAAW,CAAC;QAAC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;KAAE,CAAC,CAAA;CACrH,SAEgB,OAAO,CAAC,OAAO,CAAC,CAqFlC"}
@@ -5,6 +5,8 @@ import { resolveDshProfileName } from '../../update.js';
5
5
  import { appendSessionTitle, liveSessionCreateOptions, sliceLiveSessionSeed } from '../compat/index.js';
6
6
  import { composePreset, runningPresetOf } from '../presets.js';
7
7
  import { attachSessionToWorkspace } from '../workspace.js';
8
+ import { reserveMount } from '../../sessionMounts.js';
9
+ import { mountFailureText } from '../../sessions/resumeFailure.js';
8
10
  /** Create a detached `/fork` copy without adopting it into the foreground. */
9
11
  export function createForkSessionAction(ctx, state, deps) {
10
12
  return async () => {
@@ -32,6 +34,18 @@ export function createForkSessionAction(ctx, state, deps) {
32
34
  return false;
33
35
  }
34
36
  const forkComposed = await composePreset(ctx, runningPresetOf(source));
37
+ // Reserve BEFORE the factory, and hold it past `detached.release()`.
38
+ //
39
+ // A forked child is driven by this process for the whole creation and then
40
+ // written to once more AFTER the handle is gone (`appendSessionTitle`
41
+ // below), so "the handle was disposed" is not the moment this process stops
42
+ // touching the log. The reservation covers both, and is given back at the
43
+ // end: a fork is a standalone session the user resumes separately, not one
44
+ // this terminal keeps mounted.
45
+ const reserved = await reserveMount(String(childId));
46
+ if (!reserved.ok && reserved.reason !== 'occupied')
47
+ deps.notify(mountFailureText(reserved), { color: 'warning', timeoutMs: 8000 });
48
+ const reservation = reserved.ok ? reserved.reservation : { settle: () => { }, abandon: () => { } };
35
49
  let detached;
36
50
  try {
37
51
  detached = await deps.createDetachedHandle(() => agents.create(liveSessionCreateOptions({
@@ -49,11 +63,13 @@ export function createForkSessionAction(ctx, state, deps) {
49
63
  })));
50
64
  }
51
65
  catch {
66
+ reservation.abandon();
52
67
  deps.notify(t('fork-create-failed'), { color: 'error' });
53
68
  return false;
54
69
  }
55
70
  if (!deps.owner.current()) {
56
71
  await detached.release();
72
+ reservation.abandon();
57
73
  return false;
58
74
  }
59
75
  try {
@@ -64,6 +80,7 @@ export function createForkSessionAction(ctx, state, deps) {
64
80
  }
65
81
  if (!deps.owner.current()) {
66
82
  await detached.release();
83
+ reservation.abandon();
67
84
  return false;
68
85
  }
69
86
  try {
@@ -72,8 +89,15 @@ export function createForkSessionAction(ctx, state, deps) {
72
89
  catch (error) {
73
90
  ctx.logger.warn('dsh-tui: forked session dispose failed: %o', error);
74
91
  }
75
- const sourceTitle = state.sessionTitle.trim();
76
- appendSessionTitle(String(childId), `Fork: ${sourceTitle === '' ? String(source.id).slice(0, 8) : sourceTitle}`);
92
+ try {
93
+ const sourceTitle = state.sessionTitle.trim();
94
+ appendSessionTitle(String(childId), `Fork: ${sourceTitle === '' ? String(source.id).slice(0, 8) : sourceTitle}`);
95
+ }
96
+ finally {
97
+ // The offline title write is the last touch; from here the fork is the
98
+ // user's to resume somewhere else.
99
+ reservation.abandon();
100
+ }
77
101
  const profile = resolveDshProfileName();
78
102
  const boot = profile === undefined ? 'dsh --config cordis.yml' : `dsh --profile ${profile}`;
79
103
  const command = process.platform === 'win32'
@@ -25,6 +25,9 @@ export declare function createLiveAgentAdoption(state: LiveAdoptionState, deps:
25
25
  refreshLoadedContext(): Promise<void>;
26
26
  refreshSkillCommands(): Promise<void>;
27
27
  clearStagedImages(): void;
28
+ /** Drop the live IDE selection: the adopted session's cwd differs from
29
+ * the one the selection was made in. */
30
+ resetIdeSelection(): void;
28
31
  notifySessionSwitched(kind: 'agent-view', sessionId: string, previousSessionId: string): void;
29
32
  notifyAgentView(): void;
30
33
  }): (target: Agent) => Promise<ResumeResult>;
@@ -1 +1 @@
1
- {"version":3,"file":"session-live-adoption.d.ts","sourceRoot":"","sources":["../../../../src/dsh-adapter/channel/session-live-adoption.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAA;AAMhE,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAA;AAC3D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAE5D,KAAK,OAAO,GAAG,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAA;AACtD,KAAK,iBAAiB,GAAG,IAAI,CAC3B,YAAY,EACV,QAAQ,GACR,SAAS,GACT,KAAK,GACL,YAAY,GACZ,aAAa,GACb,UAAU,GACV,OAAO,GACP,eAAe,GACf,eAAe,GACf,cAAc,GACd,iBAAiB,GACjB,KAAK,GACL,YAAY,GACZ,WAAW,GACX,iBAAiB,GACjB,SAAS,GACT,MAAM,CACT,GAAG,UAAU,CAAC,OAAO,sBAAsB,CAAC,CAAC,CAAC,CAAC,CAAA;AAEhD,qGAAqG;AACrG,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,iBAAiB,EACxB,IAAI,EAAE;IACJ,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,CAAA;IAClC,iBAAiB,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAA;IAC3C,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;IACzB,cAAc,IAAI,IAAI,CAAA;IACtB,cAAc,IAAI,IAAI,CAAA;IACtB,SAAS,IAAI,IAAI,CAAA;IACjB,MAAM,CAAC,MAAM,EAAE,SAAS,OAAO,0BAA0B,EAAE,YAAY,EAAE,GAAG,IAAI,CAAA;IAChF,YAAY,IAAI,IAAI,CAAA;IACpB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG;QAAE,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IACxD,gBAAgB,IAAI,IAAI,CAAA;IACxB,SAAS,IAAI,IAAI,CAAA;IACjB,eAAe,IAAI,IAAI,CAAA;IACvB,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACrC,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACrC,iBAAiB,IAAI,IAAI,CAAA;IACzB,qBAAqB,CAAC,IAAI,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7F,eAAe,IAAI,IAAI,CAAA;CACxB,IAEa,QAAQ,KAAK,KAAG,OAAO,CAAC,YAAY,CAAC,CAwDpD"}
1
+ {"version":3,"file":"session-live-adoption.d.ts","sourceRoot":"","sources":["../../../../src/dsh-adapter/channel/session-live-adoption.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAA;AAMhE,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAA;AAC3D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAE5D,KAAK,OAAO,GAAG,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAA;AACtD,KAAK,iBAAiB,GAAG,IAAI,CAC3B,YAAY,EACV,QAAQ,GACR,SAAS,GACT,KAAK,GACL,YAAY,GACZ,aAAa,GACb,UAAU,GACV,OAAO,GACP,eAAe,GACf,eAAe,GACf,cAAc,GACd,iBAAiB,GACjB,KAAK,GACL,YAAY,GACZ,WAAW,GACX,iBAAiB,GACjB,SAAS,GACT,MAAM,CACT,GAAG,UAAU,CAAC,OAAO,sBAAsB,CAAC,CAAC,CAAC,CAAC,CAAA;AAEhD,qGAAqG;AACrG,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,iBAAiB,EACxB,IAAI,EAAE;IACJ,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,CAAA;IAClC,iBAAiB,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAA;IAC3C,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;IACzB,cAAc,IAAI,IAAI,CAAA;IACtB,cAAc,IAAI,IAAI,CAAA;IACtB,SAAS,IAAI,IAAI,CAAA;IACjB,MAAM,CAAC,MAAM,EAAE,SAAS,OAAO,0BAA0B,EAAE,YAAY,EAAE,GAAG,IAAI,CAAA;IAChF,YAAY,IAAI,IAAI,CAAA;IACpB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG;QAAE,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IACxD,gBAAgB,IAAI,IAAI,CAAA;IACxB,SAAS,IAAI,IAAI,CAAA;IACjB,eAAe,IAAI,IAAI,CAAA;IACvB,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACrC,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACrC,iBAAiB,IAAI,IAAI,CAAA;IACzB;6CACyC;IACzC,iBAAiB,IAAI,IAAI,CAAA;IACzB,qBAAqB,CAAC,IAAI,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7F,eAAe,IAAI,IAAI,CAAA;CACxB,IAEa,QAAQ,KAAK,KAAG,OAAO,CAAC,YAAY,CAAC,CAyDpD"}
@@ -15,6 +15,7 @@ export function createLiveAgentAdoption(state, deps) {
15
15
  state.agentId = target.id;
16
16
  state.cwd = target.session.header.cwd ?? state.cwd;
17
17
  state.displayCwd = deps.describeWorkspace(state.cwd).description ?? state.cwd;
18
+ deps.resetIdeSelection();
18
19
  deps.refreshGitBranch();
19
20
  state.agentPreset = runningPresetOf(target.session);
20
21
  const route = recordedModelRoute(snapshotLiveSessionEvents(target.session));
@@ -4,6 +4,16 @@ import { writeResumeTarget } from '../../sessionHistory.js';
4
4
  import { type SessionSummary } from '../sessions/index.js';
5
5
  import type { ChannelOwner } from './owner.js';
6
6
  import type { CredentialStatus } from './types.js';
7
+ declare module '@deepseek-ai/dsh-llm' {
8
+ interface MessageSourceMap {
9
+ 'dsh-tui-btw': {
10
+ kind: 'dsh-tui-btw';
11
+ };
12
+ 'dsh-tui-recap': {
13
+ kind: 'dsh-tui-recap';
14
+ };
15
+ }
16
+ }
7
17
  type Capture = {
8
18
  readonly agent: Agent;
9
19
  readonly generation: number;
@@ -1 +1 @@
1
- {"version":3,"file":"session-metadata.d.ts","sourceRoot":"","sources":["../../../../src/dsh-adapter/channel/session-metadata.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAA;AAEnD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAoE,iBAAiB,EAAE,MAAM,yBAAyB,CAAA;AAK7H,OAAO,EAAoE,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAE5H,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAC9C,OAAO,KAAK,EAAE,gBAAgB,EAAmB,MAAM,YAAY,CAAA;AAKnE,KAAK,OAAO,GAAG;IAAE,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAA;AACrE,KAAK,OAAO,GAAG;IACb,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;IACrB,OAAO,IAAI,OAAO,CAAA;IAClB,SAAS,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAA;CACrC,CAAA;AAED,6EAA6E;AAC7E,wBAAgB,4BAA4B,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE;IAC/D,KAAK,EAAE,IAAI,CAAC,YAAY,EAAE,SAAS,GAAG,QAAQ,CAAC,CAAA;IAC/C,OAAO,EAAE,OAAO,CAAA;IAChB,QAAQ,IAAI,MAAM,CAAA;IAClB,KAAK,IAAI,MAAM,CAAA;IACf,IAAI,IAAI,IAAI,CAAA;IACZ,YAAY,IAAI,MAAM,CAAA;IACtB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpC,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpC,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxC,oBAAoB,CAAC,IAAI,EAAE,SAAS,cAAc,EAAE,GAAG,IAAI,CAAA;IAC3D,gBAAgB,CAAC,KAAK,EAAE,KAAK,GAAG;QAAE,QAAQ,CAAC,OAAO,EAAE;YAAE,KAAK,EAAE,KAAK,CAAC;YAAC,GAAG,EAAE,MAAM,CAAA;SAAE,GAAG,OAAO,CAAC;YAAE,MAAM,EAAE,SAAS;gBAAE,IAAI,EAAE,MAAM,CAAC;gBAAC,WAAW,EAAE,MAAM,CAAC;gBAAC,MAAM,EAAE,MAAM,CAAC;gBAAC,UAAU,EAAE,OAAO,CAAA;aAAE,EAAE,CAAC;YAAC,QAAQ,EAAE,OAAO,CAAA;SAAE,CAAC,CAAA;KAAE,GAAG,SAAS,CAAA;IAC/N,gBAAgB,CAAC,KAAK,EAAE,KAAK,GAAG;QAAE,KAAK,EAAE,KAAK,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAA;CAC9D;wBAMgC,OAAO,CAAC,SAAS,cAAc,EAAE,CAAC;gCAa/B,MAAM;;;;;;;8BA6BD,MAAM,KAAG,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC;6BAsD/C,MAAM,YAAY;QAAE,MAAM,CAAC,EAAE,WAAW,CAAC;QAAC,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;KAAE;4BAkB7E;QAAE,MAAM,CAAC,EAAE,WAAW,CAAC;QAAC,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;KAAE;;;;;;;;;;;;2BAuBjE,MAAM,KAAG,IAAI;6BAOX,MAAM,KAAG,IAAI;+BAQL,MAAM,KAAG,OAAO,CAAC,OAAO,CAAC;iCASvB,MAAM,SAAS,MAAM,KAAG,OAAO,CAAC,OAAO,CAAC;EAcnF"}
1
+ {"version":3,"file":"session-metadata.d.ts","sourceRoot":"","sources":["../../../../src/dsh-adapter/channel/session-metadata.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAA;AAEnD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAoE,iBAAiB,EAAE,MAAM,yBAAyB,CAAA;AAK7H,OAAO,EAAoE,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAE5H,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAC9C,OAAO,KAAK,EAAE,gBAAgB,EAAmB,MAAM,YAAY,CAAA;AAKnE,OAAO,QAAQ,sBAAsB,CAAC;IACpC,UAAU,gBAAgB;QACxB,aAAa,EAAE;YAAE,IAAI,EAAE,aAAa,CAAA;SAAE,CAAA;QACtC,eAAe,EAAE;YAAE,IAAI,EAAE,eAAe,CAAA;SAAE,CAAA;KAC3C;CACF;AAID,KAAK,OAAO,GAAG;IAAE,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAA;AACrE,KAAK,OAAO,GAAG;IACb,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;IACrB,OAAO,IAAI,OAAO,CAAA;IAClB,SAAS,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAA;CACrC,CAAA;AAED,6EAA6E;AAC7E,wBAAgB,4BAA4B,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE;IAC/D,KAAK,EAAE,IAAI,CAAC,YAAY,EAAE,SAAS,GAAG,QAAQ,CAAC,CAAA;IAC/C,OAAO,EAAE,OAAO,CAAA;IAChB,QAAQ,IAAI,MAAM,CAAA;IAClB,KAAK,IAAI,MAAM,CAAA;IACf,IAAI,IAAI,IAAI,CAAA;IACZ,YAAY,IAAI,MAAM,CAAA;IACtB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpC,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpC,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxC,oBAAoB,CAAC,IAAI,EAAE,SAAS,cAAc,EAAE,GAAG,IAAI,CAAA;IAC3D,gBAAgB,CAAC,KAAK,EAAE,KAAK,GAAG;QAAE,QAAQ,CAAC,OAAO,EAAE;YAAE,KAAK,EAAE,KAAK,CAAC;YAAC,GAAG,EAAE,MAAM,CAAA;SAAE,GAAG,OAAO,CAAC;YAAE,MAAM,EAAE,SAAS;gBAAE,IAAI,EAAE,MAAM,CAAC;gBAAC,WAAW,EAAE,MAAM,CAAC;gBAAC,MAAM,EAAE,MAAM,CAAC;gBAAC,UAAU,EAAE,OAAO,CAAA;aAAE,EAAE,CAAC;YAAC,QAAQ,EAAE,OAAO,CAAA;SAAE,CAAC,CAAA;KAAE,GAAG,SAAS,CAAA;IAC/N,gBAAgB,CAAC,KAAK,EAAE,KAAK,GAAG;QAAE,KAAK,EAAE,KAAK,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAA;CAC9D;wBAMgC,OAAO,CAAC,SAAS,cAAc,EAAE,CAAC;gCAa/B,MAAM;;;;;;;8BA6BD,MAAM,KAAG,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC;6BAsD/C,MAAM,YAAY;QAAE,MAAM,CAAC,EAAE,WAAW,CAAC;QAAC,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;KAAE;4BAkB7E;QAAE,MAAM,CAAC,EAAE,WAAW,CAAC;QAAC,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;KAAE;;;;;;;;;;;;2BAuBjE,MAAM,KAAG,IAAI;6BAOX,MAAM,KAAG,IAAI;+BAQL,MAAM,KAAG,OAAO,CAAC,OAAO,CAAC;iCASvB,MAAM,SAAS,MAAM,KAAG,OAAO,CAAC,OAAO,CAAC;EAcnF"}
@@ -124,7 +124,7 @@ export function createSessionMetadataActions(ctx, deps) {
124
124
  stream: llm.stream.bind(llm),
125
125
  options: llmRequest(capture, [
126
126
  ...capture.agent.session.deriveMessages(),
127
- createUserMessage({ content: [{ type: 'text', text: wrapSideQuestion(question) }], source: { kind: 'plugin', plugin: 'dsh-tui/btw' } }),
127
+ createUserMessage({ content: [{ type: 'text', text: wrapSideQuestion(question) }], source: { kind: 'dsh-tui-btw' } }),
128
128
  ], true, signal),
129
129
  // Do not let an old session append streamed UI facts after a switch.
130
130
  onText: delta => { if (current(capture) && !options?.signal?.aborted)
@@ -148,7 +148,7 @@ export function createSessionMetadataActions(ctx, deps) {
148
148
  const outcome = await runSideQuestion({
149
149
  stream: llm.stream.bind(llm),
150
150
  options: llmRequest(capture, [
151
- createUserMessage({ content: [{ type: 'text', text: wrapRecapPrompt(activity) }], source: { kind: 'plugin', plugin: 'dsh-tui/recap' } }),
151
+ createUserMessage({ content: [{ type: 'text', text: wrapRecapPrompt(activity) }], source: { kind: 'dsh-tui-recap' } }),
152
152
  ], false, signal),
153
153
  onText: delta => { if (current(capture) && !options?.signal?.aborted)
154
154
  options?.onText?.(delta); },