@deepseek-harness-tui/dsh-tui 0.6.1 → 0.7.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 (379) hide show
  1. package/README.md +74 -21
  2. package/bin/dsh-tui.js +115 -25
  3. package/cordis.patch.yml +69 -17
  4. package/cordis.yml +50 -12
  5. package/lib/types/activityPrefs.d.ts +1 -1
  6. package/lib/types/activityPrefs.js +3 -3
  7. package/lib/types/cc/figures.d.ts +27 -20
  8. package/lib/types/cc/figures.d.ts.map +1 -1
  9. package/lib/types/cc/figures.js +43 -34
  10. package/lib/types/cc/format.d.ts +18 -9
  11. package/lib/types/cc/format.d.ts.map +1 -1
  12. package/lib/types/cc/format.js +26 -18
  13. package/lib/types/cc/markdown.d.ts +31 -16
  14. package/lib/types/cc/markdown.d.ts.map +1 -1
  15. package/lib/types/cc/markdown.js +283 -260
  16. package/lib/types/cc/terminal.d.ts +10 -7
  17. package/lib/types/cc/terminal.d.ts.map +1 -1
  18. package/lib/types/cc/terminal.js +62 -50
  19. package/lib/types/command-trees.d.ts +3 -0
  20. package/lib/types/command-trees.d.ts.map +1 -0
  21. package/lib/types/command-trees.js +4 -0
  22. package/lib/types/commands.d.ts +37 -1
  23. package/lib/types/commands.d.ts.map +1 -1
  24. package/lib/types/commands.js +68 -3
  25. package/lib/types/components/ActivityLine.d.ts +1 -1
  26. package/lib/types/components/ActivityLine.d.ts.map +1 -1
  27. package/lib/types/components/ActivityPicker.d.ts.map +1 -1
  28. package/lib/types/components/ActivityPicker.js +3 -4
  29. package/lib/types/components/BtwPanel.d.ts +16 -0
  30. package/lib/types/components/BtwPanel.d.ts.map +1 -0
  31. package/lib/types/components/BtwPanel.js +47 -0
  32. package/lib/types/components/CommandSuggestions.d.ts +4 -2
  33. package/lib/types/components/CommandSuggestions.d.ts.map +1 -1
  34. package/lib/types/components/CommandSuggestions.js +2 -2
  35. package/lib/types/components/EffortSlider.d.ts +15 -0
  36. package/lib/types/components/EffortSlider.d.ts.map +1 -0
  37. package/lib/types/components/EffortSlider.js +17 -0
  38. package/lib/types/components/GoalTodoPanel.d.ts +1 -1
  39. package/lib/types/components/GoalTodoPanel.d.ts.map +1 -1
  40. package/lib/types/components/HelpMenu.d.ts +5 -2
  41. package/lib/types/components/HelpMenu.d.ts.map +1 -1
  42. package/lib/types/components/HelpMenu.js +8 -3
  43. package/lib/types/components/HistorySearchDialog.d.ts +1 -1
  44. package/lib/types/components/HistorySearchDialog.d.ts.map +1 -1
  45. package/lib/types/components/HistorySearchDialog.js +21 -10
  46. package/lib/types/components/InterruptedByUser.d.ts +2 -2
  47. package/lib/types/components/InterruptedByUser.d.ts.map +1 -1
  48. package/lib/types/components/InterruptedByUser.js +4 -3
  49. package/lib/types/components/LoadedContextPanel.d.ts +1 -1
  50. package/lib/types/components/LoadedContextPanel.d.ts.map +1 -1
  51. package/lib/types/components/LogoV2.d.ts.map +1 -1
  52. package/lib/types/components/LogoV2.js +2 -1
  53. package/lib/types/components/Markdown.d.ts +11 -11
  54. package/lib/types/components/Markdown.d.ts.map +1 -1
  55. package/lib/types/components/Markdown.js +63 -57
  56. package/lib/types/components/MarkdownTable.d.ts +1 -1
  57. package/lib/types/components/MarkdownTable.js +2 -2
  58. package/lib/types/components/MessageList.d.ts +10 -2
  59. package/lib/types/components/MessageList.d.ts.map +1 -1
  60. package/lib/types/components/MessageList.js +17 -10
  61. package/lib/types/components/ModelPicker.d.ts +4 -1
  62. package/lib/types/components/ModelPicker.d.ts.map +1 -1
  63. package/lib/types/components/ModelPicker.js +16 -4
  64. package/lib/types/components/OverlayAbove.d.ts +20 -0
  65. package/lib/types/components/OverlayAbove.d.ts.map +1 -0
  66. package/lib/types/components/OverlayAbove.js +18 -0
  67. package/lib/types/components/PresetPicker.d.ts +1 -1
  68. package/lib/types/components/PresetPicker.d.ts.map +1 -1
  69. package/lib/types/components/PresetPicker.js +2 -3
  70. package/lib/types/components/PromptInput.d.ts +5 -4
  71. package/lib/types/components/PromptInput.d.ts.map +1 -1
  72. package/lib/types/components/PromptInput.js +186 -39
  73. package/lib/types/components/ResumePicker.d.ts +15 -4
  74. package/lib/types/components/ResumePicker.d.ts.map +1 -1
  75. package/lib/types/components/ResumePicker.js +25 -9
  76. package/lib/types/components/RewindPicker.d.ts +1 -1
  77. package/lib/types/components/RewindPicker.d.ts.map +1 -1
  78. package/lib/types/components/RewindPicker.js +14 -5
  79. package/lib/types/components/SearchBox.d.ts +1 -1
  80. package/lib/types/components/SearchBox.js +1 -1
  81. package/lib/types/components/Spinner/GlimmerMessage.d.ts +1 -2
  82. package/lib/types/components/Spinner/GlimmerMessage.d.ts.map +1 -1
  83. package/lib/types/components/Spinner/GlimmerMessage.js +1 -2
  84. package/lib/types/components/Spinner/SpinnerAnimationRow.d.ts +1 -1
  85. package/lib/types/components/Spinner/SpinnerAnimationRow.js +2 -2
  86. package/lib/types/components/Spinner/SpinnerGlyph.d.ts +1 -1
  87. package/lib/types/components/Spinner/SpinnerGlyph.js +1 -1
  88. package/lib/types/components/Spinner/spinnerUtils.d.ts +13 -18
  89. package/lib/types/components/Spinner/spinnerUtils.d.ts.map +1 -1
  90. package/lib/types/components/Spinner/spinnerUtils.js +67 -71
  91. package/lib/types/components/Spinner/useStalledAnimation.d.ts +1 -2
  92. package/lib/types/components/Spinner/useStalledAnimation.d.ts.map +1 -1
  93. package/lib/types/components/Spinner/useStalledAnimation.js +1 -2
  94. package/lib/types/components/StreamingMarkdown.d.ts +1 -1
  95. package/lib/types/components/StreamingMarkdown.js +1 -1
  96. package/lib/types/components/ThemePicker.d.ts +13 -9
  97. package/lib/types/components/ThemePicker.d.ts.map +1 -1
  98. package/lib/types/components/ThemePicker.js +21 -15
  99. package/lib/types/components/ThinkingToggle.d.ts +1 -1
  100. package/lib/types/components/ThinkingToggle.d.ts.map +1 -1
  101. package/lib/types/components/ThinkingToggle.js +8 -8
  102. package/lib/types/components/ToolUseLoader.d.ts +1 -1
  103. package/lib/types/components/ToolUseLoader.js +1 -1
  104. package/lib/types/components/WorkingSpinner.d.ts +2 -2
  105. package/lib/types/components/WorkingSpinner.js +2 -2
  106. package/lib/types/components/WorkspaceFlowPicker.d.ts +15 -0
  107. package/lib/types/components/WorkspaceFlowPicker.d.ts.map +1 -0
  108. package/lib/types/components/WorkspaceFlowPicker.js +19 -0
  109. package/lib/types/components/WorkspacePicker.d.ts +9 -0
  110. package/lib/types/components/WorkspacePicker.d.ts.map +1 -0
  111. package/lib/types/components/WorkspacePicker.js +13 -0
  112. package/lib/types/components/approvals/ApprovalPanel.d.ts +1 -1
  113. package/lib/types/components/approvals/ApprovalPanel.d.ts.map +1 -1
  114. package/lib/types/components/approvals/ApprovalPanel.js +2 -1
  115. package/lib/types/components/design-system/Byline.d.ts +1 -1
  116. package/lib/types/components/design-system/Byline.js +1 -1
  117. package/lib/types/components/design-system/Divider.d.ts +1 -1
  118. package/lib/types/components/design-system/Divider.js +1 -1
  119. package/lib/types/components/design-system/HintLine.d.ts +12 -0
  120. package/lib/types/components/design-system/HintLine.d.ts.map +1 -0
  121. package/lib/types/components/design-system/HintLine.js +15 -0
  122. package/lib/types/components/design-system/KeyboardShortcutHint.d.ts +1 -1
  123. package/lib/types/components/design-system/KeyboardShortcutHint.js +1 -1
  124. package/lib/types/components/design-system/ListItem.d.ts +2 -2
  125. package/lib/types/components/design-system/ListItem.d.ts.map +1 -1
  126. package/lib/types/components/design-system/ListItem.js +35 -3
  127. package/lib/types/components/design-system/LoadingState.d.ts +1 -2
  128. package/lib/types/components/design-system/LoadingState.d.ts.map +1 -1
  129. package/lib/types/components/design-system/LoadingState.js +1 -2
  130. package/lib/types/components/design-system/Pane.d.ts +2 -2
  131. package/lib/types/components/design-system/Pane.js +2 -2
  132. package/lib/types/components/design-system/ProgressBar.d.ts +1 -2
  133. package/lib/types/components/design-system/ProgressBar.d.ts.map +1 -1
  134. package/lib/types/components/design-system/ProgressBar.js +1 -2
  135. package/lib/types/components/design-system/StatusIcon.d.ts +2 -2
  136. package/lib/types/components/design-system/StatusIcon.js +2 -2
  137. package/lib/types/components/design-system/ThemeProvider.d.ts +1 -1
  138. package/lib/types/components/design-system/ThemeProvider.d.ts.map +1 -1
  139. package/lib/types/components/design-system/ThemeProvider.js +87 -26
  140. package/lib/types/components/design-system/ThemedBox.d.ts +1 -1
  141. package/lib/types/components/design-system/ThemedBox.js +1 -1
  142. package/lib/types/components/design-system/ThemedText.d.ts +2 -2
  143. package/lib/types/components/design-system/ThemedText.js +2 -2
  144. package/lib/types/components/listWindow.d.ts +26 -0
  145. package/lib/types/components/listWindow.d.ts.map +1 -0
  146. package/lib/types/components/listWindow.js +47 -0
  147. package/lib/types/components/messages/AssistantTextMessage.d.ts +1 -2
  148. package/lib/types/components/messages/AssistantTextMessage.d.ts.map +1 -1
  149. package/lib/types/components/messages/AssistantTextMessage.js +1 -2
  150. package/lib/types/components/messages/AssistantThinkingMessage.d.ts +2 -2
  151. package/lib/types/components/messages/AssistantThinkingMessage.d.ts.map +1 -1
  152. package/lib/types/components/messages/AssistantThinkingMessage.js +6 -6
  153. package/lib/types/components/messages/AssistantToolUseMessage.d.ts +12 -4
  154. package/lib/types/components/messages/AssistantToolUseMessage.d.ts.map +1 -1
  155. package/lib/types/components/messages/AssistantToolUseMessage.js +9 -5
  156. package/lib/types/components/messages/MessageMetadata.d.ts +1 -1
  157. package/lib/types/components/messages/MessageMetadata.js +1 -1
  158. package/lib/types/components/messages/UserPromptMessage.d.ts +1 -1
  159. package/lib/types/components/messages/UserPromptMessage.js +1 -1
  160. package/lib/types/components/questions/AskUserQuestionPanel.d.ts +5 -1
  161. package/lib/types/components/questions/AskUserQuestionPanel.d.ts.map +1 -1
  162. package/lib/types/components/questions/AskUserQuestionPanel.js +11 -9
  163. package/lib/types/components/questions/PlanReviewPanel.d.ts +1 -1
  164. package/lib/types/components/questions/PlanReviewPanel.d.ts.map +1 -1
  165. package/lib/types/components/questions/PlanReviewPanel.js +3 -2
  166. package/lib/types/components/trajectory/HotspotView.d.ts +14 -0
  167. package/lib/types/components/trajectory/HotspotView.d.ts.map +1 -0
  168. package/lib/types/components/trajectory/HotspotView.js +83 -0
  169. package/lib/types/components/trajectory/Inspector.d.ts +31 -0
  170. package/lib/types/components/trajectory/Inspector.d.ts.map +1 -0
  171. package/lib/types/components/trajectory/Inspector.js +67 -0
  172. package/lib/types/components/trajectory/Ledger.d.ts +20 -0
  173. package/lib/types/components/trajectory/Ledger.d.ts.map +1 -0
  174. package/lib/types/components/trajectory/Ledger.js +112 -0
  175. package/lib/types/components/trajectory/MiniWake.d.ts +24 -0
  176. package/lib/types/components/trajectory/MiniWake.d.ts.map +1 -0
  177. package/lib/types/components/trajectory/MiniWake.js +99 -0
  178. package/lib/types/components/trajectory/WaveBand.d.ts +33 -0
  179. package/lib/types/components/trajectory/WaveBand.d.ts.map +1 -0
  180. package/lib/types/components/trajectory/WaveBand.js +145 -0
  181. package/lib/types/customTheme.d.ts +6 -6
  182. package/lib/types/customTheme.d.ts.map +1 -1
  183. package/lib/types/customTheme.js +15 -12
  184. package/lib/types/dsh-adapter/approvals.d.ts.map +1 -0
  185. package/lib/types/{channel.d.ts → dsh-adapter/channel.d.ts} +184 -43
  186. package/lib/types/dsh-adapter/channel.d.ts.map +1 -0
  187. package/lib/types/{channel.js → dsh-adapter/channel.js} +972 -201
  188. package/lib/types/dsh-adapter/childStderr.d.ts.map +1 -0
  189. package/lib/types/{childStderr.js → dsh-adapter/childStderr.js} +1 -1
  190. package/lib/types/dsh-adapter/command-trees.d.ts +27 -0
  191. package/lib/types/dsh-adapter/command-trees.d.ts.map +1 -0
  192. package/lib/types/dsh-adapter/command-trees.js +42 -0
  193. package/lib/types/dsh-adapter/compat/index.d.ts +22 -0
  194. package/lib/types/dsh-adapter/compat/index.d.ts.map +1 -0
  195. package/lib/types/{compat → dsh-adapter/compat}/index.js +7 -4
  196. package/lib/types/dsh-adapter/compat/sessionLog.d.ts +86 -0
  197. package/lib/types/dsh-adapter/compat/sessionLog.d.ts.map +1 -0
  198. package/lib/types/dsh-adapter/compat/sessionLog.js +347 -0
  199. package/lib/types/dsh-adapter/contract.d.ts +20 -0
  200. package/lib/types/dsh-adapter/contract.d.ts.map +1 -0
  201. package/lib/types/dsh-adapter/contract.js +109 -0
  202. package/lib/types/dsh-adapter/index.d.ts +80 -0
  203. package/lib/types/dsh-adapter/index.d.ts.map +1 -0
  204. package/lib/types/dsh-adapter/index.js +45 -0
  205. package/lib/types/dsh-adapter/invariant.d.ts.map +1 -0
  206. package/lib/types/dsh-adapter/packaged-skills.d.ts.map +1 -0
  207. package/lib/types/{plugin.d.ts → dsh-adapter/plugin.d.ts} +17 -0
  208. package/lib/types/dsh-adapter/plugin.d.ts.map +1 -0
  209. package/lib/types/{plugin.js → dsh-adapter/plugin.js} +280 -80
  210. package/lib/types/dsh-adapter/presets.d.ts.map +1 -0
  211. package/lib/types/dsh-adapter/providerWizard.d.ts +91 -0
  212. package/lib/types/dsh-adapter/providerWizard.d.ts.map +1 -0
  213. package/lib/types/dsh-adapter/providerWizard.js +332 -0
  214. package/lib/types/{questions.d.ts → dsh-adapter/questions.d.ts} +7 -2
  215. package/lib/types/dsh-adapter/questions.d.ts.map +1 -0
  216. package/lib/types/{questions.js → dsh-adapter/questions.js} +15 -7
  217. package/lib/types/dsh-adapter/sideQuestion.d.ts +38 -0
  218. package/lib/types/dsh-adapter/sideQuestion.d.ts.map +1 -0
  219. package/lib/types/dsh-adapter/sideQuestion.js +69 -0
  220. package/lib/types/dsh-adapter/trajectory/aggregate.d.ts +46 -0
  221. package/lib/types/dsh-adapter/trajectory/aggregate.d.ts.map +1 -0
  222. package/lib/types/dsh-adapter/trajectory/aggregate.js +207 -0
  223. package/lib/types/dsh-adapter/trajectory/guards.d.ts +177 -0
  224. package/lib/types/dsh-adapter/trajectory/guards.d.ts.map +1 -0
  225. package/lib/types/dsh-adapter/trajectory/guards.js +235 -0
  226. package/lib/types/dsh-adapter/trajectory/index.d.ts +16 -0
  227. package/lib/types/dsh-adapter/trajectory/index.d.ts.map +1 -0
  228. package/lib/types/dsh-adapter/trajectory/index.js +15 -0
  229. package/lib/types/dsh-adapter/trajectory/inspect.d.ts +40 -0
  230. package/lib/types/dsh-adapter/trajectory/inspect.d.ts.map +1 -0
  231. package/lib/types/dsh-adapter/trajectory/inspect.js +160 -0
  232. package/lib/types/dsh-adapter/trajectory/projection.d.ts +128 -0
  233. package/lib/types/dsh-adapter/trajectory/projection.d.ts.map +1 -0
  234. package/lib/types/dsh-adapter/trajectory/projection.js +653 -0
  235. package/lib/types/dsh-adapter/trajectory/types.d.ts +232 -0
  236. package/lib/types/dsh-adapter/trajectory/types.d.ts.map +1 -0
  237. package/lib/types/dsh-adapter/trajectory/types.js +70 -0
  238. package/lib/types/dsh-adapter/trajectory/wave.d.ts +45 -0
  239. package/lib/types/dsh-adapter/trajectory/wave.d.ts.map +1 -0
  240. package/lib/types/dsh-adapter/trajectory/wave.js +210 -0
  241. package/lib/types/dsh-adapter/types.d.ts +23 -0
  242. package/lib/types/dsh-adapter/types.d.ts.map +1 -0
  243. package/lib/types/dsh-adapter/types.js +1 -0
  244. package/lib/types/dsh-adapter/workspace.d.ts +22 -0
  245. package/lib/types/dsh-adapter/workspace.d.ts.map +1 -0
  246. package/lib/types/dsh-adapter/workspace.js +16 -0
  247. package/lib/types/dsh-adapter/workspaces.d.ts +118 -0
  248. package/lib/types/dsh-adapter/workspaces.d.ts.map +1 -0
  249. package/lib/types/dsh-adapter/workspaces.js +290 -0
  250. package/lib/types/effortPrefs.d.ts +1 -1
  251. package/lib/types/effortPrefs.js +3 -3
  252. package/lib/types/history.js +2 -2
  253. package/lib/types/hooks/useBlink.d.ts +1 -1
  254. package/lib/types/hooks/useBlink.js +1 -1
  255. package/lib/types/i18n.d.ts +977 -36
  256. package/lib/types/i18n.d.ts.map +1 -1
  257. package/lib/types/i18n.js +307 -30
  258. package/lib/types/index.d.ts +1 -69
  259. package/lib/types/index.d.ts.map +1 -1
  260. package/lib/types/index.js +3 -31
  261. package/lib/types/ink/components/App.d.ts.map +1 -1
  262. package/lib/types/ink/components/App.js +33 -19
  263. package/lib/types/ink/dom.d.ts +15 -0
  264. package/lib/types/ink/dom.d.ts.map +1 -1
  265. package/lib/types/ink/dom.js +32 -0
  266. package/lib/types/ink/hooks/use-input.d.ts.map +1 -1
  267. package/lib/types/ink/hooks/use-input.js +8 -0
  268. package/lib/types/ink/hooks/use-terminal-size.d.ts +1 -1
  269. package/lib/types/ink/hooks/use-terminal-size.js +1 -1
  270. package/lib/types/ink/ink.d.ts.map +1 -1
  271. package/lib/types/ink/ink.js +109 -28
  272. package/lib/types/ink/input-suppression.d.ts +20 -0
  273. package/lib/types/ink/input-suppression.d.ts.map +1 -0
  274. package/lib/types/ink/input-suppression.js +26 -0
  275. package/lib/types/ink/log-update.js +21 -6
  276. package/lib/types/ink/parse-keypress.d.ts +31 -0
  277. package/lib/types/ink/parse-keypress.d.ts.map +1 -1
  278. package/lib/types/ink/parse-keypress.js +442 -8
  279. package/lib/types/ink/terminal-querier.d.ts +5 -1
  280. package/lib/types/ink/terminal-querier.d.ts.map +1 -1
  281. package/lib/types/ink/terminal-querier.js +27 -3
  282. package/lib/types/ink/terminal.d.ts +18 -0
  283. package/lib/types/ink/terminal.d.ts.map +1 -1
  284. package/lib/types/ink/terminal.js +32 -4
  285. package/lib/types/ink/termio/csi.d.ts +10 -0
  286. package/lib/types/ink/termio/csi.d.ts.map +1 -1
  287. package/lib/types/ink/termio/csi.js +20 -0
  288. package/lib/types/ink/termio/tokenize.js +10 -0
  289. package/lib/types/modelPrefs.d.ts +1 -1
  290. package/lib/types/modelPrefs.js +3 -3
  291. package/lib/types/presetPrefs.d.ts +1 -1
  292. package/lib/types/presetPrefs.js +3 -3
  293. package/lib/types/screens/Chat.d.ts +20 -4
  294. package/lib/types/screens/Chat.d.ts.map +1 -1
  295. package/lib/types/screens/Chat.js +655 -55
  296. package/lib/types/screens/StatusLine.d.ts +17 -2
  297. package/lib/types/screens/StatusLine.d.ts.map +1 -1
  298. package/lib/types/screens/StatusLine.js +12 -4
  299. package/lib/types/screens/TrajectoryScene.d.ts +16 -0
  300. package/lib/types/screens/TrajectoryScene.d.ts.map +1 -0
  301. package/lib/types/screens/TrajectoryScene.js +305 -0
  302. package/lib/types/sessionHistory.d.ts +9 -1
  303. package/lib/types/sessionHistory.d.ts.map +1 -1
  304. package/lib/types/sessionHistory.js +56 -16
  305. package/lib/types/sessionModes.d.ts +29 -0
  306. package/lib/types/sessionModes.d.ts.map +1 -0
  307. package/lib/types/sessionModes.js +45 -0
  308. package/lib/types/theme.d.ts +27 -3
  309. package/lib/types/theme.d.ts.map +1 -1
  310. package/lib/types/theme.js +48 -4
  311. package/lib/types/themePrefs.d.ts +3 -3
  312. package/lib/types/themePrefs.js +5 -5
  313. package/lib/types/trajectory/format.d.ts +100 -0
  314. package/lib/types/trajectory/format.d.ts.map +1 -0
  315. package/lib/types/trajectory/format.js +213 -0
  316. package/lib/types/trajectory/motion.d.ts +99 -0
  317. package/lib/types/trajectory/motion.d.ts.map +1 -0
  318. package/lib/types/trajectory/motion.js +143 -0
  319. package/lib/types/trajectory/query.d.ts +83 -0
  320. package/lib/types/trajectory/query.d.ts.map +1 -0
  321. package/lib/types/trajectory/query.js +187 -0
  322. package/lib/types/trajectoryPrefs.d.ts +36 -0
  323. package/lib/types/trajectoryPrefs.d.ts.map +1 -0
  324. package/lib/types/trajectoryPrefs.js +65 -0
  325. package/lib/types/update.d.ts +3 -3
  326. package/lib/types/update.d.ts.map +1 -1
  327. package/lib/types/update.js +18 -7
  328. package/lib/types/utils/clipboard.d.ts +101 -29
  329. package/lib/types/utils/clipboard.d.ts.map +1 -1
  330. package/lib/types/utils/clipboard.js +533 -55
  331. package/lib/types/utils/debug.d.ts +1 -1
  332. package/lib/types/utils/debug.js +2 -2
  333. package/lib/types/utils/execFileNoThrow.d.ts.map +1 -1
  334. package/lib/types/utils/execFileNoThrow.js +16 -6
  335. package/lib/types/utils/externalEditor.d.ts +115 -0
  336. package/lib/types/utils/externalEditor.d.ts.map +1 -0
  337. package/lib/types/utils/externalEditor.js +270 -0
  338. package/lib/types/utils/fullscreen.d.ts +2 -2
  339. package/lib/types/utils/fullscreen.js +3 -3
  340. package/lib/types/utils/loaded-context.d.ts +1 -1
  341. package/lib/types/utils/loaded-context.d.ts.map +1 -1
  342. package/lib/types/utils/modifiers.d.ts +24 -0
  343. package/lib/types/utils/modifiers.d.ts.map +1 -1
  344. package/lib/types/utils/modifiers.js +27 -0
  345. package/lib/types/utils/paths.d.ts +45 -0
  346. package/lib/types/utils/paths.d.ts.map +1 -0
  347. package/lib/types/utils/paths.js +69 -0
  348. package/lib/types/utils/shellQuote.d.ts +14 -0
  349. package/lib/types/utils/shellQuote.d.ts.map +1 -0
  350. package/lib/types/utils/shellQuote.js +39 -0
  351. package/lib/types/utils/workspaceRoot.d.ts +21 -0
  352. package/lib/types/utils/workspaceRoot.d.ts.map +1 -0
  353. package/lib/types/utils/workspaceRoot.js +47 -0
  354. package/lib/types/workspaces.d.ts +3 -0
  355. package/lib/types/workspaces.d.ts.map +1 -0
  356. package/lib/types/workspaces.js +4 -0
  357. package/package.json +25 -7
  358. package/lib/types/approvals.d.ts.map +0 -1
  359. package/lib/types/channel.d.ts.map +0 -1
  360. package/lib/types/childStderr.d.ts.map +0 -1
  361. package/lib/types/compat/index.d.ts +0 -20
  362. package/lib/types/compat/index.d.ts.map +0 -1
  363. package/lib/types/compat/sessionLog.d.ts +0 -40
  364. package/lib/types/compat/sessionLog.d.ts.map +0 -1
  365. package/lib/types/compat/sessionLog.js +0 -226
  366. package/lib/types/invariant.d.ts.map +0 -1
  367. package/lib/types/packaged-skills.d.ts.map +0 -1
  368. package/lib/types/plugin.d.ts.map +0 -1
  369. package/lib/types/presets.d.ts.map +0 -1
  370. package/lib/types/questions.d.ts.map +0 -1
  371. /package/lib/types/{approvals.d.ts → dsh-adapter/approvals.d.ts} +0 -0
  372. /package/lib/types/{approvals.js → dsh-adapter/approvals.js} +0 -0
  373. /package/lib/types/{childStderr.d.ts → dsh-adapter/childStderr.d.ts} +0 -0
  374. /package/lib/types/{invariant.d.ts → dsh-adapter/invariant.d.ts} +0 -0
  375. /package/lib/types/{invariant.js → dsh-adapter/invariant.js} +0 -0
  376. /package/lib/types/{packaged-skills.d.ts → dsh-adapter/packaged-skills.d.ts} +0 -0
  377. /package/lib/types/{packaged-skills.js → dsh-adapter/packaged-skills.js} +0 -0
  378. /package/lib/types/{presets.d.ts → dsh-adapter/presets.d.ts} +0 -0
  379. /package/lib/types/{presets.js → dsh-adapter/presets.js} +0 -0
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Input suppression window for terminal handoffs (issue #123): when stdin is
3
+ * handed to an external TUI (full-screen editor) and back, the tty can
4
+ * deliver a burst of bytes that are NOT user keystrokes — the editor's
5
+ * rmcup/mode-restore replies, CPR/DECRPM query responses, mouse-event
6
+ * fragments, or keystrokes typed into the canonical line buffer while raw
7
+ * mode was off. Parsed as input they are destructive: a stray ESC reads as
8
+ * the escape key (which CLEARS a non-empty prompt) and the rest lands as
9
+ * text garbage.
10
+ *
11
+ * resumeStdin() drains what is already buffered; this module covers what
12
+ * arrives LATE (terminal replies are async). use-input checks the window at
13
+ * the single choke point every component's input flows through, so no
14
+ * listener (Chat's ctrl+c/esc handling included) sees the burst.
15
+ */
16
+ /** Suppress all parsed input for `ms` from now (monotonic extension). */
17
+ export declare function suppressInputFor(ms: number): void;
18
+ /** True while the post-handoff suppression window is open. */
19
+ export declare function isInputSuppressed(): boolean;
20
+ //# sourceMappingURL=input-suppression.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input-suppression.d.ts","sourceRoot":"","sources":["../../../src/ink/input-suppression.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,yEAAyE;AACzE,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAGjD;AAED,8DAA8D;AAC9D,wBAAgB,iBAAiB,IAAI,OAAO,CAE3C"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Input suppression window for terminal handoffs (issue #123): when stdin is
3
+ * handed to an external TUI (full-screen editor) and back, the tty can
4
+ * deliver a burst of bytes that are NOT user keystrokes — the editor's
5
+ * rmcup/mode-restore replies, CPR/DECRPM query responses, mouse-event
6
+ * fragments, or keystrokes typed into the canonical line buffer while raw
7
+ * mode was off. Parsed as input they are destructive: a stray ESC reads as
8
+ * the escape key (which CLEARS a non-empty prompt) and the rest lands as
9
+ * text garbage.
10
+ *
11
+ * resumeStdin() drains what is already buffered; this module covers what
12
+ * arrives LATE (terminal replies are async). use-input checks the window at
13
+ * the single choke point every component's input flows through, so no
14
+ * listener (Chat's ctrl+c/esc handling included) sees the burst.
15
+ */
16
+ let suppressedUntil = 0;
17
+ /** Suppress all parsed input for `ms` from now (monotonic extension). */
18
+ export function suppressInputFor(ms) {
19
+ const until = Date.now() + ms;
20
+ if (until > suppressedUntil)
21
+ suppressedUntil = until;
22
+ }
23
+ /** True while the post-handoff suppression window is open. */
24
+ export function isInputSuppressed() {
25
+ return Date.now() < suppressedUntil;
26
+ }
@@ -452,9 +452,27 @@ function readLine(screen, y) {
452
452
  return line.trimEnd();
453
453
  }
454
454
  function fullResetSequence_CAUSES_FLICKER(frame, reason, stylePool, debug) {
455
- // After clearTerminal, cursor is at (0, 0)
456
- const screen = new VirtualScreen({ x: 0, y: 0 }, frame.viewport.width);
457
- renderFrame(screen, frame, stylePool);
455
+ // After clearTerminal the viewport is blank and the cursor is at (0, 0), so
456
+ // this paints downward from the top — and therefore must paint only what
457
+ // fits. Every row here ends in CR+LF, the bottom viewport row is reserved
458
+ // for the cursor park, and so at most viewportHeight-1 rows of content can
459
+ // land above it. Painting the whole frame regardless overflows as soon as
460
+ // the frame is as tall as the viewport: the trailing CR+LF is emitted on the
461
+ // bottom row, the terminal scrolls, and the frame's last row — the status
462
+ // hint, always the final row of the main screen — is carried off the bottom.
463
+ // A narrowing resize is what makes a frame reach full height (content wraps
464
+ // onto more rows while the row count stays put), which is why that direction
465
+ // lost its bottom row while widening never did.
466
+ //
467
+ // Painting the frame's tail instead keeps the same end state the in-place
468
+ // viewport repaint documents — frame rows [H-contentRows, H) on screen with
469
+ // the cursor parked one row below the last of them — so the next frame's
470
+ // bookkeeping needs no special case for having come through a reset.
471
+ const height = frame.screen.height;
472
+ const contentRows = Math.min(height, Math.max(1, frame.viewport.height - 1));
473
+ const startY = height - contentRows;
474
+ const screen = new VirtualScreen({ x: 0, y: startY }, frame.viewport.width);
475
+ renderFrameSlice(screen, frame, startY, height, stylePool);
458
476
  return [{ type: 'clearTerminal', reason, debug }, ...screen.diff];
459
477
  }
460
478
  /**
@@ -507,9 +525,6 @@ function repaintViewportInPlace(prev, next, stylePool) {
507
525
  renderFrameSlice(screen, next, startY, height, stylePool);
508
526
  return [{ type: 'stdout', content: anchor }, ...screen.diff];
509
527
  }
510
- function renderFrame(screen, frame, stylePool) {
511
- renderFrameSlice(screen, frame, 0, frame.screen.height, stylePool);
512
- }
513
528
  /**
514
529
  * Render a slice of rows from the frame's screen.
515
530
  * Each row is rendered followed by a newline. Cursor ends at (0, endY).
@@ -58,6 +58,17 @@ export type TerminalResponse =
58
58
  type: 'xtversion';
59
59
  name: string;
60
60
  };
61
+ /** Mutable cross-call state for the decomposed-paste matcher. */
62
+ export type Win32PasteState = {
63
+ /** true between the decomposed start and end markers */
64
+ active: boolean;
65
+ /** progress into the marker pattern currently being matched */
66
+ matched: number;
67
+ /** keys held while a marker prefix match is in flight */
68
+ held: ParsedKey[];
69
+ /** collected paste content while active */
70
+ buffer: string;
71
+ };
61
72
  /**
62
73
  * Parser state carried between parseMultipleKeypresses calls: paste mode,
63
74
  * buffered incomplete input, and the internal tokenizer instance.
@@ -66,6 +77,26 @@ export type KeyParseState = {
66
77
  mode: 'NORMAL' | 'IN_PASTE';
67
78
  incomplete: string;
68
79
  pasteBuffer: string;
80
+ /**
81
+ * Pending high surrogate from a win32-input-mode record. Uc is a UTF-16
82
+ * code unit, so supplementary-plane characters (emoji, CJK ext-B) arrive
83
+ * as two consecutive records; the high half waits here for its low half.
84
+ */
85
+ win32HighSurrogate?: number;
86
+ /**
87
+ * Pending high surrogate for the Alt+numpad synthesis path — separate
88
+ * from win32HighSurrogate because the two Alt rounds of one supplementary
89
+ * char interleave with keydown records (Alt-down, numpad digits) that
90
+ * would settle the regular slot before the low half arrives.
91
+ */
92
+ win32AltHighSurrogate?: number;
93
+ /**
94
+ * Decomposed bracketed-paste tracking for win32-input-mode. Classic
95
+ * conhost synthesizes pastes as per-char KEY_EVENT_RECORDs — including
96
+ * the ESC[200~ / ESC[201~ markers themselves — so under W32IM the markers
97
+ * arrive as ordinary key records and must be reassembled here (issue #147).
98
+ */
99
+ win32Paste?: Win32PasteState;
69
100
  _tokenizer?: Tokenizer;
70
101
  };
71
102
  /** Initial `KeyParseState` for a fresh parser. */
@@ -1 +1 @@
1
- {"version":3,"file":"parse-keypress.d.ts","sourceRoot":"","sources":["../../../src/ink/parse-keypress.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAE/B,OAAO,EAAmB,KAAK,SAAS,EAAE,MAAM,sBAAsB,CAAA;AA0EtE,gDAAgD;AAChD,eAAO,MAAM,aAAa;;;;;;CAMhB,CAAA;AAEV;;;GAGG;AACH,MAAM,MAAM,gBAAgB;AAC1B,iEAAiE;AAC/D;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE;AAClD,oEAAoE;GAClE;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE;AACnC,+DAA+D;GAC7D;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE;AACnC,iEAAiE;GAC/D;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE;AAC1C,sDAAsD;GACpD;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE;AACtD,kFAAkF;GAChF;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE;AAC7C;wEACwE;GACtE;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAA;AAuEvC;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE,QAAQ,GAAG,UAAU,CAAA;IAC3B,UAAU,EAAE,MAAM,CAAA;IAClB,WAAW,EAAE,MAAM,CAAA;IAEnB,UAAU,CAAC,EAAE,SAAS,CAAA;CACvB,CAAA;AAED,kDAAkD;AAClD,eAAO,MAAM,aAAa,EAAE,aAI3B,CAAA;AAmBD;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,aAAa,EACxB,KAAK,GAAE,MAAM,GAAG,MAAM,GAAG,IAAS,GACjC,CAAC,WAAW,EAAE,EAAE,aAAa,CAAC,CAsFhC;AA0GD;;;GAGG;AACH,eAAO,MAAM,mBAAmB,UAa/B,CAAA;AA0HD;;;GAGG;AACH,MAAM,MAAM,SAAS,GAAG;IACtB,IAAI,EAAE,KAAK,CAAA;IACX,EAAE,EAAE,OAAO,CAAA;IACX,IAAI,EAAE,MAAM,GAAG,SAAS,CAAA;IACxB,IAAI,EAAE,OAAO,CAAA;IACb,IAAI,EAAE,OAAO,CAAA;IACb,KAAK,EAAE,OAAO,CAAA;IACd,MAAM,EAAE,OAAO,CAAA;IACf,KAAK,EAAE,OAAO,CAAA;IACd,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAA;IAC5B,GAAG,EAAE,MAAM,GAAG,SAAS,CAAA;IACvB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,OAAO,CAAA;CAClB,CAAA;AAED;;6BAE6B;AAC7B,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,UAAU,CAAA;IAChB,uDAAuD;IACvD,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,gBAAgB,CAAA;CAC3B,CAAA;AAED;;0DAE0D;AAC1D,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,OAAO,CAAA;IACb;4DACwD;IACxD,MAAM,EAAE,MAAM,CAAA;IACd,2DAA2D;IAC3D,MAAM,EAAE,OAAO,GAAG,SAAS,CAAA;IAC3B,uCAAuC;IACvC,GAAG,EAAE,MAAM,CAAA;IACX,oCAAoC;IACpC,GAAG,EAAE,MAAM,CAAA;IACX,QAAQ,EAAE,MAAM,CAAA;CACjB,CAAA;AAED;2EAC2E;AAC3E,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,WAAW,GAAG,cAAc,CAAA"}
1
+ {"version":3,"file":"parse-keypress.d.ts","sourceRoot":"","sources":["../../../src/ink/parse-keypress.ts"],"names":[],"mappings":"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"}
@@ -25,6 +25,74 @@ const CSI_U_RE = /^\x1b\[(\d+)(?:;(\d+))?u/;
25
25
  // Note param order is reversed vs CSI u (modifier first, keycode second).
26
26
  // eslint-disable-next-line no-control-regex
27
27
  const MODIFY_OTHER_KEYS_RE = /^\x1b\[27;(\d+);(\d+)~/;
28
+ // win32-input-mode (ConPTY, DECSET 9001): CSI Vk;Sc;Uc;Kd;Cs;Rc _
29
+ // One record per key event, carrying the full INPUT_RECORD state:
30
+ // Vk = virtual-key code (VK_RETURN=13, VK_ESCAPE=27, VK_UP=38, ...)
31
+ // Sc = scan code (unused — Vk+Uc fully determine the key)
32
+ // Uc = UTF-16 code unit of the produced character (0 for non-printing)
33
+ // Kd = keydown(1)/keyup(0)
34
+ // Cs = dwControlKeyState (0x01/0x02 Alt, 0x04/0x08 Ctrl, 0x10 Shift;
35
+ // also NUMLOCK 0x20 / CAPSLOCK 0x80 / ENHANCED 0x100 — mask before
36
+ // testing modifiers)
37
+ // Rc = repeat count
38
+ // All six fields are optional per spec #4999 and take their KEY_EVENT_RECORD
39
+ // defaults (Vk/Sc/Uc/Kd/Cs=0, Rc=1) when omitted or empty — a reduced 'a'
40
+ // keydown is legitimately `CSI 65;30;97;1_`. This is the only encoding that
41
+ // preserves Enter's Shift/Ctrl bits on Windows (issue #147). Enabled on
42
+ // win32 instead of kitty/modifyOtherKeys.
43
+ // eslint-disable-next-line no-control-regex
44
+ const WIN32_INPUT_RE = /^\x1b\[([\d;]*)_$/;
45
+ // dwControlKeyState modifier bits (others — NUMLOCK_ON 0x20, CAPSLOCK_ON
46
+ // 0x80, ENHANCED_KEY 0x100 — are state indicators, not pressed modifiers)
47
+ const WIN32_CS_ALT = 0x01 | 0x02;
48
+ const WIN32_CS_CTRL = 0x04 | 0x08;
49
+ const WIN32_CS_SHIFT = 0x10;
50
+ // Virtual-key codes that produce no input event of their own: the bare
51
+ // modifier keys. Their pressed state rides on the NEXT real key's Cs field,
52
+ // so both their keydown and keyup records are dropped.
53
+ const WIN32_VK_MODIFIER = new Set([16, 17, 18]); // VK_SHIFT, VK_CONTROL, VK_MENU
54
+ // Virtual-key code → key name for non-printing keys. Names match the
55
+ // keyName vocabulary below so input-event's nonAlphanumericKeys filter
56
+ // clears their raw sequence from text input. Printable keys are NOT here —
57
+ // they map through Uc (or Vk for Ctrl+letter, whose Uc is a control code).
58
+ const WIN32_VK_NAMES = {
59
+ 8: 'backspace', // VK_BACK
60
+ 9: 'tab', // VK_TAB
61
+ 13: 'return', // VK_RETURN
62
+ 27: 'escape', // VK_ESCAPE
63
+ 32: 'space', // VK_SPACE
64
+ 33: 'pageup', // VK_PRIOR
65
+ 34: 'pagedown', // VK_NEXT
66
+ 35: 'end', // VK_END
67
+ 36: 'home', // VK_HOME
68
+ 37: 'left', // VK_LEFT
69
+ 38: 'up', // VK_UP
70
+ 39: 'right', // VK_RIGHT
71
+ 40: 'down', // VK_DOWN
72
+ 45: 'insert', // VK_INSERT
73
+ 46: 'delete', // VK_DELETE
74
+ };
75
+ // VK_F1 (112) .. VK_F12 (123)
76
+ for (let i = 0; i < 12; i++)
77
+ WIN32_VK_NAMES[112 + i] = `f${i + 1}`;
78
+ // OEM punctuation virtual-key codes → base character, used to recover
79
+ // Ctrl+<punctuation> combos (Ctrl+] etc.) whose Uc collapses to a control
80
+ // code. US-layout values; other layouts differ, but these combos are
81
+ // rare enough that a best-effort base key beats swallowing the event.
82
+ const WIN32_VK_OEM_CHARS = {
83
+ 186: ';', // VK_OEM_1
84
+ 187: '=', // VK_OEM_PLUS
85
+ 188: ',', // VK_OEM_COMMA
86
+ 189: '-', // VK_OEM_MINUS
87
+ 190: '.', // VK_OEM_PERIOD
88
+ 191: '/', // VK_OEM_2
89
+ 192: '`', // VK_OEM_3
90
+ 219: '[', // VK_OEM_4
91
+ 220: '\\', // VK_OEM_5
92
+ 221: ']', // VK_OEM_6
93
+ 222: "'", // VK_OEM_7
94
+ 226: '\\', // VK_OEM_102
95
+ };
28
96
  // -- Terminal response patterns (inbound sequences from the terminal itself) --
29
97
  // DECRPM: CSI ? Ps ; Pm $ y — response to DECRQM (request mode)
30
98
  // eslint-disable-next-line no-control-regex
@@ -140,6 +208,302 @@ function splitNumericParams(params) {
140
208
  return [];
141
209
  return params.split(';').map(p => parseInt(p, 10));
142
210
  }
211
+ /**
212
+ * Build a modifier-free text key from a win32 record (used for the
213
+ * Alt+numpad payload on Alt-release). `sequence` defaults to the char —
214
+ * space needs the literal ' ' so input-event lets it through as text.
215
+ */
216
+ function win32TextKey(raw, name, sequence = name) {
217
+ return {
218
+ kind: 'key',
219
+ name,
220
+ fn: false,
221
+ ctrl: false,
222
+ meta: false,
223
+ shift: false,
224
+ option: false,
225
+ super: false,
226
+ sequence,
227
+ raw,
228
+ isPasted: false,
229
+ };
230
+ }
231
+ /**
232
+ * Translate a win32-input-mode record (CSI Vk;Sc;Uc;Kd;Cs;Rc _) into a
233
+ * ParsedKey, so the rest of the input pipeline sees the same key objects as
234
+ * on VT-protocol terminals (issue #147).
235
+ *
236
+ * @param ctx - surrogate-pair scratch state. Uc is a UTF-16 code unit, so a
237
+ * supplementary-plane character (emoji, CJK ext-B) arrives as two
238
+ * consecutive records; the high half waits in `ctx.high` for its low half.
239
+ * Mutated here, never on the caller's KeyParseState — the caller threads
240
+ * it into the next call's state.
241
+ * @returns `undefined` when `s` is not a win32 record (caller falls through
242
+ * to the VT parsers); `null` for a record that must be swallowed (keyup,
243
+ * bare modifier transition, orphaned surrogate half); otherwise the key
244
+ * plus its repeat count (Rc — ConPTY coalesces held-key repeats into one
245
+ * record).
246
+ */
247
+ function parseWin32KeyEvent(s, ctx) {
248
+ const m = WIN32_INPUT_RE.exec(s);
249
+ if (!m)
250
+ return undefined;
251
+ const fields = m[1].split(';');
252
+ const num = (i, dflt) => {
253
+ const f = fields[i];
254
+ return f === undefined || f === '' ? dflt : parseInt(f, 10);
255
+ };
256
+ const vk = num(0, 0);
257
+ const uc = num(2, 0);
258
+ const keydown = num(3, 0) === 1;
259
+ const cs = num(4, 0);
260
+ // Rc coalesces auto-repeat; cap it so a corrupt/huge field can't flood the
261
+ // input queue (legitimate bursts arrive as separate records anyway).
262
+ const repeat = Math.max(1, Math.min(num(5, 1) || 1, 64));
263
+ // A line editor acts on keypresses only — keyup carries no meaning and
264
+ // would double every key if dispatched. Checked BEFORE settling a pending
265
+ // surrogate pair: CharToKeyEvents emits down+up per UTF-16 unit, so a
266
+ // supplementary character legitimately streams as high-down, high-up,
267
+ // low-down — a keyup must never clear the held high half.
268
+ if (!keydown) {
269
+ // Exception: Alt+numpad Unicode input (WindowsInbox's
270
+ // Feature_UseNumpadEventsForClipboardInput). The stream is Alt-down,
271
+ // digit records with no text, then a single Alt KEYUP whose Uc carries
272
+ // the composed character — the only payload in the stream. Ordinary
273
+ // keyups also carry Uc, so this is gated strictly on VK_MENU release
274
+ // with a nonzero Uc.
275
+ if (vk !== 18 || uc === 0)
276
+ return null;
277
+ // A supplementary-plane char is synthesized per UTF-16 unit: TWO Alt
278
+ // rounds, high half then low half, each riding its own Alt-up. The
279
+ // pending high waits in ctx.altHigh — a dedicated slot, because the
280
+ // next round's Alt-down/numpad records are keydowns that would settle
281
+ // the regular ctx.high before the low half ever arrives.
282
+ if (uc >= 0xd800 && uc <= 0xdbff) {
283
+ ctx.altHigh = uc;
284
+ return null;
285
+ }
286
+ if (uc >= 0xdc00 && uc <= 0xdfff) {
287
+ const high = ctx.altHigh;
288
+ ctx.altHigh = undefined;
289
+ if (high === undefined)
290
+ return null;
291
+ return { key: win32TextKey(s, String.fromCharCode(high, uc)), repeat: 1 };
292
+ }
293
+ // BMP payload: any pending synthesized high is orphaned by this char.
294
+ ctx.altHigh = undefined;
295
+ if (uc === 0x20) {
296
+ return { key: win32TextKey(s, 'space', ' '), repeat: 1 };
297
+ }
298
+ if (uc > 0x20 && !(uc >= 0x7f && uc <= 0x9f)) {
299
+ return { key: win32TextKey(s, String.fromCharCode(uc)), repeat: 1 };
300
+ }
301
+ return null;
302
+ }
303
+ // Every keydown settles a pending pair: a high half followed by anything
304
+ // but its low half is dropped, never combined across keys.
305
+ const highSurrogate = ctx.high;
306
+ ctx.high = undefined;
307
+ // The Alt+numpad pending high survives ONLY the synthesis stream's own
308
+ // filler records: a payload-free VK_MENU transition (the next round's
309
+ // Alt-down), or a payload-free numpad digit while Alt is held (Cs carries
310
+ // an Alt bit). Real Shift/Ctrl transitions and digits pressed without
311
+ // Alt are real input — they settle (drop) the pending high.
312
+ const altHeld = (cs & WIN32_CS_ALT) !== 0;
313
+ const isSynthesisFiller = (vk === 18 && uc === 0) || (vk >= 96 && vk <= 105 && uc === 0 && altHeld);
314
+ if (!isSynthesisFiller) {
315
+ ctx.altHigh = undefined;
316
+ }
317
+ // Bare modifier transitions: their state rides on the next real key's Cs.
318
+ if (WIN32_VK_MODIFIER.has(vk))
319
+ return null;
320
+ const shift = (cs & WIN32_CS_SHIFT) !== 0;
321
+ let ctrl = (cs & WIN32_CS_CTRL) !== 0;
322
+ let meta = (cs & WIN32_CS_ALT) !== 0;
323
+ const base = {
324
+ kind: 'key',
325
+ fn: false,
326
+ ctrl,
327
+ meta,
328
+ shift,
329
+ option: false,
330
+ super: false,
331
+ raw: s,
332
+ isPasted: false,
333
+ };
334
+ // Printable text comes through Uc, already shift/IME-composed by the
335
+ // console host — so it must win over the Vk name table: NumLock-on numpad
336
+ // keys legitimately carry the Ins/Del/Home/... cluster's Vk with the digit
337
+ // in Uc (tcell emits e.g. CSI 45;82;48;1;32;1_ for numpad 0), and only Uc
338
+ // (plus the ENHANCED_KEY bit, which text keys never set) tells them apart.
339
+ // "Printable" excludes C0, DEL and the C1 band (matching Windows
340
+ // Terminal's own codepoint > 0x20 && != 0x7f rule, extended over C1):
341
+ // Ctrl+8 / Ctrl+/ report Uc=0x7F and must reach the Ctrl recovery chain
342
+ // below.
343
+ let char;
344
+ if (uc >= 0xd800 && uc <= 0xdbff) {
345
+ ctx.high = uc;
346
+ return null;
347
+ }
348
+ if (uc >= 0xdc00 && uc <= 0xdfff) {
349
+ // Orphaned low half (no pending high): swallow immediately. Falling
350
+ // through to the Vk table would resurrect it as a named key — a stray
351
+ // CSI 32;57;56832;1;0;1_ must not become a Space.
352
+ if (highSurrogate === undefined)
353
+ return null;
354
+ char = String.fromCharCode(highSurrogate, uc);
355
+ }
356
+ else if (uc > 0x20 && !(uc >= 0x7f && uc <= 0x9f)) {
357
+ char = String.fromCharCode(uc);
358
+ }
359
+ // Space gets its own Vk-independent branch: spec-legal records omit Vk
360
+ // (CSI ;;32;1_) and Unicode-injected input arrives as VK_PACKET (231) —
361
+ // neither reaches the Vk=32 name entry below. Unlike graphic chars,
362
+ // space KEEPS ctrl/meta: Ctrl+Alt+Space is a binding, not AltGr text
363
+ // (input-event maps ctrl+space to ' ').
364
+ if (uc === 0x20) {
365
+ return { key: { ...base, name: 'space', sequence: ' ' }, repeat };
366
+ }
367
+ if (char !== undefined) {
368
+ // AltGr arrives as RightAlt + a synthesized LeftCtrl with the printable
369
+ // char in Uc — that's text input ('@', '€', '\', '|', braces on
370
+ // international layouts), not a Ctrl+Alt binding. Clearing the modifiers
371
+ // is required for the text to be insertable at all (PromptInput rejects
372
+ // input carrying ctrl/meta). Genuine Ctrl+Alt+<printable> bindings are
373
+ // indistinguishable from AltGr by Windows design.
374
+ if (ctrl && meta) {
375
+ ctrl = false;
376
+ meta = false;
377
+ }
378
+ return { key: { ...base, ctrl, meta, name: char, sequence: char }, repeat };
379
+ }
380
+ // Synthesized character records (conhost's SynthesizeKeyEvent: Vk=0,
381
+ // Sc=0, Cs=0) carry their entire payload in Uc — including the control
382
+ // chars that spell the bracketed-paste markers (ESC[200~ / ESC[201~).
383
+ // Map the editing-relevant ones to named keys so the decomposed-paste
384
+ // reassembler below can see the marker characters at all.
385
+ if (vk === 0) {
386
+ if (uc === 27)
387
+ return { key: { ...base, name: 'escape', sequence: s }, repeat };
388
+ if (uc === 13 || uc === 10)
389
+ return { key: { ...base, name: 'return', sequence: s }, repeat };
390
+ if (uc === 9)
391
+ return { key: { ...base, name: 'tab', sequence: s }, repeat };
392
+ if (uc === 8 || uc === 0x7f)
393
+ return { key: { ...base, name: 'backspace', sequence: s }, repeat };
394
+ return null;
395
+ }
396
+ // Non-printing keys by virtual-key code. sequence stays the raw record so
397
+ // input-event clears it via nonAlphanumericKeys ('space' isn't in that
398
+ // list — it needs the literal ' ' as sequence to reach text input).
399
+ const named = WIN32_VK_NAMES[vk];
400
+ if (named) {
401
+ return {
402
+ key: { ...base, name: named, sequence: named === 'space' ? ' ' : s },
403
+ repeat,
404
+ };
405
+ }
406
+ // Ctrl combos collapse Uc to a control code (Ctrl+C → 3, Ctrl+[ → 27,
407
+ // Ctrl+2 → 0). Recover the base key from Vk so the combination isn't
408
+ // swallowed: Ctrl+[ must stay usable as Escape (legacy VT parity — the
409
+ // \x1b byte), letters map to their name for bindings like Ctrl+C
410
+ // (exitOnCtrlC), punctuation via the OEM table.
411
+ if (ctrl) {
412
+ if (uc === 27) {
413
+ return { key: { ...base, name: 'escape', sequence: s }, repeat };
414
+ }
415
+ const baseChar = vk >= 65 && vk <= 90
416
+ ? String.fromCharCode(vk + 32)
417
+ : vk >= 48 && vk <= 57
418
+ ? String.fromCharCode(vk)
419
+ : WIN32_VK_OEM_CHARS[vk];
420
+ if (baseChar !== undefined) {
421
+ return { key: { ...base, name: baseChar, sequence: baseChar }, repeat };
422
+ }
423
+ }
424
+ // No usable payload (unmapped function key, dead key, Uc=0): swallow so
425
+ // the raw record can't leak into the prompt as text.
426
+ return null;
427
+ }
428
+ // Character spellings of CSI 200~ / CSI 201~ as key records: the ESC char
429
+ // arrives as a Vk=27 record (name 'escape'), the rest as text chars.
430
+ const WIN32_PASTE_START_CHARS = ['\x1b', '[', '2', '0', '0', '~'];
431
+ const WIN32_PASTE_END_CHARS = ['\x1b', '[', '2', '0', '1', '~'];
432
+ /**
433
+ * The text equivalent of a translated win32 key for paste purposes: chars
434
+ * map to themselves, named editing keys to their control char. Returns
435
+ * undefined for keys with no text meaning (arrows, F-keys).
436
+ */
437
+ function win32RecordChar(key) {
438
+ switch (key.name) {
439
+ case 'escape':
440
+ return '\x1b';
441
+ case 'space':
442
+ return ' ';
443
+ case 'tab':
444
+ return '\t';
445
+ case 'return':
446
+ return '\n';
447
+ case 'backspace':
448
+ return '\x7f';
449
+ default:
450
+ // Text keys carry their char as BOTH name and sequence; named keys
451
+ // keep the raw CSI record as sequence. This avoids a UTF-16 length
452
+ // check — a supplementary-plane char (emoji, CJK ext-B) is a
453
+ // length-2 string but still text.
454
+ return key.sequence === key.name ? key.name : undefined;
455
+ }
456
+ }
457
+ /**
458
+ * Feed one translated win32 key through the decomposed-paste matcher.
459
+ * Returns the keys to emit (empty while holding a candidate prefix or
460
+ * collecting paste content).
461
+ */
462
+ function feedWin32Paste(state, key) {
463
+ const pattern = state.active ? WIN32_PASTE_END_CHARS : WIN32_PASTE_START_CHARS;
464
+ // Marker chars never carry Ctrl/Alt in the synthesized stream; requiring
465
+ // this keeps a user's real Ctrl+[ from starting a phantom paste. Shift is
466
+ // allowed — '~' legitimately arrives with it.
467
+ const ch = key.ctrl || key.meta ? undefined : win32RecordChar(key);
468
+ if (ch !== undefined && ch === pattern[state.matched]) {
469
+ state.held.push(key);
470
+ state.matched++;
471
+ if (state.matched === pattern.length) {
472
+ state.matched = 0;
473
+ state.held = [];
474
+ if (!state.active) {
475
+ state.active = true;
476
+ state.buffer = '';
477
+ return [];
478
+ }
479
+ // End marker complete: the whole paste as a single event.
480
+ const paste = createPasteKey(state.buffer);
481
+ state.active = false;
482
+ state.buffer = '';
483
+ return [paste];
484
+ }
485
+ return [];
486
+ }
487
+ // Mismatch: release whatever prefix was held, then re-evaluate the
488
+ // current key from a clean match position (it may itself start a marker,
489
+ // e.g. ESC ESC [ 2 0 1 ~).
490
+ if (state.matched > 0) {
491
+ const held = state.held;
492
+ state.held = [];
493
+ state.matched = 0;
494
+ if (state.active) {
495
+ for (const k of held)
496
+ state.buffer += win32RecordChar(k) ?? '';
497
+ return feedWin32Paste(state, key);
498
+ }
499
+ return [...held, ...feedWin32Paste(state, key)];
500
+ }
501
+ if (state.active) {
502
+ state.buffer += win32RecordChar(key) ?? '';
503
+ return [];
504
+ }
505
+ return [key];
506
+ }
143
507
  /** Initial `KeyParseState` for a fresh parser. */
144
508
  export const INITIAL_STATE = {
145
509
  mode: 'NORMAL',
@@ -185,6 +549,23 @@ export function parseMultipleKeypresses(prevState, input = '') {
185
549
  const keys = [];
186
550
  let inPaste = prevState.mode === 'IN_PASTE';
187
551
  let pasteBuffer = prevState.pasteBuffer;
552
+ // Surrogate-pair scratch for win32-input-mode records. Threaded through a
553
+ // local object so prevState is never mutated — App.tsx seeds the parser
554
+ // with the shared INITIAL_STATE singleton, and a pending high surrogate
555
+ // leaking into it would survive into fresh parser instances.
556
+ const win32Ctx = {
557
+ high: prevState.win32HighSurrogate,
558
+ altHigh: prevState.win32AltHighSurrogate,
559
+ };
560
+ // Decomposed-paste matcher state rides on a shared mutable object across
561
+ // calls (like _tokenizer). Fresh instances never touch INITIAL_STATE —
562
+ // the field stays undefined there and the object is created on demand.
563
+ const win32Paste = prevState.win32Paste ?? {
564
+ active: false,
565
+ matched: 0,
566
+ held: [],
567
+ buffer: '',
568
+ };
188
569
  for (const token of tokens) {
189
570
  if (token.type === 'sequence') {
190
571
  if (token.value === PASTE_START) {
@@ -204,17 +585,33 @@ export function parseMultipleKeypresses(prevState, input = '') {
204
585
  pasteBuffer += token.value;
205
586
  }
206
587
  else {
207
- const response = parseTerminalResponse(token.value);
208
- if (response) {
209
- keys.push({ kind: 'response', sequence: token.value, response });
588
+ const win32 = parseWin32KeyEvent(token.value, win32Ctx);
589
+ if (win32 !== undefined) {
590
+ // win32-input-mode record. null means a swallowed event (keyup,
591
+ // bare modifier, orphaned surrogate) — the sequence is consumed
592
+ // either way and never reaches the VT keypress parser.
593
+ if (win32 !== null) {
594
+ // Keys pass through the decomposed-paste matcher: on classic
595
+ // conhost the bracketed-paste markers themselves arrive as key
596
+ // records and must be reassembled before dispatch.
597
+ for (let i = 0; i < win32.repeat; i++) {
598
+ keys.push(...feedWin32Paste(win32Paste, win32.key));
599
+ }
600
+ }
210
601
  }
211
602
  else {
212
- const mouse = parseMouseEvent(token.value);
213
- if (mouse) {
214
- keys.push(mouse);
603
+ const response = parseTerminalResponse(token.value);
604
+ if (response) {
605
+ keys.push({ kind: 'response', sequence: token.value, response });
215
606
  }
216
607
  else {
217
- keys.push(parseKeypress(token.value));
608
+ const mouse = parseMouseEvent(token.value);
609
+ if (mouse) {
610
+ keys.push(mouse);
611
+ }
612
+ else {
613
+ keys.push(parseKeypress(token.value));
614
+ }
218
615
  }
219
616
  }
220
617
  }
@@ -251,11 +648,39 @@ export function parseMultipleKeypresses(prevState, input = '') {
251
648
  inPaste = false;
252
649
  pasteBuffer = '';
253
650
  }
651
+ // Flush handling for the decomposed win32 paste: mid-paste (active) the
652
+ // 50ms quiet timer means the paste stream ended — finalize with whatever
653
+ // was collected (mirrors the VT IN_PASTE flush above; a truncated end
654
+ // marker must not strand the matcher and eat all future typing). Outside
655
+ // a paste, release any held marker-prefix keys (e.g. a lone Escape).
656
+ if (isFlush && win32Paste.active) {
657
+ let content = win32Paste.buffer;
658
+ for (const k of win32Paste.held)
659
+ content += win32RecordChar(k) ?? '';
660
+ keys.push(createPasteKey(content));
661
+ win32Paste.active = false;
662
+ win32Paste.buffer = '';
663
+ win32Paste.held = [];
664
+ win32Paste.matched = 0;
665
+ }
666
+ else if (isFlush && win32Paste.held.length > 0) {
667
+ keys.push(...win32Paste.held);
668
+ win32Paste.held = [];
669
+ win32Paste.matched = 0;
670
+ }
254
671
  // Build new state
255
672
  const newState = {
256
673
  mode: inPaste ? 'IN_PASTE' : 'NORMAL',
257
- incomplete: tokenizer.buffer(),
674
+ // App.tsx arms its flush timer whenever `incomplete` is non-empty. The
675
+ // tokenizer only reports raw bytes there, so paste-matcher holds (a
676
+ // marker prefix in flight, or an active paste) set a sentinel to get the
677
+ // same 50ms release — a lone Escape stays as responsive as in VT mode.
678
+ incomplete: tokenizer.buffer() ||
679
+ (win32Paste.held.length > 0 || win32Paste.active ? '\x1b' : ''),
258
680
  pasteBuffer,
681
+ win32HighSurrogate: win32Ctx.high,
682
+ win32AltHighSurrogate: win32Ctx.altHigh,
683
+ win32Paste,
259
684
  _tokenizer: tokenizer,
260
685
  };
261
686
  return [keys, newState];
@@ -603,6 +1028,15 @@ function parseKeypress(s = '') {
603
1028
  key.raw = undefined;
604
1029
  key.name = 'return';
605
1030
  }
1031
+ else if (s === '\x1b\r' || s === '\x1b\n') {
1032
+ // Option+Enter on terminals without extended key reporting (Terminal.app,
1033
+ // default macOS terminal) sends ESC CR when "Use Option as Meta" is on —
1034
+ // the tokenizer passes CR through as text since it's not an ESC final
1035
+ // byte, so the pair arrives here as one chunk (issue #110).
1036
+ key.raw = undefined;
1037
+ key.name = 'return';
1038
+ key.meta = true;
1039
+ }
606
1040
  else if (s === '\n') {
607
1041
  key.name = 'enter';
608
1042
  }