@deepseek-harness-tui/dsh-tui 0.10.2 → 0.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (351) hide show
  1. package/README.md +175 -123
  2. package/bin/dsh-tui.js +748 -22
  3. package/cordis.patch.yml +42 -13
  4. package/cordis.yml +5 -2
  5. package/lib/types/activityPrefs.d.ts +24 -0
  6. package/lib/types/activityPrefs.d.ts.map +1 -1
  7. package/lib/types/activityPrefs.js +50 -1
  8. package/lib/types/adapter/channel/session-projection.d.ts.map +1 -1
  9. package/lib/types/adapter/channel/session-projection.js +2 -0
  10. package/lib/types/adapter/channel/state.d.ts.map +1 -1
  11. package/lib/types/adapter/channel/state.js +3 -1
  12. package/lib/types/adapter/channel/ui-policy.d.ts +4 -1
  13. package/lib/types/adapter/channel/ui-policy.d.ts.map +1 -1
  14. package/lib/types/adapter/channel/ui-policy.js +6 -2
  15. package/lib/types/adapter/kernel/host-facade.d.ts.map +1 -1
  16. package/lib/types/adapter/kernel/host-facade.js +1 -0
  17. package/lib/types/adapter/kernel/replay.d.ts.map +1 -1
  18. package/lib/types/adapter/kernel/replay.js +3 -0
  19. package/lib/types/adapter/kernel/runtime.d.ts.map +1 -1
  20. package/lib/types/adapter/kernel/runtime.js +2 -0
  21. package/lib/types/adapter/kernel/slices/workspace.d.ts.map +1 -1
  22. package/lib/types/adapter/kernel/slices/workspace.js +1 -0
  23. package/lib/types/adapter/ports/channel-ui.d.ts +29 -5
  24. package/lib/types/adapter/ports/channel-ui.d.ts.map +1 -1
  25. package/lib/types/adapter/ports/channel-view.d.ts +66 -12
  26. package/lib/types/adapter/ports/channel-view.d.ts.map +1 -1
  27. package/lib/types/adapter/ports/channel-workspace.d.ts +23 -0
  28. package/lib/types/adapter/ports/channel-workspace.d.ts.map +1 -1
  29. package/lib/types/adapter/ports/channel.d.ts +4 -1
  30. package/lib/types/adapter/ports/channel.d.ts.map +1 -1
  31. package/lib/types/adapter/ports/workspace.d.ts +2 -0
  32. package/lib/types/adapter/ports/workspace.d.ts.map +1 -1
  33. package/lib/types/adapter/upstream/workspace-driver.d.ts.map +1 -1
  34. package/lib/types/adapter/upstream/workspace-driver.js +10 -2
  35. package/lib/types/commands.d.ts.map +1 -1
  36. package/lib/types/commands.js +1 -0
  37. package/lib/types/components/ActivityLine.d.ts +7 -2
  38. package/lib/types/components/ActivityLine.d.ts.map +1 -1
  39. package/lib/types/components/ActivityLine.js +0 -8
  40. package/lib/types/components/ContextBarView.d.ts +15 -7
  41. package/lib/types/components/ContextBarView.d.ts.map +1 -1
  42. package/lib/types/components/ContextBarView.js +26 -22
  43. package/lib/types/components/ImagePreviewOverlay.d.ts.map +1 -1
  44. package/lib/types/components/ImagePreviewOverlay.js +11 -5
  45. package/lib/types/components/Markdown.d.ts +11 -1
  46. package/lib/types/components/Markdown.d.ts.map +1 -1
  47. package/lib/types/components/Markdown.js +20 -2
  48. package/lib/types/components/MermaidDiagram.d.ts +13 -0
  49. package/lib/types/components/MermaidDiagram.d.ts.map +1 -0
  50. package/lib/types/components/MermaidDiagram.js +61 -0
  51. package/lib/types/components/MessageList.d.ts +26 -1
  52. package/lib/types/components/MessageList.d.ts.map +1 -1
  53. package/lib/types/components/MessageList.js +74 -8
  54. package/lib/types/components/PageMargin.d.ts +1 -1
  55. package/lib/types/components/PromptInput.d.ts +37 -1
  56. package/lib/types/components/PromptInput.d.ts.map +1 -1
  57. package/lib/types/components/PromptInput.js +291 -30
  58. package/lib/types/components/ScrollbarGutter.d.ts +20 -5
  59. package/lib/types/components/ScrollbarGutter.d.ts.map +1 -1
  60. package/lib/types/components/ScrollbarGutter.js +88 -10
  61. package/lib/types/components/SplitDiffView.d.ts.map +1 -1
  62. package/lib/types/components/SplitDiffView.js +2 -1
  63. package/lib/types/components/StreamingMarkdown.d.ts.map +1 -1
  64. package/lib/types/components/StreamingMarkdown.js +30 -28
  65. package/lib/types/components/SubagentCard.d.ts.map +1 -1
  66. package/lib/types/components/SubagentCard.js +12 -6
  67. package/lib/types/components/SubagentDetailScene.d.ts.map +1 -1
  68. package/lib/types/components/SubagentDetailScene.js +8 -3
  69. package/lib/types/components/Tooltip.d.ts.map +1 -1
  70. package/lib/types/components/Tooltip.js +45 -7
  71. package/lib/types/components/design-system/HintLine.d.ts +1 -2
  72. package/lib/types/components/design-system/HintLine.d.ts.map +1 -1
  73. package/lib/types/components/design-system/HintLine.js +1 -2
  74. package/lib/types/components/messages/AssistantThinkingMessage.d.ts +2 -1
  75. package/lib/types/components/messages/AssistantThinkingMessage.d.ts.map +1 -1
  76. package/lib/types/components/messages/AssistantThinkingMessage.js +2 -1
  77. package/lib/types/components/messages/AssistantToolUseMessage.d.ts +2 -2
  78. package/lib/types/components/messages/AssistantToolUseMessage.d.ts.map +1 -1
  79. package/lib/types/components/messages/AssistantToolUseMessage.js +30 -26
  80. package/lib/types/components/messages/UserPromptMessage.d.ts.map +1 -1
  81. package/lib/types/components/messages/UserPromptMessage.js +5 -7
  82. package/lib/types/components/messages/useImageInspection.d.ts.map +1 -1
  83. package/lib/types/components/messages/useImageInspection.js +19 -9
  84. package/lib/types/components/promptDraftCache.d.ts +102 -0
  85. package/lib/types/components/promptDraftCache.d.ts.map +1 -0
  86. package/lib/types/components/promptDraftCache.js +76 -0
  87. package/lib/types/components/questions/AskUserQuestionPanel.d.ts +17 -1
  88. package/lib/types/components/questions/AskUserQuestionPanel.d.ts.map +1 -1
  89. package/lib/types/components/questions/AskUserQuestionPanel.js +40 -7
  90. package/lib/types/components/questions/QuestionMinimizedBar.d.ts +12 -0
  91. package/lib/types/components/questions/QuestionMinimizedBar.d.ts.map +1 -0
  92. package/lib/types/components/questions/QuestionMinimizedBar.js +43 -0
  93. package/lib/types/components/sessions/SessionListRow.d.ts +23 -1
  94. package/lib/types/components/sessions/SessionListRow.d.ts.map +1 -1
  95. package/lib/types/components/sessions/SessionListRow.js +52 -5
  96. package/lib/types/components/workspaces/HomeWorkspaceRow.d.ts +49 -0
  97. package/lib/types/components/workspaces/HomeWorkspaceRow.d.ts.map +1 -0
  98. package/lib/types/components/workspaces/HomeWorkspaceRow.js +50 -0
  99. package/lib/types/dsh-adapter/activity-store.d.ts +221 -0
  100. package/lib/types/dsh-adapter/activity-store.d.ts.map +1 -0
  101. package/lib/types/dsh-adapter/activity-store.js +359 -0
  102. package/lib/types/dsh-adapter/bundled-presets.d.ts +10 -0
  103. package/lib/types/dsh-adapter/bundled-presets.d.ts.map +1 -0
  104. package/lib/types/dsh-adapter/bundled-presets.js +80 -0
  105. package/lib/types/dsh-adapter/channel/action-readiness.d.ts +1 -1
  106. package/lib/types/dsh-adapter/channel/action-readiness.d.ts.map +1 -1
  107. package/lib/types/dsh-adapter/channel/action-readiness.js +3 -0
  108. package/lib/types/dsh-adapter/channel/agent-view-projection.d.ts +1 -1
  109. package/lib/types/dsh-adapter/channel/agent-view-projection.d.ts.map +1 -1
  110. package/lib/types/dsh-adapter/channel/agent-view-projection.js +19 -2
  111. package/lib/types/dsh-adapter/channel/background-action.d.ts +1 -1
  112. package/lib/types/dsh-adapter/channel/background-action.d.ts.map +1 -1
  113. package/lib/types/dsh-adapter/channel/background-action.js +53 -29
  114. package/lib/types/dsh-adapter/channel/binding-events.d.ts +8 -6
  115. package/lib/types/dsh-adapter/channel/binding-events.d.ts.map +1 -1
  116. package/lib/types/dsh-adapter/channel/binding-events.js +5 -4
  117. package/lib/types/dsh-adapter/channel/binding.d.ts +19 -2
  118. package/lib/types/dsh-adapter/channel/binding.d.ts.map +1 -1
  119. package/lib/types/dsh-adapter/channel/binding.js +78 -18
  120. package/lib/types/dsh-adapter/channel/compaction.d.ts +0 -1
  121. package/lib/types/dsh-adapter/channel/compaction.d.ts.map +1 -1
  122. package/lib/types/dsh-adapter/channel/compaction.js +0 -2
  123. package/lib/types/dsh-adapter/channel/composer-images.d.ts +5 -0
  124. package/lib/types/dsh-adapter/channel/composer-images.d.ts.map +1 -1
  125. package/lib/types/dsh-adapter/channel/composer-images.js +105 -6
  126. package/lib/types/dsh-adapter/channel/context-bookkeeping.d.ts +8 -0
  127. package/lib/types/dsh-adapter/channel/context-bookkeeping.d.ts.map +1 -1
  128. package/lib/types/dsh-adapter/channel/context-bookkeeping.js +3 -2
  129. package/lib/types/dsh-adapter/channel/ide-selection.d.ts +58 -0
  130. package/lib/types/dsh-adapter/channel/ide-selection.d.ts.map +1 -0
  131. package/lib/types/dsh-adapter/channel/ide-selection.js +226 -0
  132. package/lib/types/dsh-adapter/channel/input-delivery.d.ts +6 -1
  133. package/lib/types/dsh-adapter/channel/input-delivery.d.ts.map +1 -1
  134. package/lib/types/dsh-adapter/channel/input-delivery.js +9 -1
  135. package/lib/types/dsh-adapter/channel/local-actions.d.ts +3 -19
  136. package/lib/types/dsh-adapter/channel/local-actions.d.ts.map +1 -1
  137. package/lib/types/dsh-adapter/channel/local-actions.js +2 -1
  138. package/lib/types/dsh-adapter/channel/model-actions.d.ts +4 -1
  139. package/lib/types/dsh-adapter/channel/model-actions.d.ts.map +1 -1
  140. package/lib/types/dsh-adapter/channel/model-actions.js +82 -6
  141. package/lib/types/dsh-adapter/channel/model-switch.d.ts +1 -2
  142. package/lib/types/dsh-adapter/channel/model-switch.d.ts.map +1 -1
  143. package/lib/types/dsh-adapter/channel/model-switch.js +49 -31
  144. package/lib/types/dsh-adapter/channel/projection.d.ts +4 -0
  145. package/lib/types/dsh-adapter/channel/projection.d.ts.map +1 -1
  146. package/lib/types/dsh-adapter/channel/projection.js +29 -19
  147. package/lib/types/dsh-adapter/channel/reports.d.ts.map +1 -1
  148. package/lib/types/dsh-adapter/channel/reports.js +4 -12
  149. package/lib/types/dsh-adapter/channel/session-adoption.d.ts +1 -1
  150. package/lib/types/dsh-adapter/channel/session-adoption.d.ts.map +1 -1
  151. package/lib/types/dsh-adapter/channel/session-adoption.js +1 -0
  152. package/lib/types/dsh-adapter/channel/session-fork.d.ts.map +1 -1
  153. package/lib/types/dsh-adapter/channel/session-fork.js +26 -2
  154. package/lib/types/dsh-adapter/channel/session-live-adoption.d.ts +4 -1
  155. package/lib/types/dsh-adapter/channel/session-live-adoption.d.ts.map +1 -1
  156. package/lib/types/dsh-adapter/channel/session-live-adoption.js +2 -0
  157. package/lib/types/dsh-adapter/channel/session-metadata.d.ts +10 -0
  158. package/lib/types/dsh-adapter/channel/session-metadata.d.ts.map +1 -1
  159. package/lib/types/dsh-adapter/channel/session-metadata.js +6 -4
  160. package/lib/types/dsh-adapter/channel/session-reset.d.ts +1 -1
  161. package/lib/types/dsh-adapter/channel/session-reset.d.ts.map +1 -1
  162. package/lib/types/dsh-adapter/channel/session-reset.js +0 -1
  163. package/lib/types/dsh-adapter/channel/session-resume.d.ts +12 -3
  164. package/lib/types/dsh-adapter/channel/session-resume.d.ts.map +1 -1
  165. package/lib/types/dsh-adapter/channel/session-resume.js +292 -94
  166. package/lib/types/dsh-adapter/channel/session-rewind.d.ts.map +1 -1
  167. package/lib/types/dsh-adapter/channel/session-rewind.js +34 -16
  168. package/lib/types/dsh-adapter/channel/session-tree-actions.d.ts.map +1 -1
  169. package/lib/types/dsh-adapter/channel/session-tree-actions.js +19 -3
  170. package/lib/types/dsh-adapter/channel/settings-host.d.ts.map +1 -1
  171. package/lib/types/dsh-adapter/channel/settings-host.js +4 -3
  172. package/lib/types/dsh-adapter/channel/state.d.ts +6 -1
  173. package/lib/types/dsh-adapter/channel/state.d.ts.map +1 -1
  174. package/lib/types/dsh-adapter/channel/state.js +3 -3
  175. package/lib/types/dsh-adapter/channel/subagent-projection.d.ts +21 -1
  176. package/lib/types/dsh-adapter/channel/subagent-projection.d.ts.map +1 -1
  177. package/lib/types/dsh-adapter/channel/subagent-projection.js +173 -6
  178. package/lib/types/dsh-adapter/channel/transcript.d.ts.map +1 -1
  179. package/lib/types/dsh-adapter/channel/transcript.js +6 -12
  180. package/lib/types/dsh-adapter/channel/types.d.ts +6 -1
  181. package/lib/types/dsh-adapter/channel/types.d.ts.map +1 -1
  182. package/lib/types/dsh-adapter/channel/workspace-actions.d.ts +4 -1
  183. package/lib/types/dsh-adapter/channel/workspace-actions.d.ts.map +1 -1
  184. package/lib/types/dsh-adapter/channel/workspace-actions.js +41 -1
  185. package/lib/types/dsh-adapter/channel.d.ts +1 -1
  186. package/lib/types/dsh-adapter/channel.d.ts.map +1 -1
  187. package/lib/types/dsh-adapter/channel.js +82 -20
  188. package/lib/types/dsh-adapter/compat/index.d.ts +1 -1
  189. package/lib/types/dsh-adapter/compat/index.d.ts.map +1 -1
  190. package/lib/types/dsh-adapter/compat/index.js +1 -1
  191. package/lib/types/dsh-adapter/compat/messages.d.ts +15 -0
  192. package/lib/types/dsh-adapter/compat/messages.d.ts.map +1 -0
  193. package/lib/types/dsh-adapter/compat/messages.js +15 -0
  194. package/lib/types/dsh-adapter/compat/sessionLog.d.ts +18 -0
  195. package/lib/types/dsh-adapter/compat/sessionLog.d.ts.map +1 -1
  196. package/lib/types/dsh-adapter/compat/sessionLog.js +18 -3
  197. package/lib/types/dsh-adapter/compat/settings.d.ts +35 -0
  198. package/lib/types/dsh-adapter/compat/settings.d.ts.map +1 -0
  199. package/lib/types/dsh-adapter/compat/settings.js +57 -0
  200. package/lib/types/dsh-adapter/compat/shell.d.ts +25 -0
  201. package/lib/types/dsh-adapter/compat/shell.d.ts.map +1 -0
  202. package/lib/types/dsh-adapter/compat/shell.js +11 -0
  203. package/lib/types/dsh-adapter/contract.d.ts +5 -4
  204. package/lib/types/dsh-adapter/contract.d.ts.map +1 -1
  205. package/lib/types/dsh-adapter/contract.js +17 -6
  206. package/lib/types/dsh-adapter/ide-channel.d.ts +224 -0
  207. package/lib/types/dsh-adapter/ide-channel.d.ts.map +1 -0
  208. package/lib/types/dsh-adapter/ide-channel.js +556 -0
  209. package/lib/types/dsh-adapter/index.d.ts +18 -3
  210. package/lib/types/dsh-adapter/index.d.ts.map +1 -1
  211. package/lib/types/dsh-adapter/index.js +32 -5
  212. package/lib/types/dsh-adapter/plugin.d.ts +4 -1
  213. package/lib/types/dsh-adapter/plugin.d.ts.map +1 -1
  214. package/lib/types/dsh-adapter/plugin.js +197 -49
  215. package/lib/types/dsh-adapter/preset-resolution.d.ts +8 -0
  216. package/lib/types/dsh-adapter/preset-resolution.d.ts.map +1 -1
  217. package/lib/types/dsh-adapter/preset-resolution.js +10 -0
  218. package/lib/types/dsh-adapter/session-mount-heartbeat.d.ts +53 -0
  219. package/lib/types/dsh-adapter/session-mount-heartbeat.d.ts.map +1 -0
  220. package/lib/types/dsh-adapter/session-mount-heartbeat.js +100 -0
  221. package/lib/types/dsh-adapter/sessionTree.d.ts.map +1 -1
  222. package/lib/types/dsh-adapter/sessionTree.js +3 -2
  223. package/lib/types/dsh-adapter/settings-sections.d.ts.map +1 -1
  224. package/lib/types/dsh-adapter/settings-sections.js +7 -4
  225. package/lib/types/dsh-adapter/subagents.d.ts +16 -3
  226. package/lib/types/dsh-adapter/subagents.d.ts.map +1 -1
  227. package/lib/types/dsh-adapter/subagents.js +92 -29
  228. package/lib/types/dsh-adapter/workspaces.d.ts +46 -3
  229. package/lib/types/dsh-adapter/workspaces.d.ts.map +1 -1
  230. package/lib/types/dsh-adapter/workspaces.js +116 -0
  231. package/lib/types/effortPrefs.d.ts +15 -3
  232. package/lib/types/effortPrefs.d.ts.map +1 -1
  233. package/lib/types/effortPrefs.js +37 -3
  234. package/lib/types/history.d.ts +13 -1
  235. package/lib/types/history.d.ts.map +1 -1
  236. package/lib/types/history.js +15 -2
  237. package/lib/types/homePrefs.d.ts +15 -0
  238. package/lib/types/homePrefs.d.ts.map +1 -0
  239. package/lib/types/homePrefs.js +53 -0
  240. package/lib/types/i18n.d.ts +347 -297
  241. package/lib/types/i18n.d.ts.map +1 -1
  242. package/lib/types/i18n.js +133 -85
  243. package/lib/types/ink/colorize.d.ts +10 -0
  244. package/lib/types/ink/colorize.d.ts.map +1 -1
  245. package/lib/types/ink/colorize.js +21 -0
  246. package/lib/types/ink/components/ScrollBox.d.ts.map +1 -1
  247. package/lib/types/ink/components/ScrollBox.js +12 -1
  248. package/lib/types/ink/dom.d.ts +1 -0
  249. package/lib/types/ink/dom.d.ts.map +1 -1
  250. package/lib/types/ink/hooks/use-copy-on-select.d.ts +5 -1
  251. package/lib/types/ink/hooks/use-copy-on-select.d.ts.map +1 -1
  252. package/lib/types/ink/hooks/use-copy-on-select.js +15 -1
  253. package/lib/types/ink/ink.d.ts.map +1 -1
  254. package/lib/types/ink/ink.js +36 -1
  255. package/lib/types/ink/log-update.d.ts.map +1 -1
  256. package/lib/types/ink/log-update.js +19 -1
  257. package/lib/types/ink/output.d.ts +10 -1
  258. package/lib/types/ink/output.d.ts.map +1 -1
  259. package/lib/types/ink/output.js +109 -17
  260. package/lib/types/ink/render-border.d.ts +6 -1
  261. package/lib/types/ink/render-border.d.ts.map +1 -1
  262. package/lib/types/ink/render-border.js +25 -9
  263. package/lib/types/ink/render-node-to-output.d.ts.map +1 -1
  264. package/lib/types/ink/render-node-to-output.js +48 -6
  265. package/lib/types/ink/renderer.d.ts +6 -0
  266. package/lib/types/ink/renderer.d.ts.map +1 -1
  267. package/lib/types/ink/renderer.js +2 -1
  268. package/lib/types/ink/selection.d.ts +88 -0
  269. package/lib/types/ink/selection.d.ts.map +1 -1
  270. package/lib/types/ink/selection.js +164 -0
  271. package/lib/types/ink/sixel-graphics.d.ts +19 -1
  272. package/lib/types/ink/sixel-graphics.d.ts.map +1 -1
  273. package/lib/types/ink/sixel-graphics.js +124 -12
  274. package/lib/types/ink/terminal-image.d.ts +18 -1
  275. package/lib/types/ink/terminal-image.d.ts.map +1 -1
  276. package/lib/types/ink/terminal.d.ts +17 -0
  277. package/lib/types/ink/terminal.d.ts.map +1 -1
  278. package/lib/types/ink/terminal.js +20 -1
  279. package/lib/types/screens/Chat.d.ts +20 -1
  280. package/lib/types/screens/Chat.d.ts.map +1 -1
  281. package/lib/types/screens/Chat.js +296 -76
  282. package/lib/types/screens/SessionSupervisor.d.ts +84 -0
  283. package/lib/types/screens/SessionSupervisor.d.ts.map +1 -0
  284. package/lib/types/screens/SessionSupervisor.js +350 -0
  285. package/lib/types/screens/SessionTree.js +2 -2
  286. package/lib/types/screens/Settings.d.ts.map +1 -1
  287. package/lib/types/screens/Settings.js +32 -9
  288. package/lib/types/screens/StatusLine.d.ts +18 -1
  289. package/lib/types/screens/StatusLine.d.ts.map +1 -1
  290. package/lib/types/screens/StatusLine.js +38 -19
  291. package/lib/types/screens/StatusMetrics.d.ts +79 -22
  292. package/lib/types/screens/StatusMetrics.d.ts.map +1 -1
  293. package/lib/types/screens/StatusMetrics.js +153 -88
  294. package/lib/types/screens/sessionSupervisor/model.d.ts +83 -0
  295. package/lib/types/screens/sessionSupervisor/model.d.ts.map +1 -0
  296. package/lib/types/screens/sessionSupervisor/model.js +69 -0
  297. package/lib/types/screens/sessionSupervisor/useSessionSupervisor.d.ts +120 -0
  298. package/lib/types/screens/sessionSupervisor/useSessionSupervisor.d.ts.map +1 -0
  299. package/lib/types/screens/sessionSupervisor/useSessionSupervisor.js +593 -0
  300. package/lib/types/sessionMounts.d.ts +272 -0
  301. package/lib/types/sessionMounts.d.ts.map +1 -0
  302. package/lib/types/sessionMounts.js +706 -0
  303. package/lib/types/sessions/format.d.ts.map +1 -1
  304. package/lib/types/sessions/format.js +4 -1
  305. package/lib/types/sessions/resumeFailure.d.ts +38 -0
  306. package/lib/types/sessions/resumeFailure.d.ts.map +1 -0
  307. package/lib/types/sessions/resumeFailure.js +58 -0
  308. package/lib/types/terminal-utils/mermaid.d.ts +44 -0
  309. package/lib/types/terminal-utils/mermaid.d.ts.map +1 -0
  310. package/lib/types/terminal-utils/mermaid.js +83 -0
  311. package/lib/types/tips.d.ts.map +1 -1
  312. package/lib/types/tips.js +175 -19
  313. package/lib/types/tuiDisplayPrefs.d.ts +7 -9
  314. package/lib/types/tuiDisplayPrefs.d.ts.map +1 -1
  315. package/lib/types/tuiDisplayPrefs.js +31 -28
  316. package/lib/types/update.d.ts +61 -0
  317. package/lib/types/update.d.ts.map +1 -1
  318. package/lib/types/update.js +194 -0
  319. package/lib/types/utils/fold-long-lines.d.ts +1 -1
  320. package/lib/types/utils/fold-long-lines.js +1 -1
  321. package/lib/types/utils/imageResize.d.ts +90 -0
  322. package/lib/types/utils/imageResize.d.ts.map +1 -0
  323. package/lib/types/utils/imageResize.js +272 -0
  324. package/lib/types/utils/keymap.d.ts +5 -1
  325. package/lib/types/utils/keymap.d.ts.map +1 -1
  326. package/lib/types/utils/keymap.js +23 -0
  327. package/lib/types/working-activity.d.ts +10 -9
  328. package/lib/types/working-activity.d.ts.map +1 -1
  329. package/lib/types/working-activity.js +17 -10
  330. package/lib/types/workspaces.d.ts +2 -1
  331. package/lib/types/workspaces.d.ts.map +1 -1
  332. package/lib/types/workspaces.js +1 -1
  333. package/node_modules/@deepseek-harness-tui/dsh-auth/package.json +10 -10
  334. package/package.json +126 -105
  335. package/presets/liangshen/.dsh-tui-managed.json +1 -1
  336. package/presets/liangshen/agent.cordis.yml +15 -0
  337. package/lib/types/components/design-system/KeyboardShortcutHint.d.ts +0 -19
  338. package/lib/types/components/design-system/KeyboardShortcutHint.d.ts.map +0 -1
  339. package/lib/types/components/design-system/KeyboardShortcutHint.js +0 -14
  340. package/lib/types/dsh-adapter/channel/activity.d.ts +0 -20
  341. package/lib/types/dsh-adapter/channel/activity.d.ts.map +0 -1
  342. package/lib/types/dsh-adapter/channel/activity.js +0 -113
  343. package/lib/types/screens/AgentView.d.ts +0 -23
  344. package/lib/types/screens/AgentView.d.ts.map +0 -1
  345. package/lib/types/screens/AgentView.js +0 -546
  346. package/lib/types/screens/SessionBrowser.d.ts +0 -42
  347. package/lib/types/screens/SessionBrowser.d.ts.map +0 -1
  348. package/lib/types/screens/SessionBrowser.js +0 -911
  349. package/lib/types/terminal-utils/terminal.d.ts +0 -18
  350. package/lib/types/terminal-utils/terminal.d.ts.map +0 -1
  351. package/lib/types/terminal-utils/terminal.js +0 -96
@@ -0,0 +1,58 @@
1
+ import type { ChannelSelection, SelectionAttachment } from '../../adapter/ports/channel-view.js';
2
+ import type { MentionExpansion, MentionFs } from './types.js';
3
+ /**
4
+ * Escape a path for reuse inside a quoted `<attached-file path="…">` attribute:
5
+ * POSIX filenames are legal with `"`, `&`, `<`, `>` — a raw interpolated path
6
+ * could break out of the attribute or smuggle markup into the model-facing
7
+ * block. `&` first so the replacements themselves are not re-escaped.
8
+ */
9
+ export declare function escapeSnippetAttr(value: string): string;
10
+ /**
11
+ * Build the `<attached-file path="…" selection>` block for an IDE selection:
12
+ * coordinates arrive 0-based inclusive from the extension and convert to
13
+ * sliceLines' 1-based; an endLine past EOF clamps to the last line (the model
14
+ * receives every remaining line), while a startLine past EOF yields undefined
15
+ * — the caller silently skips instead of attaching an empty or stale block.
16
+ * An empty selection is rejected here too so the guard cannot be bypassed.
17
+ */
18
+ export declare function buildSelectionBlock(selection: ChannelSelection, content: string): {
19
+ text: string;
20
+ lines: number;
21
+ } | undefined;
22
+ /**
23
+ * Append the selection's attached-file block to a message's content. Returns
24
+ * what was attached ({lines, path}) or undefined when there is nothing to
25
+ * attach — no selection, or an unresolvable/unreadable file. The caller
26
+ * passes the ENQUEUE-time snapshot (and its fs handle) so a selection made
27
+ * after submit can never attach to the wrong message.
28
+ *
29
+ * Protocol 2 carries the editor buffer's own `text` (unsaved edits
30
+ * included): when present it is attached VERBATIM and the filesystem is not
31
+ * touched — reading the disk copy would hand the model a version the user
32
+ * never saw (maintainer review round 3). The disk read remains only as the
33
+ * protocol-1 fallback.
34
+ */
35
+ export declare function attachIdeSelection(blocks: MentionExpansion['blocks'], cwd: string, selection: ChannelSelection | undefined, fs: MentionFs | undefined): Promise<SelectionAttachment | undefined>;
36
+ /**
37
+ * Derive the transcript indicator from the DURABLE user-message content:
38
+ * the `<attached-file path="…" selection count="N">` block the submit path
39
+ * appended is part of the persisted event, so a replayed session can rebuild
40
+ * the "Selected N lines from <file>" line even though the in-memory
41
+ * message-id → attachment map starts empty (maintainer review round 3: the
42
+ * session log is the source of truth — the indicator must not depend on
43
+ * process-local state).
44
+ */
45
+ export declare function replaySelectionAttachment(content: readonly unknown[] | undefined): SelectionAttachment | undefined;
46
+ /**
47
+ * Bounded map from a submitted message id → what its selection attached.
48
+ * The delivery path remembers at submit; the transcript projection reads it
49
+ * when the durable `user/message` event lands (the event carries the same
50
+ * message id) to stamp the row's indicator. FIFO-capped like the other
51
+ * row-keyed caches — ids grow monotonically and a miss only loses the
52
+ * indicator, never the attachment itself.
53
+ */
54
+ export declare function createSelectionAttachments(): {
55
+ remember(messageId: string, info: SelectionAttachment): void;
56
+ take(messageId: string): SelectionAttachment | undefined;
57
+ };
58
+ //# sourceMappingURL=ide-selection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ide-selection.d.ts","sourceRoot":"","sources":["../../../../src/dsh-adapter/channel/ide-selection.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAA;AAEhG,OAAO,KAAK,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAuB7D;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEvD;AAyCD;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,gBAAgB,EAC3B,OAAO,EAAE,MAAM,GACd;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAc7C;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,gBAAgB,CAAC,QAAQ,CAAC,EAClC,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,gBAAgB,GAAG,SAAS,EACvC,EAAE,EAAE,SAAS,GAAG,SAAS,GACxB,OAAO,CAAC,mBAAmB,GAAG,SAAS,CAAC,CAoC1C;AAED;;;;;;;;GAQG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,SAAS,OAAO,EAAE,GAAG,SAAS,GACtC,mBAAmB,GAAG,SAAS,CA8BjC;AAED;;;;;;;GAOG;AACH,wBAAgB,0BAA0B,IAAI;IAC5C,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,mBAAmB,GAAG,IAAI,CAAA;IAC5D,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,mBAAmB,GAAG,SAAS,CAAA;CACzD,CAeA"}
@@ -0,0 +1,226 @@
1
+ /**
2
+ * IDE selection consumption: turn a live editor-selection snapshot into the
3
+ * model-facing `<attached-file … selection>` block. Protocol 2 pushes carry
4
+ * the editor buffer's own selection text — that is attached verbatim; the
5
+ * disk read below remains only as the protocol-1 fallback, and every failure
6
+ * mode is silent (an IDE-side extra must never block a send).
7
+ *
8
+ * The block builder never goes through text parsing (unlike `@`-mentions):
9
+ * selection paths may contain spaces no tokenizer could survive. It reuses
10
+ * the same line-slice semantics and size-cap policy as mention attachments.
11
+ */
12
+ import { isAbsolute, join } from 'node:path';
13
+ import { MENTION_MAX_FILE_CHARS } from './mentions.js';
14
+ /**
15
+ * Slice `content` into the 1-based inclusive [`startLine`, `endLine`] range.
16
+ * Returns undefined for malformed ranges (non-safe integers, zero/negative
17
+ * start, inverted) and for a start past EOF — counted against REAL lines: a
18
+ * trailing newline splits into a phantom final element that is not a line.
19
+ */
20
+ function sliceLines(content, startLine, endLine) {
21
+ const end = endLine ?? startLine;
22
+ if (!Number.isSafeInteger(startLine) || startLine < 1)
23
+ return undefined;
24
+ if (!Number.isSafeInteger(end) || end < startLine)
25
+ return undefined;
26
+ const lines = content.split('\n');
27
+ // A trailing newline splits into a phantom final element that is not a line.
28
+ if (lines.length > 1 && lines[lines.length - 1] === '')
29
+ lines.pop();
30
+ if (startLine > lines.length)
31
+ return undefined;
32
+ return lines.slice(startLine - 1, end).join('\n');
33
+ }
34
+ /**
35
+ * Escape a path for reuse inside a quoted `<attached-file path="…">` attribute:
36
+ * POSIX filenames are legal with `"`, `&`, `<`, `>` — a raw interpolated path
37
+ * could break out of the attribute or smuggle markup into the model-facing
38
+ * block. `&` first so the replacements themselves are not re-escaped.
39
+ */
40
+ export function escapeSnippetAttr(value) {
41
+ return value.replace(/&/g, '&amp;').replace(/"/g, '&quot;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
42
+ }
43
+ /**
44
+ * Format the attached-file block from an ALREADY-SLICED body: cap it like
45
+ * @-mention attachments (same MENTION_MAX_FILE_CHARS policy, same visible
46
+ * truncation marker) and count the lines the model gets — the truncated body,
47
+ * not the request (review round 3).
48
+ *
49
+ * `allowEmpty` keeps a selection that covers ONE blank line: the body is
50
+ * legitimately empty there while the badge still says "1 line selected", and
51
+ * dropping the block made the footer and the transcript disagree (review
52
+ * round 7). Callers pass it only for a single-line range that really exists.
53
+ */
54
+ function cappedSelectionBlock(path, sliced, allowEmpty = false) {
55
+ if (sliced === '' && !allowEmpty)
56
+ return undefined;
57
+ let body = sliced;
58
+ let attached = sliced;
59
+ if (body.length > MENTION_MAX_FILE_CHARS) {
60
+ attached = body.slice(0, MENTION_MAX_FILE_CHARS);
61
+ body = `${attached}\n[… truncated]`;
62
+ }
63
+ // `count` is the number of lines in the attached BODY — the truncation
64
+ // marker line is not counted (it rides on top of the cap and the live
65
+ // indicator reports the same number). It exists so the replay path never has
66
+ // to GUESS that number from the body tail: a selection whose last line is
67
+ // literally `[… truncated]` used to lose one line when the indicator was
68
+ // rebuilt from the persisted event (fuzz rounds found 46/400 such bodies).
69
+ // Deliberately NOT `lines`: @-mention attachments already use `lines="2-4"`
70
+ // for the REQUESTED range, and overloading the key with a count would make
71
+ // the two block flavours read alike.
72
+ const lines = attached.split('\n').length;
73
+ return {
74
+ text: `<attached-file path="${escapeSnippetAttr(path)}" selection count="${lines}">\n${body}\n</attached-file>`,
75
+ lines,
76
+ };
77
+ }
78
+ /**
79
+ * Build the `<attached-file path="…" selection>` block for an IDE selection:
80
+ * coordinates arrive 0-based inclusive from the extension and convert to
81
+ * sliceLines' 1-based; an endLine past EOF clamps to the last line (the model
82
+ * receives every remaining line), while a startLine past EOF yields undefined
83
+ * — the caller silently skips instead of attaching an empty or stale block.
84
+ * An empty selection is rejected here too so the guard cannot be bypassed.
85
+ */
86
+ export function buildSelectionBlock(selection, content) {
87
+ if (selection.isEmpty)
88
+ return undefined;
89
+ // 0-based inclusive [start, end] → 1-based inclusive [start+1, end+1].
90
+ // sliceLines clamps an oversized end itself (Array#slice bounds); a start
91
+ // past EOF returns undefined and the whole attach is silently dropped.
92
+ const sliced = sliceLines(content, selection.startLine + 1, selection.endLine + 1);
93
+ if (sliced === undefined)
94
+ return undefined;
95
+ // sliceLines returning '' (not undefined) means the requested line EXISTS and
96
+ // is blank — a single blank line is a real selection the badge reports.
97
+ return cappedSelectionBlock(selection.path, sliced, selection.startLine === selection.endLine);
98
+ }
99
+ /**
100
+ * Append the selection's attached-file block to a message's content. Returns
101
+ * what was attached ({lines, path}) or undefined when there is nothing to
102
+ * attach — no selection, or an unresolvable/unreadable file. The caller
103
+ * passes the ENQUEUE-time snapshot (and its fs handle) so a selection made
104
+ * after submit can never attach to the wrong message.
105
+ *
106
+ * Protocol 2 carries the editor buffer's own `text` (unsaved edits
107
+ * included): when present it is attached VERBATIM and the filesystem is not
108
+ * touched — reading the disk copy would hand the model a version the user
109
+ * never saw (maintainer review round 3). The disk read remains only as the
110
+ * protocol-1 fallback.
111
+ */
112
+ export async function attachIdeSelection(blocks, cwd, selection, fs) {
113
+ if (selection === undefined || selection.isEmpty)
114
+ return undefined;
115
+ if (selection.text !== undefined) {
116
+ // Protocol 2: `text` is the editor's OWN text for the selection
117
+ // (document.getText(selection)) — the ABSOLUTE document coordinates ride
118
+ // along for the badge/indicator, but they must NOT slice this string:
119
+ // it already contains exactly the selected lines, so anything not
120
+ // starting at line 0 would be mis-cut or dropped entirely (review
121
+ // round 4). Attach it verbatim with the shared size cap. A full-line
122
+ // selection ends at column 0 of the NEXT line, so getText hands back a
123
+ // trailing '\n' — strip that one terminator or the body grows a phantom
124
+ // blank line and the indicator over-counts by one (review round 5).
125
+ let text = selection.text;
126
+ if (text.endsWith('\n'))
127
+ text = text.slice(0, -1);
128
+ // Triple-clicking ONE blank line hands back "\n": after the strip the body
129
+ // is empty but a line WAS selected (the footer badge says so) — keep the
130
+ // block so the indicator and the badge agree instead of attaching nothing.
131
+ const block = cappedSelectionBlock(selection.path, text, selection.text !== '');
132
+ if (block === undefined)
133
+ return undefined;
134
+ blocks.push({ type: 'text', text: block.text });
135
+ return { lines: block.lines, path: selection.path };
136
+ }
137
+ if (fs === undefined)
138
+ return undefined;
139
+ try {
140
+ const absolute = isAbsolute(selection.path) ? selection.path : join(cwd, selection.path);
141
+ const target = await fs.resolve(absolute);
142
+ const info = await fs.stat(target);
143
+ if (info?.type !== 'file')
144
+ return undefined;
145
+ const content = await fs.readText(target);
146
+ const block = buildSelectionBlock(selection, content);
147
+ if (block === undefined)
148
+ return undefined;
149
+ blocks.push({ type: 'text', text: block.text });
150
+ return { lines: block.lines, path: selection.path };
151
+ }
152
+ catch {
153
+ return undefined;
154
+ }
155
+ }
156
+ /**
157
+ * Derive the transcript indicator from the DURABLE user-message content:
158
+ * the `<attached-file path="…" selection count="N">` block the submit path
159
+ * appended is part of the persisted event, so a replayed session can rebuild
160
+ * the "Selected N lines from <file>" line even though the in-memory
161
+ * message-id → attachment map starts empty (maintainer review round 3: the
162
+ * session log is the source of truth — the indicator must not depend on
163
+ * process-local state).
164
+ */
165
+ export function replaySelectionAttachment(content) {
166
+ if (content === undefined)
167
+ return undefined;
168
+ for (const block of content) {
169
+ if (block === null || typeof block !== 'object')
170
+ continue;
171
+ const text = block.text;
172
+ if (block.type !== 'text' || typeof text !== 'string')
173
+ continue;
174
+ const opened = /^<attached-file path="([^"]+)" selection(?: count="(\d+)")?>\n/.exec(text);
175
+ if (opened === null)
176
+ continue;
177
+ let closed = text.slice(opened[0].length);
178
+ if (closed.endsWith('</attached-file>'))
179
+ closed = closed.slice(0, -'</attached-file>'.length);
180
+ // The builder writes `body\n</attached-file>` — strip the newline the
181
+ // close tag rode on, or every body counts one phantom line.
182
+ if (closed.endsWith('\n'))
183
+ closed = closed.slice(0, -1);
184
+ const lines = closed.split('\n').length;
185
+ // `count` is authoritative when present (the builder always writes it).
186
+ // Blocks persisted before it existed fall back to the old tail heuristic,
187
+ // which misreads a body whose last line is literally the truncation marker.
188
+ const counted = opened[2] === undefined ? undefined : Number(opened[2]);
189
+ return {
190
+ lines: counted ?? (closed.endsWith('\n[… truncated]') ? lines - 1 : lines),
191
+ // Reverse escapeSnippetAttr so the replayed indicator shows the path
192
+ // exactly as the live one did (`&` first so entities are not re-baked).
193
+ path: opened[1]
194
+ .replace(/&lt;/g, '<')
195
+ .replace(/&gt;/g, '>')
196
+ .replace(/&quot;/g, '"')
197
+ .replace(/&amp;/g, '&'),
198
+ };
199
+ }
200
+ return undefined;
201
+ }
202
+ /**
203
+ * Bounded map from a submitted message id → what its selection attached.
204
+ * The delivery path remembers at submit; the transcript projection reads it
205
+ * when the durable `user/message` event lands (the event carries the same
206
+ * message id) to stamp the row's indicator. FIFO-capped like the other
207
+ * row-keyed caches — ids grow monotonically and a miss only loses the
208
+ * indicator, never the attachment itself.
209
+ */
210
+ export function createSelectionAttachments() {
211
+ const byMessageId = new Map();
212
+ return {
213
+ remember(messageId, info) {
214
+ byMessageId.set(messageId, info);
215
+ while (byMessageId.size > 128) {
216
+ const oldest = byMessageId.keys().next().value;
217
+ if (oldest === undefined)
218
+ break;
219
+ byMessageId.delete(oldest);
220
+ }
221
+ },
222
+ take(messageId) {
223
+ return byMessageId.get(messageId);
224
+ },
225
+ };
226
+ }
@@ -3,6 +3,7 @@ import type { Agent } from '@deepseek-ai/dsh-agent';
3
3
  import { type UserMessage } from '@deepseek-ai/dsh-llm';
4
4
  import { type ComposerImages } from './composer-images.js';
5
5
  import type { ChannelOwner } from './owner.js';
6
+ import type { ChannelSelection, SelectionAttachment } from '../../adapter/ports/channel-view.js';
6
7
  import type { ChannelImageBlock, ChannelState, ComposerImageRef, MentionAttachments, MentionFs, PendingMessage, StagedImageInput } from './types.js';
7
8
  /** One submission's enqueue-time world: the session it was typed in, the
8
9
  * services that resolve its references, and the capabilities live then. */
@@ -14,6 +15,10 @@ interface UserTextOrigin {
14
15
  readonly fs: MentionFs | undefined;
15
16
  readonly attachments: MentionAttachments | undefined;
16
17
  readonly stagedImages: ReadonlyMap<string, ChannelImageBlock['attachment']>;
18
+ /** Live editor selection AT ENQUEUE (undefined = none). Captured here so a
19
+ * selection made while the FIFO or mention expansion parks the delivery
20
+ * can never attach to this message. */
21
+ readonly selection: ChannelSelection | undefined;
17
22
  }
18
23
  /** Input FIFO, staged attachments and decision notice timers share one lifetime. */
19
24
  export declare function createInputDelivery(ctx: Context, owner: ChannelOwner, binding: {
@@ -22,7 +27,7 @@ export declare function createInputDelivery(ctx: Context, owner: ChannelOwner, b
22
27
  id: string;
23
28
  text: string;
24
29
  images?: readonly ComposerImageRef[];
25
- }, placement: PendingMessage['placement']) => void, untrackPending: (id: string) => void, composer: ComposerImages): {
30
+ }, placement: PendingMessage['placement']) => void, untrackPending: (id: string) => void, composer: ComposerImages, selection: () => ChannelSelection | undefined, rememberSelection: (messageId: string, info: SelectionAttachment) => void): {
26
31
  dispatchUserText: (text: string, placement: PendingMessage["placement"], images?: readonly ComposerImageRef[], attach?: UserMessage) => void;
27
32
  deliverUserText: (text: string, placement: PendingMessage["placement"], images?: readonly ComposerImageRef[], attach?: UserMessage) => void;
28
33
  claimAttachments: (messages: readonly UserMessage[]) => UserMessage[];
@@ -1 +1 @@
1
- {"version":3,"file":"input-delivery.d.ts","sourceRoot":"","sources":["../../../../src/dsh-adapter/channel/input-delivery.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAA;AACnD,OAAO,EAAqB,KAAK,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAI1E,OAAO,EAIL,KAAK,cAAc,EACpB,MAAM,sBAAsB,CAAA;AAI7B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAC9C,OAAO,KAAK,EACV,iBAAiB,EACjB,YAAY,EACZ,gBAAgB,EAChB,kBAAkB,EAClB,SAAS,EACT,cAAc,EACd,gBAAgB,EACjB,MAAM,YAAY,CAAA;AAEnB;4EAC4E;AAC5E,UAAU,cAAc;IACtB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,EAAE,SAAS,GAAG,SAAS,CAAA;IAClC,QAAQ,CAAC,WAAW,EAAE,kBAAkB,GAAG,SAAS,CAAA;IACpD,QAAQ,CAAC,YAAY,EAAE,WAAW,CAAC,MAAM,EAAE,iBAAiB,CAAC,YAAY,CAAC,CAAC,CAAA;CAC5E;AAED,oFAAoF;AACpF,wBAAgB,mBAAmB,CAClC,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE;IAAE,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;CAAE,EACrE,KAAK,EAAE,MAAM,IAAI,CAAC,YAAY,EAAE,KAAK,GAAG,SAAS,GAAG,wBAAwB,CAAC,EAC7E,MAAM,EAAE,YAAY,CAAC,QAAQ,CAAC,EAC9B,YAAY,EAAE,CAAC,OAAO,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,SAAS,gBAAgB,EAAE,CAAA;CAAE,EAAE,SAAS,EAAE,cAAc,CAAC,WAAW,CAAC,KAAK,IAAI,EAC3I,cAAc,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,EACpC,QAAQ,EAAE,cAAc;6BA4Qf,MAAM,aACD,cAAc,CAAC,WAAW,CAAC,WAC9B,SAAS,gBAAgB,EAAE,WAC1B,WAAW,KACnB,IAAI;4BAcC,MAAM,aACD,cAAc,CAAC,WAAW,CAAC,WAC9B,SAAS,gBAAgB,EAAE,WAC1B,WAAW,KACnB,IAAI;iCA5Q6B,SAAS,WAAW,EAAE,KAAG,WAAW,EAAE;kCAarC,MAAM,KAAG,IAAI;0BAiIrB,CAAC,QAAQ,MAAM,WAAW,OAAO,CAAC,CAAC,CAAC,WAAW,cAAc,KAAG,OAAO,CAAC,CAAC,CAAC;6BAkIzE,IAAI;wBAaZ,gBAAgB,KAAG,OAAO,CAAC,MAAM,CAAC;wBACpC,WAAW,CAAC,MAAM,EAAE,iBAAiB,CAAC,YAAY,CAAC,CAAC;;EAGzE"}
1
+ {"version":3,"file":"input-delivery.d.ts","sourceRoot":"","sources":["../../../../src/dsh-adapter/channel/input-delivery.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAA;AACnD,OAAO,EAAqB,KAAK,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAI1E,OAAO,EAIL,KAAK,cAAc,EACpB,MAAM,sBAAsB,CAAA;AAK7B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAC9C,OAAO,KAAK,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAA;AAChG,OAAO,KAAK,EACV,iBAAiB,EACjB,YAAY,EACZ,gBAAgB,EAChB,kBAAkB,EAClB,SAAS,EACT,cAAc,EACd,gBAAgB,EACjB,MAAM,YAAY,CAAA;AAEnB;4EAC4E;AAC5E,UAAU,cAAc;IACtB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,EAAE,SAAS,GAAG,SAAS,CAAA;IAClC,QAAQ,CAAC,WAAW,EAAE,kBAAkB,GAAG,SAAS,CAAA;IACpD,QAAQ,CAAC,YAAY,EAAE,WAAW,CAAC,MAAM,EAAE,iBAAiB,CAAC,YAAY,CAAC,CAAC,CAAA;IAC3E;;4CAEwC;IACxC,QAAQ,CAAC,SAAS,EAAE,gBAAgB,GAAG,SAAS,CAAA;CACjD;AAED,oFAAoF;AACpF,wBAAgB,mBAAmB,CAClC,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE;IAAE,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;CAAE,EACrE,KAAK,EAAE,MAAM,IAAI,CAAC,YAAY,EAAE,KAAK,GAAG,SAAS,GAAG,wBAAwB,CAAC,EAC7E,MAAM,EAAE,YAAY,CAAC,QAAQ,CAAC,EAC9B,YAAY,EAAE,CAAC,OAAO,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,SAAS,gBAAgB,EAAE,CAAA;CAAE,EAAE,SAAS,EAAE,cAAc,CAAC,WAAW,CAAC,KAAK,IAAI,EAC3I,cAAc,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,EACpC,QAAQ,EAAE,cAAc,EACxB,SAAS,EAAE,MAAM,gBAAgB,GAAG,SAAS,EAC7C,iBAAiB,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,mBAAmB,KAAK,IAAI;6BAkRhE,MAAM,aACD,cAAc,CAAC,WAAW,CAAC,WAC9B,SAAS,gBAAgB,EAAE,WAC1B,WAAW,KACnB,IAAI;4BAcC,MAAM,aACD,cAAc,CAAC,WAAW,CAAC,WAC9B,SAAS,gBAAgB,EAAE,WAC1B,WAAW,KACnB,IAAI;iCAlR6B,SAAS,WAAW,EAAE,KAAG,WAAW,EAAE;kCAarC,MAAM,KAAG,IAAI;0BAuIrB,CAAC,QAAQ,MAAM,WAAW,OAAO,CAAC,CAAC,CAAC,WAAW,cAAc,KAAG,OAAO,CAAC,CAAC,CAAC;6BAkIzE,IAAI;wBAaZ,gBAAgB,KAAG,OAAO,CAAC,MAAM,CAAC;wBACpC,WAAW,CAAC,MAAM,EAAE,iBAAiB,CAAC,YAAY,CAAC,CAAC;;EAGzE"}
@@ -5,9 +5,10 @@ import { dispatchTuiDecision } from '../extension-events.js';
5
5
  import { firstStaleComposerToken, formatMissingReference, orderedComposerImages, } from './composer-images.js';
6
6
  import { expandComposerMentions } from './composer-mentions.js';
7
7
  import { normalizeInputDecision } from './decisions.js';
8
+ import { attachIdeSelection } from './ide-selection.js';
8
9
  import { mentionAttachments, mentionFs } from './mentions.js';
9
10
  /** Input FIFO, staged attachments and decision notice timers share one lifetime. */
10
- export function createInputDelivery(ctx, owner, binding, state, notify, trackPending, untrackPending, composer) {
11
+ export function createInputDelivery(ctx, owner, binding, state, notify, trackPending, untrackPending, composer, selection, rememberSelection) {
11
12
  /**
12
13
  * `@` file mentions (issue #15): expansion reads files asynchronously, so
13
14
  * every user-text delivery (submit / steer / interrupt-requeue) funnels
@@ -82,6 +83,7 @@ export function createInputDelivery(ctx, owner, binding, state, notify, trackPen
82
83
  fs: mentionFs(ctx),
83
84
  attachments: mentionAttachments(ctx),
84
85
  stagedImages: composer.snapshot(),
86
+ selection: selection(),
85
87
  });
86
88
  /**
87
89
  * Expand the text's `@` mentions and deliver ONE user message: the typed
@@ -107,10 +109,16 @@ export function createInputDelivery(ctx, owner, binding, state, notify, trackPen
107
109
  notify(t('ext-stale-dropped'), { color: 'warning', timeoutMs: 4000 });
108
110
  return;
109
111
  }
112
+ // IDE selection consumption: append the ENQUEUE-time selection as its own
113
+ // attached-file block — direct construction, never text parsing, failures
114
+ // silently skipped (an IDE-side extra must never block a send).
115
+ const selectionAttached = await attachIdeSelection(expansion.blocks, origin.cwd, origin.selection, origin.fs);
110
116
  const message = createUserMessage({
111
117
  content: expansion.blocks,
112
118
  source: { kind: 'user' },
113
119
  });
120
+ if (selectionAttached !== undefined)
121
+ rememberSelection(message.id, selectionAttached);
114
122
  // The message is real from here on: remember its attached context BEFORE
115
123
  // the agent call so the pre-step listener can find it (D6). A throwing
116
124
  // followup/steer rolls both the pending preview and this entry back.
@@ -1,21 +1,6 @@
1
+ import { type ForegroundShell } from '../compat/shell.js';
1
2
  import { type foldBack as FoldBack } from './transcript.js';
2
3
  import type { ChannelState, ToolViewPresenter } from './types.js';
3
- type Shell = {
4
- resolve(request: {
5
- command: string;
6
- workdir?: string;
7
- timeoutMs: number;
8
- }): unknown;
9
- run(spec: unknown): Promise<{
10
- stdout: {
11
- text: string;
12
- };
13
- stderr: {
14
- text: string;
15
- };
16
- timedOut: boolean;
17
- }>;
18
- };
19
4
  /** Owns local-only transcript mutations, shell output, and live subagent queries. */
20
5
  export declare function createLocalActions(deps: {
21
6
  ctx: {
@@ -54,9 +39,9 @@ export declare function createLocalActions(deps: {
54
39
  badge: string;
55
40
  label: string;
56
41
  };
57
- commandShell(cwd: string): Promise<Shell | undefined>;
42
+ commandShell(cwd: string): Promise<ForegroundShell | undefined>;
58
43
  };
59
- shell?: Shell;
44
+ shell?: ForegroundShell;
60
45
  notify: ChannelState['notify'];
61
46
  }): {
62
47
  loadOlder(): number;
@@ -66,5 +51,4 @@ export declare function createLocalActions(deps: {
66
51
  listSubagents(): Promise<string[]>;
67
52
  runLocalCommand(command: string, includeInContext: boolean): Promise<void>;
68
53
  };
69
- export {};
70
54
  //# sourceMappingURL=local-actions.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"local-actions.d.ts","sourceRoot":"","sources":["../../../../src/dsh-adapter/channel/local-actions.ts"],"names":[],"mappings":"AAOA,OAAO,EAA+B,KAAK,QAAQ,IAAI,QAAQ,EAAE,MAAM,iBAAiB,CAAA;AACxF,OAAO,KAAK,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAEjE,KAAK,KAAK,GAAG;IACX,OAAO,CAAC,OAAO,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAA;IACnF,GAAG,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE;YAAE,IAAI,EAAE,MAAM,CAAA;SAAE,CAAC;QAAC,MAAM,EAAE;YAAE,IAAI,EAAE,MAAM,CAAA;SAAE,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAA;KAAE,CAAC,CAAA;CACvG,CAAA;AAED,qFAAqF;AACrF,wBAAgB,kBAAkB,CAAC,IAAI,EAAE;IACvC,GAAG,EAAE;QAAE,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAA;IACnC,KAAK,EAAE;QAAE,OAAO,IAAI,OAAO,CAAA;KAAE,CAAA;IAC7B,OAAO,EAAE;QACP,OAAO,IAAI,OAAO,CAAA;QAClB,SAAS,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAA;QACpC,QAAQ,CAAC,KAAK,EAAE;YAAE,OAAO,EAAE,OAAO,CAAC;YAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAA;SAAE,CAAA;KACvE,CAAA;IACD,KAAK,EAAE,YAAY,CAAA;IACnB,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;IACzB,SAAS,EAAE;QAAE,KAAK,IAAI,IAAI,CAAC;QAAC,eAAe,EAAE,WAAW,CAAC,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC;QAAC,iBAAiB,EAAE,WAAW,CAAC,iBAAiB,CAAC,CAAC,QAAQ,CAAC,CAAA;KAAE,CAAA;IAClJ,SAAS,EAAE;QAAE,QAAQ,IAAI,IAAI,CAAA;KAAE,CAAA;IAC/B,IAAI,EAAE;QAAE,QAAQ,IAAI,IAAI,CAAA;KAAE,CAAA;IAC1B,QAAQ,EAAE,OAAO,QAAQ,CAAA;IACzB,SAAS,EAAE;QAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,CAAC;QAAC,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,GAAG,SAAS,CAAC,CAAA;KAAE,CAAA;IAC3I,KAAK,CAAC,EAAE,KAAK,CAAA;IACb,MAAM,EAAE,YAAY,CAAC,QAAQ,CAAC,CAAA;CAC/B;iBAIgB,MAAM;aAKV,IAAI;qBAYI,MAAM,SAAS,SAAS,MAAM,EAAE,GAAG,IAAI;4BAKhC,MAAM,GAAG,OAAO;qBAajB,OAAO,CAAC,MAAM,EAAE,CAAC;6BAmBT,MAAM,oBAAoB,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;EAqBnF"}
1
+ {"version":3,"file":"local-actions.d.ts","sourceRoot":"","sources":["../../../../src/dsh-adapter/channel/local-actions.ts"],"names":[],"mappings":"AAOA,OAAO,EAAsB,KAAK,eAAe,EAAE,MAAM,oBAAoB,CAAA;AAC7E,OAAO,EAA+B,KAAK,QAAQ,IAAI,QAAQ,EAAE,MAAM,iBAAiB,CAAA;AACxF,OAAO,KAAK,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAEjE,qFAAqF;AACrF,wBAAgB,kBAAkB,CAAC,IAAI,EAAE;IACvC,GAAG,EAAE;QAAE,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAA;IACnC,KAAK,EAAE;QAAE,OAAO,IAAI,OAAO,CAAA;KAAE,CAAA;IAC7B,OAAO,EAAE;QACP,OAAO,IAAI,OAAO,CAAA;QAClB,SAAS,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAA;QACpC,QAAQ,CAAC,KAAK,EAAE;YAAE,OAAO,EAAE,OAAO,CAAC;YAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAA;SAAE,CAAA;KACvE,CAAA;IACD,KAAK,EAAE,YAAY,CAAA;IACnB,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;IACzB,SAAS,EAAE;QAAE,KAAK,IAAI,IAAI,CAAC;QAAC,eAAe,EAAE,WAAW,CAAC,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC;QAAC,iBAAiB,EAAE,WAAW,CAAC,iBAAiB,CAAC,CAAC,QAAQ,CAAC,CAAA;KAAE,CAAA;IAClJ,SAAS,EAAE;QAAE,QAAQ,IAAI,IAAI,CAAA;KAAE,CAAA;IAC/B,IAAI,EAAE;QAAE,QAAQ,IAAI,IAAI,CAAA;KAAE,CAAA;IAC1B,QAAQ,EAAE,OAAO,QAAQ,CAAA;IACzB,SAAS,EAAE;QAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,CAAC;QAAC,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,SAAS,CAAC,CAAA;KAAE,CAAA;IACrJ,KAAK,CAAC,EAAE,eAAe,CAAA;IACvB,MAAM,EAAE,YAAY,CAAC,QAAQ,CAAC,CAAA;CAC/B;iBAIgB,MAAM;aAKV,IAAI;qBAYI,MAAM,SAAS,SAAS,MAAM,EAAE,GAAG,IAAI;4BAKhC,MAAM,GAAG,OAAO;qBAajB,OAAO,CAAC,MAAM,EAAE,CAAC;6BAmBT,MAAM,oBAAoB,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;EAqBnF"}
@@ -4,6 +4,7 @@ import { writeActivityFrames } from '../../activityPrefs.js';
4
4
  import { isPresetName, normalizeActivityPreset } from '../../components/activityFrames.js';
5
5
  import { t } from '../../i18n.js';
6
6
  import { snapshotLiveSessionEvents } from '../compat/liveSession.js';
7
+ import { runForegroundShell } from '../compat/shell.js';
7
8
  import { LOCAL_OUTPUT_LIMIT, preview } from './transcript.js';
8
9
  /** Owns local-only transcript mutations, shell output, and live subagent queries. */
9
10
  export function createLocalActions(deps) {
@@ -90,7 +91,7 @@ export function createLocalActions(deps) {
90
91
  return;
91
92
  if (executor) {
92
93
  try {
93
- const result = await executor.run(executor.resolve({ command, workdir: cwd, timeoutMs: 30000 }));
94
+ const result = await runForegroundShell(executor, { command, workdir: cwd, timeoutMs: 30000 });
94
95
  output = result.stdout.text.trim() || result.stderr.text.trim() || (result.timedOut ? '(timed out)' : '(no output)');
95
96
  }
96
97
  catch (error) {
@@ -11,13 +11,16 @@ type Binding = ReturnType<typeof createChannelBinding>;
11
11
  * This owns the async catalog caches and their generation fences; callers only
12
12
  * compose its surface into ChannelState after the state has been constructed.
13
13
  */
14
- export declare function createModelActions(ctx: Context, state: Pick<ChannelState, 'provider' | 'model' | 'reasoningEffort' | 'effortLevels' | 'agentPreset' | 'working' | 'emit'>, deps: {
14
+ export declare function createModelActions(ctx: Context, state: Pick<ChannelState, 'provider' | 'model' | 'reasoningEffort' | 'effortLevels' | 'agentPreset' | 'working' | 'contextWindow' | 'emit'>, deps: {
15
15
  owner: Pick<ChannelOwner, 'current'>;
16
16
  binding: Pick<Binding, 'capture' | 'isCurrent'>;
17
17
  selection: ModelSelectionRef;
18
18
  initialEffort?: string;
19
19
  agent(): Agent;
20
20
  notify: ChannelState['notify'];
21
+ /** Re-check the context-low warning after a refreshed route metadata
22
+ * answer carries a newer contextWindow than the session started with. */
23
+ checkContextWarning(): void;
21
24
  }): {
22
25
  selection: ModelSelectionRef;
23
26
  applyPreferredEffort: () => Promise<void>;
@@ -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 [];
@@ -5,7 +5,7 @@ import type { ChannelOwner } from './owner.js';
5
5
  import { resetSessionProjection } from './session-reset.js';
6
6
  import type { ChannelState } from './types.js';
7
7
  type Binding = ReturnType<typeof createChannelBinding>;
8
- type SwitchState = Parameters<typeof resetSessionProjection>[0] & Pick<ChannelState, 'cwd' | 'working' | 'status' | 'agentId' | 'agentPreset' | 'provider' | 'model' | 'contextWindow' | 'effortLevels' | 'reasoningEffort' | 'emit'>;
8
+ type SwitchState = Parameters<typeof resetSessionProjection>[0] & Pick<ChannelState, 'cwd' | 'working' | 'status' | 'agentId' | 'sessionId' | 'agentPreset' | 'provider' | 'model' | 'contextWindow' | 'effortLevels' | 'reasoningEffort' | 'emit'>;
9
9
  /** Model-route adoption transaction. It settles compaction before its fork snapshot and owns the post-commit reset. */
10
10
  export declare function createModelSwitchAction(ctx: Context, state: SwitchState, deps: {
11
11
  owner: Pick<ChannelOwner, 'current'>;
@@ -25,7 +25,6 @@ export declare function createModelSwitchAction(ctx: Context, state: SwitchState
25
25
  refreshSkillCommands(): Promise<void>;
26
26
  clearStagedImages(): void;
27
27
  dropModelCompletion(): void;
28
- onModelSwitch(model: string): void;
29
28
  notify: ChannelState['notify'];
30
29
  }): (provider: string, model: string) => Promise<boolean>;
31
30
  export {};
@@ -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,WAAW,GAAG,aAAa,GAAG,UAAU,GAAG,OAAO,GAAG,eAAe,GAAG,cAAc,GAAG,iBAAiB,GAAG,MAAM,CAAC,CAAA;AAEhK,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,MAAM,EAAE,YAAY,CAAC,QAAQ,CAAC,CAAA;CAC/B,IAEa,UAAU,MAAM,EAAE,OAAO,MAAM,KAAG,OAAO,CAAC,OAAO,CAAC,CA4EjE"}